diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2007-09-06 15:54:22 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2007-09-06 15:54:22 (GMT) |
commit | 3bed8703631cbcffb215ccd82235fcc293e14218 (patch) | |
tree | bf56b0bcd4f41986f17138059f6349df78f0c059 /tools/lib | |
parent | 3eb8c81b8046d282ced9c2d94e7132058243013e (diff) | |
download | hdf5-3bed8703631cbcffb215ccd82235fcc293e14218.zip hdf5-3bed8703631cbcffb215ccd82235fcc293e14218.tar.gz hdf5-3bed8703631cbcffb215ccd82235fcc293e14218.tar.bz2 |
[svn-r14136] Description:
Move H5Gget_num_objs() and several minor macros, etc. to deprecated
symbols section, replacing it with H5Gget_info().
Tested on:
FreeBSD/32 6.2 (duty)
FreeBSD/64 6.2 (liberty)
Linux/32 2.6 (kagiso)
Linux/64 2.6 (smirom)
AIX/32 5.3 (copper)
Solaris/32 5.10 (linew)
Mac OS X/32 10.4.10 (amazon)
Diffstat (limited to 'tools/lib')
-rw-r--r-- | tools/lib/h5diff.c | 316 | ||||
-rw-r--r-- | tools/lib/h5diff.h | 4 | ||||
-rw-r--r-- | tools/lib/h5diff_dset.c | 4 | ||||
-rw-r--r-- | tools/lib/h5trav.c | 1305 | ||||
-rw-r--r-- | tools/lib/h5trav.h | 57 |
5 files changed, 848 insertions, 838 deletions
diff --git a/tools/lib/h5diff.c b/tools/lib/h5diff.c index 1710347..2d7cc7d 100644 --- a/tools/lib/h5diff.c +++ b/tools/lib/h5diff.c @@ -186,180 +186,156 @@ hsize_t h5diff(const char *fname1, const char *objname2, diff_opt_t *options) { - int nobjects1, nobjects2; - trav_info_t *info1 = NULL; - trav_info_t *info2 = NULL; - hid_t file1_id=(-1), file2_id=(-1); - char filenames[2][1024]; - hsize_t nfound = 0; + trav_info_t *info1; + trav_info_t *info2; + hid_t file1_id = (-1), file2_id = (-1); + char filenames[2][1024]; + hsize_t nfound = 0; - memset(filenames, 0, 1024*2); + memset(filenames, 0, 1024*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; - } + 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 - *------------------------------------------------------------------------- - */ + /*------------------------------------------------------------------------- + * 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; + /* 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_PARALLEL - if(g_Parallel) - { - /* Let tasks know that they won't be needed */ - phdiff_dismiss_workers(); - } + if(g_Parallel) + { + /* Let tasks know that they won't be needed */ + phdiff_dismiss_workers(); + } #endif - 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; + } + if ((file2_id = H5Fopen (fname2, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + { + printf ("h5diff: <%s>: unable to open file\n", fname2); + options->err_stat = 1; #ifdef H5_HAVE_PARALLEL - if(g_Parallel) - { - /* Let tasks know that they won't be needed */ - phdiff_dismiss_workers(); - } + if(g_Parallel) + { + /* Let tasks know that they won't be needed */ + phdiff_dismiss_workers(); + } #endif - 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 file contents\n"); - options->err_stat = 1; -#ifdef H5_HAVE_PARALLEL - if(g_Parallel) - { - /* Let tasks know that they won't be needed */ - phdiff_dismiss_workers(); - } -#endif - goto out; - } + goto out; + } + /* enable error reporting */ + } + H5E_END_TRY; -/*------------------------------------------------------------------------- - * get the list of objects in the files - *------------------------------------------------------------------------- - */ + /*------------------------------------------------------------------------- + * Initialize the info structs + *------------------------------------------------------------------------- + */ + trav_info_init(&info1); + trav_info_init(&info2); - 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); + /*------------------------------------------------------------------------- + * get the list of objects in the files + *------------------------------------------------------------------------- + */ + if(h5trav_getinfo(file1_id, info1) < 0 || h5trav_getinfo(file2_id, info2) < 0) + { + printf("Error: Could not get file contents\n"); + options->err_stat = 1; #ifdef H5_HAVE_PARALLEL - if(g_Parallel) - { - /* Let tasks know that they won't be needed */ - phdiff_dismiss_workers(); - } + if(g_Parallel) + { + /* Let tasks know that they won't be needed */ + phdiff_dismiss_workers(); + } #endif - goto out; - } - - h5trav_getinfo (file1_id, info1, 0); - h5trav_getinfo (file2_id, info2, 0); + goto out; + } -/*------------------------------------------------------------------------- - * object name was supplied - *------------------------------------------------------------------------- - */ + /*------------------------------------------------------------------------- + * object name was supplied + *------------------------------------------------------------------------- + */ - if (objname1) - { + if (objname1) + { #ifdef H5_HAVE_PARALLEL - if(g_Parallel) - { - /* Let tasks know that they won't be needed */ - phdiff_dismiss_workers(); - } + if(g_Parallel) + { + /* Let tasks know that they won't be needed */ + phdiff_dismiss_workers(); + } #endif - assert (objname2); - options->cmn_objs = 1; /* eliminate warning */ - nfound = diff_compare (file1_id, fname1, objname1, nobjects1, info1, - file2_id, fname2, objname2, nobjects2, info2, - options); - } + assert (objname2); + options->cmn_objs = 1; /* eliminate warning */ + nfound = diff_compare (file1_id, fname1, objname1, info1, + file2_id, fname2, objname2, info2, + options); + } -/*------------------------------------------------------------------------- - * compare all - *------------------------------------------------------------------------- - */ + /*------------------------------------------------------------------------- + * compare all + *------------------------------------------------------------------------- + */ - else - { + else + { #ifdef H5_HAVE_PARALLEL - if(g_Parallel) - { - int i; + if(g_Parallel) + { + int i; - if( (strlen(fname1) > 1024) || (strlen(fname2) > 1024)) - { - fprintf(stderr, "The parallel diff only supports path names up to 1024 characters\n"); - MPI_Abort(MPI_COMM_WORLD, 0); - } + if((HDstrlen(fname1) > 1024) || (HDstrlen(fname2) > 1024)) + { + fprintf(stderr, "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); + HDstrcpy(filenames[0], fname1); + HDstrcpy(filenames[1], fname2); - /* Alert the worker tasks that there's going to be work. */ + /* 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); - } + 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 (file1_id, nobjects1, info1, - file2_id, nobjects2, info2, options); - } + nfound = diff_match(file1_id, info1, file2_id, info2, options); + } - h5trav_freeinfo (info1, nobjects1); - h5trav_freeinfo (info2, nobjects2); + trav_info_free(info1); + trav_info_free(info2); out: - /* close */ - H5E_BEGIN_TRY - { - H5Fclose (file1_id); - H5Fclose (file2_id); - } - H5E_END_TRY; + /* close */ + H5E_BEGIN_TRY + { + H5Fclose(file1_id); + H5Fclose(file2_id); + } + H5E_END_TRY; - return nfound; + return nfound; } @@ -383,18 +359,16 @@ out: *------------------------------------------------------------------------- */ 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; + int more_names_exist = (info1->nused > 0 && info2->nused > 0) ? 1 : 0; trav_table_t *table = NULL; int cmp; - int curr1 = 0; - int curr2 = 0; + size_t curr1 = 0; + size_t curr2 = 0; unsigned infile[2]; char c1, c2; hsize_t nfound = 0; @@ -409,12 +383,12 @@ hsize_t diff_match (hid_t file1_id, while (more_names_exist) { /* criteria is string compare */ - cmp = strcmp (info1[curr1].name, info2[curr2].name); + cmp = HDstrcmp(info1->paths[curr1].path, info2->paths[curr2].path); if (cmp == 0) { infile[0] = 1; infile[1] = 1; - trav_table_addflags (infile, info1[curr1].name, info1[curr1].type, + trav_table_addflags (infile, info1->paths[curr1].path, info1->paths[curr1].type, table); curr1++; @@ -424,7 +398,7 @@ hsize_t diff_match (hid_t file1_id, { infile[0] = 1; infile[1] = 0; - trav_table_addflags (infile, info1[curr1].name, info1[curr1].type, + trav_table_addflags (infile, info1->paths[curr1].path, info1->paths[curr1].type, table); curr1++; } @@ -432,37 +406,36 @@ hsize_t diff_match (hid_t file1_id, { infile[0] = 0; infile[1] = 1; - trav_table_addflags (infile, info2[curr2].name, info2[curr2].type, + trav_table_addflags (infile, info2->paths[curr2].path, info2->paths[curr2].type, table); curr2++; } - more_names_exist = (curr1 < nobjects1 && curr2 < nobjects2) ? 1 : 0; - + more_names_exist = (curr1 < info1->nused && curr2 < info2->nused) ? 1 : 0; } /* end while */ /* list1 did not end */ - if (curr1 < nobjects1) + if (curr1 < info1->nused) { - while (curr1 < nobjects1) + while (curr1 < info1->nused) { infile[0] = 1; infile[1] = 0; - trav_table_addflags (infile, info1[curr1].name, info1[curr1].type, + trav_table_addflags (infile, info1->paths[curr1].path, info1->paths[curr1].type, table); curr1++; } } /* list2 did not end */ - if (curr2 < nobjects2) + if (curr2 < info2->nused) { - while (curr2 < nobjects2) + while (curr2 < info2->nused) { infile[0] = 0; infile[1] = 1; - trav_table_addflags (infile, info2[curr2].name, info2[curr2].type, + trav_table_addflags (infile, info2->paths[curr2].path, info2->paths[curr2].type, table); curr2++; } @@ -789,17 +762,6 @@ hsize_t diff_match (hid_t file1_id, /* 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; } @@ -821,20 +783,18 @@ hsize_t diff_match (hid_t file1_id, hsize_t diff_compare (hid_t file1_id, const char *file1_name, const char *obj1_name, - int nobjects1, trav_info_t * info1, hid_t file2_id, const char *file2_name, const char *obj2_name, - int nobjects2, trav_info_t * info2, diff_opt_t * options) { int f1 = 0, f2 = 0; hsize_t nfound = 0; - int i = h5trav_getindex (obj1_name, nobjects1, info1); - int j = h5trav_getindex (obj2_name, nobjects2, info2); + ssize_t i = h5trav_getindex (info1, obj1_name); + ssize_t j = h5trav_getindex (info2, obj2_name); if (i == -1) { @@ -855,23 +815,23 @@ hsize_t diff_compare (hid_t file1_id, } /* use the name with "/" first, as obtained by iterator function */ - obj1_name = info1[i].name; - obj2_name = info2[j].name; + obj1_name = info1->paths[i].path; + obj2_name = info2->paths[j].path; /* objects are not the same type */ - if (info1[i].type != info2[j].type) + if (info1->paths[i].type != info2->paths[j].type) { if (options->m_verbose) parallel_print ("Comparison not possible: <%s> is of type %s and <%s> is of type %s\n", - obj1_name, get_type (info1[i].type), obj2_name, - get_type (info2[j].type)); + obj1_name, get_type (info1->paths[i].type), obj2_name, + get_type (info2->paths[j].type)); options->not_cmp=1; return 0; } nfound = - diff (file1_id, obj1_name, file2_id, obj2_name, options, info1[i].type); + diff (file1_id, obj1_name, file2_id, obj2_name, options, info1->paths[i].type); return nfound; } diff --git a/tools/lib/h5diff.h b/tools/lib/h5diff.h index 9125d7c..e22502f 100644 --- a/tools/lib/h5diff.h +++ b/tools/lib/h5diff.h @@ -94,20 +94,16 @@ hsize_t diff( hid_t file1_id, hsize_t diff_compare( hid_t file1_id, const char *file1_name, const char *obj1_name, - int nobjects1, trav_info_t *info1, hid_t file2_id, const char *file2_name, const char *obj2_name, - int nobjects2, trav_info_t *info2, diff_opt_t *options ); 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 ); diff --git a/tools/lib/h5diff_dset.c b/tools/lib/h5diff_dset.c index b5a2872..d3a7078 100644 --- a/tools/lib/h5diff_dset.c +++ b/tools/lib/h5diff_dset.c @@ -25,6 +25,7 @@ * *------------------------------------------------------------------------- */ +#if defined (H5DIFF_DEBUG) static void print_size (int rank, hsize_t *dims) { @@ -40,6 +41,7 @@ print_size (int rank, hsize_t *dims) parallel_print("]\n" ); } +#endif /* H5DIFF_DEBUG */ @@ -279,8 +281,6 @@ hsize_t diff_datasetid( hid_t did1, storage_size1=H5Dget_storage_size(did1); storage_size2=H5Dget_storage_size(did2); - if (storage_size1<0 || storage_size2<0) - goto error; if (storage_size1==0 || storage_size2==0) { diff --git a/tools/lib/h5trav.c b/tools/lib/h5trav.c index 6ff68d5..65cca66 100644 --- a/tools/lib/h5trav.c +++ b/tools/lib/h5trav.c @@ -18,255 +18,357 @@ #include "H5private.h" /*------------------------------------------------------------------------- - * local functions + * local typedefs *------------------------------------------------------------------------- */ -static int traverse( hid_t loc_id, - const char *group_name, - trav_table_t *table, - trav_info_t *info, - int *idx, - int print); +typedef struct trav_addr_t { + size_t nalloc; + size_t nused; + haddr_t *addrs; +} trav_addr_t; + +typedef struct { + herr_t (*visit_obj)(const char *path_name, const H5O_info_t *oinfo, hbool_t already_visited, void *udata); + herr_t (*visit_lnk)(const char *path_name, const H5L_info_t *linfo, void *udata); + void *udata; /* User data to pass to callbacks */ +} trav_visitor_t; + +typedef struct { + trav_addr_t *seen; /* List of addresses seen already */ + const char *curr_path; /* Current path to parent group */ + const trav_visitor_t *visitor; /* Information for visiting each link/object */ +} trav_ud_traverse_t; + +typedef struct { + hid_t fid; /* File ID being traversed */ + trav_table_t *table; /* Table for tracking name of objects with >1 hard link */ +} trav_print_udata_t; -static hssize_t get_nnames( hid_t loc_id, - const char *group_name ); +/*------------------------------------------------------------------------- + * local functions + *------------------------------------------------------------------------- + */ +static void trav_table_add(trav_table_t *table, + const char *objname, + const H5O_info_t *oinfo); -static herr_t get_name_type( hid_t loc_id, - const char *group_name, - int idx, - char **name, - H5G_obj_t *type ); +static size_t trav_table_search(const trav_table_t *table, haddr_t objno); +static void trav_table_addlink(trav_table_t *table, + size_t j /* the object index */, + const char *path); /*------------------------------------------------------------------------- * "h5trav info" public functions. used in h5diff *------------------------------------------------------------------------- */ + /*------------------------------------------------------------------------- - * Function: h5trav_getinfo + * Function: trav_addr_add * - * Purpose: get an array of "trav_info_t" , containing the name and type of - * objects in the file + * Purpose: Add a hardlink address to visited data structure * - * Return: number of object names in file + * Return: void * - * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * Programmer: Quincey Koziol, koziol@hdfgroup.org * - * Date: November 6, 2002 + * Date: September 1, 2007 * *------------------------------------------------------------------------- */ - -int h5trav_getinfo(hid_t file_id, - trav_info_t *info, - int print ) +static void +trav_addr_add(trav_addr_t *visited, haddr_t addr) { - trav_table_t *table = NULL; - int nnames = 0; - - /* init table */ - trav_table_init(&table); + size_t idx; /* Index of address to use */ - /* iterate starting on the root group */ - if((nnames = traverse(file_id, "/", table, info, &nnames, print)) < 0) - return -1; + /* Allocate space if necessary */ + if(visited->nused == visited->nalloc) { + visited->nalloc = MAX(1, visited->nalloc * 2);; + visited->addrs = (haddr_t *)HDrealloc(visited->addrs, visited->nalloc * sizeof(haddr_t)); + } /* end if */ - /* free table */ - trav_table_free(table); - - return nnames; -} + /* Append it */ + idx = visited->nused++; + visited->addrs[idx] = addr; +} /* end trav_addr_add() */ + /*------------------------------------------------------------------------- - * Function: h5trav_getindex + * Function: trav_addr_visited * - * Purpose: get index of OBJ in list + * Purpose: Check if an address has already been visited * - * Return: index, -1 if not found + * Return: TRUE/FALSE * - * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * Programmer: Quincey Koziol, koziol@hdfgroup.org * - * Date: May 9, 2003 + * Date: September 1, 2007 * *------------------------------------------------------------------------- */ - -int h5trav_getindex( const char *obj, int nobjs, trav_info_t *info ) +static hbool_t +trav_addr_visited(trav_addr_t *visited, haddr_t addr) { - char *pdest; - int result; - int i; - - for ( i = 0; i < nobjs; i++) - { - if ( strcmp(obj,info[i].name)==0 ) - return i; - - pdest = strstr( info[i].name, obj ); - result = (int)(pdest - info[i].name); - - /* found at position 1, meaning without '/' */ - if( pdest != NULL && result==1 ) - return i; - } - return -1; -} + size_t u; /* Local index variable */ + + /* Look for address */ + for(u = 0; u < visited->nused; u++) + /* Check for address already in array */ + if(visited->addrs[u] == addr) + return(TRUE); + + /* Didn't find address */ + return(FALSE); +} /* end trav_addr_visited() */ + /*------------------------------------------------------------------------- - * Function: h5trav_freeinfo + * Function: traverse_cb * - * Purpose: free info memory + * Purpose: Iterator callback for traversing objects in file + * + * Programmer: Quincey Koziol, koziol@hdfgroup.org + * + * Date: September 1, 2007 * *------------------------------------------------------------------------- */ +static herr_t +traverse_cb(hid_t loc_id, const char *link_name, const H5L_info_t *linfo, + void *_udata) +{ + trav_ud_traverse_t *udata = (trav_ud_traverse_t *)_udata; /* User data */ + hbool_t is_group = FALSE; /* If the object is a group */ + hbool_t already_visited = FALSE; /* Whether the link/object was already visited */ + char *link_path; /* Full path name of a link */ + + /* Construct the full path name of this link */ + link_path = (char*)HDmalloc(HDstrlen(udata->curr_path) + HDstrlen(link_name) + 2); + HDassert(link_path); + HDstrcpy(link_path, udata->curr_path); + HDstrcat(link_path, "/"); + HDstrcat(link_path, link_name); + + /* Perform the correct action for different types of links */ + if(linfo->type == H5L_TYPE_HARD) { + H5O_info_t oinfo; + + /* Get information about the object */ + if(H5Oget_info(loc_id, link_name, &oinfo, H5P_DEFAULT) < 0) + return(H5_ITER_ERROR); + + /* If the object has multiple links, add it to the list of addresses + * already visited, if it isn't there already + */ + if(oinfo.rc > 1) { + already_visited = trav_addr_visited(udata->seen, oinfo.addr); + if(!already_visited) + trav_addr_add(udata->seen, oinfo.addr); + } /* end if */ + + /* Check if object is a group, for later */ + is_group = (oinfo.type == H5O_TYPE_GROUP) ? TRUE : FALSE; + + /* Make 'visit object' callback */ + (*udata->visitor->visit_obj)(link_path, &oinfo, already_visited, udata->visitor->udata); + } /* end if */ + else { + /* Make 'visit link' callback */ + (*udata->visitor->visit_lnk)(link_path, linfo, udata->visitor->udata); + } /* end else */ + + /* Check for group that we haven't visited yet & recurse */ + if(is_group && !already_visited) { + const char *prev_path = udata->curr_path; /* Previous path to link's parent group */ + + /* Set current path to this object */ + udata->curr_path = link_path; + + /* Iterate over all links in group object */ + if(H5Literate(loc_id, link_name, H5_INDEX_NAME, H5_ITER_INC, NULL, traverse_cb, udata, H5P_DEFAULT) < 0) + return(H5_ITER_ERROR); + + /* Restore path in udata */ + udata->curr_path = prev_path; + } /* end if */ + + /* Free path name for current link/object */ + HDfree(link_path); + + return(H5_ITER_CONT); +} /* end traverse_cb() */ -void h5trav_freeinfo( trav_info_t *info, int nobjs ) + +/*------------------------------------------------------------------------- + * Function: traverse + * + * Purpose: Iterate over all the objects/links in a file. Conforms to the + * "visitor" pattern. + * + * Return: 0 on success, -1 on failure + * + * Programmer: Quincey Koziol, koziol@hdfgroup.org + * + * Date: September 1, 2007 + * + *------------------------------------------------------------------------- + */ +static int +traverse(hid_t file_id, const trav_visitor_t *visitor) { - int i; - if ( info ) - { - for ( i = 0; i < nobjs; i++) - { - if (info[i].name) - HDfree( info[i].name ); - } - HDfree(info); - } + H5O_info_t oinfo; /* Object info for root group */ + trav_addr_t seen; /* List of addresses seen */ + trav_ud_traverse_t udata; /* User data for iteration callback */ + + /* Get info for root group */ + if(H5Oget_info(file_id, "/", &oinfo, H5P_DEFAULT) < 0) + return -1; + + /* Visit the root group of the file */ + (*visitor->visit_obj)("/", &oinfo, FALSE, visitor->udata); + + /* Init addresses seen */ + seen.nused = seen.nalloc = 0; + seen.addrs = NULL; + + /* Check for multiple links to root group */ + if(oinfo.rc > 1) + trav_addr_add(&seen, oinfo.addr); + + /* Set up user data structure */ + udata.seen = &seen; + udata.curr_path = ""; + udata.visitor = visitor; + + /* Iterate over all links in root group */ + if(H5Literate(file_id, "/", H5_INDEX_NAME, H5_ITER_INC, NULL, traverse_cb, &udata, H5P_DEFAULT) < 0) + return -1; + + /* Free visited addresses table */ + if(seen.addrs) + HDfree(seen.addrs); + + return 0; } + /*------------------------------------------------------------------------- - * Function: h5trav_printinfo + * Function: trav_info_add * - * Purpose: print list of names in file + * Purpose: Add a link path & type to info struct * * Return: void * - * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * Programmer: Quincey Koziol, koziol@hdfgroup.org * - * Date: May 9, 2003 + * Date: September 1, 2007 * *------------------------------------------------------------------------- */ -void h5trav_printinfo(int nobjs, trav_info_t *travi) +static void +trav_info_add(trav_info_t *info, const char *path, H5G_obj_t obj_type) { - int i; - for ( i = 0; i < nobjs; i++) - { - switch ( travi[i].type ) - { - case H5G_GROUP: - printf(" %-10s %s\n", "group", travi[i].name ); - break; - case H5G_DATASET: - printf(" %-10s %s\n", "dataset", travi[i].name ); - break; - case H5G_TYPE: - printf(" %-10s %s\n", "datatype", travi[i].name ); - break; - case H5G_LINK: - printf(" %-10s %s\n", "link", travi[i].name ); - break; - case H5G_UDLINK: - printf(" %-10s %s\n", "User defined link", travi[i].name ); - break; - default: - printf(" %-10s %s\n", "User defined object", travi[i].name ); - break; - } - } -} + size_t idx; /* Index of address to use */ + /* Allocate space if necessary */ + if(info->nused == info->nalloc) { + info->nalloc = MAX(1, info->nalloc * 2);; + info->paths = (trav_path_t *)HDrealloc(info->paths, info->nalloc * sizeof(trav_path_t)); + } /* end if */ + + /* Append it */ + idx = info->nused++; + info->paths[idx].path = HDstrdup(path); + info->paths[idx].type = obj_type; +} /* end trav_info_add() */ + + /*------------------------------------------------------------------------- - * "h5trav table" public functions. used in h5repack + * Function: trav_info_visit_obj + * + * Purpose: Callback for visiting object, with 'info' structure + * + * Return: 0 on success, -1 on failure + * + * Programmer: Quincey Koziol, koziol@hdfgroup.org + * + * Date: September 1, 2007 + * *------------------------------------------------------------------------- */ +static int +trav_info_visit_obj(const char *path, const H5O_info_t *oinfo, + hbool_t UNUSED already_visited, void *udata) +{ + /* Add the object to the 'info' struct */ + /* (object types map directly to "group" types) */ + trav_info_add((trav_info_t *)udata, path, (H5G_obj_t)oinfo->type); + + return(0); +} /* end trav_info_visit_obj() */ + /*------------------------------------------------------------------------- - * Function: h5trav_getindext + * Function: trav_info_visit_lnk * - * Purpose: get index of NAME in list + * Purpose: Callback for visiting link, with 'info' structure * - * Return: index, -1 if not found + * Return: 0 on success, -1 on failure * - * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * Programmer: Quincey Koziol, koziol@hdfgroup.org * - * Date: December 18, 2003 + * Date: September 1, 2007 * *------------------------------------------------------------------------- */ - -int h5trav_getindext(const char *name, trav_table_t *table) +static int +trav_info_visit_lnk(const char *path, const H5L_info_t *linfo, void *udata) { - char *pdest; - int result; - unsigned int i, j; - - for ( i = 0; i < table->nobjs; i++) - { - if ( strcmp(name,table->objs[i].name)==0 ) - return i; - - pdest = strstr( table->objs[i].name, name ); - result = (int)(pdest - table->objs[i].name); - - /* found at position 1, meaning without '/' */ - if( pdest != NULL && result==1 && strlen(table->objs[i].name)-1==strlen(name)) - return i; - - /* search also in the list of links */ - if (table->objs[i].nlinks) - { - for ( j=0; j<table->objs[i].nlinks; j++) - { - if ( strcmp(name,table->objs[i].links[j].new_name)==0 ) - return i; - - pdest = strstr( table->objs[i].links[j].new_name, name ); - result = (int)(pdest - table->objs[i].links[j].new_name); - - /* found at position 1, meaning without '/' */ - if( pdest != NULL && result==1 ) - return i; - - } - } - - } - return -1; -} + /* Add the link to the 'info' struct */ + trav_info_add((trav_info_t *)udata, path, ((linfo->type == H5L_TYPE_SOFT) ? H5G_LINK : H5G_UDLINK)); + return(0); +} /* end trav_info_visit_lnk() */ + + /*------------------------------------------------------------------------- - * Function: h5trav_gettable + * Function: h5trav_getinfo * - * Purpose: get the trav_table_t struct + * Purpose: get an array of "trav_info_t" , containing the name and type of + * objects in the file * - * Return: 0, -1 on error + * Return: number of object names in file * * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu * - * Date: December 17, 2003 + * Date: November 6, 2002 * *------------------------------------------------------------------------- */ - -int h5trav_gettable(hid_t fid, trav_table_t *travt) +int +h5trav_getinfo(hid_t file_id, trav_info_t *info) { - int nnames = 0; + trav_visitor_t info_visitor; /* Visitor structure for trav_info_t's */ - /* iterate starting on the root group */ - if((nnames = traverse(fid, "/", travt, NULL, &nnames, 0)) < 0) + /* Init visitor structure */ + info_visitor.visit_obj = trav_info_visit_obj; + info_visitor.visit_lnk = trav_info_visit_lnk; + info_visitor.udata = info; + + /* Traverse all objects in the file, visiting each object & link */ + if(traverse(file_id, &info_visitor) < 0) return -1; return 0; } /*------------------------------------------------------------------------- - * Function: h5trav_printtable + * Function: h5trav_getindex * - * Purpose: print list of objects in file + * Purpose: get index of OBJ in list * - * Return: void + * Return: index, -1 if not found * * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu * @@ -274,403 +376,219 @@ int h5trav_gettable(hid_t fid, trav_table_t *travt) * *------------------------------------------------------------------------- */ -void h5trav_printtable(trav_table_t *table) + +ssize_t +h5trav_getindex(const trav_info_t *info, const char *obj) { - unsigned int i, j; - - for ( i = 0; i < table->nobjs; i++) - { - switch ( table->objs[i].type ) - { - case H5G_GROUP: - printf(" %-10s %s\n", "group", table->objs[i].name ); - break; - case H5G_DATASET: - printf(" %-10s %s\n", "dataset", table->objs[i].name ); - break; - case H5G_TYPE: - printf(" %-10s %s\n", "datatype", table->objs[i].name ); - break; - case H5G_LINK: - printf(" %-10s %s\n", "link", table->objs[i].name ); - break; - default: - printf(" %-10s %s\n", "User defined object", table->objs[i].name ); - break; - } - - if (table->objs[i].nlinks) - { - for ( j=0; j<table->objs[i].nlinks; j++) - { - printf(" %-10s %s\n", " hardlink", table->objs[i].links[j].new_name ); - } - } - - } -} + size_t u; /* Local index variable */ + + /* Loop over all paths in 'info' struct, looking for object */ + for(u = 0; u < info->nused; u++) { + /* Check for object name having full path (with leading '/') */ + if(HDstrcmp(obj, info->paths[u].path) == 0) + return((ssize_t)u); + + /* Check for object name without leading '/' */ + if(HDstrcmp(obj, (info->paths[u].path + 1)) == 0) + return((ssize_t)u); + } /* end for */ + + return((ssize_t)-1); +} /* end h5trav_getindex() */ /*------------------------------------------------------------------------- - * Function: get_nnames + * Function: trav_info_init * - * Purpose: Counts the number of names in the group GROUP_NAME + * Purpose: Initialize the info * - * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu - * - * Date: October 10, 2002 + * Return: void * - * Return: - * Success: The return value of the first operator that - * returns non-zero, or zero if all members were - * processed with no operator returning non-zero. + * Programmer: Quincey Koziol, koziol@hdfgroup.org * - * Failure: Negative if something goes wrong within the - * library, or the negative value returned by one - * of the operators. + * Date: September 6, 2007 * *------------------------------------------------------------------------- */ -static hssize_t get_nnames( hid_t loc_id, const char *group_name ) +void +trav_info_init(trav_info_t **_info) { - hid_t gid; - hsize_t nobjs = 0; + trav_info_t *info = (trav_info_t *)HDmalloc(sizeof(trav_info_t)); - /* Open the group */ - if((gid = H5Gopen2(loc_id, group_name, H5P_DEFAULT)) < 0) - return(-1); + /* Init info structure */ + info->nused = info->nalloc = 0; + info->paths = NULL; - /* Retrieve the number of objects in it */ - if(H5Gget_num_objs(gid, &nobjs) < 0) - return(-1); + *_info = info; +} /* end trav_info_init() */ - /* Close the group */ - if(H5Gclose(gid) < 0) - return(-1); + +/*------------------------------------------------------------------------- + * Function: trav_info_free + * + * Purpose: free info memory + * + *------------------------------------------------------------------------- + */ - return((hssize_t)nobjs); -} +void +trav_info_free(trav_info_t *info) +{ + size_t u; /* Local index variable */ + + if(info) { + /* Free path names */ + for(u = 0; u < info->nused; u++) + HDfree(info->paths[u].path); + HDfree(info->paths); + HDfree(info); + } /* end if */ +} /* end trav_info_free() */ /*------------------------------------------------------------------------- - * Function: opget_info - * - * Purpose: operator function + * "h5trav table" public functions. used in h5repack + *------------------------------------------------------------------------- + */ + + +/*------------------------------------------------------------------------- + * Function: trav_table_visit_obj * - * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * Purpose: Callback for visiting object, with 'table' sructure * - * Date: October 10, 2002 + * Return: 0 on success, -1 on failure * - * Comments: + * Programmer: Quincey Koziol, koziol@hdfgroup.org * - * Modifications: + * Date: September 1, 2007 * *------------------------------------------------------------------------- */ - -static herr_t -opget_info(hid_t loc_id, const char *name, const H5L_info_t *linfo, void *op_data) +static int +trav_table_visit_obj(const char *path, const H5O_info_t *oinfo, + hbool_t already_visited, void *udata) { - H5G_stat_t statbuf; + trav_table_t *table = (trav_table_t *)udata; - if(H5Gget_objinfo(loc_id, name, FALSE, &statbuf) < 0) - return -1; + /* Check if we've already seen this object */ + if(!already_visited) + /* add object to table */ + trav_table_add(table, path, oinfo); + else { + size_t found; /* Index of original object seen */ - ((trav_info_t *)op_data)->type = statbuf.type; - ((trav_info_t *)op_data)->name = (char *)HDstrdup(name); + /* Look for object in existing table */ + found = trav_table_search(table, oinfo->addr); + HDassert(found < table->nobjs); - /* Define 1 for return. This will cause the iterator to stop */ - return 1; -} + /* Add alias for object to table */ + trav_table_addlink(table, found, path); + } /* end else */ + return(0); +} /* end trav_table_visit_obj() */ + /*------------------------------------------------------------------------- - * Function: get_name_type + * Function: trav_table_visit_lnk * - * Purpose: + * Purpose: Callback for visiting link, with 'table' sructure * - * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * Return: 0 on success, -1 on failure + * + * Programmer: Quincey Koziol, koziol@hdfgroup.org + * + * Date: September 1, 2007 + * + *------------------------------------------------------------------------- + */ +static int +trav_table_visit_lnk(const char *path, const H5L_info_t UNUSED *linfo, void *udata) +{ + /* Add the link to the 'table' struct */ + trav_table_add((trav_table_t *)udata, path, NULL); + + return(0); +} /* end trav_table_visit_lnk() */ + + +/*------------------------------------------------------------------------- + * Function: h5trav_gettable * - * Date: October 10, 2002 + * Purpose: get the trav_table_t struct * - * Return: - * Success: The return value of the first operator that - * returns non-zero, or zero if all members were - * processed with no operator returning non-zero. + * Return: 0, -1 on error * - * Failure: Negative if something goes wrong within the - * library, or the negative value returned by one - * of the operators. + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: December 17, 2003 * *------------------------------------------------------------------------- */ -static herr_t get_name_type( hid_t loc_id, - const char *group_name, - int _idx, - char **name, - H5G_obj_t *type ) +int +h5trav_gettable(hid_t fid, trav_table_t *table) { - trav_info_t info; - hsize_t idx = (hsize_t)_idx; - - if(H5Literate(loc_id, group_name, H5_INDEX_NAME, H5_ITER_INC, &idx, opget_info, (void *)&info, H5P_DEFAULT) < 0) - return -1; + trav_visitor_t table_visitor; /* Visitor structure for trav_table_t's */ - *name = info.name; - *type = info.type; + /* Init visitor structure */ + table_visitor.visit_obj = trav_table_visit_obj; + table_visitor.visit_lnk = trav_table_visit_lnk; + table_visitor.udata = table; + /* Traverse all objects in the file, visiting each object & link */ + if(traverse(fid, &table_visitor) < 0) + return -1; return 0; } /*------------------------------------------------------------------------- - * Function: traverse + * Function: h5trav_getindext * - * Purpose: recursive function that searches HDF5 objects in LOC_ID + * Purpose: get index of NAME in list * - * Return: number of objects found in LOC_ID + * Return: index, -1 if not found * * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu * - * Date: November 4, 2002 + * Date: December 18, 2003 * *------------------------------------------------------------------------- */ -static int traverse(hid_t loc_id, - const char *group_name, - trav_table_t *table, - trav_info_t *info, - int *idx, - int print) +int +h5trav_getindext(const char *name, const trav_table_t *table) { - haddr_t objno; /* Compact form of object's location */ - char *name = NULL; - H5G_obj_t type; - int n_names; - char *path = NULL; - H5G_stat_t statbuf; - int inserted_objs = 0; - int i, j; - - /* get the number of names */ - if((n_names = (int)get_nnames(loc_id, group_name)) < 0) - return -1; - - for(i = 0; i < n_names; i++) { - if(get_name_type(loc_id, group_name, i, &name, &type) < 0) - return -1; - - /* allocate path buffer */ - path = (char*) HDmalloc(HDstrlen(group_name) + HDstrlen(name) + 2); - - /* initialize path */ - HDstrcpy( path, group_name ); - if(HDstrcmp(group_name, "/") != 0) - HDstrcat( path, "/" ); - HDstrcat(path, name); - - /* disable error reporting */ - H5E_BEGIN_TRY { - /* get info */ - H5Gget_objinfo( loc_id, path, FALSE, &statbuf); - } H5E_END_TRY; - objno = (haddr_t)statbuf.objno[0] | ((haddr_t)statbuf.objno[1] << (8 * sizeof(long))); - - /* add to array */ - if(info) { - info[*idx].name = (char *)HDstrdup(path); - info[*idx].type = type; - (*idx)++; + unsigned int i; + + for(i = 0; i < table->nobjs; i++) { + /* Check for object name having full path (with leading '/') */ + if(HDstrcmp(name, table->objs[i].name) == 0) + return(i); + + /* Check for object name without leading '/' */ + if(HDstrcmp(name, table->objs[i].name + 1) == 0) + return(i); + + /* search also in the list of links */ + if(table->objs[i].nlinks) { + unsigned int j; + + for ( j=0; j<table->objs[i].nlinks; j++) { + /* Check for object name having full path (with leading '/') */ + if(HDstrcmp(name, table->objs[i].links[j].new_name) == 0) + return(i); + + /* Check for object name without leading '/' */ + if(HDstrcmp(name, table->objs[i].links[j].new_name + 1) == 0) + return(i); + } /* end for */ } /* end if */ + } /* end for */ - switch(type) { - /*------------------------------------------------------------------------- - * H5G_GROUP - *------------------------------------------------------------------------- - */ - case H5G_GROUP: - /* increment */ - inserted_objs++; - - /* nlink is number of hard links to object */ - if(statbuf.nlink > 0 && trav_table_search(objno, table) == -1) { - /* add object to table */ - trav_table_add(objno, path, H5G_GROUP, table); - - /* print it */ - if(print) - printf(" %-10s %s\n", "group", path); - - /* recurse with the absolute name */ - inserted_objs += traverse(loc_id, path, table, info, idx, print); - } /* end if */ - - /* search table group with more than one link to it */ - if(statbuf.nlink > 1) { - if((j = trav_table_search(objno, table)) < 0) - return -1; - - trav_table_addlink(table, j, path); - - if(table->objs[j].displayed == 0) { - table->objs[j].displayed = 1; - } - else { - /* print it */ - if (print) - printf(" %-10s %s %s %s\n", "group", path, "->", table->objs[j].name ); - } - } /* end if */ - break; - - /*------------------------------------------------------------------------- - * H5G_DATASET - *------------------------------------------------------------------------- - */ - case H5G_DATASET: - /* increment */ - inserted_objs++; - - /* nlink is number of hard links to object */ - if(statbuf.nlink > 0 && trav_table_search(objno, table) == -1) { - /* add object to table */ - trav_table_add(objno, path, H5G_DATASET, table ); - - /* print it */ - if(print) - printf(" %-10s %s\n", "dataset", path ); - } /* end if */ - - /* search table dataset with more than one link to it */ - if(statbuf.nlink > 1) { - if((j = trav_table_search(objno, table)) < 0) - return -1; - - trav_table_addlink(table, j, path); - - if(table->objs[j].displayed == 0) { - table->objs[j].displayed = 1; - } - else { - /* print it */ - if(print) - printf(" %-10s %s %s %s\n", "dataset", path, "->", table->objs[j].name); - } /* displayed==1 */ - } /* nlink>1 */ - break; - - /*------------------------------------------------------------------------- - * H5G_TYPE - *------------------------------------------------------------------------- - */ - - case H5G_TYPE: - /* increment */ - inserted_objs++; - - /* nlink is number of hard links to object */ - if(statbuf.nlink > 0 && trav_table_search(objno, table) == -1) { - /* add object to table */ - trav_table_add(objno, path, H5G_TYPE, table); - - /* print it */ - if(print) - printf(" %-10s %s\n", "datatype", path ); - } /* end if */ - break; - - - /*------------------------------------------------------------------------- - * H5G_LINK - *------------------------------------------------------------------------- - */ - - case H5G_LINK: - /* increment */ - inserted_objs++; - - /* add object to table */ - trav_table_add(HADDR_UNDEF, path, H5G_LINK, table); - - if(statbuf.linklen > 0) { - char *targbuf; - - targbuf = HDmalloc(statbuf.linklen); - assert(targbuf); - H5Lget_val(loc_id, path, targbuf, statbuf.linklen, H5P_DEFAULT); - if(print) - printf(" %-10s %s -> %s\n", "link", path, targbuf); - free(targbuf); - } - else { - if(print) - printf(" %-10s %s ->\n", "link", path); - } - break; - - /*------------------------------------------------------------------------- - * H5G_UDLINK - *------------------------------------------------------------------------- - */ - - case H5G_UDLINK: - { - H5L_info_t linkbuf; - - /* increment */ - inserted_objs++; - - /* add object to table */ - trav_table_add(HADDR_UNDEF, path, H5G_UDLINK, table); - - /* Get type of link */ - H5E_BEGIN_TRY { - /* get link class info */ - H5Lget_info(loc_id, path, &linkbuf, H5P_DEFAULT); - } H5E_END_TRY; - - if(linkbuf.type == H5L_TYPE_EXTERNAL) { - if(statbuf.linklen > 0) { - char *targbuf; - const char *filename; - const char *objname; - - targbuf = HDmalloc(statbuf.linklen); - assert(targbuf); - H5Lget_val(loc_id, path, targbuf, statbuf.linklen, H5P_DEFAULT); - H5Lunpack_elink_val(targbuf, statbuf.linklen, NULL, &filename, &objname); - if(print) - printf(" %-10s %s -> %s %s\n", "ext link", path, filename, objname); - free(targbuf); - } /* end if */ - else { - if(print) - printf(" %-10s %s ->\n", "udlink", path); - } /* end else */ - } /* end if */ - else { /* Unknown user-defined type */ - if(print) - printf(" %-10s %s ->\n", "UD link type", path); - } /* end else */ - } - break; - - - default: - HDfprintf(stderr, "traverse: Unknown object %d!\n", type); - return(-1); - break; - } /* end switch */ - - if(name) - HDfree(name); - if(path) - HDfree(path); - } /* i */ - - return inserted_objs; + return -1; } /*------------------------------------------------------------------------- @@ -687,15 +605,15 @@ static int traverse(hid_t loc_id, *------------------------------------------------------------------------- */ -int trav_table_search(haddr_t objno, trav_table_t *table ) +static size_t +trav_table_search(const trav_table_t *table, haddr_t objno) { - unsigned int i; + size_t i; - for (i = 0; i < table->nobjs; i++) - if (table->objs[i].objno == objno) - return i; - - return -1; + for(i = 0; i < table->nobjs; i++) + if(table->objs[i].objno == objno) + return(i); + return(i); } @@ -713,41 +631,66 @@ int trav_table_search(haddr_t objno, trav_table_t *table ) *------------------------------------------------------------------------- */ -void trav_table_add(haddr_t objno, - char *name, - H5G_obj_t type, - trav_table_t *table) +static void +trav_table_add(trav_table_t *table, + const char *path, + const H5O_info_t *oinfo) { - unsigned int i; - - if (table->nobjs == table->size) { - table->size *= 2; - table->objs = - (trav_obj_t*)HDrealloc(table->objs, table->size * sizeof(trav_obj_t)); - - for (i = table->nobjs; i < table->size; i++) { - table->objs[i].objno = 0; - table->objs[i].flags[0] = table->objs[i].flags[1] = 0; - table->objs[i].displayed = 0; - table->objs[i].type = H5G_UNKNOWN; - table->objs[i].name = NULL; - table->objs[i].links = NULL; - table->objs[i].nlinks = 0; - table->objs[i].sizelinks = 0; - } - } - - i = table->nobjs++; - table->objs[i].objno = objno; - table->objs[i].flags[0] = table->objs[i].flags[1] = 0; - HDfree(table->objs[i].name); - table->objs[i].name = (char *)HDstrdup(name); - table->objs[i].type = type; - table->objs[i].links = NULL; - table->objs[i].nlinks = 0; + size_t new; + + if(table->nobjs == table->size) { + table->size = MAX(1, table->size * 2); + table->objs = (trav_obj_t*)HDrealloc(table->objs, table->size * sizeof(trav_obj_t)); + } /* end if */ + + new = table->nobjs++; + table->objs[new].objno = oinfo ? oinfo->addr : HADDR_UNDEF; + table->objs[new].flags[0] = table->objs[new].flags[1] = 0; + table->objs[new].name = (char *)HDstrdup(path); + table->objs[new].type = oinfo ? (H5G_obj_t)oinfo->type : H5G_LINK; + table->objs[new].nlinks = 0; + table->objs[new].sizelinks = 0; + table->objs[new].links = NULL; +} + +/*------------------------------------------------------------------------- + * Function: trav_table_addlink + * + * Purpose: Add a hardlink name to the object + * + * Return: void + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: December 17, 2003 + * + *------------------------------------------------------------------------- + */ + +static void +trav_table_addlink(trav_table_t *table, + size_t j /* the object index */, + const char *path) +{ + size_t new; + + /* already inserted */ + if(HDstrcmp(table->objs[j].name, path) == 0) + return; + + /* allocate space if necessary */ + if(table->objs[j].nlinks == (unsigned)table->objs[j].sizelinks) { + table->objs[j].sizelinks = MAX(1, table->objs[j].sizelinks * 2); + table->objs[j].links = (trav_link_t*)HDrealloc(table->objs[j].links, table->objs[j].sizelinks * sizeof(trav_link_t)); + } /* end if */ + + /* insert it */ + new = table->objs[j].nlinks++; + table->objs[j].links[new].new_name = (char *)HDstrdup(path); } + /*------------------------------------------------------------------------- * Function: trav_table_addflags * @@ -767,34 +710,22 @@ void trav_table_addflags(unsigned *flags, H5G_obj_t type, trav_table_t *table) { - unsigned int i; - - if (table->nobjs == table->size) { - table->size *= 2; - table->objs = - (trav_obj_t*)HDrealloc(table->objs, table->size * sizeof(trav_obj_t)); - - for (i = table->nobjs; i < table->size; i++) { - table->objs[i].objno = 0; - table->objs[i].flags[0] = table->objs[i].flags[1] = 0; - table->objs[i].displayed = 0; - table->objs[i].type = H5G_UNKNOWN; - table->objs[i].name = NULL; - table->objs[i].links = NULL; - table->objs[i].nlinks = 0; - table->objs[i].sizelinks = 0; - } - } - - i = table->nobjs++; - table->objs[i].objno = 0; - table->objs[i].flags[0] = flags[0]; - table->objs[i].flags[1] = flags[1]; - HDfree(table->objs[i].name); - table->objs[i].name = (char *)HDstrdup(name); - table->objs[i].type = type; - table->objs[i].links = NULL; - table->objs[i].nlinks = 0; + unsigned int new; + + if(table->nobjs == table->size) { + table->size = MAX(1, table->size * 2); + table->objs = (trav_obj_t *)HDrealloc(table->objs, table->size * sizeof(trav_obj_t)); + } + + new = table->nobjs++; + table->objs[new].objno = 0; + table->objs[new].flags[0] = flags[0]; + table->objs[new].flags[1] = flags[1]; + table->objs[new].name = (char *)HDstrdup(name); + table->objs[new].type = type; + table->objs[new].nlinks = 0; + table->objs[new].sizelinks = 0; + table->objs[new].links = NULL; } @@ -812,28 +743,15 @@ void trav_table_addflags(unsigned *flags, *------------------------------------------------------------------------- */ -void trav_table_init( trav_table_t **tbl ) +void trav_table_init(trav_table_t **tbl) { - unsigned int i; - trav_table_t* table = (trav_table_t*) HDmalloc(sizeof(trav_table_t)); - - table->size = 20; - table->nobjs = 0; - table->objs = - (trav_obj_t*)HDmalloc(table->size * sizeof(trav_obj_t)); - - for (i = 0; i < table->size; i++) { - table->objs[i].objno = 0; - table->objs[i].flags[0] = table->objs[i].flags[1] = 0; - table->objs[i].displayed = 0; - table->objs[i].type = H5G_UNKNOWN; - table->objs[i].name = NULL; - table->objs[i].links = NULL; - table->objs[i].nlinks = 0; - table->objs[i].sizelinks = 0; - } - - *tbl = table; + trav_table_t* table = (trav_table_t*) HDmalloc(sizeof(trav_table_t)); + + table->size = 0; + table->nobjs = 0; + table->objs = NULL; + + *tbl = table; } @@ -854,60 +772,193 @@ void trav_table_init( trav_table_t **tbl ) void trav_table_free( trav_table_t *table ) { - unsigned int i, j; - - for ( i = 0; i < table->nobjs; i++) - { - HDfree( table->objs[i].name ); - if (table->objs[i].nlinks) - { - for ( j=0; j<table->objs[i].nlinks; j++) - HDfree( table->objs[i].links[j].new_name ); - - HDfree(table->objs[i].links); - } - } - HDfree(table->objs); - HDfree(table); - + if(table->objs) { + unsigned int i; + + for(i = 0; i < table->nobjs; i++) { + HDfree(table->objs[i].name ); + if(table->objs[i].nlinks) { + unsigned int j; + + for(j = 0; j < table->objs[i].nlinks; j++) + HDfree(table->objs[i].links[j].new_name); + + HDfree(table->objs[i].links); + } /* end if */ + } /* end for */ + HDfree(table->objs); + } /* end if */ + HDfree(table); } + +/*------------------------------------------------------------------------- + * Function: trav_print_visit_obj + * + * Purpose: Callback for visiting object, when printing info + * + * Return: 0 on success, -1 on failure + * + * Programmer: Quincey Koziol, koziol@hdfgroup.org + * + * Date: September 6, 2007 + * + *------------------------------------------------------------------------- + */ +static int +trav_print_visit_obj(const char *path, const H5O_info_t *oinfo, + hbool_t already_visited, void *udata) +{ + trav_print_udata_t *print_udata = (trav_print_udata_t *)udata; + + /* Print the name of the object */ + /* (no new-line, so that objects that we've encountered before can print + * the name of the original object) + */ + switch(oinfo->type) { + case H5O_TYPE_GROUP: + printf(" %-10s %s", "group", path); + break; + + case H5O_TYPE_DATASET: + printf(" %-10s %s", "dataset", path); + break; + + case H5O_TYPE_NAMED_DATATYPE: + printf(" %-10s %s", "datatype", path); + break; + + default: + printf(" %-10s %s", "unknown object type", path); + break; + } /* end switch */ + + /* Check if we've already seen this object */ + if(!already_visited) { + /* Finish printing line about object */ + printf("\n"); + + /* Check if we will encounter another hard link to this object */ + if(oinfo->rc > 1) { + /* Add object to table */ + trav_table_add(print_udata->table, path, oinfo); + } /* end if */ + } /* end if */ + else { + size_t found; /* Index of original object seen */ + + /* Locate object in table */ + found = trav_table_search(print_udata->table, oinfo->addr); + HDassert(found < print_udata->table->nobjs); + + /* Print the link's destination */ + printf(" -> %s\n", print_udata->table->objs[found].name); + } /* end else */ + return(0); +} /* end trav_print_visit_obj() */ + + /*------------------------------------------------------------------------- - * Function: trav_table_addlink + * Function: trav_print_visit_lnk * - * Purpose: Add a hardlink name to the object + * Purpose: Callback for visiting link, when printing info * - * Return: void + * Return: 0 on success, -1 on failure * - * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * Programmer: Quincey Koziol, koziol@hdfgroup.org * - * Date: December 17, 2003 + * Date: September 6, 2007 + * + *------------------------------------------------------------------------- + */ +static int +trav_print_visit_lnk(const char *path, const H5L_info_t *linfo, void *udata) +{ + trav_print_udata_t *print_udata = (trav_print_udata_t *)udata; + + /* Print appropriate information for the type of link */ + switch(linfo->type) { + case H5L_TYPE_SOFT: + if(linfo->u.val_size > 0) { + char *targbuf = HDmalloc(linfo->u.val_size + 1); + HDassert(targbuf); + + H5Lget_val(print_udata->fid, path, targbuf, linfo->u.val_size + 1, H5P_DEFAULT); + printf(" %-10s %s -> %s\n", "link", path, targbuf); + free(targbuf); + } /* end if */ + else + printf(" %-10s %s ->\n", "link", path); + break; + + case H5L_TYPE_EXTERNAL: + if(linfo->u.val_size > 0) { + char *targbuf; + const char *filename; + const char *objname; + + targbuf = HDmalloc(linfo->u.val_size + 1); + assert(targbuf); + + H5Lget_val(print_udata->fid, path, targbuf, linfo->u.val_size + 1, H5P_DEFAULT); + H5Lunpack_elink_val(targbuf, linfo->u.val_size, NULL, &filename, &objname); + printf(" %-10s %s -> %s %s\n", "ext link", path, filename, objname); + free(targbuf); + } /* end if */ + else + printf(" %-10s %s ->\n", "ext link", path); + break; + + default: + printf(" %-10s %s -> ???\n", "unknown type of UD link", path); + break; + } /* end switch() */ + + return(0); +} /* end trav_print_visit_lnk() */ + + +/*------------------------------------------------------------------------- + * Function: h5trav_print + * + * Purpose: Print information about the objects & links in the file + * + * Return: 0, -1 on error + * + * Programmer: Quincey Koziol, koziol@hdfgroup.org + * + * Date: September 6, 2007 * *------------------------------------------------------------------------- */ -void trav_table_addlink(trav_table_t *table, - int j /* the object index */, - char *path ) +int +h5trav_print(hid_t fid) { - unsigned int k; - - /* already inserted */ - if (strcmp(table->objs[j].name,path)==0) - return; - - /* allocate space if necessary */ - if (table->objs[j].nlinks == (unsigned)table->objs[j].sizelinks) { - table->objs[j].sizelinks += 2; - table->objs[j].links = - (trav_link_t*)HDrealloc(table->objs[j].links, - table->objs[j].sizelinks * sizeof(trav_link_t)); - } - - /* insert it */ - k=table->objs[j].nlinks++; - table->objs[j].links[k].new_name = (char*)HDstrdup(path); -} + trav_table_t *table = NULL; /* Table for objects w/multiple hard links */ + trav_print_udata_t print_udata; /* User data for traversal */ + trav_visitor_t print_visitor; /* Visitor structure for printing objects */ + + /* Initialize the table */ + trav_table_init(&table); + + /* Init user data for printing */ + print_udata.fid = fid; + print_udata.table = table; + + /* Init visitor structure */ + print_visitor.visit_obj = trav_print_visit_obj; + print_visitor.visit_lnk = trav_print_visit_lnk; + print_visitor.udata = &print_udata; + /* Traverse all objects in the file, visiting each object & link */ + if(traverse(fid, &print_visitor) < 0) + return -1; + + /* Free table */ + trav_table_free(table); + + return 0; +} diff --git a/tools/lib/h5trav.h b/tools/lib/h5trav.h index c11d835..4218013 100644 --- a/tools/lib/h5trav.h +++ b/tools/lib/h5trav.h @@ -32,9 +32,15 @@ typedef H5G_obj_t H5G_obj_t1; -typedef struct trav_info_t { - char *name; +typedef struct trav_path_t { + char *path; H5G_obj_t type; +} trav_path_t; + +typedef struct trav_info_t { + size_t nalloc; + size_t nused; + trav_path_t *paths; } trav_info_t; @@ -56,11 +62,10 @@ typedef struct trav_obj_t { haddr_t objno; /* object number from H5Gget_objinfo */ unsigned flags[2]; /* h5diff.object is present or not in both files*/ char *name; /* name */ - int displayed; /* hard link already traversed once */ H5G_obj_t type; /* type of object */ trav_link_t *links; /* array of possible link names */ - int sizelinks; /* size of links array */ - unsigned nlinks; /* number of links */ + size_t sizelinks; /* size of links array */ + size_t nlinks; /* number of links */ } trav_obj_t; @@ -70,8 +75,8 @@ typedef struct trav_obj_t { */ typedef struct trav_table_t { - unsigned size; - unsigned nobjs; + size_t size; + size_t nobjs; trav_obj_t *objs; } trav_table_t; @@ -89,25 +94,37 @@ extern "C" { * "h5trav info" public functions *------------------------------------------------------------------------- */ -int h5trav_getinfo( hid_t fid, trav_info_t *info, int print ); -int h5trav_getindex( const char *obj, int nobjs, trav_info_t *info ); -void h5trav_freeinfo( trav_info_t *info, int nobjs ); -void h5trav_printinfo(int nobjs, trav_info_t *info); +int h5trav_getinfo(hid_t file_id, trav_info_t *info); +ssize_t h5trav_getindex(const trav_info_t *info, const char *obj); /*------------------------------------------------------------------------- * "h5trav table" public functions *------------------------------------------------------------------------- */ -int h5trav_getindext(const char *obj,trav_table_t *travt); int h5trav_gettable(hid_t fid, trav_table_t *travt); -void h5trav_printtable(trav_table_t *table); +int h5trav_getindext(const char *obj, const trav_table_t *travt); + +/*------------------------------------------------------------------------- + * "h5trav print" public functions + *------------------------------------------------------------------------- + */ +int h5trav_print(hid_t fid); #ifdef __cplusplus } #endif /*------------------------------------------------------------------------- + * info private functions + *------------------------------------------------------------------------- + */ + +void trav_info_init(trav_info_t **info); + +void trav_info_free(trav_info_t *info); + +/*------------------------------------------------------------------------- * table private functions *------------------------------------------------------------------------- */ @@ -116,25 +133,11 @@ void trav_table_init(trav_table_t **table); void trav_table_free(trav_table_t *table); -int trav_table_search(haddr_t objno, - trav_table_t *table ); - -void trav_table_add(haddr_t objno, - char *objname, - H5G_obj_t type, - trav_table_t *table); - void trav_table_addflags(unsigned *flags, char *objname, H5G_obj_t type, trav_table_t *table); - -void trav_table_addlink(trav_table_t *table, - int j /* the object index */, - char *path ); - - #endif /* H5TRAV_H__ */ |