aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortradke <tradke@b32723a9-ab3a-4a60-88e2-2e5d99d7c17a>2001-12-21 17:02:46 +0000
committertradke <tradke@b32723a9-ab3a-4a60-88e2-2e5d99d7c17a>2001-12-21 17:02:46 +0000
commit450116f38c45498f1b0dec42b3c029c0e7057a36 (patch)
tree68d8263e8b2664c2704faf08f5e98d9994aa2844
parent1f58ee9eba058953cc6f98c067a73ab294abccb7 (diff)
Changed recovery code to use opendir(3), readdir(3), closedir(3) instead of
non-POSIX routine scandir(3). This also gets rid of a nasty compiler warning (scandir isn't standardized). git-svn-id: http://svn.cactuscode.org/arrangements/CactusBase/IOUtil/trunk@143 b32723a9-ab3a-4a60-88e2-2e5d99d7c17a
-rw-r--r--src/CheckpointRecovery.c234
1 files changed, 115 insertions, 119 deletions
diff --git a/src/CheckpointRecovery.c b/src/CheckpointRecovery.c
index 71e98c1..a2858ae 100644
--- a/src/CheckpointRecovery.c
+++ b/src/CheckpointRecovery.c
@@ -19,11 +19,7 @@
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
-
-#ifdef HAVE_SCANDIR
-#include <ctype.h>
#include <dirent.h>
-#endif
static const char *rcsid = "$Header$";
CCTK_FILEVERSION(CactusBase_IOUtil_CheckpointRecovery_c)
@@ -44,23 +40,22 @@ static cHandledData *RecoverFunctions = NULL;
static int num_functions = 0;
static int checkpoint_file_exists = 0;
-#ifdef HAVE_SCANDIR
-/* prefix and extension of potential recovery files */
-static char *recoverFilePrefix;
-static const char *recoverFileExtension;
-#endif
+
+/********************************************************************
+ ******************** Internal Typedefs ************************
+ ********************************************************************/
+typedef struct
+{
+ char *basename;
+ int iteration;
+} filelist_t;
/********************************************************************
******************** Internal Routines ************************
********************************************************************/
static void SetInputFlag (int vindex, const char *optstring, void *arg);
-
-#ifdef HAVE_SCANDIR
-/* prototypes of the select and sort routine used by scandir(3) */
-static int IOUtil_RecoverFileSelect (struct dirent *entry);
-static int IOUtil_RecoverFileCompare (struct dirent **a, struct dirent **b);
-#endif
+static int CompareFiles (const void *a, const void *b);
/************************************************************************
@@ -508,7 +503,8 @@ void IOUtil_RecoverIDFromDatafiles (cGH *GH)
0 if in "autoprobe" mode and no cp files were found, or<BR>
+1 if parameter recovery was successful for some cp file,<BR>
-1 if in "auto" mode and no checkpoint files were found,
- or if parameter recovery failed for some cp file
+ or if parameter recovery failed for some cp file,<BR>
+ -2 if in "auto*" mode and recovery dir doesn't exist
@endreturndesc
@@*/
int IOUtil_RecoverParameters (int (*recoverFn) (cGH *GH,
@@ -517,20 +513,17 @@ int IOUtil_RecoverParameters (int (*recoverFn) (cGH *GH,
const char *fileExtension,
const char *fileType)
{
- int retval; /* the return value */
- cGH *dummyGH = NULL; /* there's no GH yet but the callback routine
- expects a GH pointer */
-#ifdef HAVE_SCANDIR
- int i, nRecoverFiles;
- struct dirent **recoverFileList = NULL;
-#endif
+ int len, extension_len, recover_file_len, retval;
+ unsigned int num_files;
+ DIR *dir;
+ const char *p;
+ struct dirent *file;
+ filelist_t *filelist, *tmp;
DECLARE_CCTK_PARAMETERS
if (CCTK_Equals (recover, "auto") || CCTK_Equals (recover, "autoprobe"))
{
- retval = CCTK_Equals (recover, "auto") ? -1 : 0;
-#ifdef HAVE_SCANDIR
if (verbose)
{
CCTK_VInfo (CCTK_THORNSTRING, "Searching for %s checkpoint files "
@@ -538,54 +531,115 @@ int IOUtil_RecoverParameters (int (*recoverFn) (cGH *GH,
fileType, recover_file, recovery_dir);
}
- /* set the file prefix and extension for selecting valid checkpoint files */
- /* we have to pass it via global variables to the select() routine
- because it doesn't receive user-supplied arguments */
- recoverFilePrefix = (char *) malloc (strlen (recover_file) + 5);
- sprintf (recoverFilePrefix, "%s.it_", recover_file);
- recoverFileExtension = fileExtension;
+ dir = opendir (recovery_dir);
+ if (! dir)
+ {
+ CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Recovery directory '%s' doesn't exist", recovery_dir);
+ return (-2);
+ }
/* get the list of potential recovery files */
- nRecoverFiles = scandir (recovery_dir, &recoverFileList,
- IOUtil_RecoverFileSelect,
- IOUtil_RecoverFileCompare);
+ extension_len = strlen (fileExtension);
+ recover_file_len = strlen (recover_file);
+ num_files = 0;
+ filelist = NULL;
- if (nRecoverFiles <= 0)
+ while ((file = readdir (dir)) != NULL)
{
- CCTK_VWarn (retval ? 1 : 3, __LINE__, __FILE__, CCTK_THORNSTRING,
- "No %s checkpoint files with basefilename '%s' found in "
- "recovery directory '%s'",
- fileType, recover_file, recovery_dir);
+ /* first check the file prefix */
+ if (strncmp (file->d_name, recover_file, recover_file_len) ||
+ strncmp (file->d_name + recover_file_len, ".it_", 4))
+ {
+ continue;
+ }
+
+ /* now check if there is an iteration number following the file prefix */
+ for (p = file->d_name + recover_file_len + 4; *p && *p != '.'; p++)
+ {
+ if (! isdigit ((int) *p))
+ {
+ break;
+ }
+ }
+ if (*p != '.')
+ {
+ continue;
+ }
+
+ /* check for a '.file_<processor>' suffix for chunked output
+ We only select the chunked output file of processor 0 in that case. */
+ if (! strncmp (p, ".file_", 6) && strncmp (p, ".file_0", 7))
+ {
+ continue;
+ }
+
+ /* finally check the file type suffix */
+ len = strlen (file->d_name);
+ if (len < extension_len ||
+ strcmp (file->d_name + len - extension_len, fileExtension))
+ {
+ continue;
+ }
+
+ /* found a recovery file by that basename */
+ if (num_files == 0)
+ {
+ tmp = (filelist_t *) malloc (sizeof (filelist_t));
+ }
+ else
+ {
+ tmp = (filelist_t *) realloc (filelist,
+ (num_files+1) * sizeof (filelist_t));
+ }
+ if (tmp == NULL)
+ {
+ CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Failed to allocate memory for file list");
+ continue;
+ }
+ filelist = tmp;
+ filelist[num_files].basename = strdup (file->d_name);
+ /* cut the filename after the iteration number field */
+ filelist[num_files].basename[p - file->d_name] = 0;
+ filelist[num_files].iteration = atoi (file->d_name + recover_file_len+4);
+
+ num_files++;
}
- else
+ closedir (dir);
+
+ retval = CCTK_Equals (recover, "auto") ? -1 : 0;
+ if (num_files)
{
+ /* sort the list according to their iteration numbers */
+ qsort (filelist, num_files, sizeof (filelist_t), CompareFiles);
+
/* loop over all recovery files found and call the callback routine;
skip all following files after the first successful recovery (when
recoverFn() returned a positive value) */
- for (i = 0; i < nRecoverFiles; i++)
+ while (num_files--)
{
if (retval <= 0)
{
- retval = recoverFn (dummyGH, recoverFileList[i]->d_name,
+ retval = recoverFn (NULL, filelist[num_files].basename,
CP_RECOVER_PARAMETERS);
}
- free (recoverFileList[i]);
+ free (filelist[num_files].basename);
}
- free (recoverFileList);
+ free (filelist);
+ }
+ else
+ {
+ CCTK_VWarn (retval ? 1 : 3, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "No %s checkpoint files with basefilename '%s' found in "
+ "recovery directory '%s'",
+ fileType, recover_file, recovery_dir);
}
-#else
- /* no scandir(3) ? give up ! */
- CCTK_WARN (0, "You cannot use 'IO::recover = \"auto\"' on "
- "this architecture because it doesn't provide scandir(3) to "
- "automatically look for checkpoint files.\n"
- "Please use 'IO::recover = \"manual\"' instead !");
-
-#endif
}
else
{
/* just call the recovery routine */
- retval = (*recoverFn) (dummyGH, recover_file, CP_RECOVER_PARAMETERS);
+ retval = (*recoverFn) (NULL, recover_file, CP_RECOVER_PARAMETERS);
}
if (retval < 0)
@@ -798,72 +852,6 @@ int IOUtil_RestartFromRecovery (const cGH *GH)
/***************************** local routines ******************************/
-#ifdef HAVE_SCANDIR
-
-/* function to be called by scandir(3) to select potential recovery
- files in the given recovery directory (see IOUtil_RecoverParameters()) */
-static int IOUtil_RecoverFileSelect (struct dirent *entry)
-{
- char *p;
- int len, prefixLen, extLen;
-
-
- len = strlen (entry->d_name);
- prefixLen = strlen (recoverFilePrefix);
-
- /* At first check for recoverFilePrefix in the beginning of the filename */
- if (strncmp (entry->d_name, recoverFilePrefix, prefixLen))
- {
- return (0);
- }
-
- /* Now check if there is an iteration number following the file prefix. */
- for (p = (char *) entry->d_name + prefixLen; *p && *p != '.'; p++)
- {
- if (! isdigit ((int) *p))
- {
- return (0);
- }
- }
-
- /* Check for a '.file_<processor>' suffix for chunked output.
- We only select the chunked output file of processor 0 in that case. */
- if (p - entry->d_name < len)
- {
- if (! strncmp (p, ".file_", 6) && strncmp (p, ".file_0", 7))
- {
- return (0);
- }
- }
-
- /* Finally check the suffix */
- extLen = strlen (recoverFileExtension);
- if (len < extLen || strcmp (entry->d_name+len-extLen, recoverFileExtension))
- {
- return (0);
- }
-
- /* Cut the file name after the iteration number field
- because we only need the basefilename later on. */
- *p = 0;
-
- return (1);
-}
-
-
-/* function to be called by scandir(3) to sort the list of potential recovery
- files by their iteration number (see IOUtil_RecoverParameters()) */
-static int IOUtil_RecoverFileCompare (struct dirent **a, struct dirent **b)
-{
- int len = strlen (recoverFilePrefix);
-
-
- /* note that this causes the file list to be sorted in descendent order */
- return (atoi ((*b)->d_name + len) - atoi ((*a)->d_name + len));
-}
-#endif /* HAVE_SCANDIR */
-
-
/* callback for CCTK_TraverseString() to set the input flag
for the given variable */
static void SetInputFlag (int vindex, const char *optstring, void *flags)
@@ -877,3 +865,11 @@ static void SetInputFlag (int vindex, const char *optstring, void *flags)
optstring);
}
}
+
+
+/* callback for qsort() to sort the list of recovery files found */
+static int CompareFiles (const void *a, const void *b)
+{
+ return (((const filelist_t *) a)->iteration -
+ ((const filelist_t *) b)->iteration);
+}