From 839f1092da94c17b5f541acdd899e00bc13ef31f Mon Sep 17 00:00:00 2001 From: Leon Arber Date: Thu, 27 Jan 2005 18:21:05 -0500 Subject: [svn-r9877] Purpose: Bug fix: Temporary fix for h5repack failures in all parallel builds. Description: The parallel additions to h5diff interfered with h5repack. Solution: Added a second set of "parallel" functions to h5diff.c. h5repack uses the serial versions, whereas h5diff will use the parallel versions. Also, h5diff will now be smart about when to enter parallel mode. If is run with mpirun with more than 1 task, it will enter parallel mode. Otherwise, it will stay in serial mode as before. Platforms tested: heping (serial and parallel) Misc. update: --- tools/h5diff/h5diff_main.c | 15 +-- tools/lib/h5diff.c | 314 ++++++++++++++++++++++++++++++++++++++++++++- tools/lib/h5diff.h | 15 +++ tools/lib/h5diff_util.c | 2 +- tools/lib/ph5diff.h | 6 +- 5 files changed, 334 insertions(+), 18 deletions(-) diff --git a/tools/h5diff/h5diff_main.c b/tools/h5diff/h5diff_main.c index bab980a..d25904f 100644 --- a/tools/h5diff/h5diff_main.c +++ b/tools/h5diff/h5diff_main.c @@ -73,13 +73,6 @@ int main(int argc, const char *argv[]) MPI_Comm_rank(MPI_COMM_WORLD, &nID); MPI_Comm_size(MPI_COMM_WORLD, &g_nTasks); - if(g_nTasks < 2) - { - printf("Must have at least 2 tasks to run parallel diff\n"); - MPI_Finalize(); - exit(-1); - } - /* Have the manager process the command-line */ if(nID == 0) { @@ -224,10 +217,14 @@ int main(int argc, const char *argv[]) }/*for*/ - nfound = h5diff(fname1,fname2,objname1,objname2,&options); + if(g_nTasks < 2) + nfound = h5diff(fname1,fname2,objname1,objname2,&options); + else + nfound = h5diff_parallel(fname1,fname2,objname1,objname2,&options); #ifdef H5_HAVE_PH5DIFF - MPI_Barrier(MPI_COMM_WORLD); + if(g_nTasks > 1) + MPI_Barrier(MPI_COMM_WORLD); #endif /*------------------------------------------------------------------------- diff --git a/tools/lib/h5diff.c b/tools/lib/h5diff.c index 1807f4b..0b8bb7e 100644 --- a/tools/lib/h5diff.c +++ b/tools/lib/h5diff.c @@ -33,6 +33,7 @@ print_objname (diff_opt_t * options, hsize_t nfound) return ((options->m_verbose || nfound) && !options->m_quiet) ? 1 : 0; } + /*------------------------------------------------------------------------- * Function: h5diff * @@ -85,6 +86,313 @@ h5diff (const char *fname1, printf ("h5diff: <%s>: unable to open file\n", fname1); options->err_stat = 1; + goto out; + } + if ((file2_id = H5Fopen (fname2, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + { + printf ("h5diff: <%s>: unable to open file\n", fname2); + options->err_stat = 1; + + goto out; + } + /* enable error reporting */ + } + H5E_END_TRY; + + +/*------------------------------------------------------------------------- + * get the number of objects in the files + *------------------------------------------------------------------------- + */ + nobjects1 = h5trav_getinfo (file1_id, NULL, 0); + nobjects2 = h5trav_getinfo (file2_id, NULL, 0); + + if (nobjects1 < 0 || nobjects2 < 0) + { + printf ("Error: Could not get get file contents\n"); + options->err_stat = 1; + goto out; + } + + assert (nobjects1 > 0); + assert (nobjects2 > 0); + +/*------------------------------------------------------------------------- + * get the list of objects in the files + *------------------------------------------------------------------------- + */ + + info1 = (trav_info_t *) malloc (nobjects1 * sizeof (trav_info_t)); + info2 = (trav_info_t *) malloc (nobjects2 * sizeof (trav_info_t)); + if (info1 == NULL || info2 == NULL) + { + printf ("Error: Not enough memory for object list\n"); + options->err_stat = 1; + if (info1) + h5trav_freeinfo (info1, nobjects1); + if (info2) + h5trav_freeinfo (info2, nobjects1); + goto out; + } + + h5trav_getinfo (file1_id, info1, 0); + h5trav_getinfo (file2_id, info2, 0); + +/*------------------------------------------------------------------------- + * object name was supplied + *------------------------------------------------------------------------- + */ + + if (objname1) + { + + assert (objname2); + options->cmn_objs = 1; /* eliminate warning */ + nfound = diff_compare (file1_id, fname1, objname1, nobjects1, info1, + file2_id, fname2, objname2, nobjects2, info2, + options); + } + +/*------------------------------------------------------------------------- + * compare all + *------------------------------------------------------------------------- + */ + + else + { + + nfound = diff_match (file1_id, nobjects1, info1, + file2_id, nobjects2, info2, options); + } + + + h5trav_freeinfo (info1, nobjects1); + h5trav_freeinfo (info2, nobjects2); + +out: + /* close */ + H5E_BEGIN_TRY + { + H5Fclose (file1_id); + H5Fclose (file2_id); + } + H5E_END_TRY; + + return nfound; +} + + + +/*------------------------------------------------------------------------- + * Function: diff_match + * + * Purpose: Find common objects; the algorithm used for this search is the + * cosequential match algorithm and is described in + * Folk, Michael; Zoellick, Bill. (1992). File Structures. Addison-Wesley. + * + * Return: Number of differences found + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: May 9, 2003 + * + *------------------------------------------------------------------------- + */ +hsize_t +diff_match (hid_t file1_id, + int nobjects1, + trav_info_t * info1, + hid_t file2_id, + int nobjects2, trav_info_t * info2, diff_opt_t * options) +{ + int more_names_exist = (nobjects1 > 0 && nobjects2 > 0) ? 1 : 0; + trav_table_t *table = NULL; + int cmp; + int curr1 = 0; + int curr2 = 0; + unsigned infile[2]; + char c1, c2; + hsize_t nfound = 0; + int i; + + /*------------------------------------------------------------------------- + * build the list + *------------------------------------------------------------------------- + */ + trav_table_init (&table); + + while (more_names_exist) + { + /* criteria is string compare */ + cmp = strcmp (info1[curr1].name, info2[curr2].name); + if (cmp == 0) + { + infile[0] = 1; + infile[1] = 1; + trav_table_addflags (infile, info1[curr1].name, info1[curr1].type, + table); + + curr1++; + curr2++; + } + else if (cmp < 0) + { + infile[0] = 1; + infile[1] = 0; + trav_table_addflags (infile, info1[curr1].name, info1[curr1].type, + table); + curr1++; + } + else + { + infile[0] = 0; + infile[1] = 1; + trav_table_addflags (infile, info2[curr2].name, info2[curr2].type, + table); + curr2++; + } + + more_names_exist = (curr1 < nobjects1 && curr2 < nobjects2) ? 1 : 0; + + + } /* end while */ + + /* list1 did not end */ + if (curr1 < nobjects1) + { + while (curr1 < nobjects1) + { + infile[0] = 1; + infile[1] = 0; + trav_table_addflags (infile, info1[curr1].name, info1[curr1].type, + table); + curr1++; + } + } + + /* list2 did not end */ + if (curr2 < nobjects2) + { + while (curr2 < nobjects2) + { + infile[0] = 0; + infile[1] = 1; + trav_table_addflags (infile, info2[curr2].name, info2[curr2].type, + table); + curr2++; + } + } + + /*------------------------------------------------------------------------- + * print the list + *------------------------------------------------------------------------- + */ + + if (options->m_verbose) + { + printf ("\n"); + printf ("file1 file2\n"); + printf ("---------------------------------------\n"); + for (i = 0; i < table->nobjs; i++) + { + c1 = (table->objs[i].flags[0]) ? 'x' : ' '; + c2 = (table->objs[i].flags[1]) ? 'x' : ' '; + printf ("%5c %6c %-15s\n", c1, c2, table->objs[i].name); + } + printf ("\n"); + } + + + /*------------------------------------------------------------------------- + * do the diff for common objects + *------------------------------------------------------------------------- + */ + + for (i = 0; i < table->nobjs; i++) + { + if (table->objs[i].flags[0] && table->objs[i].flags[1]) + { + int workerFound = 0; + options->cmn_objs = 1; + nfound += diff (file1_id, + table->objs[i].name, + file2_id, + table->objs[i].name, options, table->objs[i].type); + } + + } + /* free table */ + trav_table_free (table); + + + /*------------------------------------------------------------------------- + * do the diff for the root. + * this is a special case, we get an ID for the root group and call diff() + * with this ID; it compares only the root group attributes + *------------------------------------------------------------------------- + */ + + /* the manager can do this. */ + nfound += diff (file1_id, "/", file2_id, "/", options, H5G_GROUP); + + return nfound; +} + + + + +/*------------------------------------------------------------------------- + * Function: h5diff_parallel + * + * Purpose: public function, can be called in an application program. + * return differences between 2 HDF5 files + * + * Return: Number of differences found. + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: October 22, 2003 + * + *------------------------------------------------------------------------- + */ + +hsize_t +h5diff_parallel (const char *fname1, + const char *fname2, + const char *objname1, const char *objname2, diff_opt_t * options) +{ + int nobjects1, nobjects2, i; + trav_info_t *info1 = NULL; + trav_info_t *info2 = NULL; + hid_t file1_id=(-1), file2_id=(-1); + char filenames[2][255]; + hsize_t nfound = 0; + + memset(filenames, 0, 255*2); + + + if (options->m_quiet && (options->m_verbose || options->m_report)) + { + printf + ("Error: -q (quiet mode) cannot be added to verbose or report modes\n"); + options->err_stat = 1; + return 0; + } + +/*------------------------------------------------------------------------- + * open the files first; if they are not valid, no point in continuing + *------------------------------------------------------------------------- + */ + + /* disable error reporting */ + H5E_BEGIN_TRY + { + /* Open the files */ + if ((file1_id = H5Fopen (fname1, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + { + printf ("h5diff: <%s>: unable to open file\n", fname1); + options->err_stat = 1; + #ifdef H5_HAVE_PH5DIFF /* Let tasks know that they won't be needed */ for(i=1; i - -#else -#define PARALLEL 0 #endif -- cgit v0.12