summaryrefslogtreecommitdiffstats
path: root/tools/lib
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2007-09-06 15:54:22 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2007-09-06 15:54:22 (GMT)
commit3bed8703631cbcffb215ccd82235fcc293e14218 (patch)
treebf56b0bcd4f41986f17138059f6349df78f0c059 /tools/lib
parent3eb8c81b8046d282ced9c2d94e7132058243013e (diff)
downloadhdf5-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.c316
-rw-r--r--tools/lib/h5diff.h4
-rw-r--r--tools/lib/h5diff_dset.c4
-rw-r--r--tools/lib/h5trav.c1305
-rw-r--r--tools/lib/h5trav.h57
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__ */