diff options
Diffstat (limited to 'tools/lib/h5diff.c')
-rw-r--r-- | tools/lib/h5diff.c | 660 |
1 files changed, 196 insertions, 464 deletions
diff --git a/tools/lib/h5diff.c b/tools/lib/h5diff.c index 0b8bb7e..39be45b 100644 --- a/tools/lib/h5diff.c +++ b/tools/lib/h5diff.c @@ -46,6 +46,9 @@ print_objname (diff_opt_t * options, hsize_t nfound) * * Date: October 22, 2003 * + * Modifications: Jan 2005 Leon Arber, larber@uiuc.edu + * Added support for parallel diffing + * *------------------------------------------------------------------------- */ @@ -58,10 +61,10 @@ h5diff (const char *fname1, trav_info_t *info1 = NULL; trav_info_t *info2 = NULL; hid_t file1_id=(-1), file2_id=(-1); - char filenames[2][255]; + char filenames[2][1024]; hsize_t nfound = 0; - memset(filenames, 0, 255*2); + memset(filenames, 0, 1024*2); if (options->m_quiet && (options->m_verbose || options->m_report)) @@ -86,317 +89,13 @@ 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) +#ifdef H5_HAVE_PARALLEL + if(g_Parallel) { - infile[0] = 1; - infile[1] = 1; - trav_table_addflags (infile, info1[curr1].name, info1[curr1].type, - table); - - curr1++; - curr2++; + /* Let tasks know that they won't be needed */ + for(i=1; i<g_nTasks; i++) + MPI_Send(filenames, 1024*2, MPI_CHAR, i, MPI_TAG_END, MPI_COMM_WORLD); } - 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<g_nTasks; i++) - MPI_Send(filenames, 255*2, MPI_CHAR, i, MPI_TAG_END, MPI_COMM_WORLD); #endif goto out; @@ -406,10 +105,13 @@ h5diff_parallel (const char *fname1, printf ("h5diff: <%s>: unable to open file\n", fname2); options->err_stat = 1; -#ifdef H5_HAVE_PH5DIFF - /* Let tasks know that they won't be needed */ - for(i=1; i<g_nTasks; i++) - MPI_Send(filenames, 255*2, MPI_CHAR, i, MPI_TAG_END, MPI_COMM_WORLD); +#ifdef H5_HAVE_PARALLEL + if(g_Parallel) + { + /* Let tasks know that they won't be needed */ + for(i=1; i<g_nTasks; i++) + MPI_Send(filenames, 1024*2, MPI_CHAR, i, MPI_TAG_END, MPI_COMM_WORLD); + } #endif goto out; @@ -465,10 +167,13 @@ h5diff_parallel (const char *fname1, if (objname1) { -#ifdef H5_HAVE_PH5DIFF - /* Let tasks know that they won't be needed */ - for(i=1; i<g_nTasks; i++) - MPI_Send(filenames, 255*2, MPI_CHAR, i, MPI_TAG_END, MPI_COMM_WORLD); +#ifdef H5_HAVE_PARALLEL + if(g_Parallel) + { + /* Let tasks know that they won't be needed */ + for(i=1; i<g_nTasks; i++) + MPI_Send(filenames, 1024*2, MPI_CHAR, i, MPI_TAG_END, MPI_COMM_WORLD); + } #endif assert (objname2); options->cmn_objs = 1; /* eliminate warning */ @@ -485,16 +190,25 @@ h5diff_parallel (const char *fname1, else { -#ifdef H5_HAVE_PH5DIFF - strncpy(filenames[0], fname1, 255); - strncpy(filenames[1], fname2, 255); - - /* Alert the worker tasks that there's going to be work. */ +#ifdef H5_HAVE_PARALLEL + if(g_Parallel) + { + if( (strlen(fname1) > 1024) || (strlen(fname2) > 1024)) + { + printf("The parallel diff only supports path names up to 1024 characters\n"); + MPI_Abort(MPI_COMM_WORLD, 0); + } + + strcpy(filenames[0], fname1); + strcpy(filenames[1], fname2); - for(i=1; i<g_nTasks; i++) - MPI_Send(filenames, 255*2, MPI_CHAR, i, MPI_TAG_PARALLEL, MPI_COMM_WORLD); + /* Alert the worker tasks that there's going to be work. */ + + for(i=1; i<g_nTasks; i++) + MPI_Send(filenames, 1024*2, MPI_CHAR, i, MPI_TAG_PARALLEL, MPI_COMM_WORLD); + } #endif - nfound = diff_match_parallel (file1_id, nobjects1, info1, + nfound = diff_match (file1_id, nobjects1, info1, file2_id, nobjects2, info2, options); } @@ -517,7 +231,7 @@ out: /*------------------------------------------------------------------------- - * Function: diff_match_parallel + * Function: diff_match * * Purpose: Find common objects; the algorithm used for this search is the * cosequential match algorithm and is described in @@ -528,11 +242,14 @@ out: * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu * * Date: May 9, 2003 + * + * Modifications: Jan 2005 Leon Arber, larber@uiuc.edu + * Added support for parallel diffing * *------------------------------------------------------------------------- */ hsize_t -diff_match_parallel (hid_t file1_id, +diff_match (hid_t file1_id, int nobjects1, trav_info_t * info1, hid_t file2_id, @@ -641,8 +358,7 @@ diff_match_parallel (hid_t file1_id, *------------------------------------------------------------------------- */ { -#ifdef H5_HAVE_PH5DIFF - /*SEND NAMES/OBJS OFF TO WORKER TASKS FOR DIFF'ING HERE */ +#ifdef H5_HAVE_PARALLEL char* workerTasks = malloc((g_nTasks-1) * sizeof(char)); int n; int busyTasks=0; @@ -661,191 +377,207 @@ diff_match_parallel (hid_t file1_id, { int workerFound = 0; options->cmn_objs = 1; -#ifndef H5_HAVE_PH5DIFF - nfound += diff (file1_id, - table->objs[i].name, - file2_id, - table->objs[i].name, options, table->objs[i].type); -#else - /* We're in parallel mode */ - - /*Set up args to pass to worker task. */ - strncpy(args.name, table->objs[i].name, 255); - args.options = *options; - args.type= table->objs[i].type; - - /* if there are any outstanding print requests, let's handle one. */ - if(busyTasks > 0) + if(!g_Parallel) + { + nfound += diff (file1_id, + table->objs[i].name, + file2_id, + table->objs[i].name, options, table->objs[i].type); + } +#ifdef H5_HAVE_PARALLEL + else { - int incomingMessage; - /* check if any tasks freed up, and didn't need to print. */ - MPI_Iprobe(MPI_ANY_SOURCE, MPI_TAG_DONE, MPI_COMM_WORLD, &incomingMessage, &Status); + /* We're in parallel mode */ - if(incomingMessage) + /*Set up args to pass to worker task. */ + if(strlen(table->objs[i].name) > 255) { - workerTasks[Status.MPI_SOURCE-1] = 1; - MPI_Recv(&nFoundbyWorker, 1, MPI_LONG_LONG, Status.MPI_SOURCE, MPI_TAG_DONE, MPI_COMM_WORLD, &Status); - nfound += nFoundbyWorker; - busyTasks--; + printf("The parallel diff only supports object names up to 255 characters\n"); + MPI_Abort(MPI_COMM_WORLD, 0); } + + strcpy(args.name, table->objs[i].name); + args.options = *options; + args.type= table->objs[i].type; - /* check to see if the print token was returned. */ - if(!havePrintToken) + /* if there are any outstanding print requests, let's handle one. */ + if(busyTasks > 0) { + int incomingMessage; + /* check if any tasks freed up, and didn't need to print. */ + MPI_Iprobe(MPI_ANY_SOURCE, MPI_TAG_DONE, MPI_COMM_WORLD, &incomingMessage, &Status); - /* check incoming queue for token */ - MPI_Iprobe(MPI_ANY_SOURCE, MPI_TAG_TOK_RETURN, MPI_COMM_WORLD, &incomingMessage, &Status); - - /* incoming token implies free task. */ if(incomingMessage) { workerTasks[Status.MPI_SOURCE-1] = 1; - MPI_Recv(&nFoundbyWorker, 1, MPI_LONG_LONG, Status.MPI_SOURCE, MPI_TAG_TOK_RETURN, MPI_COMM_WORLD, &Status); + MPI_Recv(&nFoundbyWorker, 1, MPI_LONG_LONG, Status.MPI_SOURCE, MPI_TAG_DONE, MPI_COMM_WORLD, &Status); nfound += nFoundbyWorker; busyTasks--; - havePrintToken = 1; } - } - /* check to see if anyone needs the print token. */ - if(havePrintToken) - { - /* check incoming queue for print token requests */ - MPI_Iprobe(MPI_ANY_SOURCE, MPI_TAG_TOK_REQUEST, MPI_COMM_WORLD, &incomingMessage, &Status); - if(incomingMessage) + /* check to see if the print token was returned. */ + if(!havePrintToken) { - MPI_Recv(NULL, 0, MPI_BYTE, Status.MPI_SOURCE, MPI_TAG_TOK_REQUEST, MPI_COMM_WORLD, &Status); - MPI_Send(NULL, 0, MPI_BYTE, Status.MPI_SOURCE, MPI_TAG_PRINT_TOK, MPI_COMM_WORLD); - havePrintToken = 0; + + /* check incoming queue for token */ + MPI_Iprobe(MPI_ANY_SOURCE, MPI_TAG_TOK_RETURN, MPI_COMM_WORLD, &incomingMessage, &Status); + + /* incoming token implies free task. */ + if(incomingMessage) + { + workerTasks[Status.MPI_SOURCE-1] = 1; + MPI_Recv(&nFoundbyWorker, 1, MPI_LONG_LONG, Status.MPI_SOURCE, MPI_TAG_TOK_RETURN, MPI_COMM_WORLD, &Status); + nfound += nFoundbyWorker; + busyTasks--; + havePrintToken = 1; + } + } + + /* check to see if anyone needs the print token. */ + if(havePrintToken) + { + /* check incoming queue for print token requests */ + MPI_Iprobe(MPI_ANY_SOURCE, MPI_TAG_TOK_REQUEST, MPI_COMM_WORLD, &incomingMessage, &Status); + if(incomingMessage) + { + MPI_Recv(NULL, 0, MPI_BYTE, Status.MPI_SOURCE, MPI_TAG_TOK_REQUEST, MPI_COMM_WORLD, &Status); + MPI_Send(NULL, 0, MPI_BYTE, Status.MPI_SOURCE, MPI_TAG_PRINT_TOK, MPI_COMM_WORLD); + havePrintToken = 0; + } } } - } - /* check array of tasks to see which ones are free. - * Manager task never does work, so freeTasks[0] is really - * worker task 0. */ + /* check array of tasks to see which ones are free. + * Manager task never does work, so freeTasks[0] is really + * worker task 0. */ - for(n=1; (n<g_nTasks) && !workerFound; n++) - { - if(workerTasks[n-1]) + for(n=1; (n<g_nTasks) && !workerFound; n++) { - /* send file id's and names to first free worker */ - MPI_Send(&args, sizeof(struct diff_args), MPI_BYTE, n, MPI_TAG_ARGS, MPI_COMM_WORLD); + if(workerTasks[n-1]) + { + /* send file id's and names to first free worker */ + MPI_Send(&args, sizeof(struct diff_args), MPI_BYTE, n, MPI_TAG_ARGS, MPI_COMM_WORLD); - /* increment counter for total number of prints. */ - busyTasks++; + /* increment counter for total number of prints. */ + busyTasks++; - /* mark worker as busy */ - workerTasks[n-1] = 0; - workerFound = 1; - } + /* mark worker as busy */ + workerTasks[n-1] = 0; + workerFound = 1; + } - } + } - if(!workerFound) - { - /* if they were all busy, we've got to wait for one free up before we can move on. - * if we don't have the token, some task is currently printing so we'll wait for that task to return it. */ - if(!havePrintToken) + if(!workerFound) { - MPI_Probe(MPI_ANY_SOURCE, MPI_TAG_TOK_RETURN, MPI_COMM_WORLD, &Status); - - if(Status.MPI_TAG == MPI_TAG_TOK_RETURN) + /* if they were all busy, we've got to wait for one free up before we can move on. + * if we don't have the token, some task is currently printing so we'll wait for that task to return it. */ + if(!havePrintToken) { - MPI_Recv(&nFoundbyWorker, 1, MPI_LONG_LONG, Status.MPI_SOURCE, MPI_TAG_TOK_RETURN, MPI_COMM_WORLD, &Status); - havePrintToken = 1; - nfound += nFoundbyWorker; - /* send this task the work unit. */ - MPI_Send(&args, sizeof(struct diff_args), MPI_BYTE, Status.MPI_SOURCE, MPI_TAG_ARGS, MPI_COMM_WORLD); + MPI_Probe(MPI_ANY_SOURCE, MPI_TAG_TOK_RETURN, MPI_COMM_WORLD, &Status); + + if(Status.MPI_TAG == MPI_TAG_TOK_RETURN) + { + MPI_Recv(&nFoundbyWorker, 1, MPI_LONG_LONG, Status.MPI_SOURCE, MPI_TAG_TOK_RETURN, MPI_COMM_WORLD, &Status); + havePrintToken = 1; + nfound += nFoundbyWorker; + /* send this task the work unit. */ + MPI_Send(&args, sizeof(struct diff_args), MPI_BYTE, Status.MPI_SOURCE, MPI_TAG_ARGS, MPI_COMM_WORLD); + } + else + { + printf("ERROR: Invalid (%d) tag received\n", Status.MPI_TAG); + MPI_Abort(MPI_COMM_WORLD, 0); + MPI_Finalize(); + } } + /* if we do have the token, check for task to free up, or wait for a task to request it */ else { - printf("ERROR: Invalid (%d) tag received\n", Status.MPI_TAG); - MPI_Abort(MPI_COMM_WORLD, 0); - MPI_Finalize(); + MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &Status); + + if(Status.MPI_TAG == MPI_TAG_DONE) + { + MPI_Recv(&nFoundbyWorker, 1, MPI_LONG_LONG, Status.MPI_SOURCE, MPI_TAG_DONE, MPI_COMM_WORLD, &Status); + nfound += nFoundbyWorker; + MPI_Send(&args, sizeof(struct diff_args), MPI_BYTE, Status.MPI_SOURCE, MPI_TAG_ARGS, MPI_COMM_WORLD); + } + else if(Status.MPI_TAG == MPI_TAG_TOK_REQUEST) + { + MPI_Recv(NULL, 0, MPI_BYTE, Status.MPI_SOURCE, MPI_TAG_TOK_REQUEST, MPI_COMM_WORLD, &Status); + MPI_Send(NULL, 0, MPI_BYTE, Status.MPI_SOURCE, MPI_TAG_PRINT_TOK, MPI_COMM_WORLD); + + MPI_Recv(&nFoundbyWorker, 1, MPI_LONG_LONG, Status.MPI_SOURCE, MPI_TAG_TOK_RETURN, MPI_COMM_WORLD, &Status); + nfound += nFoundbyWorker; + MPI_Send(&args, sizeof(struct diff_args), MPI_BYTE, Status.MPI_SOURCE, MPI_TAG_ARGS, MPI_COMM_WORLD); + } + else + { + printf("ERROR: Invalid tag (%d) received \n", Status.MPI_TAG); + MPI_Abort(MPI_COMM_WORLD, 0); + MPI_Finalize(); + } } - } - /* if we do have the token, check for task to free up, or wait for a task to request it */ - else - { - MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &Status); - - if(Status.MPI_TAG == MPI_TAG_DONE) - { - MPI_Recv(&nFoundbyWorker, 1, MPI_LONG_LONG, Status.MPI_SOURCE, MPI_TAG_DONE, MPI_COMM_WORLD, &Status); - nfound += nFoundbyWorker; - MPI_Send(&args, sizeof(struct diff_args), MPI_BYTE, Status.MPI_SOURCE, MPI_TAG_ARGS, MPI_COMM_WORLD); - } - else if(Status.MPI_TAG == MPI_TAG_TOK_REQUEST) - { - MPI_Recv(NULL, 0, MPI_BYTE, Status.MPI_SOURCE, MPI_TAG_TOK_REQUEST, MPI_COMM_WORLD, &Status); - MPI_Send(NULL, 0, MPI_BYTE, Status.MPI_SOURCE, MPI_TAG_PRINT_TOK, MPI_COMM_WORLD); - - MPI_Recv(&nFoundbyWorker, 1, MPI_LONG_LONG, Status.MPI_SOURCE, MPI_TAG_TOK_RETURN, MPI_COMM_WORLD, &Status); - nfound += nFoundbyWorker; - MPI_Send(&args, sizeof(struct diff_args), MPI_BYTE, Status.MPI_SOURCE, MPI_TAG_ARGS, MPI_COMM_WORLD); - } - else - { - printf("ERROR: Invalid tag (%d) received \n", Status.MPI_TAG); - MPI_Abort(MPI_COMM_WORLD, 0); - MPI_Finalize(); - } - } + } } #endif } } -#ifdef H5_HAVE_PH5DIFF - while(busyTasks > 0) /* make sure all tasks are done */ +#ifdef H5_HAVE_PARALLEL + if(g_Parallel) { - MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &Status); - if(Status.MPI_TAG == MPI_TAG_DONE) - { - MPI_Recv(&nFoundbyWorker, 1, MPI_LONG_LONG, Status.MPI_SOURCE, MPI_TAG_DONE, MPI_COMM_WORLD, &Status); - nfound += nFoundbyWorker; - busyTasks--; - } - else if(Status.MPI_TAG == MPI_TAG_TOK_REQUEST) + while(busyTasks > 0) /* make sure all tasks are done */ { - MPI_Recv(NULL, 0, MPI_BYTE, Status.MPI_SOURCE, MPI_TAG_TOK_REQUEST, MPI_COMM_WORLD, &Status); - if(havePrintToken) + MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &Status); + if(Status.MPI_TAG == MPI_TAG_DONE) { - MPI_Send(NULL, 0, MPI_BYTE, Status.MPI_SOURCE, MPI_TAG_PRINT_TOK, MPI_COMM_WORLD); - MPI_Recv(&nFoundbyWorker, 1, MPI_LONG_LONG, Status.MPI_SOURCE, MPI_TAG_TOK_RETURN, MPI_COMM_WORLD, &Status); + MPI_Recv(&nFoundbyWorker, 1, MPI_LONG_LONG, Status.MPI_SOURCE, MPI_TAG_DONE, MPI_COMM_WORLD, &Status); nfound += nFoundbyWorker; busyTasks--; } - else /* someone else must have it...wait for them to return it, then give it to the task that just asked for it. */ + else if(Status.MPI_TAG == MPI_TAG_TOK_REQUEST) + { + MPI_Recv(NULL, 0, MPI_BYTE, Status.MPI_SOURCE, MPI_TAG_TOK_REQUEST, MPI_COMM_WORLD, &Status); + if(havePrintToken) + { + MPI_Send(NULL, 0, MPI_BYTE, Status.MPI_SOURCE, MPI_TAG_PRINT_TOK, MPI_COMM_WORLD); + MPI_Recv(&nFoundbyWorker, 1, MPI_LONG_LONG, Status.MPI_SOURCE, MPI_TAG_TOK_RETURN, MPI_COMM_WORLD, &Status); + nfound += nFoundbyWorker; + busyTasks--; + } + else /* someone else must have it...wait for them to return it, then give it to the task that just asked for it. */ + { + int source = Status.MPI_SOURCE; + MPI_Recv(&nFoundbyWorker, 1, MPI_LONG_LONG, MPI_ANY_SOURCE, MPI_TAG_TOK_RETURN, MPI_COMM_WORLD, &Status); + nfound += nFoundbyWorker; + busyTasks--; + MPI_Send(NULL, 0, MPI_BYTE, source, MPI_TAG_PRINT_TOK, MPI_COMM_WORLD); + } + } + else if(Status.MPI_TAG == MPI_TAG_TOK_RETURN) { - int source = Status.MPI_SOURCE; - MPI_Recv(&nFoundbyWorker, 1, MPI_LONG_LONG, MPI_ANY_SOURCE, MPI_TAG_TOK_RETURN, MPI_COMM_WORLD, &Status); + MPI_Recv(&nFoundbyWorker, 1, MPI_LONG_LONG, Status.MPI_SOURCE, MPI_TAG_TOK_RETURN, MPI_COMM_WORLD, &Status); nfound += nFoundbyWorker; busyTasks--; - MPI_Send(NULL, 0, MPI_BYTE, source, MPI_TAG_PRINT_TOK, MPI_COMM_WORLD); + havePrintToken = 1; + } + else + { + printf("ERROR!! Invalid tag (%d) received \n", Status.MPI_TAG); + MPI_Abort(MPI_COMM_WORLD, 0); } } - else if(Status.MPI_TAG == MPI_TAG_TOK_RETURN) - { - MPI_Recv(&nFoundbyWorker, 1, MPI_LONG_LONG, Status.MPI_SOURCE, MPI_TAG_TOK_RETURN, MPI_COMM_WORLD, &Status); - nfound += nFoundbyWorker; - busyTasks--; - havePrintToken = 1; - } - else - { - printf("ERROR!! Invalid tag (%d) received \n", Status.MPI_TAG); - MPI_Abort(MPI_COMM_WORLD, 0); - } + + for(i=1; i<g_nTasks; i++) + MPI_Send(NULL, 0, MPI_BYTE, i, MPI_TAG_END, MPI_COMM_WORLD); } - for(i=1; i<g_nTasks; i++) - MPI_Send(NULL, 0, MPI_BYTE, i, MPI_TAG_END, MPI_COMM_WORLD); + free(workerTasks); #endif } /* free table */ |