diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2007-11-24 16:49:36 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2007-11-24 16:49:36 (GMT) |
commit | 2f36ea99d4ad1b036d377719e49eaab2dec64444 (patch) | |
tree | 63be7c282767004339c49aa0e738e6a62630c280 /tools/lib | |
parent | 083357dad3334473507a97e17593a9d68e42d69f (diff) | |
download | hdf5-2f36ea99d4ad1b036d377719e49eaab2dec64444.zip hdf5-2f36ea99d4ad1b036d377719e49eaab2dec64444.tar.gz hdf5-2f36ea99d4ad1b036d377719e49eaab2dec64444.tar.bz2 |
[svn-r14284] Description:
Add H5Lvisit_by_name() API routine to library.
Eliminated all (five!) other group traversal routines and changed them
all to use the new API routine.
Cleaned up output of h5ls & h5stat:
- Issue error when requesting recursive traversal of a file
with the "group info" flag, but no group given
- Print info about root group in all(?) appropriate situations
- Don't print "verbose" information about root group until the
root group is in the list of objects to display
(mostly because h5ls & h5stat had a different twist on traversing the
groups in a file that the other utilities)
Tested on:
FreeBSD/32 6.2 (duty) in debug mode
FreeBSD/64 6.2 (liberty) w/C++ & FORTRAN, in debug mode
Linux/32 2.6 (kagiso) w/PGI compilers, w/C++ & FORTRAN, w/threadsafe,
in debug mode
Linux/64-amd64 2.6 (smirom) w/default API=1.6.x, w/C++ & FORTRAN,
in production mode
Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN,
in production mode
Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN,
w/szip filter, in production mode
Mac OS X/32 10.4.10 (amazon) in debug mode
Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in production mode
Diffstat (limited to 'tools/lib')
-rw-r--r-- | tools/lib/h5tools_ref.c | 192 | ||||
-rw-r--r-- | tools/lib/h5tools_utils.c | 186 | ||||
-rw-r--r-- | tools/lib/h5tools_utils.h | 2 | ||||
-rw-r--r-- | tools/lib/h5trav.c | 276 | ||||
-rw-r--r-- | tools/lib/h5trav.h | 14 |
5 files changed, 285 insertions, 385 deletions
diff --git a/tools/lib/h5tools_ref.c b/tools/lib/h5tools_ref.c index 123065b..de1e2c3 100644 --- a/tools/lib/h5tools_ref.c +++ b/tools/lib/h5tools_ref.c @@ -20,6 +20,7 @@ #include "H5SLprivate.h" #include "h5tools.h" #include "h5tools_utils.h" +#include "h5trav.h" /* @@ -42,15 +43,12 @@ typedef struct { } ref_path_node_t; static H5SL_t *ref_path_table = NULL; /* the "table" (implemented with a skip list) */ -static hid_t thefile; +static hid_t thefile = (-1); extern char *progname; extern int d_status; static int ref_path_table_put(const char *, haddr_t objno); -static hbool_t ref_path_table_find(haddr_t objno); -static herr_t fill_ref_path_table_cb(hid_t group, const char *obj_name, - const H5L_info_t *linfo, void *op_data); /*------------------------------------------------------------------------- * Function: free_ref_path_info @@ -77,6 +75,61 @@ free_ref_path_info(void *item, void UNUSED *key, void UNUSED *operator_data/*in, } /*------------------------------------------------------------------------- + * Function: init_ref_path_cb + * + * Purpose: Called by interator to create references for + * all objects and enter them in the table. + * + * Return: Error status. + * + * Programmer: REMcG + * + *------------------------------------------------------------------------- + */ +static herr_t +init_ref_path_cb(const char *obj_name, const H5O_info_t *oinfo, + const char *already_seen, void UNUSED *_udata) +{ + /* Check if the object is already in the path table */ + if(NULL == already_seen) { + /* Insert the object into the path table */ + ref_path_table_put(obj_name, oinfo->addr); + } /* end if */ + + return 0; +} + +/*------------------------------------------------------------------------- + * Function: init_ref_path_table + * + * Purpose: Initalize the reference path table + * + * Return: Non-negative on success, negative on failure + * + * Programmer: Quincey Koziol + * + *------------------------------------------------------------------------- + */ +static int +init_ref_path_table(void) +{ + /* Sanity check */ + HDassert(thefile > 0); + + /* Create skip list to store reference path information */ + if((ref_path_table = H5SL_create(H5SL_TYPE_HADDR, 0.5, (size_t)16))==NULL) + return (-1); + + /* Iterate over objects in this file */ + if(h5trav_visit(thefile, "/", TRUE, TRUE, init_ref_path_cb, NULL, NULL) < 0) { + error_msg(progname, "unable to construct reference path table\n"); + d_status = EXIT_FAILURE; + } /* end if */ + + return(0); +} + +/*------------------------------------------------------------------------- * Function: term_ref_path_table * * Purpose: Terminate the reference path table @@ -137,39 +190,11 @@ ref_path_table_lookup(const char *thepath) if(H5Oget_info_by_name(thefile, thepath, &oi, H5P_DEFAULT) < 0) return HADDR_UNDEF; - /* All existing objects in the file had better be in the table */ - HDassert(ref_path_table_find(oi.addr)); - /* Return OID */ return(oi.addr); } /*------------------------------------------------------------------------- - * Function: ref_path_table_find - * - * Purpose: Looks up a table entry given a object number. - * Used during construction of the table. - * - * Return: TRUE/FALSE on success, can't fail - * - * Programmer: Quincey Koziol - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static hbool_t -ref_path_table_find(haddr_t objno) -{ - HDassert(ref_path_table); - - if(H5SL_search(ref_path_table, &objno) == NULL) - return FALSE; - else - return TRUE; -} - -/*------------------------------------------------------------------------- * Function: ref_path_table_put * * Purpose: Enter the 'obj' with 'path' in the table (assumes its not @@ -200,7 +225,7 @@ ref_path_table_put(const char *path, haddr_t objno) return(-1); new_node->objno = objno; - new_node->path = path; + new_node->path = HDstrdup(path); return(H5SL_insert(ref_path_table, new_node, &(new_node->objno))); } @@ -237,17 +262,17 @@ get_fake_xid (void) { haddr_t ref_path_table_gen_fake(const char *path) { - const char *dup_path; haddr_t fake_objno; - if((dup_path = HDstrdup(path)) == NULL) - return HADDR_UNDEF; - /* Generate fake ID for string */ fake_objno = get_fake_xid(); - /* Insert "fake" object into table (takes ownership of path) */ - ref_path_table_put(dup_path, fake_objno); + /* Create ref path table, if it hasn't already been created */ + if(ref_path_table == NULL) + init_ref_path_table(); + + /* Insert "fake" object into table */ + ref_path_table_put(path, fake_objno); return(fake_objno); } @@ -271,74 +296,19 @@ lookup_ref_path(haddr_t ref) ref_path_node_t *node; /* Be safer for h5ls */ - if(!ref_path_table) + if(thefile < 0) return(NULL); + /* Create ref path table, if it hasn't already been created */ + if(ref_path_table == NULL) + init_ref_path_table(); + node = H5SL_search(ref_path_table, &ref); return(node ? node->path : NULL); } /*------------------------------------------------------------------------- - * Function: fill_ref_path_table_cb - * - * Purpose: Called by interator to create references for - * all objects and enter them in the table. - * - * Return: Error status. - * - * Programmer: REMcG - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -fill_ref_path_table_cb(hid_t group, const char *obj_name, const H5L_info_t *linfo, - void *op_data) -{ - if(linfo->type == H5L_TYPE_HARD) { - H5O_info_t oinfo; - - H5Oget_info_by_name(group, obj_name, &oinfo, H5P_DEFAULT); - - /* Check if the object is already in the path table */ - if(!ref_path_table_find(oinfo.addr)) { - const char *obj_prefix = (const char *)op_data; - size_t tmp_len; - char *thepath; - - /* Compute length for this object's path */ - tmp_len = HDstrlen(obj_prefix) + HDstrlen(obj_name) + 2; - - /* Allocate room for the path for this object */ - if((thepath = (char *)HDmalloc(tmp_len)) == NULL) - return FAIL; - - /* Build the name for this object */ - HDstrcpy(thepath, obj_prefix); - HDstrcat(thepath, "/"); - HDstrcat(thepath, obj_name); - - /* Insert the object into the path table (takes ownership of the path) */ - ref_path_table_put(thepath, oinfo.addr); - - if(oinfo.type == H5O_TYPE_GROUP) { - /* Iterate over objects in this group, using this group's - * name as their prefix - */ - if(H5Literate_by_name(group, obj_name, H5_INDEX_NAME, H5_ITER_INC, NULL, fill_ref_path_table_cb, thepath, H5P_DEFAULT) < 0) { - error_msg(progname, "unable to dump group \"%s\"\n", thepath); - d_status = EXIT_FAILURE; - } /* end if */ - } /* end if */ - } /* end if */ - } /* end if */ - - return 0; -} - -/*------------------------------------------------------------------------- * Function: fill_ref_path_table * * Purpose: Called by interator to create references for @@ -348,37 +318,15 @@ fill_ref_path_table_cb(hid_t group, const char *obj_name, const H5L_info_t *linf * * Programmer: REMcG * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t fill_ref_path_table(hid_t fid) { - H5O_info_t oinfo; - char *root_path; - /* Set file ID for later queries (XXX: this should be fixed) */ thefile = fid; - /* Create skip list to store reference path information */ - if((ref_path_table = H5SL_create(H5SL_TYPE_HADDR, 0.5, (size_t)16))==NULL) - return (-1); - - /* Build the name for root group */ - root_path = HDstrdup("/"); - - /* Get info for root group */ - H5Oget_info_by_name(fid, root_path, &oinfo, H5P_DEFAULT); - - /* Insert the root group into the path table (takes ownership of path) */ - ref_path_table_put(root_path, oinfo.addr); - - /* Iterate over objects in this file */ - if(H5Literate(fid, H5_INDEX_NAME, H5_ITER_INC, NULL, fill_ref_path_table_cb, (void *)"") < 0) { - error_msg(progname, "unable to dump root group\n"); - d_status = EXIT_FAILURE; - } /* end if */ + /* Defer creating the ref path table until it's needed */ return 0; } diff --git a/tools/lib/h5tools_utils.c b/tools/lib/h5tools_utils.c index cb38e7a..512a3fb 100644 --- a/tools/lib/h5tools_utils.c +++ b/tools/lib/h5tools_utils.c @@ -30,6 +30,7 @@ #include "h5tools_utils.h" #include "H5private.h" +#include "h5trav.h" /* global variables */ int nCols = 80; @@ -44,10 +45,7 @@ static void init_table(table_t **tbl); #ifdef H5DUMP_DEBUG static void dump_table(char* tablename, table_t *table); #endif /* H5DUMP_DEBUG */ -static void add_obj(table_t *table, haddr_t objno, char *objname, hbool_t recorded); -static char * build_obj_path_name(const char *prefix, const char *name); -static herr_t find_objs_cb(hid_t group, const char *name, const H5L_info_t *info, - void *op_data); +static void add_obj(table_t *table, haddr_t objno, const char *objname, hbool_t recorded); /*------------------------------------------------------------------------- @@ -428,44 +426,15 @@ search_obj(table_t *table, haddr_t objno) { unsigned u; - for (u = 0; u < table->nobjs; u++) - if (table->objs[u].objno == objno) - return &(table->objs[u]); + for(u = 0; u < table->nobjs; u++) + if(table->objs[u].objno == objno) + return &(table->objs[u]); return NULL; } /*------------------------------------------------------------------------- - * Function: build_obj_path_name - * - * Purpose: Allocate space & build path name from prefix & name - * - * Return: Success: SUCCEED - * - * Failure: FAIL - * - * Programmer: Quincey Koziol - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static char * -build_obj_path_name(const char *prefix, const char *name) -{ - char *path; - - path = HDmalloc(HDstrlen(prefix) + HDstrlen(name) + 2); - HDstrcpy(path, prefix); - HDstrcat(path,"/"); - HDstrcat(path,name); /* absolute name of the data set */ - - return(path); -} /* end build_obj_path_name() */ - - -/*------------------------------------------------------------------------- * Function: find_objs_cb * * Purpose: Callback to find objects, committed types and store them in tables @@ -481,90 +450,65 @@ build_obj_path_name(const char *prefix, const char *name) *------------------------------------------------------------------------- */ static herr_t -find_objs_cb(hid_t group, const char *name, const H5L_info_t UNUSED *linfo, void *op_data) +find_objs_cb(const char *name, const H5O_info_t *oinfo, const char *already_seen, + void *op_data) { - H5O_info_t oinfo; find_objs_t *info = (find_objs_t*)op_data; herr_t ret_value = 0; - if(H5Oget_info_by_name(group, name, &oinfo, H5P_DEFAULT) < 0) - ; /* keep going */ - else { - switch(oinfo.type) { - char *tmp; - size_t tmp_len; - - case H5O_TYPE_GROUP: - if(search_obj(info->group_table, oinfo.addr) == NULL) { - char *old_prefix; + switch(oinfo->type) { + case H5O_TYPE_GROUP: + if(NULL == already_seen) + add_obj(info->group_table, oinfo->addr, name, TRUE); + break; - tmp = build_obj_path_name(info->prefix, name); - add_obj(info->group_table, oinfo.addr, tmp, TRUE); + case H5O_TYPE_DATASET: + if(NULL == already_seen) { + hid_t dset; - old_prefix = info->prefix; - tmp_len = HDstrlen(tmp); - info->prefix = HDmalloc(tmp_len+1); - HDstrcpy(info->prefix, tmp); + /* Add the dataset to the list of objects */ + add_obj(info->dset_table, oinfo->addr, name, TRUE); - if(H5Literate_by_name(group, name, H5_INDEX_NAME, H5_ITER_INC, NULL, find_objs_cb, (void *)info, H5P_DEFAULT) < 0) - ret_value = FAIL; + /* Check for a dataset that uses a named datatype */ + if((dset = H5Dopen2(info->fid, name, H5P_DEFAULT)) >= 0) { + hid_t type = H5Dget_type(dset); - info->prefix = old_prefix; - } /* end if */ - break; - - case H5O_TYPE_DATASET: - if(search_obj(info->dset_table, oinfo.addr) == NULL) { - hid_t dset; - - tmp = build_obj_path_name(info->prefix, name); - add_obj(info->dset_table, oinfo.addr, tmp, TRUE); - - if((dset = H5Dopen2(group, name, H5P_DEFAULT)) >= 0) { - hid_t type; + if(H5Tcommitted(type) > 0) { + H5O_info_t type_oinfo; - type = H5Dget_type(dset); - - if(H5Tcommitted(type) > 0) { - H5Oget_info(type, &oinfo); - if(search_obj(info->type_table, oinfo.addr) == NULL) { - char *type_name = HDstrdup(tmp); - - add_obj(info->type_table, oinfo.addr, type_name, FALSE); - } /* end if */ - } /* end if */ - - H5Tclose(type); - H5Dclose(dset); + H5Oget_info(type, &type_oinfo); + if(search_obj(info->type_table, type_oinfo.addr) == NULL) + add_obj(info->type_table, type_oinfo.addr, name, FALSE); } /* end if */ - else - ret_value = FAIL; - } /* end if */ - break; - case H5O_TYPE_NAMED_DATATYPE: - { - obj_t *found_obj; - - tmp = build_obj_path_name(info->prefix, name); - if((found_obj = search_obj(info->type_table, oinfo.addr)) == NULL) - add_obj(info->type_table, oinfo.addr, tmp, TRUE); - else { - /* Use latest version of name */ - HDfree(found_obj->objname); - found_obj->objname = HDstrdup(tmp); - - /* Mark named datatype as having valid name */ - found_obj->recorded = TRUE; - } /* end else */ - break; - } - - default: - /* Ignore links, etc. */ - break; + H5Tclose(type); + H5Dclose(dset); + } /* end if */ + else + ret_value = FAIL; + } /* end if */ + break; + + case H5O_TYPE_NAMED_DATATYPE: + { + obj_t *found_obj; + + if((found_obj = search_obj(info->type_table, oinfo->addr)) == NULL) + add_obj(info->type_table, oinfo->addr, name, TRUE); + else { + /* Use latest version of name */ + HDfree(found_obj->objname); + found_obj->objname = HDstrdup(name); + + /* Mark named datatype as having valid name */ + found_obj->recorded = TRUE; + } /* end else */ + break; } - } /* end else */ + + default: + break; + } /* end switch */ return ret_value; } @@ -589,31 +533,19 @@ herr_t init_objs(hid_t fid, find_objs_t *info, table_t **group_table, table_t **dset_table, table_t **type_table) { - H5O_info_t oinfo; - /* Initialize the tables */ init_table(group_table); init_table(dset_table); init_table(type_table); /* Init the find_objs_t */ - info->prefix = HDcalloc(1, 1); + info->fid = fid; info->group_table = *group_table; info->type_table = *type_table; info->dset_table = *dset_table; - /* add the root group as an object, it may have hard links to it */ - if(H5Oget_info(fid, &oinfo) < 0) - return FAIL; - else { - /* call with an empty string, it appends '/' group separator */ - char *tmp = build_obj_path_name(info->prefix, ""); - - add_obj(info->group_table, oinfo.addr, tmp, TRUE); - } /* end else */ - /* Find all shared objects */ - return(H5Literate(fid, H5_INDEX_NAME, H5_ITER_INC, NULL, find_objs_cb, (void *)info)); + return(h5trav_visit(fid, "/", TRUE, TRUE, find_objs_cb, NULL, info)); } @@ -632,22 +564,22 @@ init_objs(hid_t fid, find_objs_t *info, table_t **group_table, *------------------------------------------------------------------------- */ static void -add_obj(table_t *table, haddr_t objno, char *objname, hbool_t record) +add_obj(table_t *table, haddr_t objno, const char *objname, hbool_t record) { unsigned u; /* See if we need to make table larger */ - if (table->nobjs == table->size) { + if(table->nobjs == table->size) { table->size *= 2; - table->objs = HDrealloc(table->objs, table->size * sizeof(obj_t)); - } + table->objs = HDrealloc(table->objs, table->size * sizeof(table->objs[0])); + } /* end if */ /* Increment number of objects in table */ u = table->nobjs++; /* Set information about object */ table->objs[u].objno = objno; - table->objs[u].objname = objname; + table->objs[u].objname = HDstrdup(objname); table->objs[u].recorded = record; table->objs[u].displayed = 0; } diff --git a/tools/lib/h5tools_utils.h b/tools/lib/h5tools_utils.h index e604e5a..e7b175c 100644 --- a/tools/lib/h5tools_utils.h +++ b/tools/lib/h5tools_utils.h @@ -95,7 +95,7 @@ typedef struct table_t { /*this struct stores the information that is passed to the find_objs function*/ typedef struct find_objs_t { - char *prefix; + hid_t fid; table_t *group_table; table_t *type_table; table_t *dset_table; diff --git a/tools/lib/h5trav.c b/tools/lib/h5trav.c index 97de021..14ced60 100644 --- a/tools/lib/h5trav.c +++ b/tools/lib/h5trav.c @@ -24,24 +24,25 @@ typedef struct trav_addr_t { size_t nalloc; size_t nused; - haddr_t *addrs; + struct { + haddr_t addr; + char *path; + } *objs; } 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); + h5trav_obj_func_t visit_obj; /* Callback for visiting objects */ + h5trav_lnk_func_t visit_lnk; /* Callback for visiting links */ 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; /*------------------------------------------------------------------------- @@ -52,10 +53,8 @@ static void trav_table_add(trav_table_t *table, const char *objname, const H5O_info_t *oinfo); -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 */, + haddr_t objno, const char *path); /*------------------------------------------------------------------------- @@ -78,19 +77,20 @@ static void trav_table_addlink(trav_table_t *table, *------------------------------------------------------------------------- */ static void -trav_addr_add(trav_addr_t *visited, haddr_t addr) +trav_addr_add(trav_addr_t *visited, haddr_t addr, const char *path) { size_t idx; /* Index of address to use */ /* 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)); + visited->objs = HDrealloc(visited->objs, visited->nalloc * sizeof(visited->objs[0])); } /* end if */ /* Append it */ idx = visited->nused++; - visited->addrs[idx] = addr; + visited->objs[idx].addr = addr; + visited->objs[idx].path = HDstrdup(path); } /* end trav_addr_add() */ @@ -107,7 +107,7 @@ trav_addr_add(trav_addr_t *visited, haddr_t addr) * *------------------------------------------------------------------------- */ -static hbool_t +static const char * trav_addr_visited(trav_addr_t *visited, haddr_t addr) { size_t u; /* Local index variable */ @@ -115,11 +115,11 @@ trav_addr_visited(trav_addr_t *visited, haddr_t addr) /* Look for address */ for(u = 0; u < visited->nused; u++) /* Check for address already in array */ - if(visited->addrs[u] == addr) - return(TRUE); + if(visited->objs[u].addr == addr) + return(visited->objs[u].path); /* Didn't find address */ - return(FALSE); + return(NULL); } /* end trav_addr_visited() */ @@ -135,68 +135,44 @@ trav_addr_visited(trav_addr_t *visited, haddr_t addr) *------------------------------------------------------------------------- */ static herr_t -traverse_cb(hid_t loc_id, const char *link_name, const H5L_info_t *linfo, +traverse_cb(hid_t loc_id, const char *path, 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 */ + char *full_name; + const char *already_visited = NULL; /* Whether the link/object was already visited */ - /* 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); + /* Create the full path name for the link */ + full_name = HDmalloc(HDstrlen(path) + 2); + *full_name = '/'; + HDstrcpy(full_name + 1, path); /* 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_by_name(loc_id, link_name, &oinfo, H5P_DEFAULT) < 0) + if(H5Oget_info_by_name(loc_id, path, &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; + if(oinfo.rc > 1) + if(NULL == (already_visited = trav_addr_visited(udata->seen, oinfo.addr))) + trav_addr_add(udata->seen, oinfo.addr, full_name); /* Make 'visit object' callback */ if(udata->visitor->visit_obj) - (*udata->visitor->visit_obj)(link_path, &oinfo, already_visited, udata->visitor->udata); + (*udata->visitor->visit_obj)(full_name, &oinfo, already_visited, udata->visitor->udata); } /* end if */ else { /* Make 'visit link' callback */ if(udata->visitor->visit_lnk) - (*udata->visitor->visit_lnk)(link_path, linfo, udata->visitor->udata); + (*udata->visitor->visit_lnk)(full_name, 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_by_name(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); + HDfree(full_name); return(H5_ITER_CONT); } /* end traverse_cb() */ @@ -217,39 +193,58 @@ traverse_cb(hid_t loc_id, const char *link_name, const H5L_info_t *linfo, *------------------------------------------------------------------------- */ static int -traverse(hid_t file_id, const trav_visitor_t *visitor) +traverse(hid_t file_id, const char *grp_name, hbool_t visit_start, + hbool_t recurse, const trav_visitor_t *visitor) { - 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 */ + H5O_info_t oinfo; /* Object info for starting group */ - /* Get info for root group */ - if(H5Oget_info(file_id, &oinfo) < 0) + /* Get info for starting object */ + if(H5Oget_info_by_name(file_id, grp_name, &oinfo, H5P_DEFAULT) < 0) return -1; - /* Visit the root group of the file */ - (*visitor->visit_obj)("/", &oinfo, FALSE, visitor->udata); + /* Visit the starting object */ + if(visit_start && visitor->visit_obj) + (*visitor->visit_obj)(grp_name, &oinfo, NULL, visitor->udata); - /* Init addresses seen */ - seen.nused = seen.nalloc = 0; - seen.addrs = NULL; + /* Go visiting, if the object is a group */ + if(oinfo.type == H5O_TYPE_GROUP) { + trav_addr_t seen; /* List of addresses seen */ + trav_ud_traverse_t udata; /* User data for iteration callback */ - /* Check for multiple links to root group */ - if(oinfo.rc > 1) - trav_addr_add(&seen, oinfo.addr); + /* Init addresses seen */ + seen.nused = seen.nalloc = 0; + seen.objs = NULL; - /* Set up user data structure */ - udata.seen = &seen; - udata.curr_path = ""; - udata.visitor = visitor; + /* Check for multiple links to top group */ + if(oinfo.rc > 1) + trav_addr_add(&seen, oinfo.addr, grp_name); - /* Iterate over all links in root group */ - if(H5Literate(file_id, H5_INDEX_NAME, H5_ITER_INC, NULL, traverse_cb, &udata) < 0) - return -1; + /* Set up user data structure */ + udata.seen = &seen; + udata.visitor = visitor; - /* Free visited addresses table */ - if(seen.addrs) - HDfree(seen.addrs); + /* Check for iteration of links vs. visiting all links recursively */ + if(recurse) { + /* Visit all links in group, recursively */ + if(H5Lvisit_by_name(file_id, grp_name, H5_INDEX_NAME, H5_ITER_INC, traverse_cb, &udata, H5P_DEFAULT) < 0) + return -1; + } /* end if */ + else { + /* Iterate over links in group */ + if(H5Literate_by_name(file_id, grp_name, H5_INDEX_NAME, H5_ITER_INC, NULL, traverse_cb, &udata, H5P_DEFAULT) < 0) + return -1; + } /* end else */ + + /* Free visited addresses table */ + if(seen.objs) { + size_t u; /* Local index variable */ + + /* Free paths to objects */ + for(u = 0; u < seen.nused; u++) + HDfree(seen.objs[u].path); + HDfree(seen.objs); + } /* end if */ + } /* end if */ return 0; } @@ -301,7 +296,7 @@ trav_info_add(trav_info_t *info, const char *path, h5trav_type_t obj_type) */ static int trav_info_visit_obj(const char *path, const H5O_info_t *oinfo, - hbool_t UNUSED already_visited, void *udata) + const char UNUSED *already_visited, void *udata) { /* Add the object to the 'info' struct */ /* (object types map directly to "traversal" types) */ @@ -359,7 +354,7 @@ h5trav_getinfo(hid_t file_id, trav_info_t *info) info_visitor.udata = info; /* Traverse all objects in the file, visiting each object & link */ - if(traverse(file_id, &info_visitor) < 0) + if(traverse(file_id, "/", TRUE, TRUE, &info_visitor) < 0) return -1; return 0; @@ -470,24 +465,17 @@ trav_info_free(trav_info_t *info) */ static int trav_table_visit_obj(const char *path, const H5O_info_t *oinfo, - hbool_t already_visited, void *udata) + const char *already_visited, void *udata) { trav_table_t *table = (trav_table_t *)udata; /* Check if we've already seen this object */ - if(!already_visited) + if(NULL == already_visited) /* add object to table */ trav_table_add(table, path, oinfo); - else { - size_t found; /* Index of original object seen */ - - /* Look for object in existing table */ - found = trav_table_search(table, oinfo->addr); - HDassert(found < table->nobjs); - + else /* Add alias for object to table */ - trav_table_addlink(table, found, path); - } /* end else */ + trav_table_addlink(table, oinfo->addr, path); return(0); } /* end trav_table_visit_obj() */ @@ -541,7 +529,7 @@ h5trav_gettable(hid_t fid, trav_table_t *table) table_visitor.udata = table; /* Traverse all objects in the file, visiting each object & link */ - if(traverse(fid, &table_visitor) < 0) + if(traverse(fid, "/", TRUE, TRUE, &table_visitor) < 0) return -1; return 0; } @@ -670,25 +658,33 @@ trav_table_add(trav_table_t *table, */ static void -trav_table_addlink(trav_table_t *table, - size_t j /* the object index */, - const char *path) +trav_table_addlink(trav_table_t *table, haddr_t objno, const char *path) { - size_t new; + size_t i; /* Local index variable */ - /* already inserted */ - if(HDstrcmp(table->objs[j].name, path) == 0) - return; + for(i = 0; i < table->nobjs; i++) { + if(table->objs[i].objno == objno) { + size_t n; - /* 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 */ + /* already inserted? */ + if(HDstrcmp(table->objs[i].name, path) == 0) + return; + + /* allocate space if necessary */ + if(table->objs[i].nlinks == (unsigned)table->objs[i].sizelinks) { + table->objs[i].sizelinks = MAX(1, table->objs[i].sizelinks * 2); + table->objs[i].links = (trav_link_t*)HDrealloc(table->objs[i].links, table->objs[i].sizelinks * sizeof(trav_link_t)); + } /* end if */ - /* insert it */ - new = table->objs[j].nlinks++; - table->objs[j].links[new].new_name = (char *)HDstrdup(path); + /* insert it */ + n = table->objs[i].nlinks++; + table->objs[i].links[n].new_name = (char *)HDstrdup(path); + + return; + } /* end for */ + } /* end for */ + + HDassert(0 && "object not in table?!?"); } @@ -809,10 +805,8 @@ void trav_table_free( trav_table_t *table ) */ static int trav_print_visit_obj(const char *path, const H5O_info_t *oinfo, - hbool_t already_visited, void *udata) + const char *already_visited, void UNUSED *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) @@ -836,26 +830,12 @@ trav_print_visit_obj(const char *path, const H5O_info_t *oinfo, } /* end switch */ /* Check if we've already seen this object */ - if(!already_visited) { + if(NULL == 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 */ + else + /* Print the link's original name */ + printf(" -> %s\n", already_visited); return(0); } /* end trav_print_visit_obj() */ @@ -938,16 +918,11 @@ trav_print_visit_lnk(const char *path, const H5L_info_t *linfo, void *udata) int h5trav_print(hid_t fid) { - 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; @@ -955,11 +930,42 @@ h5trav_print(hid_t fid) print_visitor.udata = &print_udata; /* Traverse all objects in the file, visiting each object & link */ - if(traverse(fid, &print_visitor) < 0) + if(traverse(fid, "/", TRUE, TRUE, &print_visitor) < 0) return -1; - /* Free table */ - trav_table_free(table); + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: h5trav_visit + * + * Purpose: Generic traversal routine for visiting objects and links + * + * Return: 0, -1 on error + * + * Programmer: Quincey Koziol, koziol@hdfgroup.org + * + * Date: November 6, 2007 + * + *------------------------------------------------------------------------- + */ + +int +h5trav_visit(hid_t fid, const char *grp_name, hbool_t visit_start, + hbool_t recurse, h5trav_obj_func_t visit_obj, h5trav_lnk_func_t visit_lnk, + void *udata) +{ + trav_visitor_t visitor; /* Visitor structure for objects */ + + /* Init visitor structure */ + visitor.visit_obj = visit_obj; + visitor.visit_lnk = visit_lnk; + visitor.udata = udata; + + /* Traverse all objects in the file, visiting each object & link */ + if(traverse(fid, grp_name, visit_start, recurse, &visitor) < 0) + return -1; return 0; } diff --git a/tools/lib/h5trav.h b/tools/lib/h5trav.h index 05bc3cb..5c07331 100644 --- a/tools/lib/h5trav.h +++ b/tools/lib/h5trav.h @@ -18,6 +18,12 @@ #include "hdf5.h" +/* Typedefs for visiting objects */ +typedef herr_t (*h5trav_obj_func_t)(const char *path_name, const H5O_info_t *oinfo, + const char *first_seen, void *udata); +typedef herr_t (*h5trav_lnk_func_t)(const char *path_name, const H5L_info_t *linfo, + void *udata); + /*------------------------------------------------------------------------- * public enum to specify type of an object * the TYPE can be: @@ -101,6 +107,14 @@ extern "C" { #endif /*------------------------------------------------------------------------- + * "h5trav general" public functions + *------------------------------------------------------------------------- + */ +int h5trav_visit(hid_t file_id, const char *grp_name, hbool_t visit_start, + hbool_t recurse, h5trav_obj_func_t visit_obj, h5trav_lnk_func_t visit_lnk, + void *udata); + +/*------------------------------------------------------------------------- * "h5trav info" public functions *------------------------------------------------------------------------- */ |