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/h5trav.c | |
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/h5trav.c')
-rw-r--r-- | tools/lib/h5trav.c | 276 |
1 files changed, 141 insertions, 135 deletions
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; } |