From 2f36ea99d4ad1b036d377719e49eaab2dec64444 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Sat, 24 Nov 2007 11:49:36 -0500 Subject: [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 --- MANIFEST | 1 + src/H5F.c | 12 +- src/H5FD.c | 10 +- src/H5Fprivate.h | 2 + src/H5G.c | 461 +++++++++++++++++++++- src/H5Gcompact.c | 8 +- src/H5Gdense.c | 47 +-- src/H5Gdeprec.c | 4 +- src/H5Glink.c | 33 +- src/H5Gname.c | 282 +++++-------- src/H5Gnode.c | 52 +-- src/H5Gobj.c | 45 +-- src/H5Gpkg.h | 43 +- src/H5Gprivate.h | 2 +- src/H5Gstab.c | 10 +- src/H5L.c | 72 +++- src/H5Lpublic.h | 3 + src/H5O.c | 48 ++- src/H5Olinfo.c | 7 +- src/H5Oprivate.h | 1 + src/H5R.c | 2 +- src/H5SL.c | 42 +- src/H5SLprivate.h | 3 +- src/H5private.h | 6 + test/getname.c | 91 +++-- test/mount.c | 26 +- tools/h5copy/h5copy.c | 4 +- tools/h5dump/h5dump.c | 10 +- tools/h5ls/h5ls.c | 524 ++++++++++--------------- tools/h5ls/testh5ls.sh | 1 + tools/h5stat/h5stat.c | 327 +++++---------- tools/h5stat/testfiles/h5stat_filters-file.ddl | 1 - tools/h5stat/testfiles/h5stat_filters.ddl | 1 - tools/h5stat/testfiles/h5stat_newgrat.ddl | 1 - tools/h5stat/testfiles/h5stat_tsohm.ddl | 1 - tools/lib/h5tools_ref.c | 192 ++++----- tools/lib/h5tools_utils.c | 186 +++------ tools/lib/h5tools_utils.h | 2 +- tools/lib/h5trav.c | 276 ++++++------- tools/lib/h5trav.h | 14 + tools/testfiles/h5copytst.out.ls | 3 + tools/testfiles/h5mkgrp_nested.ls | 3 + tools/testfiles/h5mkgrp_nested_latest.ls | 4 + tools/testfiles/h5mkgrp_nested_mult.ls | 3 + tools/testfiles/h5mkgrp_nested_mult_latest.ls | 4 + tools/testfiles/h5mkgrp_several.ls | 3 + tools/testfiles/h5mkgrp_several_latest.ls | 4 + tools/testfiles/h5mkgrp_single.ls | 3 + tools/testfiles/h5mkgrp_single_latest.ls | 4 + tools/testfiles/tall-2.ls | 1 + tools/testfiles/tarray1.ls | 1 + tools/testfiles/tattr2.ls | 143 ------- tools/testfiles/tcomp-1.ls | 1 + tools/testfiles/tdset-1.ls | 1 + tools/testfiles/textlink-1.ls | 1 + tools/testfiles/tgroup-1.ls | 40 +- tools/testfiles/tgroup-2.ls | 4 + tools/testfiles/tloop-1.ls | 1 + tools/testfiles/tnestcomp-1.ls | 1 + tools/testfiles/tsaf.ls | 1 + tools/testfiles/tslink-1.ls | 1 + tools/testfiles/tstr-1.ls | 1 + tools/testfiles/tudlink-1.ls | 1 + tools/testfiles/tvldtypes1.ls | 1 + 64 files changed, 1541 insertions(+), 1542 deletions(-) create mode 100644 tools/testfiles/tgroup-2.ls diff --git a/MANIFEST b/MANIFEST index bc6ef0a..00afbc9 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1238,6 +1238,7 @@ ./tools/testfiles/tcomp-1.ls ./tools/testfiles/tdset-1.ls ./tools/testfiles/tgroup-1.ls +./tools/testfiles/tgroup-2.ls ./tools/testfiles/tgroup.ls ./tools/testfiles/thlink-1.ls ./tools/testfiles/tloop-1.ls diff --git a/src/H5F.c b/src/H5F.c index 8844b8d..045705f 100644 --- a/src/H5F.c +++ b/src/H5F.c @@ -2444,8 +2444,6 @@ H5F_get_driver_id(const H5F_t *f) * Programmer: Quincey Koziol * March 27, 2002 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t @@ -2455,13 +2453,13 @@ H5F_get_fileno(const H5F_t *f, unsigned long *filenum) FUNC_ENTER_NOAPI(H5F_get_fileno, FAIL) - assert(f); - assert(f->shared); - assert(f->shared->lf); - assert(filenum); + HDassert(f); + HDassert(f->shared); + HDassert(f->shared->lf); + HDassert(filenum); /* Retrieve the file's serial number */ - if(H5FD_get_fileno(f->shared->lf,filenum) < 0) + if(H5FD_get_fileno(f->shared->lf, filenum) < 0) HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "can't retrieve fileno") done: diff --git a/src/H5FD.c b/src/H5FD.c index 096509e..0cf70ca 100644 --- a/src/H5FD.c +++ b/src/H5FD.c @@ -3795,22 +3795,20 @@ done: * Programmer: Quincey Koziol * March 27, 2002 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t H5FD_get_fileno(const H5FD_t *file, unsigned long *filenum) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5FD_get_fileno, FAIL) - assert(file); - assert(filenum); + HDassert(file); + HDassert(filenum); /* Retrieve the file's serial number */ - HDmemcpy(filenum,&file->fileno,sizeof(file->fileno)); + *filenum = file->fileno; done: FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index f9a1f57..1044b14 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -267,6 +267,7 @@ typedef struct H5F_t H5F_t; #define H5F_INTENT(F) ((F)->intent) #define H5F_GET_FC_DEGREE(F) ((F)->shared->fc_degree) #define H5F_STORE_MSG_CRT_IDX(F) ((F)->shared->store_msg_crt_idx) +#define H5F_GET_FILENO(F,FILENUM) ((FILENUM) = (F)->shared->lf->fileno) #else /* H5F_PACKAGE */ #define H5F_FCPL(F) (H5F_get_fcpl(F)) #define H5F_SIZEOF_ADDR(F) (H5F_sizeof_addr(F)) @@ -285,6 +286,7 @@ typedef struct H5F_t H5F_t; #define H5F_INTENT(F) (H5F_get_intent(F)) #define H5F_GET_FC_DEGREE(F) (H5F_get_fc_degree(F)) #define H5F_STORE_MSG_CRT_IDX(F) (H5F_store_msg_crt_idx(F)) +#define H5F_GET_FILENO(F,FILENUM) (H5F_get_filenum((F), &(FILENUM))) #endif /* H5F_PACKAGE */ diff --git a/src/H5G.c b/src/H5G.c index bca0332..116cdf8 100644 --- a/src/H5G.c +++ b/src/H5G.c @@ -88,6 +88,7 @@ #include "H5Gpkg.h" /* Groups */ #include "H5Iprivate.h" /* IDs */ #include "H5Lprivate.h" /* Links */ +#include "H5MMprivate.h" /* Memory management */ #include "H5Pprivate.h" /* Property lists */ /* Local macros */ @@ -100,14 +101,43 @@ typedef struct { H5G_loc_t *loc; /* Pointer to the location for insertion */ } H5G_trav_ins_t; +/* User data for application-style iteration over links in a group */ +typedef struct { + hid_t gid; /* The group ID for the application callback */ + H5G_link_iterate_t lnk_op; /* Application callback */ + void *op_data; /* Application's op data */ +} H5G_iter_appcall_ud_t; + +/* User data for recursive traversal over links from a group */ +typedef struct { + hid_t gid; /* The group ID for the starting group */ + H5G_loc_t *curr_loc; /* Location of starting group */ + hid_t lapl_id; /* LAPL for walking across links */ + hid_t dxpl_id; /* DXPL for operations */ + H5_index_t idx_type; /* Index to use */ + H5_iter_order_t order; /* Iteration order within index */ + H5SL_t *visited; /* Skip list for tracking visited nodes */ + char *path; /* Path name of the link */ + size_t curr_path_len; /* Current length of the path in the buffer */ + size_t path_buf_size; /* Size of path buffer */ + H5L_iterate_t op; /* Application callback */ + void *op_data; /* Application's op data */ +} H5G_iter_visit_ud_t; + + /* Package variables */ + /* Local variables */ /* Declare a free list to manage the H5G_t struct */ H5FL_DEFINE(H5G_t); H5FL_DEFINE(H5G_shared_t); +/* Declare the free list to manage H5_obj_t's */ +H5FL_DEFINE_STATIC(H5_obj_t); + + /* Private prototypes */ static herr_t H5G_open_oid(H5G_t *grp, hid_t dxpl_id); @@ -366,7 +396,7 @@ H5Gopen2(hid_t loc_id, const char *name, hid_t gapl_id) if((grp = H5G_open_name(&loc, name, gapl_id, H5AC_dxpl_id)) == NULL) HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group") - /* Register an atom for the group */ + /* Register an ID for the group */ if((ret_value = H5I_register(H5I_GROUP, grp)) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group") @@ -1019,8 +1049,8 @@ H5G_open_name(const H5G_loc_t *loc, const char *name, hid_t gapl_id, H5G_loc_t grp_loc; /* Location used to open group */ H5G_name_t grp_path; /* Opened object group hier. path */ H5O_loc_t grp_oloc; /* Opened object object location */ - H5O_type_t obj_type; /* Type of object at location */ hbool_t loc_found = FALSE; /* Location at 'name' found */ + H5O_type_t obj_type; /* Type of object at location */ H5G_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5G_open_name, NULL) @@ -1145,7 +1175,7 @@ H5G_open(const H5G_loc_t *loc, hid_t dxpl_id) ret_value = grp; done: - if (!ret_value && grp) { + if(!ret_value && grp) { H5O_loc_free(&(grp->oloc)); H5G_name_free(&(grp->path)); H5FL_FREE(H5G_t,grp); @@ -1522,3 +1552,428 @@ H5G_unmount(H5G_t *grp) FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5G_unmount() */ + +/*------------------------------------------------------------------------- + * Function: H5G_iterate_cb + * + * Purpose: Callback function for iterating over links in a group + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Oct 3, 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_iterate_cb(const H5O_link_t *lnk, void *_udata) +{ + H5G_iter_appcall_ud_t *udata = (H5G_iter_appcall_ud_t *)_udata; /* User data for callback */ + herr_t ret_value = H5_ITER_ERROR; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_iterate_cb) + + /* Sanity check */ + HDassert(lnk); + HDassert(udata); + + switch(udata->lnk_op.op_type) { +#ifndef H5_NO_DEPRECATED_SYMBOLS + case H5G_LINK_OP_OLD: + /* Make the old-type application callback */ + ret_value = (udata->lnk_op.op_func.op_old)(udata->gid, lnk->name, udata->op_data); + break; +#endif /* H5_NO_DEPRECATED_SYMBOLS */ + + case H5G_LINK_OP_NEW: + { + H5L_info_t info; /* Link info */ + + /* Retrieve the info for the link */ + if(H5G_link_to_info(lnk, &info) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for link") + + /* Make the application callback */ + ret_value = (udata->lnk_op.op_func.op_new)(udata->gid, lnk->name, &info, udata->op_data); + } + break; + } /* end switch */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_iterate_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_iterate + * + * Purpose: Private function for iterating over links in a group + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Oct 3, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_iterate(hid_t loc_id, const char *group_name, + H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, + const H5G_link_iterate_t *lnk_op, void *op_data, hid_t lapl_id, hid_t dxpl_id) +{ + H5G_loc_t loc; /* Location of parent for group */ + hid_t gid = -1; /* ID of group to iterate over */ + H5G_t *grp; /* Pointer to group data structure to iterate over */ + H5G_iter_appcall_ud_t udata; /* User data for callback */ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_iterate, FAIL) + + /* Sanity check */ + HDassert(group_name); + HDassert(last_lnk); + HDassert(lnk_op && lnk_op->op_func.op_new); + + /* + * Open the group on which to operate. We also create a group ID which + * we can pass to the application-defined operator. + */ + if(H5G_loc(loc_id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(NULL == (grp = H5G_open_name(&loc, group_name, lapl_id, dxpl_id))) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group") + if((gid = H5I_register(H5I_GROUP, grp)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group") + + /* Set up user data for callback */ + udata.gid = gid; + udata.lnk_op = *lnk_op; + udata.op_data = op_data; + + /* Call the real group iteration routine */ + if((ret_value = H5G_obj_iterate(&(grp->oloc), idx_type, order, skip, last_lnk, H5G_iterate_cb, &udata, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "error iterating over links") + +done: + /* Release the group opened */ + if(gid > 0) { + if(H5I_dec_ref(gid) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close group") + } /* end if */ + else if(grp && H5G_close(grp) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to release group") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_iterate() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_free_visit_visited + * + * Purpose: Free the key for an object visited during a group traversal + * + * Return: Non-negative on success, negative on failure + * + * Programmer: Quincey Koziol + * Nov 4, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_free_visit_visited(void *item, void UNUSED *key, void UNUSED *operator_data/*in,out*/) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_free_visit_visited) + + H5FL_FREE(H5_obj_t, item); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5G_free_visit_visited() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_visit_cb + * + * Purpose: Callback function for recursively visiting links from a group + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Nov 4, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_visit_cb(const H5O_link_t *lnk, void *_udata) +{ + H5G_iter_visit_ud_t *udata = (H5G_iter_visit_ud_t *)_udata; /* User data for callback */ + H5L_info_t info; /* Link info */ + H5G_loc_t obj_loc; /* Location of object */ + H5G_name_t obj_path; /* Object's group hier. path */ + H5O_loc_t obj_oloc; /* Object's object location */ + hbool_t obj_found = FALSE; /* Object at 'name' found */ + size_t old_path_len = udata->curr_path_len; /* Length of path before appending this link's name */ + size_t link_name_len; /* Length of link's name */ + size_t len_needed; /* Length of path string needed */ + herr_t ret_value = H5_ITER_CONT; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_visit_cb) + + /* Sanity check */ + HDassert(lnk); + HDassert(udata); + + /* Check if we will need more space to store this link's relative path */ + /* ("+2" is for string terminator and possible '/' for group separator later) */ + link_name_len = HDstrlen(lnk->name); + len_needed = udata->curr_path_len + link_name_len + 2; + if(len_needed > udata->path_buf_size) { + void *new_path; /* Pointer to new path buffer */ + + /* Attempt to allocate larger buffer for path */ + if(NULL == (new_path = H5MM_realloc(udata->path, len_needed))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate path string") + udata->path = new_path; + udata->path_buf_size = len_needed; + } /* end if */ + + /* Build the link's relative path name */ + HDassert(udata->path[old_path_len] == '\0'); + HDstrcpy(&(udata->path[old_path_len]), lnk->name); + udata->curr_path_len += link_name_len; + + /* Construct the link info from the link message */ + if(H5G_link_to_info(lnk, &info) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for link") + + /* Make the application callback */ + ret_value = (udata->op)(udata->gid, udata->path, &info, udata->op_data); + + /* Check for doing more work */ + if(ret_value == H5_ITER_CONT && lnk->type == H5L_TYPE_HARD) { + H5O_type_t otype; /* Basic object type (group, dataset, etc.) */ + H5_obj_t obj_pos; /* Object "position" for this object */ + unsigned rc; /* Reference count of object */ + + /* Set up opened group location to fill in */ + obj_loc.oloc = &obj_oloc; + obj_loc.path = &obj_path; + H5G_loc_reset(&obj_loc); + + /* Find the object using the LAPL passed in */ + /* (Correctly handles mounted files) */ + if(H5G_loc_find(udata->curr_loc, lnk->name, &obj_loc/*out*/, udata->lapl_id, udata->dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5_ITER_ERROR, "object not found") + obj_found = TRUE; + + /* Construct unique "position" for this object */ + H5F_GET_FILENO(obj_oloc.file, obj_pos.fileno); + obj_pos.addr = obj_oloc.addr; + + /* Check if we've seen the object the link references before */ + if(NULL == H5SL_search(udata->visited, &obj_pos)) { + /* Get the object's reference count and type */ + if(H5O_get_rc_and_type(&obj_oloc, udata->dxpl_id, &rc, &otype) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get object info") + + /* If its ref count is > 1, we add it to the list of visited objects */ + /* (because it could come up again during traversal) */ + if(rc > 1) { + H5_obj_t *new_node; /* New object node for visited list */ + + /* Allocate new object "position" node */ + if((new_node = H5FL_MALLOC(H5_obj_t)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate object node") + + /* Set node information */ + *new_node = obj_pos; + + /* Add to list of visited objects */ + if(H5SL_insert(udata->visited, new_node, new_node) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, H5_ITER_ERROR, "can't insert object node into visited list") + } /* end if */ + + /* If it's a group, we recurse into it */ + if(otype == H5O_TYPE_GROUP) { + H5G_loc_t *old_loc = udata->curr_loc; /* Pointer to previous group location info */ + H5_index_t idx_type = udata->idx_type; /* Type of index to use */ + H5O_linfo_t linfo; /* Link info message */ + + /* Add the path separator to the current path */ + HDassert(udata->path[udata->curr_path_len] == '\0'); + HDstrcpy(&(udata->path[udata->curr_path_len]), "/"); + udata->curr_path_len++; + + /* Attempt to get the link info for this group */ + if(H5G_obj_get_linfo(&obj_oloc, &linfo, udata->dxpl_id)) { + /* Check for creation order tracking, if creation order index lookup requested */ + if(idx_type == H5_INDEX_CRT_ORDER) { + /* Check if creation order is tracked */ + if(!linfo.track_corder) + /* Switch to name order for this group */ + idx_type = H5_INDEX_NAME; + } /* end if */ + else + HDassert(idx_type == H5_INDEX_NAME); + } /* end if */ + else { + /* Clear error stack from not finding the link info message */ + H5E_clear_stack(NULL); + + /* Can only perform name lookups on groups with symbol tables */ + if(idx_type != H5_INDEX_NAME) + /* Switch to name order for this group */ + idx_type = H5_INDEX_NAME; + } /* end if */ + + /* Point to this group's location info */ + udata->curr_loc = &obj_loc; + + /* Iterate over links in group */ + ret_value = H5G_obj_iterate(&obj_oloc, idx_type, udata->order, (hsize_t)0, NULL, H5G_visit_cb, udata, udata->dxpl_id); + + /* Restore location */ + udata->curr_loc = old_loc; + } /* end if */ + } /* end if */ + } /* end if */ + +done: + /* Reset path back to incoming path */ + udata->path[old_path_len] = '\0'; + udata->curr_path_len = old_path_len; + + /* Release resources */ + if(obj_found && H5G_loc_free(&obj_loc) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, H5_ITER_ERROR, "can't free location") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_visit_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_visit + * + * Purpose: Recursively visit all the links in a group and all + * the groups that are linked to from that group. Links within + * each group are visited according to the order within the + * specified index (unless the specified index does not exist for + * a particular group, then the "name" index is used). + * + * NOTE: Each _link_ reachable from the initial group will only be + * visited once. However, because an object may be reached from + * more than one link, the visitation may call the application's + * callback with more than one link that points to a particular + * _object_. + * + * 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. + * + * Failure: Negative if something goes wrong within the + * library, or the negative value returned by one + * of the operators. + * + * + * + * Programmer: Quincey Koziol + * November 4 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_visit(hid_t loc_id, const char *group_name, H5_index_t idx_type, + H5_iter_order_t order, H5L_iterate_t op, void *op_data, hid_t lapl_id, + hid_t dxpl_id) +{ + H5G_iter_visit_ud_t udata; /* User data for callback */ + H5O_linfo_t linfo; /* Link info message */ + hid_t gid = (-1); /* Group ID */ + H5G_t *grp = NULL; /* Group opened */ + H5G_loc_t loc; /* Location of group passed in */ + H5G_loc_t start_loc; /* Location of starting group */ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_visit, FAIL) + + /* Check args */ + if(H5G_loc(loc_id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + + /* Open the group to begin visiting within */ + if((grp = H5G_open_name(&loc, group_name, lapl_id, dxpl_id)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group") + + /* Register an ID for the starting group */ + if((gid = H5I_register(H5I_GROUP, grp)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group") + + /* Get the location of the starting group */ + if(H5G_loc(gid, &start_loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + + /* Set up user data */ + udata.gid = gid; + udata.curr_loc = &start_loc; + udata.lapl_id = lapl_id; + udata.dxpl_id = dxpl_id; + udata.idx_type = idx_type; + udata.order = order; + udata.op = op; + udata.op_data = op_data; + + /* Allocate space for the path name */ + if(NULL == (udata.path = H5MM_strdup(""))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate path name buffer") + udata.path_buf_size = 1; + udata.curr_path_len = 0; + + /* Create skip list to store reference path information */ + if((udata.visited = H5SL_create(H5SL_TYPE_OBJ, 0.5, (size_t)16)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "can't create skip list for visited objects") + + /* Attempt to get the link info for this group */ + if(H5G_obj_get_linfo(&(grp->oloc), &linfo, dxpl_id)) { + /* Check for creation order tracking, if creation order index lookup requested */ + if(idx_type == H5_INDEX_CRT_ORDER) { + /* Check if creation order is tracked */ + if(!linfo.track_corder) + /* Switch to name order for this group */ + idx_type = H5_INDEX_NAME; + } /* end if */ + else + HDassert(idx_type == H5_INDEX_NAME); + } /* end if */ + else { + /* Clear error stack from not finding the link info message */ + H5E_clear_stack(NULL); + + /* Can only perform name lookups on groups with symbol tables */ + if(idx_type != H5_INDEX_NAME) + /* Switch to name order for this group */ + idx_type = H5_INDEX_NAME; + } /* end if */ + + /* Call the link iteration routine */ + if((ret_value = H5G_obj_iterate(&(grp->oloc), idx_type, order, (hsize_t)0, NULL, H5G_visit_cb, &udata, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't visit links") + +done: + /* Release user data resources */ + H5MM_xfree(udata.path); + if(udata.visited) + H5SL_destroy(udata.visited, H5G_free_visit_visited, NULL); + + /* Release the group opened */ + if(gid > 0) { + if(H5I_dec_ref(gid) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close group") + } /* end if */ + else if(grp && H5G_close(grp) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to release group") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_visit() */ + diff --git a/src/H5Gcompact.c b/src/H5Gcompact.c index 042d29a..b0340a7 100644 --- a/src/H5Gcompact.c +++ b/src/H5Gcompact.c @@ -406,9 +406,9 @@ done: *------------------------------------------------------------------------- */ herr_t -H5G_compact_iterate(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo, +H5G_compact_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, - hid_t gid, H5G_link_iterate_t *lnk_op, void *op_data) + H5G_lib_iterate_t op, void *op_data) { H5G_link_table_t ltable = {0, NULL}; /* Link table */ herr_t ret_value; /* Return value */ @@ -418,14 +418,14 @@ H5G_compact_iterate(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo, /* Sanity check */ HDassert(oloc); HDassert(linfo); - HDassert(lnk_op && lnk_op->u.lib_op); + HDassert(op); /* Build table of all link messages */ if(H5G_compact_build_table(oloc, dxpl_id, linfo, idx_type, order, <able) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create link message table") /* Iterate over links in table */ - if((ret_value = H5G_link_iterate_table(<able, skip, last_lnk, gid, lnk_op, op_data)) < 0) + if((ret_value = H5G_link_iterate_table(<able, skip, last_lnk, op, op_data)) < 0) HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed"); done: diff --git a/src/H5Gdense.c b/src/H5Gdense.c index 2b7493b..ed53a47 100644 --- a/src/H5Gdense.c +++ b/src/H5Gdense.c @@ -90,9 +90,8 @@ typedef struct { hsize_t count; /* # of links examined */ /* downward (from application) */ - hid_t gid; /* Group ID for application callback */ hsize_t skip; /* Number of links to skip */ - const H5G_link_iterate_t *lnk_op; /* Callback for each link */ + H5G_lib_iterate_t op; /* Callback for each link */ void *op_data; /* Callback data for each link */ /* upward */ @@ -799,7 +798,6 @@ H5G_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, /* Allocate space for the table entries */ if(ltable->nlinks > 0) { H5G_dense_bt_ud_t udata; /* User data for iteration callback */ - H5G_link_iterate_t lnk_op; /* Link operator */ /* Allocate the table to store the links */ if((ltable->lnks = H5MM_malloc(sizeof(H5O_link_t) * ltable->nlinks)) == NULL) @@ -809,12 +807,8 @@ H5G_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, udata.ltable = ltable; udata.curr_lnk = 0; - /* Build iterator operator */ - lnk_op.op_type = H5G_LINK_OP_LIB; - lnk_op.u.lib_op = H5G_dense_build_table_cb; - /* Iterate over the links in the group, building a table of the link messages */ - if(H5G_dense_iterate(f, dxpl_id, linfo, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, NULL, (hid_t)0, &lnk_op, &udata) < 0) + if(H5G_dense_iterate(f, dxpl_id, linfo, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, NULL, H5G_dense_build_table_cb, &udata) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over links") /* Sort link table in correct iteration order */ @@ -904,32 +898,8 @@ H5G_dense_iterate_bt2_cb(const void *_record, void *_bt2_udata) H5G_dense_iterate_fh_cb, &fh_udata) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTOPERATE, H5_ITER_ERROR, "heap op callback failed") - /* Check which type of callback to make */ - switch(bt2_udata->lnk_op->op_type) { -#ifndef H5_NO_DEPRECATED_SYMBOLS - case H5G_LINK_OP_OLD: - /* Make the old-type application callback */ - ret_value = (bt2_udata->lnk_op->u.old_op)(bt2_udata->gid, fh_udata.lnk->name, bt2_udata->op_data); - break; -#endif /* H5_NO_DEPRECATED_SYMBOLS */ - - case H5G_LINK_OP_APP: - { - H5L_info_t info; /* Link info */ - - /* Retrieve the info for the link */ - if(H5G_link_to_info(fh_udata.lnk, &info) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for link") - - /* Make the application callback */ - ret_value = (bt2_udata->lnk_op->u.app_op)(bt2_udata->gid, fh_udata.lnk->name, &info, bt2_udata->op_data); - } - break; - - case H5G_LINK_OP_LIB: - /* Call the library's callback */ - ret_value = (bt2_udata->lnk_op->u.lib_op)(fh_udata.lnk, bt2_udata->op_data); - } /* end switch */ + /* Make the callback */ + ret_value = (bt2_udata->op)(fh_udata.lnk, bt2_udata->op_data); /* Release the space allocated for the link */ H5O_msg_free(H5O_LINK_ID, fh_udata.lnk); @@ -964,7 +934,7 @@ done: herr_t H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, - hid_t gid, const H5G_link_iterate_t *lnk_op, void *op_data) + H5G_lib_iterate_t op, void *op_data) { H5HF_t *fheap = NULL; /* Fractal heap handle */ H5G_link_table_t ltable = {0, NULL}; /* Table of links */ @@ -979,7 +949,7 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, */ HDassert(f); HDassert(linfo); - HDassert(lnk_op && lnk_op->u.lib_op); + HDassert(op); /* Determine the address of the index to use */ if(idx_type == H5_INDEX_NAME) { @@ -1018,10 +988,9 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, udata.f = f; udata.dxpl_id = dxpl_id; udata.fheap = fheap; - udata.gid = gid; udata.skip = skip; udata.count = 0; - udata.lnk_op = lnk_op; + udata.op = op; udata.op_data = op_data; /* Iterate over the records in the v2 B-tree's "native" order */ @@ -1039,7 +1008,7 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "error building table of links") /* Iterate over links in table */ - if((ret_value = H5G_link_iterate_table(<able, skip, last_lnk, gid, lnk_op, op_data)) < 0) + if((ret_value = H5G_link_iterate_table(<able, skip, last_lnk, op, op_data)) < 0) HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed"); } /* end else */ diff --git a/src/H5Gdeprec.c b/src/H5Gdeprec.c index 52b607d..01c4edb 100644 --- a/src/H5Gdeprec.c +++ b/src/H5Gdeprec.c @@ -770,10 +770,10 @@ H5Giterate(hid_t loc_id, const char *name, int *idx_p, H5G_iterate_t op, /* Build link operator info */ lnk_op.op_type = H5G_LINK_OP_OLD; - lnk_op.u.old_op = op; + lnk_op.op_func.op_old = op; /* Call private function. */ - if((ret_value = H5G_obj_iterate(loc_id, name, H5_INDEX_NAME, H5_ITER_INC, idx, &last_obj, &lnk_op, op_data, H5P_DEFAULT, H5AC_ind_dxpl_id)) < 0) + if((ret_value = H5G_iterate(loc_id, name, H5_INDEX_NAME, H5_ITER_INC, idx, &last_obj, &lnk_op, op_data, H5P_DEFAULT, H5AC_ind_dxpl_id)) < 0) HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "group iteration failed") /* Set the index we stopped at */ diff --git a/src/H5Glink.c b/src/H5Glink.c index 7292245..75a3e83 100644 --- a/src/H5Glink.c +++ b/src/H5Glink.c @@ -603,7 +603,7 @@ H5G_link_sort_table(H5G_link_table_t *ltable, H5_index_t idx_type, */ herr_t H5G_link_iterate_table(const H5G_link_table_t *ltable, hsize_t skip, - hsize_t *last_lnk, hid_t gid, const H5G_link_iterate_t *lnk_op, void *op_data) + hsize_t *last_lnk, const H5G_lib_iterate_t op, void *op_data) { size_t u; /* Local index variable */ herr_t ret_value = H5_ITER_CONT; /* Return value */ @@ -612,7 +612,7 @@ H5G_link_iterate_table(const H5G_link_table_t *ltable, hsize_t skip, /* Sanity check */ HDassert(ltable); - HDassert(lnk_op); + HDassert(op); /* Skip over links, if requested */ if(last_lnk) @@ -621,32 +621,8 @@ H5G_link_iterate_table(const H5G_link_table_t *ltable, hsize_t skip, /* Iterate over link messages */ H5_ASSIGN_OVERFLOW(/* To: */ u, /* From: */ skip, /* From: */ hsize_t, /* To: */ size_t) for(; u < ltable->nlinks && !ret_value; u++) { - /* Check which kind of callback to make */ - switch(lnk_op->op_type) { -#ifndef H5_NO_DEPRECATED_SYMBOLS - case H5G_LINK_OP_OLD: - /* Make the old-type application callback */ - ret_value = (lnk_op->u.old_op)(gid, ltable->lnks[u].name, op_data); - break; -#endif /* H5_NO_DEPRECATED_SYMBOLS */ - - case H5G_LINK_OP_APP: - { - H5L_info_t info; /* Link info */ - - /* Retrieve the info for the link */ - if(H5G_link_to_info(&(ltable->lnks[u]), &info) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for link") - - /* Make the application callback */ - ret_value = (lnk_op->u.app_op)(gid, ltable->lnks[u].name, &info, op_data); - } - break; - - case H5G_LINK_OP_LIB: - /* Call the library's callback */ - ret_value = (lnk_op->u.lib_op)(&(ltable->lnks[u]), op_data); - } /* end switch */ + /* Make the callback */ + ret_value = (op)(&(ltable->lnks[u]), op_data); /* Increment the number of entries passed through */ if(last_lnk) @@ -657,7 +633,6 @@ H5G_link_iterate_table(const H5G_link_table_t *ltable, hsize_t skip, if(ret_value < 0) HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed"); -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_link_iterate_table() */ diff --git a/src/H5Gname.c b/src/H5Gname.c index e341ee7..bde9e23 100644 --- a/src/H5Gname.c +++ b/src/H5Gname.c @@ -50,21 +50,15 @@ typedef struct H5G_names_t { } H5G_names_t; /* Info to pass to the iteration function when building name */ -typedef struct H5G_ref_path_iter_t { +typedef struct H5G_gnba_iter_t { /* In */ - hid_t file; /* File id where it came from */ + const H5O_loc_t *loc; /* The location of the object we're looking for */ hid_t lapl_id; /* LAPL for operations */ hid_t dxpl_id; /* DXPL for operations */ - hbool_t is_root_group; /* Flag to indicate that the root group is being looked at */ - const H5O_loc_t *loc; /* The location of the object we're looking for */ - - /* In/Out */ - H5SL_t *ref_path_table; /* Skip list for tracking visited nodes */ - size_t max_container_len; /* Maximum size of container */ /* Out */ - char *container; /* full name of the container object */ -} H5G_ref_path_iter_t; + char *path; /* Name of the object */ +} H5G_gnba_iter_t; /* Private macros */ @@ -85,9 +79,6 @@ static H5RS_str_t *H5G_build_fullpath_refstr_refstr(const H5RS_str_t *prefix_r, static herr_t H5G_name_move_path(H5RS_str_t **path_r_ptr, const char *full_suffix, const char *src_path, const char *dst_path); static int H5G_name_replace_cb(void *obj_ptr, hid_t obj_id, void *key); -static herr_t H5G_refname_iterator(hid_t group, const char *name, - const H5L_info_t *link_info, void *_udata); -static herr_t H5G_free_ref_path_node(void *item, void *key, void *operator_data/*in,out*/); /*------------------------------------------------------------------------- @@ -468,7 +459,7 @@ H5G_get_name(hid_t id, char *name/*out*/, size_t size, hid_t lapl_id, HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve file ID") /* Search for name of object */ - if((len = H5G_get_refobj_name(file, lapl_id, dxpl_id, loc.oloc, name, size)) < 0) { + if((len = H5G_get_name_by_addr(file, lapl_id, dxpl_id, loc.oloc, name, size)) < 0) { H5I_dec_ref(file); HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't determine name") } /* end if */ @@ -1039,222 +1030,139 @@ done: /*------------------------------------------------------------------------- - * Function: H5G_refname_iterator + * Function: H5G_get_name_by_addr_cb * - * Purpose: The iterator which traverses all objects in a file looking for - * one that matches the object that is being looked for. + * Purpose: Callback for retrieving object's name by address * - * Return: 1 on success, 0 to continue searching, negative on failure. - * - * Programmer: Leon Arber, Nov 1, 2006. + * Return: Positive if path is for object desired + * 0 if not correct object + * negative on failure. * - * Modifications: - * Quincey Koziol, Nov. 3, 2006 - * Cleaned up code. + * Programmer: Quincey Koziol + * November 4 2007 * *------------------------------------------------------------------------- */ static herr_t -H5G_refname_iterator(hid_t group, const char *name, const H5L_info_t *link_info, +H5G_get_name_by_addr_cb(hid_t gid, const char *path, const H5L_info_t *linfo, void *_udata) { - H5G_ref_path_iter_t *udata = (H5G_ref_path_iter_t*)_udata; - herr_t ret_value = H5_ITER_CONT; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5G_refname_iterator) - - /* We only care about hard links */ - if(link_info->type == H5L_TYPE_HARD) { - H5G_loc_t loc; /* Group location of parent */ - - /* Look up group's location */ - if(H5G_loc(group, &loc) < 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5_ITER_ERROR, "not a location") - - /* Check for finding the object */ - /* (checks against the file in the location as well, to make certain that - * the correct object is found in a mounted file hierarchy) - */ - if(udata->loc->addr == link_info->u.address && udata->loc->file == loc.oloc->file) { - size_t len_needed; /* Length of container string needed */ - - /* Build the object's full name */ - len_needed = HDstrlen(udata->container) + HDstrlen(name) + 2; - if(len_needed > udata->max_container_len) { - void *new_container; /* Pointer to new container */ - - if(NULL == (new_container = H5MM_realloc(udata->container, len_needed))) - HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate path string") - udata->container = new_container; - udata->max_container_len = len_needed; - } /* end if */ - HDstrcat(udata->container, name); + H5G_gnba_iter_t *udata = (H5G_gnba_iter_t *)_udata; /* User data for iteration */ + H5G_loc_t obj_loc; /* Location of object */ + H5G_name_t obj_path; /* Object's group hier. path */ + H5O_loc_t obj_oloc; /* Object's object location */ + hbool_t obj_found = FALSE; /* Object at 'path' found */ + herr_t ret_value = H5_ITER_CONT; /* Return value */ - /* We found a match so we return immediately */ - HGOTO_DONE(H5_ITER_STOP) - } /* end if */ - else { - H5O_info_t oinfo; /* Object information */ - H5O_loc_t tmp_oloc; /* Temporary object location */ + FUNC_ENTER_NOAPI_NOINIT(H5G_get_name_by_addr_cb) - /* Check if we've seen this object before */ - if(H5SL_search(udata->ref_path_table, &link_info->u.address)) - HGOTO_DONE(H5_ITER_CONT) + /* Sanity check */ + HDassert(path); + HDassert(linfo); + HDassert(udata->loc); + HDassert(udata->path == NULL); - /* Go retrieve the object information */ - tmp_oloc.file = loc.oloc->file; - tmp_oloc.addr = link_info->u.address; - if(H5O_get_info(&tmp_oloc, udata->dxpl_id, FALSE, &oinfo) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5_ITER_ERROR, "unable to get object info") + /* Check for hard link with correct address */ + if(linfo->type == H5L_TYPE_HARD && udata->loc->addr == linfo->u.address) { + H5G_loc_t grp_loc; /* Location of group */ - /* If its ref count is > 1, we add it to the list of visited objects */ - if(oinfo.rc > 1) { - haddr_t *new_node; /* New path node for table */ + /* Get group's location */ + if(H5G_loc(gid, &grp_loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5_ITER_ERROR, "bad group location") - /* Allocate new path node */ - if((new_node = H5FL_MALLOC(haddr_t)) == NULL) - HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate path node") + /* Set up opened object location to fill in */ + obj_loc.oloc = &obj_oloc; + obj_loc.path = &obj_path; + H5G_loc_reset(&obj_loc); - /* Set node information */ - *new_node = link_info->u.address; + /* Find the object */ + if(H5G_loc_find(&grp_loc, path, &obj_loc/*out*/, udata->lapl_id, udata->dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5_ITER_ERROR, "object not found") + obj_found = TRUE; - /* Insert into skip list */ - if(H5SL_insert(udata->ref_path_table, new_node, new_node) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, H5_ITER_ERROR, "can't insert path node into table") - } /* end if */ + /* Check for object in same file (handles mounted files) */ + /* (re-verify address, in case we traversed a file mount) */ + if(udata->loc->addr == obj_loc.oloc->addr && udata->loc->file == obj_loc.oloc->file) { + udata->path = H5MM_strdup(path); - /* If it's a group, we recurse into it */ - if(oinfo.type == H5O_TYPE_GROUP) { - H5G_link_iterate_t lnk_op; /* Link operator */ - hsize_t last_obj; - size_t len_needed; /* Length of container string needed */ - size_t len; - - /* Build full path name of group to recurse into */ - len = HDstrlen(udata->container); - len_needed = len + HDstrlen(name) + 2; - if(len_needed > udata->max_container_len) { - void *new_container; /* Pointer to new container */ - - if(NULL == (new_container = H5MM_realloc(udata->container, len_needed))) - HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate path string") - udata->container = new_container; - udata->max_container_len = len_needed; - } /* end if */ - if(!udata->is_root_group) - HDstrcat(udata->container, name); - else - udata->is_root_group = FALSE; - HDstrcat(udata->container, "/"); - - /* Build iterator operator */ - lnk_op.op_type = H5G_LINK_OP_APP; - lnk_op.u.app_op = H5G_refname_iterator; - - ret_value = H5G_obj_iterate(udata->file, udata->container, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, &last_obj, &lnk_op, udata, udata->lapl_id, udata->dxpl_id); - - /* If we didn't find the object, truncate the name to not include group name anymore */ - if(!ret_value) - udata->container[len] = '\0'; - } /* end if */ - } /* end else */ + /* We found a match so we return immediately */ + HGOTO_DONE(H5_ITER_STOP) + } /* end if */ } /* end if */ + +done: + if(obj_found && H5G_loc_free(&obj_loc) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, H5_ITER_ERROR, "can't free location") -done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5G_refname_iterator() */ +} /* end H5G_get_name_by_addr_cb() */ /*------------------------------------------------------------------------- - * Function: H5G_free_ref_path_node - * - * Purpose: Free the key for a reference path table node - * - * Return: Non-negative on success, negative on failure + * Function: H5G_get_name_by_addr * - * Programmer: Quincey Koziol - * - * Modifications: - * Leon Arber, Oct. 25, 2006. Moved into H5G from h5ls - * tools lib for looking up path to reference. - * - * Quincey Koziol, Nov. 3, 2006 - * Cleaned up code. - * - *------------------------------------------------------------------------- - */ -static herr_t -H5G_free_ref_path_node(void *item, void UNUSED *key, void UNUSED *operator_data/*in,out*/) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_free_ref_path_node) - - H5FL_FREE(haddr_t, item); - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5G_free_ref_path_node() */ - - -/*------------------------------------------------------------------------- - * Function: H5G_get_refobj_name - * - * Purpose: Tries to figure out the path to a reference. + * Purpose: Tries to figure out the path to an object from it's address * * Return: returns size of path name, and copies it into buffer * pointed to by name if that buffer is big enough. * 0 if it cannot find the path * negative on failure. * - * Programmer: Leon Arber, Nov 1, 2006. - * - * Modifications: - * Quincey Koziol, Nov. 3, 2006 - * Cleaned up code. + * Programmer: Quincey Koziol + * November 4 2007 * *------------------------------------------------------------------------- */ ssize_t -H5G_get_refobj_name(hid_t file, hid_t lapl_id, hid_t dxpl_id, const H5O_loc_t *loc, +H5G_get_name_by_addr(hid_t file, hid_t lapl_id, hid_t dxpl_id, const H5O_loc_t *loc, char *name, size_t size) { - H5G_ref_path_iter_t udata; /* User data for iteration */ - H5G_loc_t root_loc; /* Root location */ - H5L_info_t root_info; /* Link info for root group */ + H5G_gnba_iter_t udata; /* User data for iteration */ + H5G_loc_t root_loc; /* Root group's location */ + hbool_t found_obj = FALSE; /* If we found the object */ herr_t status; /* Status from iteration */ ssize_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5G_get_refobj_name, FAIL) + FUNC_ENTER_NOAPI(H5G_get_name_by_addr, FAIL) - /* Construct the link info for the root group */ + /* Construct the link info for the file's root group */ if(H5G_loc(file, &root_loc) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get root group's location") - HDmemset(&root_info, 0, sizeof(root_info)); - root_info.type = H5L_TYPE_HARD; - root_info.u.address = root_loc.oloc->addr; - - /* Set up user data for iterator */ - udata.file = file; - udata.lapl_id = lapl_id; - udata.dxpl_id = dxpl_id; - udata.is_root_group = TRUE; - if(NULL == (udata.container = H5MM_strdup(""))) - HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate root group name") - udata.max_container_len = 1; - udata.loc = loc; - - /* Create skip list to store reference path information */ - if((udata.ref_path_table = H5SL_create(H5SL_TYPE_HADDR, 0.5, (size_t)16)) == NULL) - HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "can't create skip list for path nodes") - - /* Iterate over all the objects in the file */ - if((status = H5G_refname_iterator(file, "/", &root_info, &udata)) < 0) - HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "group iteration failed while looking for object name") - else if(status > 0) { + + /* Check for root group being the object looked for */ + if(root_loc.oloc->addr == loc->addr && root_loc.oloc->file == loc->file) { + udata.path = H5MM_strdup(""); + found_obj = TRUE; + } /* end if */ + else { + /* Set up user data for iterator */ + udata.loc = loc; + udata.lapl_id = lapl_id; + udata.dxpl_id = dxpl_id; + udata.path = NULL; + + /* Visit all the links in the file */ + if((status = H5G_visit(file, "/", H5_INDEX_NAME, H5_ITER_NATIVE, H5G_get_name_by_addr_cb, &udata, lapl_id, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "group traversal failed while looking for object name") + else if(status > 0) + found_obj = TRUE; + } /* end else */ + + /* Check for finding the object */ + if(found_obj) { + size_t full_path_len = HDstrlen(udata.path) + 1; /* Length of path + 1 (for "/") */ + /* Set the length of the full path */ - ret_value = HDstrlen(udata.container); + ret_value = full_path_len; /* If there's a buffer provided, copy into it, up to the limit of its size */ if(name) { - HDstrncpy(name, udata.container, size); + /* Copy the initial path separator */ + HDstrcpy(name, "/"); + + /* Append the rest of the path */ + /* (less one character, for the initial path separator) */ + HDstrncat(name, udata.path, (size - 1)); if((size_t)ret_value >= size) name[size - 1] = '\0'; } /* end if */ @@ -1264,10 +1172,8 @@ H5G_get_refobj_name(hid_t file, hid_t lapl_id, hid_t dxpl_id, const H5O_loc_t *l done: /* Release resources */ - H5MM_xfree(udata.container); - if(udata.ref_path_table) - H5SL_destroy(udata.ref_path_table, H5G_free_ref_path_node, NULL); + H5MM_xfree(udata.path); FUNC_LEAVE_NOAPI(ret_value) -} /* end H5G_get_refobj_name() */ +} /* end H5G_get_name_by_addr() */ diff --git a/src/H5Gnode.c b/src/H5Gnode.c index 6cff5a0..92d5717 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -1431,51 +1431,23 @@ H5G_node_iterate(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t ad if(udata->skip > 0) --udata->skip; else { - const char *name; /* Pointer to link name in heap */ + H5O_link_t lnk; /* Link for entry */ + const char *name; /* Pointer to link name in heap */ /* Get the pointer to the name of the link in the heap */ name = H5HL_offset_into(f, udata->heap, ents[u].name_off); HDassert(name); - /* Check which type of callback to make */ - switch(udata->lnk_op->op_type) { -#ifndef H5_NO_DEPRECATED_SYMBOLS - case H5G_LINK_OP_OLD: - /* Make the old-type application callback */ - ret_value = (udata->lnk_op->u.old_op)(udata->group_id, name, udata->op_data); - break; -#endif /* H5_NO_DEPRECATED_SYMBOLS */ - - case H5G_LINK_OP_APP: - { - H5L_info_t info; /* Link info for entry */ - - /* Make a link info for an entry */ - if(H5G_ent_to_info(f, &info, udata->heap, &ents[u]) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for symbol table entry") - - /* Make the application callback */ - ret_value = (udata->lnk_op->u.app_op)(udata->group_id, name, &info, udata->op_data); - } - break; - - case H5G_LINK_OP_LIB: - /* Call the library's callback */ - { - H5O_link_t lnk; /* Link for entry */ - - /* Convert the entry to a link */ - if(H5G_ent_to_link(f, &lnk, udata->heap, &ents[u], name) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTCONVERT, H5_ITER_ERROR, "unable to convert symbol table entry to link") - - /* Call the library's callback */ - ret_value = (udata->lnk_op->u.lib_op)(&lnk, udata->op_data); - - /* Release memory for link object */ - if(H5O_msg_reset(H5O_LINK_ID, &lnk) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, H5_ITER_ERROR, "unable to release link message") - } - } /* end switch */ + /* Convert the entry to a link */ + if(H5G_ent_to_link(f, &lnk, udata->heap, &ents[u], name) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCONVERT, H5_ITER_ERROR, "unable to convert symbol table entry to link") + + /* Make the callback */ + ret_value = (udata->op)(&lnk, udata->op_data); + + /* Release memory for link object */ + if(H5O_msg_reset(H5O_LINK_ID, &lnk) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, H5_ITER_ERROR, "unable to release link message") } /* end else */ /* Increment the number of entries passed through */ diff --git a/src/H5Gobj.c b/src/H5Gobj.c index 00bac73..af8f6df 100644 --- a/src/H5Gobj.c +++ b/src/H5Gobj.c @@ -533,7 +533,6 @@ H5G_obj_insert(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *obj_lnk, H5O_linfo_t new_linfo = H5G_CRT_LINK_INFO_DEF; /* Link information */ H5O_ginfo_t new_ginfo = H5G_CRT_GROUP_INFO_DEF; /* Group information */ H5G_obj_stab_it_ud1_t udata; /* User data for iteration */ - H5G_link_iterate_t lnk_op; /* Link operator */ /* Convert group to "new format" group, in order to hold the information */ @@ -549,12 +548,8 @@ H5G_obj_insert(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *obj_lnk, udata.grp_oloc = grp_oloc; udata.dxpl_id = dxpl_id; - /* Build iterator operator */ - lnk_op.op_type = H5G_LINK_OP_LIB; - lnk_op.u.lib_op = H5G_obj_stab_to_new_cb; - /* Iterate through all links in "old format" group and insert them into new format */ - if(H5G_stab_iterate(grp_oloc, dxpl_id, H5_ITER_NATIVE, (hsize_t)0, NULL, (hid_t)0, &lnk_op, &udata) < 0) + if(H5G_stab_iterate(grp_oloc, dxpl_id, H5_ITER_NATIVE, (hsize_t)0, NULL, H5G_obj_stab_to_new_cb, &udata) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over old format links") /* Remove the symbol table message from the group */ @@ -636,36 +631,21 @@ done: *------------------------------------------------------------------------- */ herr_t -H5G_obj_iterate(hid_t loc_id, const char *group_name, +H5G_obj_iterate(const H5O_loc_t *grp_oloc, H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, - H5G_link_iterate_t *lnk_op, void *op_data, hid_t lapl_id, hid_t dxpl_id) + H5G_lib_iterate_t op, void *op_data, hid_t dxpl_id) { - H5G_loc_t loc; /* Location of parent for group */ H5O_linfo_t linfo; /* Link info message */ - hid_t gid = -1; /* ID of group to iterate over */ - H5G_t *grp; /* Pointer to group data structure to iterate over */ herr_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5G_obj_iterate, FAIL) /* Sanity check */ - HDassert(group_name); - HDassert(last_lnk); - HDassert(lnk_op && lnk_op->u.lib_op); - - /* - * Open the group on which to operate. We also create a group ID which - * we can pass to the application-defined operator. - */ - if(H5G_loc(loc_id, &loc) < 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") - if(NULL == (grp = H5G_open_name(&loc, group_name, lapl_id, dxpl_id))) - HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group") - if((gid = H5I_register(H5I_GROUP, grp)) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group") + HDassert(grp_oloc); + HDassert(op); /* Attempt to get the link info for this group */ - if(H5G_obj_get_linfo(&(grp->oloc), &linfo, dxpl_id)) { + if(H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) { /* Check for going out of bounds */ if(skip > 0 && (size_t)skip >= linfo.nlinks) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "index out of bound") @@ -679,13 +659,13 @@ H5G_obj_iterate(hid_t loc_id, const char *group_name, if(H5F_addr_defined(linfo.fheap_addr)) { /* Iterate over the links in the group, building a table of the link messages */ - if((ret_value = H5G_dense_iterate(grp->oloc.file, dxpl_id, &linfo, idx_type, order, skip, last_lnk, gid, lnk_op, op_data)) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over links") + if((ret_value = H5G_dense_iterate(grp_oloc->file, dxpl_id, &linfo, idx_type, order, skip, last_lnk, op, op_data)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over dense links") } /* end if */ else { /* Get the object's name from the link messages */ - if((ret_value = H5G_compact_iterate(&(grp->oloc), dxpl_id, &linfo, idx_type, order, skip, last_lnk, gid, lnk_op, op_data)) < 0) - HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over links") + if((ret_value = H5G_compact_iterate(grp_oloc, dxpl_id, &linfo, idx_type, order, skip, last_lnk, op, op_data)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over compact links") } /* end else */ } /* end if */ else { @@ -697,14 +677,11 @@ H5G_obj_iterate(hid_t loc_id, const char *group_name, HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "no creation order index to query") /* Iterate over symbol table */ - if((ret_value = H5G_stab_iterate(&(grp->oloc), dxpl_id, order, skip, last_lnk, gid, lnk_op, op_data)) < 0) + if((ret_value = H5G_stab_iterate(grp_oloc, dxpl_id, order, skip, last_lnk, op, op_data)) < 0) HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over symbol table") } /* end else */ done: - if(gid > 0) - H5I_dec_ref(gid); /*also closes 'grp'*/ - FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_obj_iterate() */ diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h index f5b2582..2d936a9 100644 --- a/src/H5Gpkg.h +++ b/src/H5Gpkg.h @@ -134,18 +134,16 @@ typedef herr_t (*H5G_lib_iterate_t)(const H5O_link_t *lnk, void *op_data); typedef struct { enum { #ifndef H5_NO_DEPRECATED_SYMBOLS - H5G_LINK_OP_OLD, /* Old application callback */ + H5G_LINK_OP_OLD, /* "Old" application callback */ #endif /* H5_NO_DEPRECATED_SYMBOLS */ - H5G_LINK_OP_APP, /* Application callback */ - H5G_LINK_OP_LIB /* Library internal callback */ + H5G_LINK_OP_NEW /* "New" application callback */ } op_type; union { #ifndef H5_NO_DEPRECATED_SYMBOLS - H5G_iterate_t old_op; /* Old application callback for each link */ + H5G_iterate_t op_old; /* "Old" application callback for each link */ #endif /* H5_NO_DEPRECATED_SYMBOLS */ - H5L_iterate_t app_op; /* Application callback for each link */ - H5G_lib_iterate_t lib_op; /* Library internal callback for each link */ - } u; + H5L_iterate_t op_new; /* "New" application callback for each link */ + } op_func; } H5G_link_iterate_t; /* Data structure to hold table of links for a group */ @@ -210,10 +208,9 @@ typedef struct H5G_bt_lkp_t { */ typedef struct H5G_bt_it_it_t { /* downward */ - hid_t group_id; /*group id to pass to iteration operator */ H5HL_t *heap; /*symbol table heap */ hsize_t skip; /*initial entries to skip */ - H5G_link_iterate_t *lnk_op; /*iteration operator */ + H5G_lib_iterate_t op; /*iteration operator */ void *op_data; /*user-defined operator data */ /* upward */ @@ -342,6 +339,12 @@ H5_DLL H5G_t *H5G_create_named(const H5G_loc_t *loc, const char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id, hid_t dxpl_id); H5_DLL H5G_t *H5G_open_name(const H5G_loc_t *loc, const char *name, hid_t gapl_id, hid_t dxpl_id); +H5_DLL herr_t H5G_iterate(hid_t loc_id, const char *group_name, + H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, + const H5G_link_iterate_t *lnk_op, void *op_data, hid_t lapl_id, hid_t dxpl_id); +H5_DLL herr_t H5G_visit(hid_t loc_id, const char *group_name, + H5_index_t idx_type, H5_iter_order_t order, H5L_iterate_t op, void *op_data, + hid_t lapl_id, hid_t dxpl_id); /* * Group hierarchy traversal routines @@ -374,9 +377,8 @@ H5_DLL herr_t H5G_stab_insert(const H5O_loc_t *grp_oloc, const char *name, H5_DLL herr_t H5G_stab_insert_real(H5F_t *f, H5O_stab_t *stab, const char *name, H5O_link_t *obj_lnk, hid_t dxpl_id); H5_DLL herr_t H5G_stab_delete(H5F_t *f, hid_t dxpl_id, const H5O_stab_t *stab); -H5_DLL herr_t H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, - H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, hid_t gid, - H5G_link_iterate_t *lnk_op, void *op_data); +H5_DLL herr_t H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order, + hsize_t skip, hsize_t *last_lnk, H5G_lib_iterate_t op, void *op_data); H5_DLL herr_t H5G_stab_count(struct H5O_loc_t *oloc, hsize_t *num_objs, hid_t dxpl_id); H5_DLL herr_t H5G_stab_bh_size(H5F_t *f, hid_t dxpl_id, const H5O_stab_t *stab, H5_ih_info_t *bh_info); @@ -444,8 +446,7 @@ H5_DLL herr_t H5G_link_copy_file(H5F_t *dst_file, hid_t dxpl_id, H5_DLL herr_t H5G_link_sort_table(H5G_link_table_t *ltable, H5_index_t idx_type, H5_iter_order_t order); H5_DLL herr_t H5G_link_iterate_table(const H5G_link_table_t *ltable, - hsize_t skip, hsize_t *last_lnk, hid_t gid, const H5G_link_iterate_t *lnk_op, - void *op_data); + hsize_t skip, hsize_t *last_lnk, const H5G_lib_iterate_t op, void *op_data); H5_DLL herr_t H5G_link_release_table(H5G_link_table_t *ltable); H5_DLL herr_t H5G_link_name_replace(H5F_t *file, hid_t dxpl_id, H5RS_str_t *grp_full_path_r, const H5O_link_t *lnk); @@ -461,9 +462,9 @@ H5_DLL herr_t H5G_compact_remove(const H5O_loc_t *oloc, hid_t dxpl_id, H5_DLL herr_t H5G_compact_remove_by_idx(const H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo, H5RS_str_t *grp_full_path_r, H5_index_t idx_type, H5_iter_order_t order, hsize_t n); -H5_DLL herr_t H5G_compact_iterate(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo, - H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, - hid_t gid, H5G_link_iterate_t *lnk_op, void *op_data); +H5_DLL herr_t H5G_compact_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, + const H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order, + hsize_t skip, hsize_t *last_lnk, H5G_lib_iterate_t op, void *op_data); H5_DLL herr_t H5G_compact_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk, hid_t dxpl_id); H5_DLL herr_t H5G_compact_lookup_by_idx(H5O_loc_t *oloc, hid_t dxpl_id, @@ -487,7 +488,7 @@ H5_DLL herr_t H5G_dense_lookup_by_idx(H5F_t *f, hid_t dxpl_id, hsize_t n, H5O_link_t *lnk); H5_DLL herr_t H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, - hid_t gid, const H5G_link_iterate_t *lnk_op, void *op_data); + H5G_lib_iterate_t op, void *op_data); H5_DLL ssize_t H5G_dense_get_name_by_idx(H5F_t *f, hid_t dxpl_id, H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, char *name, size_t size); @@ -510,9 +511,9 @@ H5_DLL H5O_linfo_t * H5G_obj_get_linfo(const H5O_loc_t *grp_oloc, H5O_linfo_t *linfo, hid_t dxpl_id); H5_DLL herr_t H5G_obj_insert(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *obj_lnk, hbool_t adj_link, hid_t dxpl_id); -H5_DLL herr_t H5G_obj_iterate(hid_t loc_id, const char *group_name, - H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_obj, - H5G_link_iterate_t *lnk_op, void *op_data, hid_t lapl_id, hid_t dxpl_id); +H5_DLL herr_t H5G_obj_iterate(const H5O_loc_t *grp_oloc, + H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, + H5G_lib_iterate_t op, void *op_data, hid_t dxpl_id); H5_DLL herr_t H5G_obj_info(H5O_loc_t *oloc, H5G_info_t *grp_info, hid_t dxpl_id); H5_DLL ssize_t H5G_obj_get_name_by_idx(H5O_loc_t *oloc, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, char* name, size_t size, hid_t dxpl_id); diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index 9717b77..0ddb3e9 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -189,7 +189,7 @@ H5_DLL herr_t H5G_name_copy(H5G_name_t *dst, const H5G_name_t *src, H5_copy_dept H5_DLL herr_t H5G_name_free(H5G_name_t *name); H5_DLL ssize_t H5G_get_name(hid_t id, char *name/*out*/, size_t size, hid_t lapl_id, hid_t dxpl_id); -H5_DLL ssize_t H5G_get_refobj_name(hid_t fid, hid_t lapl_id, hid_t dxpl_id, +H5_DLL ssize_t H5G_get_name_by_addr(hid_t fid, hid_t lapl_id, hid_t dxpl_id, const struct H5O_loc_t *loc, char* name, size_t size); /* diff --git a/src/H5Gstab.c b/src/H5Gstab.c index 1887943..61af068 100644 --- a/src/H5Gstab.c +++ b/src/H5Gstab.c @@ -484,8 +484,7 @@ done: */ herr_t H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order, - hsize_t skip, hsize_t *last_lnk, hid_t gid, - H5G_link_iterate_t *lnk_op, void *op_data) + hsize_t skip, hsize_t *last_lnk, H5G_lib_iterate_t op, void *op_data) { H5HL_t *heap = NULL; /* Local heap for group */ H5O_stab_t stab; /* Info about symbol table */ @@ -496,7 +495,7 @@ H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order, /* Sanity check */ HDassert(oloc); - HDassert(lnk_op && lnk_op->u.app_op); + HDassert(op); /* Get the B-tree info */ if(NULL == H5O_msg_read(oloc, H5O_STAB_ID, &stab, dxpl_id)) @@ -512,11 +511,10 @@ H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order, H5G_bt_it_it_t udata; /* User data to pass to B-tree callback */ /* Build udata to pass through H5B_iterate() to H5G_node_iterate() */ - udata.group_id = gid; udata.heap = heap; udata.skip = skip; udata.final_ent = last_lnk; - udata.lnk_op = lnk_op; + udata.op = op; udata.op_data = op_data; /* Iterate over the group members */ @@ -550,7 +548,7 @@ H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order, HGOTO_ERROR(H5E_SYM, H5E_CANTSORT, FAIL, "error sorting link messages") /* Iterate over links in table */ - if((ret_value = H5G_link_iterate_table(<able, skip, last_lnk, gid, lnk_op, op_data)) < 0) + if((ret_value = H5G_link_iterate_table(<able, skip, last_lnk, op, op_data)) < 0) HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed"); } /* end else */ diff --git a/src/H5L.c b/src/H5L.c index 020f7c2..9917fe7 100644 --- a/src/H5L.c +++ b/src/H5L.c @@ -1170,11 +1170,11 @@ H5Literate(hid_t grp_id, H5_index_t idx_type, H5_iter_order_t order, last_lnk = 0; /* Build link operator info */ - lnk_op.op_type = H5G_LINK_OP_APP; - lnk_op.u.app_op = op; + lnk_op.op_type = H5G_LINK_OP_NEW; + lnk_op.op_func.op_new = op; /* Iterate over the links */ - if((ret_value = H5G_obj_iterate(grp_id, ".", idx_type, order, idx, &last_lnk, &lnk_op, op_data, H5P_DEFAULT, H5AC_ind_dxpl_id)) < 0) + if((ret_value = H5G_iterate(grp_id, ".", idx_type, order, idx, &last_lnk, &lnk_op, op_data, H5P_DEFAULT, H5AC_ind_dxpl_id)) < 0) HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "link iteration failed") /* Set the index we stopped at */ @@ -1242,11 +1242,11 @@ H5Literate_by_name(hid_t loc_id, const char *group_name, last_lnk = 0; /* Build link operator info */ - lnk_op.op_type = H5G_LINK_OP_APP; - lnk_op.u.app_op = op; + lnk_op.op_type = H5G_LINK_OP_NEW; + lnk_op.op_func.op_new = op; /* Iterate over the links */ - if((ret_value = H5G_obj_iterate(loc_id, group_name, idx_type, order, idx, &last_lnk, &lnk_op, op_data, lapl_id, H5AC_ind_dxpl_id)) < 0) + if((ret_value = H5G_iterate(loc_id, group_name, idx_type, order, idx, &last_lnk, &lnk_op, op_data, lapl_id, H5AC_ind_dxpl_id)) < 0) HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "link iteration failed") /* Set the index we stopped at */ @@ -1257,6 +1257,66 @@ done: FUNC_LEAVE_API(ret_value) } /* end H5Literate_by_name() */ + +/*------------------------------------------------------------------------- + * Function: H5Lvisit_by_name + * + * Purpose: Recursively visit all the links in a group and all + * the groups that are linked to from that group. Links within + * each group are visited according to the order within the + * specified index (unless the specified index does not exist for + * a particular group, then the "name" index is used). + * + * NOTE: Each _link_ reachable from the initial group will only be + * visited once. However, because an object may be reached from + * more than one link, the visitation may call the application's + * callback with more than one link that points to a particular + * _object_. + * + * 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. + * + * Failure: Negative if something goes wrong within the + * library, or the negative value returned by one + * of the operators. + * + * Programmer: Quincey Koziol + * November 3 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Lvisit_by_name(hid_t loc_id, const char *group_name, H5_index_t idx_type, + H5_iter_order_t order, H5L_iterate_t op, void *op_data, hid_t lapl_id) +{ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_API(H5Lvisit_by_name, FAIL) + + /* Check args */ + if(!group_name || !*group_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified") + if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified") + if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified") + if(!op) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no callback operator specified") + if(H5P_DEFAULT == lapl_id) + lapl_id = H5P_LINK_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID") + + /* Call internal group visitation routine */ + if((ret_value = H5G_visit(loc_id, group_name, idx_type, order, op, op_data, lapl_id, H5AC_ind_dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "link visitation failed") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Lvisit_by_name() */ + /* *------------------------------------------------------------------------- *------------------------------------------------------------------------- diff --git a/src/H5Lpublic.h b/src/H5Lpublic.h index 1645e4b..0dc3f65 100644 --- a/src/H5Lpublic.h +++ b/src/H5Lpublic.h @@ -170,6 +170,9 @@ H5_DLL herr_t H5Literate(hid_t grp_id, H5_index_t idx_type, H5_DLL herr_t H5Literate_by_name(hid_t loc_id, const char *group_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx, H5L_iterate_t op, void *op_data, hid_t lapl_id); +H5_DLL herr_t H5Lvisit_by_name(hid_t loc_id, const char *group_name, + H5_index_t idx_type, H5_iter_order_t order, H5L_iterate_t op, + void *op_data, hid_t lapl_id); /* UD link functions */ H5_DLL herr_t H5Lcreate_ud(hid_t link_loc_id, const char *link_name, diff --git a/src/H5O.c b/src/H5O.c index 94435f5..67aa960 100644 --- a/src/H5O.c +++ b/src/H5O.c @@ -2121,8 +2121,7 @@ H5O_get_info(H5O_loc_t *oloc, hid_t dxpl_id, hbool_t want_ih_info, H5O_info_t *o HDmemset(oinfo, 0, sizeof(*oinfo)); /* Retrieve the file's fileno */ - if(H5F_get_fileno(oloc->file, &oinfo->fileno) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unable to read fileno") + H5F_GET_FILENO(oloc->file, oinfo->fileno); /* Set the object's address */ oinfo->addr = oloc->addr; @@ -2412,3 +2411,48 @@ H5O_get_oh_addr(const H5O_t *oh) FUNC_LEAVE_NOAPI(oh->chunk[0].addr) } /* end H5O_get_oh_addr() */ + +/*------------------------------------------------------------------------- + * Function: H5O_get_rc_and_type + * + * Purpose: Retrieve an object's reference count and type + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * November 4 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_get_rc_and_type(const H5O_loc_t *oloc, hid_t dxpl_id, unsigned *rc, H5O_type_t *otype) +{ + H5O_t *oh = NULL; /* Object header */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_get_rc_and_type, FAIL) + + /* Check args */ + HDassert(oloc); + HDassert(rc); + HDassert(otype); + + /* Get the object header */ + if(NULL == (oh = H5AC_protect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header") + + /* Set the object's reference count */ + *rc = oh->nlink; + + /* Retrieve the type of the object */ + if(H5O_obj_type_real(oh, otype) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type") + +done: + if(oh && H5AC_unprotect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, oh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_get_rc_and_type() */ + diff --git a/src/H5Olinfo.c b/src/H5Olinfo.c index 660b0e1..384353c 100644 --- a/src/H5Olinfo.c +++ b/src/H5Olinfo.c @@ -513,7 +513,6 @@ H5O_linfo_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, /* Check for copying dense link storage */ if(H5F_addr_defined(linfo_src->fheap_addr)) { H5O_linfo_postcopy_ud_t udata; /* User data for iteration callback */ - H5G_link_iterate_t lnk_op; /* Link operator */ /* Set up dense link iteration user data */ udata.src_oloc = src_oloc; @@ -522,12 +521,8 @@ H5O_linfo_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, udata.dxpl_id = dxpl_id; udata.cpy_info = cpy_info; - /* Build iterator operator */ - lnk_op.op_type = H5G_LINK_OP_LIB; - lnk_op.u.lib_op = H5O_linfo_post_copy_file_cb; - /* Iterate over the links in the group, building a table of the link messages */ - if(H5G_dense_iterate(src_oloc->file, dxpl_id, linfo_src, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, NULL, (hid_t)0, &lnk_op, &udata) < 0) + if(H5G_dense_iterate(src_oloc->file, dxpl_id, linfo_src, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, NULL, H5O_linfo_post_copy_file_cb, &udata) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over links") } /* end if */ diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 31738a9..ce7aba0 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -553,6 +553,7 @@ H5_DLL hid_t H5O_open_name(H5G_loc_t *loc, const char *name, hid_t lapl_id); H5_DLL herr_t H5O_get_nlinks(const H5O_loc_t *loc, hid_t dxpl_id, hsize_t *nlinks); H5_DLL void *H5O_obj_create(H5F_t *f, H5O_type_t obj_type, void *crt_info, H5G_loc_t *obj_loc, hid_t dxpl_id); H5_DLL haddr_t H5O_get_oh_addr(const H5O_t *oh); +H5_DLL herr_t H5O_get_rc_and_type(const H5O_loc_t *oloc, hid_t dxpl_id, unsigned *rc, H5O_type_t *otype); /* Object header message routines */ H5_DLL herr_t H5O_msg_create(const H5O_loc_t *loc, unsigned type_id, unsigned mesg_flags, diff --git a/src/H5R.c b/src/H5R.c index 627626b..ae8720e 100644 --- a/src/H5R.c +++ b/src/H5R.c @@ -885,7 +885,7 @@ H5R_get_name(H5F_t *f, hid_t lapl_id, hid_t dxpl_id, hid_t id, H5R_type_t ref_ty HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't retrieve file ID") /* Get name, length, etc. */ - if((ret_value = H5G_get_refobj_name(file_id, lapl_id, dxpl_id, &oloc, name, size)) < 0) + if((ret_value = H5G_get_name_by_addr(file_id, lapl_id, dxpl_id, &oloc, name, size)) < 0) HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't determine name") done: diff --git a/src/H5SL.c b/src/H5SL.c index 53c0f2d..94f0d23 100644 --- a/src/H5SL.c +++ b/src/H5SL.c @@ -99,19 +99,27 @@ /* Define a code template for comparing scalar keys for the "CMP" in the H5SL_LOCATE macro */ #define H5SL_LOCATE_SCALAR_CMP(TYPE,PKEY1,PKEY2) \ - (*(TYPE *)PKEY1<*(TYPE *)PKEY2) + (*(TYPE *)PKEY1 < *(TYPE *)PKEY2) /* Define a code template for comparing string keys for the "CMP" in the H5SL_LOCATE macro */ #define H5SL_LOCATE_STRING_CMP(TYPE,PKEY1,PKEY2) \ - (HDstrcmp(PKEY1,PKEY2)<0) + (HDstrcmp(PKEY1, PKEY2) < 0) + +/* Define a code template for comparing H5_obj_t keys for the "CMP" in the H5SL_LOCATE macro */ +#define H5SL_LOCATE_OBJ_CMP(TYPE,PKEY1,PKEY2) \ + ((((TYPE *)PKEY1)->fileno < ((TYPE *)PKEY2)->fileno) ? TRUE : (((TYPE *)PKEY1)->addr < ((TYPE *)PKEY2)->addr)) /* Define a code template for comparing scalar keys for the "EQ" in the H5SL_LOCATE macro */ #define H5SL_LOCATE_SCALAR_EQ(TYPE,PKEY1,PKEY2) \ - (*(TYPE *)PKEY1==*(TYPE *)PKEY2) + (*(TYPE *)PKEY1 == *(TYPE *)PKEY2) /* Define a code template for comparing string keys for the "EQ" in the H5SL_LOCATE macro */ #define H5SL_LOCATE_STRING_EQ(TYPE,PKEY1,PKEY2) \ - (HDstrcmp(PKEY1,PKEY2)==0) + (HDstrcmp(PKEY1, PKEY2) == 0) + +/* Define a code template for comparing H5_obj_ keys for the "EQ" in the H5SL_LOCATE macro */ +#define H5SL_LOCATE_OBJ_EQ(TYPE,PKEY1,PKEY2) \ + ((((TYPE *)PKEY1)->fileno == ((TYPE *)PKEY2)->fileno) && (((TYPE *)PKEY1)->addr == ((TYPE *)PKEY2)->addr)) /* Macro used to find node for operation */ #define H5SL_LOCATE(OP,DOUPDATE,CMP,SLIST,X,UPDATE,I,TYPE,KEY,CHECKED) \ @@ -378,6 +386,10 @@ H5SL_insert_common(H5SL_t *slist, void *item, const void *key) case H5SL_TYPE_SIZE: H5SL_INSERT(SCALAR, slist, x, update, i, const size_t, key, checked) break; + + case H5SL_TYPE_OBJ: + H5SL_INSERT(OBJ, slist, x, update, i, const H5_obj_t, key, checked) + break; } /* end switch */ /* 'key' must not have been found in existing list, if we get here */ @@ -571,7 +583,7 @@ H5SL_create(H5SL_type_t type, double p, size_t max_level) /* Check args */ HDassert(p>0.0 && p<1.0); HDassert(max_level>0 && max_level<=H5SL_LEVEL_MAX); - HDassert(type>=H5SL_TYPE_INT && type<=H5SL_TYPE_SIZE); + HDassert(type>=H5SL_TYPE_INT && type<=H5SL_TYPE_OBJ); /* Allocate skip list structure */ if((new_slist=H5FL_MALLOC(H5SL_t))==NULL) @@ -808,6 +820,10 @@ H5SL_remove(H5SL_t *slist, const void *key) case H5SL_TYPE_SIZE: H5SL_REMOVE(SCALAR, slist, x, update, i, const size_t, key, checked) break; + + case H5SL_TYPE_OBJ: + H5SL_REMOVE(OBJ, slist, x, update, i, const H5_obj_t, key, checked) + break; } /* end switch */ done: @@ -955,6 +971,10 @@ H5SL_search(H5SL_t *slist, const void *key) case H5SL_TYPE_SIZE: H5SL_SEARCH(SCALAR, slist, x, -, i, const size_t, key, checked) break; + + case H5SL_TYPE_OBJ: + H5SL_SEARCH(OBJ, slist, x, -, i, const H5_obj_t, key, checked) + break; } /* end switch */ /* 'key' must not have been found in list, if we get here */ @@ -1034,6 +1054,10 @@ H5SL_less(H5SL_t *slist, const void *key) case H5SL_TYPE_SIZE: H5SL_SEARCH(SCALAR, slist, x, -, i, const size_t, key, checked) break; + + case H5SL_TYPE_OBJ: + H5SL_SEARCH(OBJ, slist, x, -, i, const H5_obj_t, key, checked) + break; } /* end switch */ /* An exact match for 'key' must not have been found in list, if we get here */ @@ -1126,6 +1150,10 @@ H5SL_greater(H5SL_t *slist, const void *key) case H5SL_TYPE_SIZE: H5SL_SEARCH(SCALAR, slist, x, -, i, const size_t, key, checked) break; + + case H5SL_TYPE_OBJ: + H5SL_SEARCH(OBJ, slist, x, -, i, const H5_obj_t, key, checked) + break; } /* end switch */ /* An exact match for 'key' must not have been found in list, if we get here */ @@ -1208,6 +1236,10 @@ H5SL_find(H5SL_t *slist, const void *key) case H5SL_TYPE_SIZE: H5SL_FIND(SCALAR, slist, x, -, i, const size_t, key, checked) break; + + case H5SL_TYPE_OBJ: + H5SL_FIND(OBJ, slist, x, -, i, const H5_obj_t, key, checked) + break; } /* end switch */ /* 'key' must not have been found in list, if we get here */ diff --git a/src/H5SLprivate.h b/src/H5SLprivate.h index 98c1b84..9f73893 100644 --- a/src/H5SLprivate.h +++ b/src/H5SLprivate.h @@ -46,7 +46,8 @@ typedef enum { H5SL_TYPE_STR, /* Skip list keys are 'char *'s (ie. strings) */ H5SL_TYPE_HSIZE, /* Skip list keys are 'hsize_t's */ H5SL_TYPE_UNSIGNED, /* Skip list keys are 'unsigned's */ - H5SL_TYPE_SIZE /* Skip list keys are 'size_t's */ + H5SL_TYPE_SIZE, /* Skip list keys are 'size_t's */ + H5SL_TYPE_OBJ /* Skip list keys are 'H5_obj_t's */ } H5SL_type_t; /**********/ diff --git a/src/H5private.h b/src/H5private.h index dad4e13..3ac4da3 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -485,6 +485,12 @@ typedef enum { H5_COPY_DEEP /* Deep copy from source to destination, including duplicating fields pointed to */ } H5_copy_depth_t; +/* Unique object "position" */ +typedef struct { + unsigned long fileno; /* The unique identifier for the file of the object */ + haddr_t addr; /* The unique address of the object's header in that file */ +} H5_obj_t; + /* * Redefine all the POSIX functions. We should never see a POSIX * function (or any other non-HDF5 function) in the source! diff --git a/test/getname.c b/test/getname.c index 685bfbf..22abb79 100644 --- a/test/getname.c +++ b/test/getname.c @@ -65,11 +65,11 @@ check_name(hid_t id, const char *chk_name, const char *chk_user_path) /* Get name */ *name = '\0'; - if(H5Iget_name(id, name, NAME_BUF_SIZE) < 0) goto error; + if(H5Iget_name(id, name, NAME_BUF_SIZE) < 0) TEST_ERROR /* Get user path */ *user_path = '\0'; - if(H5G_user_path_test(id, user_path, &user_path_len, &user_path_hidden) < 0) goto error; + if(H5G_user_path_test(id, user_path, &user_path_len, &user_path_hidden) < 0) TEST_ERROR /* Check on name from H5Iget_name() */ if(HDstrcmp(name, chk_name)) goto error; @@ -78,7 +78,7 @@ check_name(hid_t id, const char *chk_name, const char *chk_user_path) if(HDstrcmp(user_path, chk_user_path)) goto error; /* Check that if user path is hidden, the name from H5Iget_name() and the user path should be different */ - if(user_path_hidden && !HDstrcmp(chk_name, chk_user_path)) goto error; + if(user_path_hidden && !HDstrcmp(chk_name, chk_user_path)) TEST_ERROR /* Everything matches */ return 0; @@ -713,10 +713,10 @@ test_main(hid_t file_id, hid_t fapl) PASSED(); -/*------------------------------------------------------------------------- - * Test H5Iget_name with H5Fmount; long name - *------------------------------------------------------------------------- - */ + /*------------------------------------------------------------------------- + * Test H5Iget_name with H5Fmount; long name + *------------------------------------------------------------------------- + */ TESTING("H5Iget_name with H5Fmount; long name"); @@ -726,9 +726,9 @@ test_main(hid_t file_id, hid_t fapl) if((group3_id = H5Gcreate2(file_id, "/g13/g1/g2", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR /* Close */ - H5Gclose(group_id); - H5Gclose(group2_id); - H5Gclose(group3_id); + if(H5Gclose(group_id) < 0) FAIL_STACK_ERROR + if(H5Gclose(group2_id) < 0) FAIL_STACK_ERROR + if(H5Gclose(group3_id) < 0) FAIL_STACK_ERROR /* Create second file and group "g" in it */ file1_id = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl); @@ -1144,6 +1144,7 @@ test_main(hid_t file_id, hid_t fapl) char name2[SMALL_NAME_BUF_SIZE]; /* Get name */ + *name2 = '\0'; name_len=H5Iget_name(group_id, name2, SMALL_NAME_BUF_SIZE); /* Check that name is longer */ @@ -1182,6 +1183,7 @@ test_main(hid_t file_id, hid_t fapl) if(!name3) TEST_ERROR /* Get name with dynamic buffer */ + *name3 = '\0'; if(H5Iget_name(group_id, name3, name_len + 1) < 0) TEST_ERROR /* Verify */ @@ -1189,6 +1191,7 @@ test_main(hid_t file_id, hid_t fapl) *name3 = '\0'; /* Get name with smaller buffer */ + *name3 = '\0'; if(H5Iget_name(group_id, name3, 3) < 0) TEST_ERROR /* Verify */ @@ -2513,80 +2516,96 @@ test_obj_ref(hid_t fapl) TESTING("getting path to normal dataset in root group"); if((dataset2 = H5Rdereference(dataset, H5R_OBJECT, &wbuf[0])) < 0) FAIL_STACK_ERROR - i = H5Iget_name(dataset2,(char*)buf, sizeof(buf)); + *buf = '\0'; + i = H5Iget_name(dataset2, (char*)buf, sizeof(buf)); if(H5Dclose(dataset2) < 0) FAIL_STACK_ERROR if(!((HDstrcmp(buf, "/Dataset3") == 0) &&(i == 9))) TEST_ERROR - i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[0],(char*)buf, sizeof(buf)); + *buf = '\0'; + i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[0], (char*)buf, sizeof(buf)); if(!((HDstrcmp(buf, "/Dataset3") == 0) &&(i == 9))) TEST_ERROR PASSED() HDmemset(buf, 0, sizeof(buf)); TESTING("getting path to dataset in /Group1"); if((dataset2 = H5Rdereference(dataset, H5R_OBJECT, &wbuf[1])) < 0) FAIL_STACK_ERROR - i = H5Iget_name(dataset2,(char*)buf, sizeof(buf)); + *buf = '\0'; + i = H5Iget_name(dataset2, (char*)buf, sizeof(buf)); if(H5Dclose(dataset2) < 0) FAIL_STACK_ERROR if(!((HDstrcmp(buf, "/Group1/Dataset2") == 0) &&(i == 16))) TEST_ERROR - i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[1],(char*)buf, sizeof(buf)); + *buf = '\0'; + i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[1], (char*)buf, sizeof(buf)); if(!((HDstrcmp(buf, "/Group1/Dataset2") == 0) &&(i == 16))) TEST_ERROR PASSED() HDmemset(buf, 0, sizeof(buf)); TESTING("getting path to /Group1"); if((group = H5Rdereference(dataset, H5R_OBJECT, &wbuf[2])) < 0) FAIL_STACK_ERROR - i = H5Iget_name(group,(char*)buf, sizeof(buf)); + *buf = '\0'; + i = H5Iget_name(group, (char*)buf, sizeof(buf)); if(H5Gclose(group) < 0) FAIL_STACK_ERROR if(!((HDstrcmp(buf, "/Group1") == 0) &&(i == 7))) TEST_ERROR - i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[2],(char*)buf, sizeof(buf)); + *buf = '\0'; + i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[2], (char*)buf, sizeof(buf)); if(!((HDstrcmp(buf, "/Group1") == 0) &&(i == 7))) TEST_ERROR PASSED() HDmemset(buf, 0, sizeof(buf)); TESTING("getting path to datatype in /Group1"); if((tid1 = H5Rdereference(dataset, H5R_OBJECT, &wbuf[3])) < 0) FAIL_STACK_ERROR - i = H5Iget_name(tid1,(char*)buf, sizeof(buf)); + *buf = '\0'; + i = H5Iget_name(tid1, (char*)buf, sizeof(buf)); if(H5Tclose(tid1) < 0) FAIL_STACK_ERROR if(!((HDstrcmp(buf, "/Group1/Datatype1") == 0) &&(i == 17))) TEST_ERROR - i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[3],(char*)buf, sizeof(buf)); + *buf = '\0'; + i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[3], (char*)buf, sizeof(buf)); if(!((HDstrcmp(buf, "/Group1/Datatype1") == 0) &&(i == 17))) TEST_ERROR PASSED() HDmemset(buf, 0, sizeof(buf)); TESTING("getting path to dataset in nested group"); if((dataset2 = H5Rdereference(dataset, H5R_OBJECT, &wbuf[4])) < 0) FAIL_STACK_ERROR - i = H5Iget_name(dataset2,(char*)buf, sizeof(buf)); + *buf = '\0'; + i = H5Iget_name(dataset2, (char*)buf, sizeof(buf)); if(H5Dclose(dataset2) < 0) FAIL_STACK_ERROR if(!((HDstrcmp(buf, "/Group1/Group2/Dataset4") == 0) &&(i == 23))) TEST_ERROR - i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[4],(char*)buf, sizeof(buf)); + *buf = '\0'; + i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[4], (char*)buf, sizeof(buf)); if(!((HDstrcmp(buf, "/Group1/Group2/Dataset4") == 0) &&(i == 23))) TEST_ERROR PASSED() HDmemset(buf, 0, sizeof(buf)); TESTING("getting path to nested group"); if((group = H5Rdereference(dataset, H5R_OBJECT, &wbuf[5])) < 0) FAIL_STACK_ERROR - i = H5Iget_name(group,(char*)buf, sizeof(buf)); + *buf = '\0'; + i = H5Iget_name(group, (char*)buf, sizeof(buf)); if(H5Gclose(group) < 0) FAIL_STACK_ERROR if(!((HDstrcmp(buf, "/Group1/Group2") == 0) &&(i == 14))) TEST_ERROR - i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[5],(char*)buf, sizeof(buf)); + *buf = '\0'; + i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[5], (char*)buf, sizeof(buf)); if(!((HDstrcmp(buf, "/Group1/Group2") == 0) &&(i == 14))) TEST_ERROR PASSED() HDmemset(buf, 0, sizeof(buf)); TESTING("getting path to dataset created via hard link"); if((dataset2 = H5Rdereference(dataset, H5R_OBJECT, &wbuf[6])) < 0) FAIL_STACK_ERROR - i = H5Iget_name(dataset2,(char*)buf, sizeof(buf)); + *buf = '\0'; + i = H5Iget_name(dataset2, (char*)buf, sizeof(buf)); if(H5Dclose(dataset2) < 0) FAIL_STACK_ERROR if(!((HDstrcmp(buf, "/Group1/Dataset5") == 0) &&(i == 16))) TEST_ERROR - i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[6],(char*)buf, sizeof(buf)); + *buf = '\0'; + i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[6], (char*)buf, sizeof(buf)); if(!((HDstrcmp(buf, "/Group1/Dataset5") == 0) &&(i == 16))) TEST_ERROR PASSED() HDmemset(buf, 0, sizeof(buf)); TESTING("getting path to root group"); if((group = H5Rdereference(dataset, H5R_OBJECT, &wbuf[7])) < 0) FAIL_STACK_ERROR - i = H5Iget_name(group,(char*)buf, sizeof(buf)); + *buf = '\0'; + i = H5Iget_name(group, (char*)buf, sizeof(buf)); if(H5Gclose(group) < 0) FAIL_STACK_ERROR if(!((HDstrcmp(buf, "/") == 0) &&(i == 1))) TEST_ERROR - i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[7],(char*)buf, sizeof(buf)); + *buf = '\0'; + i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[7], (char*)buf, sizeof(buf)); if(!((HDstrcmp(buf, "/") == 0) &&(i == 1))) TEST_ERROR PASSED() @@ -2596,10 +2615,12 @@ test_obj_ref(hid_t fapl) TESTING("getting path to dataset hidden by a mounted file"); if((dataset2 = H5Rdereference(dataset, H5R_OBJECT, &wbuf[4])) < 0) FAIL_STACK_ERROR + *buf = '\0'; i = H5Iget_name(dataset2, (char*)buf, sizeof(buf)); if(H5Dclose(dataset2) < 0) FAIL_STACK_ERROR if(i != 0) TEST_ERROR - i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[4],(char*)buf, sizeof(buf)); + *buf = '\0'; + i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[4], (char*)buf, sizeof(buf)); if(i != 0) TEST_ERROR PASSED() @@ -2610,10 +2631,12 @@ test_obj_ref(hid_t fapl) FAIL_STACK_ERROR TESTING("getting path to dataset that has been unlinked"); + *buf = '\0'; i = H5Iget_name(dataset2, (char*)buf, sizeof(buf)); if(H5Dclose(dataset2) < 0) FAIL_STACK_ERROR if(i != 0) TEST_ERROR - i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[1],(char*)buf, sizeof(buf)); + *buf = '\0'; + i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[1], (char*)buf, sizeof(buf)); if(i != 0) TEST_ERROR PASSED() @@ -2735,7 +2758,8 @@ test_reg_ref(hid_t fapl) /* Get name of the dataset the first region reference points to using H5Rget_name */ TESTING("H5Rget_name to get name from region reference(hyperslab)"); - name_size1 = H5Rget_name(dsetr_id, H5R_DATASET_REGION, &ref_out[0],(char*)buf1, NAME_BUF_SIZE); + *buf1 = '\0'; + name_size1 = H5Rget_name(dsetr_id, H5R_DATASET_REGION, &ref_out[0], (char*)buf1, NAME_BUF_SIZE); if(!((HDstrcmp(buf1, "/MATRIX") == 0) &&(name_size1 == 7))) TEST_ERROR PASSED() @@ -2745,7 +2769,8 @@ test_reg_ref(hid_t fapl) dsetv_id = H5Rdereference(dsetr_id, H5R_DATASET_REGION, &ref_out[0]); /* Get name of the dataset the first region reference points using H5Iget_name */ - name_size2 = H5Iget_name(dsetv_id,(char*)buf2, NAME_BUF_SIZE); + *buf2 = '\0'; + name_size2 = H5Iget_name(dsetv_id, (char*)buf2, NAME_BUF_SIZE); if(!((HDstrcmp(buf2, "/MATRIX") == 0) &&(name_size2 == 7))) TEST_ERROR if((status = H5Dclose(dsetv_id)) < 0) TEST_ERROR @@ -2754,7 +2779,8 @@ test_reg_ref(hid_t fapl) /* Get name of the dataset the second region reference points to using H5Rget_name */ TESTING("H5Rget_name to get name from region reference(pnt selec)"); - name_size1 = H5Rget_name(dsetr_id, H5R_DATASET_REGION, &ref_out[1],(char*)buf1, NAME_BUF_SIZE); + *buf1 = '\0'; + name_size1 = H5Rget_name(dsetr_id, H5R_DATASET_REGION, &ref_out[1], (char*)buf1, NAME_BUF_SIZE); if(!((HDstrcmp(buf1, "/MATRIX") == 0) &&(name_size1 == 7))) TEST_ERROR PASSED() @@ -2764,7 +2790,8 @@ test_reg_ref(hid_t fapl) if((dsetv_id = H5Rdereference(dsetr_id, H5R_DATASET_REGION, &ref_out[1])) < 0) TEST_ERROR /* Get name of the dataset the first region reference points using H5Iget_name */ - name_size2 = H5Iget_name(dsetv_id,(char*)buf2, NAME_BUF_SIZE); + *buf2 = '\0'; + name_size2 = H5Iget_name(dsetv_id, (char*)buf2, NAME_BUF_SIZE); if(!((HDstrcmp(buf2, "/MATRIX") == 0) &&(name_size2 == 7))) TEST_ERROR if((status = H5Dclose(dsetv_id)) < 0) TEST_ERROR diff --git a/test/mount.c b/test/mount.c index 2ce9a2a..e6aa881 100644 --- a/test/mount.c +++ b/test/mount.c @@ -1170,6 +1170,7 @@ test_mount_after_close(hid_t fapl) if((gidABMX = H5Gopen2(gidAB, "M/X", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR /* Check name */ + *objname = '\0'; if(H5Iget_name(gidABMX, objname, (size_t)NAME_BUF_SIZE) < 0) FAIL_STACK_ERROR if(HDstrcmp(objname, "/A/B/M/X")) TEST_ERROR @@ -1180,6 +1181,7 @@ test_mount_after_close(hid_t fapl) if((gidABC = H5Gopen2(gidAB, "C", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR /* Check name */ + *objname = '\0'; if(H5Iget_name(gidABC, objname, (size_t)NAME_BUF_SIZE) < 0) FAIL_STACK_ERROR if(HDstrcmp(objname, "/A/B/C")) TEST_ERROR @@ -1190,6 +1192,7 @@ test_mount_after_close(hid_t fapl) if((gidABT = H5Gopen2(gidAB, "T", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR /* Check name */ + *objname = '\0'; if(H5Iget_name(gidABT, objname, (size_t)NAME_BUF_SIZE) < 0) FAIL_STACK_ERROR if(HDstrcmp(objname, "/A/B/T")) TEST_ERROR @@ -1200,6 +1203,7 @@ test_mount_after_close(hid_t fapl) if((didABMXYD = H5Dopen2(gidAB, "M/X/Y/D", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR /* Check name */ + *objname = '\0'; if(H5Iget_name(didABMXYD, objname, (size_t)NAME_BUF_SIZE) < 0) FAIL_STACK_ERROR if(HDstrcmp(objname, "/A/B/M/X/Y/D")) TEST_ERROR @@ -1370,6 +1374,7 @@ test_mount_after_unmount(hid_t fapl) TEST_ERROR /* Check name */ + *objname = '\0'; if(H5Iget_name( gidAMXX, objname, (size_t)NAME_BUF_SIZE ) < 0) TEST_ERROR if(HDstrcmp(objname, "/A/M/X/X")) @@ -1389,6 +1394,7 @@ test_mount_after_unmount(hid_t fapl) TEST_ERROR /* Check name */ + *objname = '\0'; if(H5Iget_name( gidAMXMY, objname, (size_t)NAME_BUF_SIZE ) < 0) TEST_ERROR if(HDstrcmp(objname, "/A/M/X/M/Y")) @@ -1435,6 +1441,7 @@ test_mount_after_unmount(hid_t fapl) TEST_ERROR /* Check name */ + *objname = '\0'; if(H5Iget_name( gidBMZ, objname, (size_t)NAME_BUF_SIZE ) < 0) TEST_ERROR if(HDstrcmp(objname, "/B/M/Z")) @@ -2721,6 +2728,7 @@ test_mult_mount(hid_t fapl) TEST_ERROR /* Check name */ + *name = '\0'; if(H5Iget_name(gidAMT, name, (size_t)NAME_BUF_SIZE ) < 0) TEST_ERROR if(HDstrcmp(name, "/A/M/T")) @@ -2738,6 +2746,7 @@ test_mult_mount(hid_t fapl) TEST_ERROR /* Check name */ + *name = '\0'; if(H5Iget_name(gidBS, name, (size_t)NAME_BUF_SIZE ) < 0) TEST_ERROR if(HDstrcmp(name, "/B/S")) @@ -2924,6 +2933,7 @@ test_nested_survive(hid_t fapl) TEST_ERROR /* Check name */ + *name = '\0'; if((name_len = H5Iget_name(gidAM, name, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR if(name_len == 0 || HDstrcmp(name, "/A/M")) @@ -2934,9 +2944,10 @@ test_nested_survive(hid_t fapl) TEST_ERROR /* Check name */ + *name = '\0'; if((name_len = H5Iget_name(gidAM, name, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR - if(name_len == 0 || HDstrcmp(name, "/M")) + if(name_len != 0 || HDstrcmp(name, "")) TEST_ERROR /* Open object in file #3 through file #1 mount path (should fail) */ @@ -2951,6 +2962,7 @@ test_nested_survive(hid_t fapl) TEST_ERROR /* Check name */ + *name = '\0'; if(H5Iget_name(gidMS, name, (size_t)NAME_BUF_SIZE ) < 0) TEST_ERROR if(HDstrcmp(name, "/M/S")) @@ -2969,6 +2981,7 @@ test_nested_survive(hid_t fapl) TEST_ERROR /* Check name */ + *name = '\0'; if(H5Iget_name(gidAMS, name, (size_t)NAME_BUF_SIZE ) < 0) TEST_ERROR if(HDstrcmp(name, "/A/M/S")) @@ -3122,6 +3135,7 @@ test_close_parent(hid_t fapl) TEST_ERROR /* Check the name of "M" is still defined */ + *name = '\0'; if((name_len = H5Iget_name(gidM, name, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR if(name_len == 0 || HDstrcmp(name, "/A/M")) @@ -3132,6 +3146,7 @@ test_close_parent(hid_t fapl) TEST_ERROR /* Check the name of "M" is defined in its file */ + *name = '\0'; if((name_len = H5Iget_name(gidM, name, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR if(name_len == 0 || HDstrcmp(name, "/M")) @@ -3407,6 +3422,7 @@ test_cut_graph(hid_t fapl) TEST_ERROR /* Check name */ + *name = '\0'; if((name_len = H5Iget_name(gidM, name, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR if(name_len == 0 || HDstrcmp(name, "/A/E/M")) @@ -3417,6 +3433,7 @@ test_cut_graph(hid_t fapl) TEST_ERROR /* Check name */ + *name = '\0'; if((name_len = H5Iget_name(gidQ, name, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR if(name_len == 0 || HDstrcmp(name, "/B/I/Q")) @@ -3477,6 +3494,7 @@ test_cut_graph(hid_t fapl) TEST_ERROR /* Check the name of "K" is correct */ + *name = '\0'; if((name_len = H5Iget_name(gidK, name, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR if(name_len == 0 || HDstrcmp(name, "/D/K")) @@ -3497,6 +3515,7 @@ test_cut_graph(hid_t fapl) TEST_ERROR /* Check the name of "O" is correct */ + *name = '\0'; if((name_len = H5Iget_name(gidO, name, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR if(name_len == 0 || HDstrcmp(name, "/B/H/O")) @@ -3506,12 +3525,14 @@ test_cut_graph(hid_t fapl) TEST_ERROR /* Check the name of "M" is defined in its file */ + *name = '\0'; if((name_len = H5Iget_name(gidM, name, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR if(name_len == 0 || HDstrcmp(name, "/E/M")) TEST_ERROR /* Check the name of "Q" is still defined */ + *name = '\0'; if((name_len = H5Iget_name(gidQ, name, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR if(name_len == 0 || HDstrcmp(name, "/B/I/Q")) @@ -3539,6 +3560,7 @@ test_cut_graph(hid_t fapl) TEST_ERROR /* Check the name of "Q" is defined in its file */ + *name = '\0'; if((name_len = H5Iget_name(gidQ, name, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR if(name_len == 0 || HDstrcmp(name, "/I/Q")) @@ -3549,6 +3571,7 @@ test_cut_graph(hid_t fapl) TEST_ERROR /* Check the name of "O" is correct */ + *name = '\0'; if((name_len = H5Iget_name(gidO, name, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR if(name_len == 0 || HDstrcmp(name, "/H/O")) @@ -3719,6 +3742,7 @@ test_symlink(hid_t fapl) TEST_ERROR /* Check the name of "L" is correct */ + *name = '\0'; if((name_len = H5Iget_name(gidL, name, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR if(name_len == 0 || HDstrcmp(name, "/L")) diff --git a/tools/h5copy/h5copy.c b/tools/h5copy/h5copy.c index cadb0d0..216b2bb 100644 --- a/tools/h5copy/h5copy.c +++ b/tools/h5copy/h5copy.c @@ -199,8 +199,8 @@ main (int argc, const char *argv[]) unsigned flag=0; unsigned verbose=0; unsigned parents=0; - hid_t ocpl_id; /* Object copy property list */ - hid_t lcpl_id; /* Link creation property list */ + hid_t ocpl_id = (-1); /* Object copy property list */ + hid_t lcpl_id = (-1); /* Link creation property list */ char str_flag[20]; int opt; diff --git a/tools/h5dump/h5dump.c b/tools/h5dump/h5dump.c index c69c5d70..28534bf 100644 --- a/tools/h5dump/h5dump.c +++ b/tools/h5dump/h5dump.c @@ -3952,7 +3952,7 @@ main(int argc, const char *argv[]) /* allocate and initialize internal data structure */ init_prefix(&prefix, prefix_len); - /* find all objects that might be targets of a reference */ + /* Prepare to find objects that might be targets of a reference */ fill_ref_path_table(fid); if(doxml) { @@ -4094,7 +4094,6 @@ done: free_table(type_table); HDfree(prefix); - HDfree(info.prefix); HDfree(fname); /* To Do: clean up XML table */ @@ -5342,8 +5341,7 @@ xml_dump_group(hid_t gid, const char *name) if(HDstrcmp(name, "/") == 0) { isRoot = 1; - tmp = HDmalloc(2); - HDstrcpy(tmp, "/"); + tmp = HDstrdup("/"); } else { tmp = HDmalloc(HDstrlen(prefix) + HDstrlen(name) + 2); HDstrcpy(tmp, prefix); @@ -5401,8 +5399,8 @@ xml_dump_group(hid_t gid, const char *name) ptrstr = malloc(100); t_objname = xml_escape_the_name(found_obj->objname); par_name = xml_escape_the_name(par); - xml_name_to_XID(par,parentxid,100,1); - xml_name_to_XID(found_obj->objname,ptrstr,100,1); + xml_name_to_XID(found_obj->objname, ptrstr, 100, 1); + xml_name_to_XID(par, parentxid, 100, 1); printf("<%sGroupPtr OBJ-XID=\"%s\" H5Path=\"%s\" " "Parents=\"%s\" H5ParentPaths=\"%s\" />\n", xmlnsprefix, diff --git a/tools/h5ls/h5ls.c b/tools/h5ls/h5ls.c index 2c56cb5..80b45d8 100644 --- a/tools/h5ls/h5ls.c +++ b/tools/h5ls/h5ls.c @@ -27,6 +27,15 @@ #include "H5private.h" #include "h5tools.h" #include "h5tools_utils.h" +#include "h5trav.h" + +#define NAME_BUF_SIZE 2048 + +/* Struct to pass through to visitors */ +typedef struct { + hid_t fid; /* File ID */ + const char *fname; /* Filename */ +}iter_t; /* Command-line switches */ static int verbose_g = 0; /* lots of extra output */ @@ -43,21 +52,7 @@ static hbool_t show_errors_g = FALSE; /* print HDF5 error messages */ static hbool_t simple_output_g = FALSE; /* make output more machine-readable */ static hbool_t show_file_name_g = FALSE; /* show file name for full names */ static hbool_t no_line_wrap_g = FALSE; /* show data content without line wrap */ - -/* Info to pass to the iteration functions */ -typedef struct iter_t { - const char *container; /* full name of the container object */ -} iter_t; - -/* Table containing object id and object name */ -static struct { - int nalloc; /* number of slots allocated */ - int nobjs; /* number of objects */ - struct { - haddr_t id; /* object number */ - char *name; /* full object name */ - } *obj; -} idtab_g; +static hbool_t display_root_g = FALSE; /* show root group in output? */ /* Information about how to display each type of object */ static struct dispatch_t { @@ -68,17 +63,13 @@ static struct dispatch_t { herr_t (*list2)(hid_t obj, const char *name); } dispatch_g[H5O_TYPE_NTYPES]; -#define DISPATCH(TYPE, NAME, OPEN, CLOSE, LIST1, LIST2) { \ +#define DISPATCH(TYPE, NAME, LIST1, LIST2) { \ dispatch_g[TYPE].name = (NAME); \ - dispatch_g[TYPE].open = (OPEN); \ - dispatch_g[TYPE].close = (CLOSE); \ dispatch_g[TYPE].list1 = (LIST1); \ dispatch_g[TYPE].list2 = (LIST2); \ } -static herr_t list(hid_t group, const char *name, const H5L_info_t *linfo, void *cd); static void display_type(hid_t type, int ind); -static char *fix_name(const char *path, const char *base); const char *progname="h5ls"; int d_status; @@ -131,76 +122,6 @@ usage: %s [OPTIONS] [OBJECTS...]\n\ /*------------------------------------------------------------------------- - * Function: sym_insert - * - * Purpose: Add a symbol to the table. - * - * Return: void - * - * Programmer: Robb Matzke - * Thursday, January 21, 1999 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static void -sym_insert(const H5O_info_t *oi, const char *name) -{ - int n; - - /* Don't add it if the link count is 1 because such an object can only - * have one name. */ - if(oi->rc < 2) - return; - - /* Extend the table */ - if(idtab_g.nobjs >= idtab_g.nalloc) { - idtab_g.nalloc = MAX(256, 2*idtab_g.nalloc); - idtab_g.obj = realloc(idtab_g.obj, idtab_g.nalloc*sizeof(idtab_g.obj[0])); - } /* end if */ - - /* Insert the entry */ - n = idtab_g.nobjs++; - idtab_g.obj[n].id = oi->addr; - idtab_g.obj[n].name = HDstrdup(name); -} - - -/*------------------------------------------------------------------------- - * Function: sym_lookup - * - * Purpose: Find another name for the specified object. - * - * Return: Success: Ptr to another name. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * Thursday, January 21, 1999 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static char * -sym_lookup(const H5O_info_t *oi) -{ - int n; - - /*only one name possible*/ - if(oi->rc < 2) - return NULL; - - for(n = 0; n < idtab_g.nobjs; n++) - if(idtab_g.obj[n].id == oi->addr) - return idtab_g.obj[n].name; - - return NULL; -} - - -/*------------------------------------------------------------------------- * Function: display_string * * Purpose: Print a string value by escaping unusual characters. If @@ -278,6 +199,55 @@ display_string(FILE *stream, const char *s, hbool_t escape_spaces) /*------------------------------------------------------------------------- + * Function: display_obj_name + * + * Purpose: Print an object name and another string. + * + * Return: Success: TRUE + * + * Failure: FALSE, nothing printed + * + * Programmer: Quincey Koziol + * Tuesday, November 6, 2007 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +display_obj_name(FILE *stream, const iter_t *iter, const char *oname, + const char *s) +{ + static char fullname[NAME_BUF_SIZE]; /* Buffer for file and/or object name */ + const char *name = fullname; /* Pointer to buffer for printing */ + int n; + + if(show_file_name_g) + sprintf(fullname, "%s/%s", iter->fname, oname); + else + name = oname; + + /* Print the object name, either full name or base name */ + if(fullname_g) + n = display_string(stream, name, TRUE); + else { + const char *last_sep; /* The location of the last group separator */ + + /* Find the last component of the path name */ + if(NULL == (last_sep = HDstrrchr(name, '/'))) + last_sep = name; + else { + last_sep++; + } /* end else */ + n = display_string(stream, last_sep, TRUE); + } /* end else */ + printf("%*s ", MAX(0, (24 - n)), s); + + return TRUE; +} + + +/*------------------------------------------------------------------------- * Function: display_native_type * * Purpose: Prints the name of a native C data type. @@ -1326,7 +1296,7 @@ list_attr(hid_t obj, const char *attr_name, const H5A_info_t UNUSED *ainfo, void UNUSED *op_data) { hid_t attr, space, type, p_type; - hsize_t size[64], nelmts = 1; + hsize_t size[H5S_MAX_RANK], nelmts = 1; int ndims, i, n; size_t need; hsize_t temp_need; @@ -1460,8 +1430,8 @@ list_attr(hid_t obj, const char *attr_name, const H5A_info_t UNUSED *ainfo, static herr_t dataset_list1(hid_t dset) { - hsize_t cur_size[64]; /* current dataset dimensions */ - hsize_t max_size[64]; /* maximum dataset dimensions */ + hsize_t cur_size[H5S_MAX_RANK]; /* current dataset dimensions */ + hsize_t max_size[H5S_MAX_RANK]; /* maximum dataset dimensions */ hid_t space; /* data space */ int ndims; /* dimensionality */ H5S_class_t space_type; /* type of dataspace */ @@ -1524,7 +1494,6 @@ dataset_list2(hid_t dset, const char UNUSED *name) off_t f_offset; /* offset in external file */ hsize_t f_size; /* bytes used in external file */ hsize_t total, used; /* total size or offset */ - hsize_t chsize[64]; /* chunk size in elements */ int ndims; /* dimensionality */ int n, max_len; /* max extern file name length */ double utilization; /* percent utilization of storage */ @@ -1537,6 +1506,8 @@ dataset_list2(hid_t dset, const char UNUSED *name) /* Print information about chunked storage */ if (H5D_CHUNKED==H5Pget_layout(dcpl)) { + hsize_t chsize[64]; /* chunk size in elements */ + ndims = H5Pget_chunk(dcpl, NELMTS(chsize), chsize/*out*/); printf(" %-10s {", "Chunks:"); total = H5Tget_size(type); @@ -1645,39 +1616,9 @@ dataset_list2(hid_t dset, const char UNUSED *name) /*------------------------------------------------------------------------- - * Function: group_list2 - * - * Purpose: List information about a group which should appear after - * information which is general to all objects. - * - * Return: Success: 0 - * - * Failure: -1 - * - * Programmer: Robb Matzke - * Thursday, January 21, 1999 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -group_list2(hid_t grp, const char *name) -{ - iter_t iter; - - if (recursive_g) { - iter.container = name; - H5Literate(grp, H5_INDEX_NAME, H5_ITER_INC, NULL, list, &iter); - } - return 0; -} - - -/*------------------------------------------------------------------------- * Function: datatype_list2 * - * Purpose: List information about a data type which should appear after + * Purpose: List information about a datatype which should appear after * information which is general to all objects. * * Return: Success: 0 @@ -1704,80 +1645,56 @@ datatype_list2(hid_t type, const char UNUSED *name) /*------------------------------------------------------------------------- - * Function: list + * Function: list_obj * - * Purpose: Prints the group member name. + * Purpose: Prints information about an object * * Return: Success: 0 * * Failure: -1 * - * Programmer: Robb Matzke - * Monday, March 23, 1998 + * Programmer: Quincey Koziol + * Tuesday, November 6, 2007 * - * Modifications: - * Robb Matzke, LLNL, 2003-06-06 - * If simple_output_g (set by `--simple') is turned on then - * the modification time is printed as UTC instead of the - * local timezone. *------------------------------------------------------------------------- */ static herr_t -list(hid_t group, const char *name, const H5L_info_t *linfo, void *_iter) +list_obj(const char *name, const H5O_info_t *oinfo, const char *first_seen, void *_iter) { + H5O_type_t obj_type = oinfo->type; /* Type of the object */ iter_t *iter = (iter_t*)_iter; - char *fullname = NULL; - int n; - /* Print the object name, either full name or base name */ - fullname = fix_name(iter->container, name); - if(fullname_g) - n = display_string(stdout, fullname, TRUE); - else - n = display_string(stdout, name, TRUE); - printf("%*s ", MAX(0, (24 - n)), ""); - - /* Actions on objects */ - if(linfo->type == H5L_TYPE_HARD) { - H5O_info_t oi; - char *s; - hid_t obj; - - /* Get object information */ - if(H5Oget_info_by_name(group, name, &oi, H5P_DEFAULT) < 0) { - puts("**NOT FOUND**"); - return 0; - } else if(oi.type < 0 || oi.type >= H5O_TYPE_NTYPES) { - printf("Unknown type(%d)", (int)oi.type); - oi.type = H5O_TYPE_UNKNOWN; - } - if(oi.type >= 0 && dispatch_g[oi.type].name) - fputs(dispatch_g[oi.type].name, stdout); - - /* If the object has already been printed then just show the object ID - * and return. */ - if((s = sym_lookup(&oi))) { - printf(", same as "); - display_string(stdout, s, TRUE); - printf("\n"); - goto done; - } /* end if */ - else - sym_insert(&oi, fullname); + /* Print the link's name, either full name or base name */ + display_obj_name(stdout, iter, name, ""); + + /* Check object information */ + if(oinfo->type < 0 || oinfo->type >= H5O_TYPE_NTYPES) { + printf("Unknown type(%d)", (int)oinfo->type); + obj_type = H5O_TYPE_UNKNOWN; + } + if(obj_type >= 0 && dispatch_g[obj_type].name) + fputs(dispatch_g[obj_type].name, stdout); + + /* Check if we've seen this object before */ + if(first_seen) { + printf(", same as "); + display_string(stdout, first_seen, TRUE); + printf("\n"); + } /* end if */ + else { + hid_t obj = (-1); /* ID of object opened */ /* Open the object. Not all objects can be opened. If this is the case * then return right away. */ - if(oi.type >= 0 && - (NULL == dispatch_g[oi.type].open || - (obj = (dispatch_g[oi.type].open)(group, name, H5P_DEFAULT)) < 0)) { + if(obj_type >= 0 && (obj = H5Oopen(iter->fid, name, H5P_DEFAULT)) < 0) { printf(" *ERROR*\n"); goto done; } /* end if */ /* List the first line of information for the object. */ - if(oi.type >= 0 && dispatch_g[oi.type].list1) - (dispatch_g[oi.type].list1)(obj); + if(obj_type >= 0 && dispatch_g[obj_type].list1) + (dispatch_g[obj_type].list1)(obj); putchar('\n'); /* Show detailed information about the object, beginning with information @@ -1786,22 +1703,22 @@ list(hid_t group, const char *name, const H5L_info_t *linfo, void *_iter) char comment[50]; /* Display attributes */ - if(oi.type >= 0) + if(obj_type >= 0) H5Aiterate2(obj, H5_INDEX_NAME, H5_ITER_INC, NULL, list_attr, NULL); /* Object location & reference count */ - printf(" %-10s %lu:"H5_PRINTF_HADDR_FMT"\n", "Location:", oi.fileno, oi.addr); - printf(" %-10s %u\n", "Links:", (unsigned)oi.rc); + printf(" %-10s %lu:"H5_PRINTF_HADDR_FMT"\n", "Location:", oinfo->fileno, oinfo->addr); + printf(" %-10s %u\n", "Links:", (unsigned)oinfo->rc); /* Modification time */ - if(oi.mtime > 0) { + if(oinfo->mtime > 0) { char buf[256]; struct tm *tm; if(simple_output_g) - tm = HDgmtime(&(oi.mtime)); + tm = HDgmtime(&(oinfo->mtime)); else - tm = HDlocaltime(&(oi.mtime)); + tm = HDlocaltime(&(oinfo->mtime)); if(tm) { HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm); printf(" %-10s %s\n", "Modified:", buf); @@ -1810,7 +1727,7 @@ list(hid_t group, const char *name, const H5L_info_t *linfo, void *_iter) /* Object comment */ comment[0] = '\0'; - H5Oget_comment_by_name(group, name, comment, sizeof(comment), H5P_DEFAULT); + H5Oget_comment(obj, comment, sizeof(comment)); HDstrcpy(comment + sizeof(comment) - 4, "..."); if(comment[0]) { printf(" %-10s \"", "Comment:"); @@ -1820,118 +1737,91 @@ list(hid_t group, const char *name, const H5L_info_t *linfo, void *_iter) } /* end if */ /* Detailed list for object */ - if(oi.type >= 0 && dispatch_g[oi.type].list2) - (dispatch_g[oi.type].list2)(obj, fullname); + if(obj_type >= 0 && dispatch_g[obj_type].list2) + (dispatch_g[obj_type].list2)(obj, name); /* Close the object. */ - if(oi.type >= 0 && dispatch_g[oi.type].close) - (dispatch_g[oi.type].close)(obj); - } /* end if */ - /* Actions on links */ - else { - char *buf; - - HDfputs("-> ", stdout); - switch(linfo->type) { - case H5L_TYPE_SOFT: - if((buf = HDmalloc(linfo->u.val_size)) == NULL) - goto done; - - if(H5Lget_val(group, name, buf, linfo->u.val_size, H5P_DEFAULT) < 0) { - HDfree(buf); - goto done; - } /* end if */ - - HDfputs(buf, stdout); - HDfree(buf); - break; - - case H5L_TYPE_EXTERNAL: - { - const char *filename; - const char *path; - - if((buf = HDmalloc(linfo->u.val_size)) == NULL) - goto done; - - if(H5Lget_val(group, name, buf, linfo->u.val_size, H5P_DEFAULT) < 0) { - HDfree(buf); - goto done; - } /* end if */ - if(H5Lunpack_elink_val(buf, linfo->u.val_size, NULL, &filename, &path) < 0) { - HDfree(buf); - goto done; - } /* end if */ - - HDfputs("file: ", stdout); - HDfputs(filename, stdout); - HDfputs(" path: ", stdout); - HDfputs(path, stdout); - } - break; - - default: - HDfputs("cannot follow UD links", stdout); - break; - } /* end switch */ - HDfputc('\n', stdout); + if(obj_type >= 0) + H5Oclose(obj); } /* end else */ done: - if(fullname) - free(fullname); return 0; -} /* end list() */ +} /* end list_obj() */ /*------------------------------------------------------------------------- - * Function: fix_name + * Function: list_lnk * - * Purpose: Returns a malloc'd buffer that contains the PATH and BASE - * names separated by a single slash. It also removes duplicate - * and trailing slashes. + * Purpose: Prints information about a link * - * Return: Success: Ptr to fixed name from malloc() - * - * Failure: NULL + * Return: Success: 0 * - * Programmer: Robb Matzke - * Thursday, January 21, 1999 + * Failure: -1 * - * Modifications: + * Programmer: Quincey Koziol + * Thursday, November 8, 2007 * *------------------------------------------------------------------------- */ -static char * -fix_name(const char *path, const char *base) +static herr_t +list_lnk(const char *name, const H5L_info_t *linfo, void *_iter) { - size_t n = (path ? HDstrlen(path) : 0) + (base ? HDstrlen(base) : 0) + 3; - char *s = HDmalloc(n), prev='\0'; - size_t len = 0; - - if (path) { - /* Path, followed by slash */ - for (/*void*/; *path; path++) - if ('/'!=*path || '/'!=prev) - prev = s[len++] = *path; - if ('/' != prev) - prev = s[len++] = '/'; - } + char *buf; + iter_t *iter = (iter_t*)_iter; - if (base) { - /* Base name w/o trailing slashes */ - const char *end = base + HDstrlen(base); - while (end > base && '/' == end[-1]) - --end; + /* Print the link's name, either full name or base name */ + display_obj_name(stdout, iter, name, ""); - for (/*void*/; base < end; base++) - if ('/' != *base || '/' != prev) - prev = s[len++] = *base; - } + HDfputs("-> ", stdout); + switch(linfo->type) { + case H5L_TYPE_SOFT: + if((buf = HDmalloc(linfo->u.val_size)) == NULL) + goto done; - s[len] = '\0'; - return s; -} + if(H5Lget_val(iter->fid, name, buf, linfo->u.val_size, H5P_DEFAULT) < 0) { + HDfree(buf); + goto done; + } /* end if */ + + HDfputs(buf, stdout); + HDfree(buf); + break; + + case H5L_TYPE_EXTERNAL: + { + const char *filename; + const char *path; + + if((buf = HDmalloc(linfo->u.val_size)) == NULL) + goto done; + + if(H5Lget_val(iter->fid, name, buf, linfo->u.val_size, H5P_DEFAULT) < 0) { + HDfree(buf); + goto done; + } /* end if */ + if(H5Lunpack_elink_val(buf, linfo->u.val_size, NULL, &filename, &path) < 0) { + HDfree(buf); + goto done; + } /* end if */ + + HDfputs("file: ", stdout); + HDfputs(filename, stdout); + HDfputs(" path: ", stdout); + HDfputs(path, stdout); + HDfree(buf); + } + break; + + default: + HDfputs("cannot follow UD links", stdout); + break; + } /* end switch */ + HDfputc('\n', stdout); + +done: + return 0; +} /* end list_lnk() */ /*------------------------------------------------------------------------- @@ -2059,10 +1949,10 @@ leave(int ret) int main(int argc, const char *argv[]) { - hid_t file = -1, root = -1; + hid_t file = -1; char *fname = NULL, *oname = NULL, *x; const char *s = NULL; - char *rest, *container = NULL; + char *rest; int argno; static char root_name[] = "/"; char drivername[50]; @@ -2072,9 +1962,9 @@ main(int argc, const char *argv[]) h5tools_init(); /* Build object display table */ - DISPATCH(H5O_TYPE_GROUP, "Group", H5Gopen2, H5Gclose, NULL, group_list2); - DISPATCH(H5O_TYPE_DATASET, "Dataset", H5Dopen2, H5Dclose, dataset_list1, dataset_list2); - DISPATCH(H5O_TYPE_NAMED_DATATYPE, "Type", H5Topen2, H5Tclose, NULL, datatype_list2); + DISPATCH(H5O_TYPE_GROUP, "Group", NULL, NULL); + DISPATCH(H5O_TYPE_DATASET, "Dataset", dataset_list1, dataset_list2); + DISPATCH(H5O_TYPE_NAMED_DATATYPE, "Type", NULL, datatype_list2); /* Default output width */ width_g = get_width(); @@ -2230,6 +2120,13 @@ main(int argc, const char *argv[]) leave(1); } /* end if */ + /* Check for conflicting arguments */ + if(recursive_g && grp_literal_g) { + fprintf(stderr, "Error: 'recursive' option not compatible with 'group info' option!\n\n"); + usage(); + leave(1); + } /* end if */ + /* Turn off HDF5's automatic error printing unless you're debugging h5ls */ if(!show_errors_g) H5Eset_auto2(H5E_DEFAULT, NULL, NULL); @@ -2249,7 +2146,6 @@ main(int argc, const char *argv[]) * doesn't exist). */ show_file_name_g = (argc-argno > 1); /*show file names if more than one*/ while(argno < argc) { - H5O_info_t oi; H5L_info_t li; iter_t iter; @@ -2281,24 +2177,21 @@ main(int argc, const char *argv[]) } /* end if */ if(oname) oname++; - if(!oname || !*oname) + if(!oname || !*oname) { oname = root_name; + if(recursive_g) + display_root_g = TRUE; + } /* end if */ + + /* Remember the file information for later */ + iter.fname = fname; + iter.fid = file; /* Check for root group as object name */ if(HDstrcmp(oname, root_name)) { /* Check the type of link given */ if(H5Lget_info(file, oname, &li, H5P_DEFAULT) < 0) { - char *fullname = NULL; - int n; - - fullname = fix_name(oname, "/"); - if(fullname_g) - n = display_string(stdout, fullname, TRUE); - else - n = display_string(stdout, oname, TRUE); - printf("%*s \n", MAX(0, (24 - n)), "**NOT FOUND**"); - - HDfree(fullname); + display_obj_name(stdout, &iter, oname, "**NOT FOUND**"); leave(1); } /* end if */ } /* end if */ @@ -2306,34 +2199,25 @@ main(int argc, const char *argv[]) li.type = H5L_TYPE_HARD; /* Open the object and display it's information */ - if(li.type == H5L_TYPE_HARD && H5Oget_info_by_name(file, oname, &oi, H5P_DEFAULT) >= 0 && H5O_TYPE_GROUP == oi.type && !grp_literal_g) { - /* Specified name is a group. List the complete contents of the group. */ - sym_insert(&oi, oname); - iter.container = container = fix_name((show_file_name_g ? fname : ""), oname); - - /* list root attributes */ - if(verbose_g > 0) { - if((root = H5Gopen2(file, "/", H5P_DEFAULT)) < 0) - leave(1); - H5Aiterate2(root, H5_INDEX_NAME, H5_ITER_INC, NULL, list_attr, NULL); - if(H5Gclose(root) < 0) - leave(1); - } /* end if */ + if(li.type == H5L_TYPE_HARD) { + H5O_info_t oi; /* Information for object */ - /* list */ - H5Literate_by_name(file, oname, H5_INDEX_NAME, H5_ITER_INC, NULL, list, &iter, H5P_DEFAULT); - free(container); - } else if((root = H5Gopen2(file, "/", H5P_DEFAULT)) < 0) { - leave(1); /*major problem!*/ - } else { - /* Specified name is a non-group object -- list that object. The - * container for the object is everything up to the base name. - */ - iter.container = show_file_name_g ? fname : "/"; - list(root, oname, &li, &iter); - if(H5Gclose(root) < 0) + /* Retrieve info for object to list */ + if(H5Oget_info_by_name(file, oname, &oi, H5P_DEFAULT) < 0) { + display_obj_name(stdout, &iter, oname, "**NOT FOUND**"); leave(1); - } + } /* end if */ + + /* Check for group iteration */ + if(H5O_TYPE_GROUP == oi.type && !grp_literal_g) + /* Specified name is a group. List the complete contents of the group. */ + h5trav_visit(file, oname, display_root_g, recursive_g, list_obj, list_lnk, &iter); + else + /* Specified name is a non-group object -- list that object */ + list_obj(oname, &oi, NULL, &iter); + } else + /* Specified name is not for object -- list that link */ + list_lnk(oname, &li, &iter); H5Fclose(file); free(fname); } /* end while */ diff --git a/tools/h5ls/testh5ls.sh b/tools/h5ls/testh5ls.sh index ab36eb4..f25db4e 100755 --- a/tools/h5ls/testh5ls.sh +++ b/tools/h5ls/testh5ls.sh @@ -112,6 +112,7 @@ TOOLTEST tgroup.ls -w80 tgroup.h5 # test for displaying groups TOOLTEST tgroup-1.ls -w80 -r -g tgroup.h5 +TOOLTEST tgroup-2.ls -w80 -g tgroup.h5/g1 # test for displaying simple space datasets TOOLTEST tdset-1.ls -w80 -r -d tdset.h5 diff --git a/tools/h5stat/h5stat.c b/tools/h5stat/h5stat.c index c69d801..f03efd7 100644 --- a/tools/h5stat/h5stat.c +++ b/tools/h5stat/h5stat.c @@ -47,8 +47,7 @@ typedef struct ohdr_info_t { /* Info to pass to the iteration functions */ typedef struct iter_t { - const char *container; /* Full name of the container object */ - unsigned long curr_depth; /* Current depth of hierarchy */ + hid_t fid; /* File ID */ unsigned long uniq_groups; /* Number of unique groups */ unsigned long uniq_dsets; /* Number of unique datasets */ @@ -56,7 +55,6 @@ typedef struct iter_t { unsigned long uniq_links; /* Number of unique links */ unsigned long uniq_others; /* Number of other unique objects */ - unsigned long max_depth; /* Maximum depth of hierarchy */ unsigned long max_links; /* Maximum # of links to an object */ hsize_t max_fanout; /* Maximum fanout from a group */ unsigned long num_small_groups[SIZE_SMALL_GROUPS]; /* Size of small groups tracked */ @@ -95,16 +93,6 @@ typedef struct iter_t { } iter_t; -/* Table containing object id and object name */ -static struct { - int nalloc; /* number of slots allocated */ - int nobjs; /* number of objects */ - struct { - haddr_t id; /* object number */ - char *name; /* full object name */ - } *obj; -} idtab_g; - const char *progname = "h5stat"; int d_status = EXIT_SUCCESS; static int display_all = TRUE; @@ -260,123 +248,6 @@ ceil_log10(unsigned long x) /*------------------------------------------------------------------------- - * Function: sym_insert - * - * Purpose: Add a symbol to the table. - * - * Return: void - * - * Programmer: Robb Matzke - * Thursday, January 21, 1999 - * - *------------------------------------------------------------------------- - */ -static void -sym_insert(H5O_info_t *oi, const char *name) -{ - /* Don't add it if the link count is 1 because such an object can only - * have one name. */ - if(oi->rc > 1) { - int n; - - /* Extend the table */ - if(idtab_g.nobjs >= idtab_g.nalloc) { - idtab_g.nalloc = MAX(256, 2 * idtab_g.nalloc); - idtab_g.obj = realloc(idtab_g.obj, idtab_g.nalloc * sizeof(idtab_g.obj[0])); - } /* end if */ - - /* Insert the entry */ - n = idtab_g.nobjs++; - idtab_g.obj[n].id = oi->addr; - idtab_g.obj[n].name = strdup(name); - } /* end if */ -} /* end sym_insert() */ - - -/*------------------------------------------------------------------------- - * Function: sym_lookup - * - * Purpose: Find another name for the specified object. - * - * Return: Success: Ptr to another name. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * Thursday, January 21, 1999 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static char * -sym_lookup(H5O_info_t *oi) -{ - int n; - - /*only one name possible*/ - if(oi->rc < 2) - return NULL; - - for(n = 0; n < idtab_g.nobjs; n++) - if(idtab_g.obj[n].id == oi->addr) - return idtab_g.obj[n].name; - - return NULL; -} /* end sym_lookup() */ - - -/*------------------------------------------------------------------------- - * Function: fix_name - * - * Purpose: Returns a malloc'd buffer that contains the PATH and BASE - * names separated by a single slash. It also removes duplicate - * and trailing slashes. - * - * Return: Success: Ptr to fixed name from malloc() - * - * Failure: NULL - * - * Programmer: Robb Matzke - * Thursday, January 21, 1999 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static char * -fix_name(const char *path, const char *base) -{ - size_t n = (path ? strlen(path) : 0) + (base ? strlen(base) : 0) + 3; - char *s = malloc(n), prev='\0'; - size_t len = 0; - - if (path) { - /* Path, followed by slash */ - for (/*void*/; *path; path++) - if ('/'!=*path || '/'!=prev) - prev = s[len++] = *path; - if ('/' != prev) - prev = s[len++] = '/'; - } - - if (base) { - /* Base name w/o trailing slashes */ - const char *end = base + strlen(base); - while (end > base && '/' == end[-1]) - --end; - - for (/*void*/; base < end; base++) - if ('/' != *base || '/' != prev) - prev = s[len++] = *base; - } - - s[len] = '\0'; - return s; -} - - -/*------------------------------------------------------------------------- * Function: attribute_stats * * Purpose: Gather statistics about attributes on an object @@ -453,25 +324,21 @@ attribute_stats(iter_t *iter, const H5O_info_t *oi) *------------------------------------------------------------------------- */ static herr_t -group_stats(hid_t group, const char *name, const char *fullname, - const H5O_info_t *oi, H5L_iterate_t walk, iter_t *iter) +group_stats(iter_t *iter, const char *name, const H5O_info_t *oi) { - const char *last_container; H5G_info_t ginfo; /* Group information */ unsigned bin; /* "bin" the number of objects falls in */ herr_t ret; /* Gather statistics about this type of object */ iter->uniq_groups++; - if(iter->curr_depth > iter->max_depth) - iter->max_depth = iter->curr_depth; /* Get object header information */ iter->group_ohdr_info.total_size += oi->hdr.space.total; iter->group_ohdr_info.free_size += oi->hdr.space.free; /* Get group information */ - ret = H5Gget_info_by_name(group, name, &ginfo, H5P_DEFAULT); + ret = H5Gget_info_by_name(iter->fid, name, &ginfo, H5P_DEFAULT); assert(ret >= 0); /* Update link stats */ @@ -506,18 +373,6 @@ group_stats(hid_t group, const char *name, const char *fullname, ret = attribute_stats(iter, oi); assert(ret >= 0); - /* Update current container info */ - last_container = iter->container; - iter->container = fullname; - iter->curr_depth++; - - /* Recursively descend into current group's objects */ - H5Literate_by_name(group, name, H5_INDEX_NAME, H5_ITER_INC, NULL, walk, iter, H5P_DEFAULT); - - /* Revert current container info */ - iter->container = last_container; - iter->curr_depth--; - return 0; } /* end group_stats() */ @@ -549,7 +404,7 @@ group_stats(hid_t group, const char *name, const char *fullname, *------------------------------------------------------------------------- */ static herr_t -dataset_stats(hid_t group, const char *name, const H5O_info_t *oi, iter_t *iter) +dataset_stats(iter_t *iter, const char *name, const H5O_info_t *oi) { unsigned bin; /* "bin" the number of objects falls in */ hid_t did; /* Dataset ID */ @@ -575,7 +430,7 @@ dataset_stats(hid_t group, const char *name, const H5O_info_t *oi, iter_t *iter) iter->dset_ohdr_info.total_size += oi->hdr.space.total; iter->dset_ohdr_info.free_size += oi->hdr.space.free; - did = H5Dopen2(group, name, H5P_DEFAULT); + did = H5Dopen2(iter->fid, name, H5P_DEFAULT); assert(did > 0); /* Update dataset metadata info */ @@ -710,89 +565,90 @@ dataset_stats(hid_t group, const char *name, const H5O_info_t *oi, iter_t *iter) /*------------------------------------------------------------------------- - * Function: walk + * Function: obj_stats * - * Purpose: Gather statistics about the file + * Purpose: Gather statistics about an object * * Return: Success: 0 - * Failure: -1 * - * Programmer: Quincey Koziol - * Tuesday, August 16, 2005 + * Failure: -1 * - * Modifications: + * Programmer: Quincey Koziol + * Tuesday, November 6, 2007 * *------------------------------------------------------------------------- */ static herr_t -walk(hid_t group, const char *name, const H5L_info_t *linfo, void *_iter) +obj_stats(const char *path, const H5O_info_t *oi, const char *already_visited, + void *_iter) { iter_t *iter = (iter_t *)_iter; - char *fullname = NULL; - herr_t ret; /* Generic return value */ - - if(!linfo || linfo->type == H5L_TYPE_HARD) { - H5O_info_t oi; - char *s; - - /* Get object information */ - ret = H5Oget_info_by_name(group, name, &oi, H5P_DEFAULT); - assert(ret >= 0); - - /* If the object has already been printed then just show the object ID - * and return. */ - if((s = sym_lookup(&oi))) { - printf("%s same as %s\n", name, s); - } else { - /* Get the full object name */ - fullname = fix_name(iter->container, name); - sym_insert(&oi, fullname); - - /* Gather some statistics about the object */ - if(oi.rc > iter->max_links) - iter->max_links = oi.rc; - - switch(oi.type) { - case H5O_TYPE_GROUP: - group_stats(group, name, fullname, &oi, walk, iter); - break; - - case H5O_TYPE_DATASET: - dataset_stats(group, name, &oi, iter); - break; - - case H5O_TYPE_NAMED_DATATYPE: - /* Gather statistics about this type of object */ - iter->uniq_types++; - break; - - default: - /* Gather statistics about this type of object */ - iter->uniq_others++; - break; - } /* end switch */ - } - } /* end if */ - else { - switch(linfo->type) { - case H5L_TYPE_SOFT: - case H5L_TYPE_EXTERNAL: - /* Gather statistics about links and UD links */ - iter->uniq_links++; + + /* If the object has already been seen then just return */ + if(NULL == already_visited) { + /* Gather some general statistics about the object */ + if(oi->rc > iter->max_links) + iter->max_links = oi->rc; + + switch(oi->type) { + case H5O_TYPE_GROUP: + group_stats(iter, path, oi); + break; + + case H5O_TYPE_DATASET: + dataset_stats(iter, path, oi); + break; + + case H5O_TYPE_NAMED_DATATYPE: + /* Gather statistics about this type of object */ + iter->uniq_types++; break; default: /* Gather statistics about this type of object */ iter->uniq_others++; break; - } /* end switch() */ - } /* end else */ + } /* end switch */ + } /* end if */ - if(fullname) - free(fullname); + return 0; +} /* end obj_stats() */ + + +/*------------------------------------------------------------------------- + * Function: lnk_stats + * + * Purpose: Gather statistics about a link + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Quincey Koziol + * Tuesday, November 6, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +lnk_stats(const char UNUSED *path, const H5L_info_t *li, void *_iter) +{ + iter_t *iter = (iter_t *)_iter; + + switch(li->type) { + case H5L_TYPE_SOFT: + case H5L_TYPE_EXTERNAL: + /* Gather statistics about links and UD links */ + iter->uniq_links++; + break; + + default: + /* Gather statistics about this type of object */ + iter->uniq_others++; + break; + } /* end switch() */ return 0; -} +} /* end lnk_stats() */ /*------------------------------------------------------------------------- @@ -915,13 +771,13 @@ parse_command_line(int argc, const char *argv[]) *------------------------------------------------------------------------- */ static herr_t -iter_init(iter_t *iter) +iter_init(iter_t *iter, hid_t fid) { /* Clear everything to zeros */ - memset(iter, 0, sizeof(*iter)); + HDmemset(iter, 0, sizeof(*iter)); - /* Initialize non-zero information */ - iter->container = "/"; + /* Set the file ID for later use in callbacks */ + iter->fid = fid; return 0; } @@ -953,7 +809,6 @@ print_file_info(const iter_t *iter) printf("\t# of unique links: %lu\n", iter->uniq_links); printf("\t# of unique other: %lu\n", iter->uniq_others); printf("\tMax. # of links to object: %lu\n", iter->max_links); - printf("\tMax. depth of hierarchy: %lu\n", iter->max_depth); HDfprintf(stdout, "\tMax. # of objects in group: %Hu\n", iter->max_fanout); return 0; @@ -1318,8 +1173,6 @@ main(int argc, const char *argv[]) const char *fname = NULL; hid_t fid; struct handler_t *hand; - char root[] = "/"; - int i; H5F_info_t finfo; @@ -1329,25 +1182,23 @@ main(int argc, const char *argv[]) /* Initialize h5tools lib */ h5tools_init(); hand = parse_command_line (argc, argv); - if (!hand) { + if(!hand) { error_msg(progname, "unable to parse command line arguments \n"); leave(EXIT_FAILURE); - } + } /* end if */ fname = argv[opt_ind]; - if(!display_object) - hand[0].obj = root; printf("Filename: %s\n", fname); fid = H5Fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT); - if (fid < 0) { + if(fid < 0) { error_msg(progname, "unable to open file \"%s\"\n", fname); leave(EXIT_FAILURE); - } + } /* end if */ /* Initialize iter structure */ - iter_init(&iter); + iter_init(&iter, fid); /* Get storge info for SOHM's btree/list/heap and superblock extension */ if(H5Fget_info(fid, &finfo) < 0) @@ -1357,15 +1208,23 @@ main(int argc, const char *argv[]) iter.SM_hdr_storage_size = finfo.sohm.hdr_size; iter.SM_index_storage_size = finfo.sohm.msgs_info.index_size; iter.SM_heap_storage_size = finfo.sohm.msgs_info.heap_size; - } + } /* end else */ /* Walk the objects or all file */ - i = 0; - while(hand[i].obj) { - walk(fid, hand[i].obj, NULL, &iter); - print_statistics(hand[i].obj, &iter); - i++; - } /* end while */ + if(display_object) { + unsigned u; + + u = 0; + while(hand[u].obj) { + h5trav_visit(fid, hand[u].obj, TRUE, TRUE, obj_stats, lnk_stats, &iter); + print_statistics(hand[u].obj, &iter); + u++; + } /* end while */ + } /* end if */ + else { + h5trav_visit(fid, "/", TRUE, TRUE, obj_stats, lnk_stats, &iter); + print_statistics("/", &iter); + } /* end else */ free(hand); diff --git a/tools/h5stat/testfiles/h5stat_filters-file.ddl b/tools/h5stat/testfiles/h5stat_filters-file.ddl index c6aeef0..7b8f47f 100644 --- a/tools/h5stat/testfiles/h5stat_filters-file.ddl +++ b/tools/h5stat/testfiles/h5stat_filters-file.ddl @@ -9,5 +9,4 @@ File information # of unique links: 0 # of unique other: 0 Max. # of links to object: 1 - Max. depth of hierarchy: 0 Max. # of objects in group: 16 diff --git a/tools/h5stat/testfiles/h5stat_filters.ddl b/tools/h5stat/testfiles/h5stat_filters.ddl index 4dd6aee..df2e304 100644 --- a/tools/h5stat/testfiles/h5stat_filters.ddl +++ b/tools/h5stat/testfiles/h5stat_filters.ddl @@ -9,7 +9,6 @@ File information # of unique links: 0 # of unique other: 0 Max. # of links to object: 1 - Max. depth of hierarchy: 0 Max. # of objects in group: 16 Object header size: (total/unused) Groups: 48/8 diff --git a/tools/h5stat/testfiles/h5stat_newgrat.ddl b/tools/h5stat/testfiles/h5stat_newgrat.ddl index 228d565..6881ca9 100644 --- a/tools/h5stat/testfiles/h5stat_newgrat.ddl +++ b/tools/h5stat/testfiles/h5stat_newgrat.ddl @@ -9,7 +9,6 @@ File information # of unique links: 0 # of unique other: 0 Max. # of links to object: 1 - Max. depth of hierarchy: 1 Max. # of objects in group: 351 Object header size: (total/unused) Groups: 51597/32292 diff --git a/tools/h5stat/testfiles/h5stat_tsohm.ddl b/tools/h5stat/testfiles/h5stat_tsohm.ddl index 572965e..15a058e 100644 --- a/tools/h5stat/testfiles/h5stat_tsohm.ddl +++ b/tools/h5stat/testfiles/h5stat_tsohm.ddl @@ -9,7 +9,6 @@ File information # of unique links: 0 # of unique other: 0 Max. # of links to object: 1 - Max. depth of hierarchy: 0 Max. # of objects in group: 2 Object header size: (total/unused) Groups: 51/2 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 *------------------------------------------------------------------------- */ diff --git a/tools/testfiles/h5copytst.out.ls b/tools/testfiles/h5copytst.out.ls index c4d1778..785c3f0 100644 --- a/tools/testfiles/h5copytst.out.ls +++ b/tools/testfiles/h5copytst.out.ls @@ -2,6 +2,9 @@ Expected output for 'h5ls ../testfiles/h5copytst.out.h5' ############################# Opened "../testfiles/h5copytst.out.h5" with sec2 driver. +/ Group + Location: 1:96 + Links: 1 /A Group Location: 1:90344 Links: 1 diff --git a/tools/testfiles/h5mkgrp_nested.ls b/tools/testfiles/h5mkgrp_nested.ls index 2b9fb25..472656d 100644 --- a/tools/testfiles/h5mkgrp_nested.ls +++ b/tools/testfiles/h5mkgrp_nested.ls @@ -2,6 +2,9 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_nested.h5' ############################# Opened "../testfiles/h5mkgrp_nested.h5" with sec2 driver. +/ Group + Location: 1:96 + Links: 1 /one Group Location: 1:800 Links: 1 diff --git a/tools/testfiles/h5mkgrp_nested_latest.ls b/tools/testfiles/h5mkgrp_nested_latest.ls index f0bab6f..c00292d 100644 --- a/tools/testfiles/h5mkgrp_nested_latest.ls +++ b/tools/testfiles/h5mkgrp_nested_latest.ls @@ -2,6 +2,10 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_nested_latest.h5' ############################# Opened "../testfiles/h5mkgrp_nested_latest.h5" with sec2 driver. +/ Group + Location: 1:48 + Links: 1 + Modified: XXXX-XX-XX XX:XX:XX XXX /one Group Location: 1:195 Links: 1 diff --git a/tools/testfiles/h5mkgrp_nested_mult.ls b/tools/testfiles/h5mkgrp_nested_mult.ls index 4fccd83..6a22ffd 100644 --- a/tools/testfiles/h5mkgrp_nested_mult.ls +++ b/tools/testfiles/h5mkgrp_nested_mult.ls @@ -2,6 +2,9 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_nested_mult.h5' ############################# Opened "../testfiles/h5mkgrp_nested_mult.h5" with sec2 driver. +/ Group + Location: 1:96 + Links: 1 /one Group Location: 1:800 Links: 1 diff --git a/tools/testfiles/h5mkgrp_nested_mult_latest.ls b/tools/testfiles/h5mkgrp_nested_mult_latest.ls index 7835050..0b19ff9 100644 --- a/tools/testfiles/h5mkgrp_nested_mult_latest.ls +++ b/tools/testfiles/h5mkgrp_nested_mult_latest.ls @@ -2,6 +2,10 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_nested_mult_latest.h5' ############################# Opened "../testfiles/h5mkgrp_nested_mult_latest.h5" with sec2 driver. +/ Group + Location: 1:48 + Links: 1 + Modified: XXXX-XX-XX XX:XX:XX XXX /one Group Location: 1:195 Links: 1 diff --git a/tools/testfiles/h5mkgrp_several.ls b/tools/testfiles/h5mkgrp_several.ls index dcbe3eb..bbf5c92 100644 --- a/tools/testfiles/h5mkgrp_several.ls +++ b/tools/testfiles/h5mkgrp_several.ls @@ -2,6 +2,9 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_several.h5' ############################# Opened "../testfiles/h5mkgrp_several.h5" with sec2 driver. +/ Group + Location: 1:96 + Links: 1 /one Group Location: 1:800 Links: 1 diff --git a/tools/testfiles/h5mkgrp_several_latest.ls b/tools/testfiles/h5mkgrp_several_latest.ls index c59107e..a3b5224 100644 --- a/tools/testfiles/h5mkgrp_several_latest.ls +++ b/tools/testfiles/h5mkgrp_several_latest.ls @@ -2,6 +2,10 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_several_latest.h5' ############################# Opened "../testfiles/h5mkgrp_several_latest.h5" with sec2 driver. +/ Group + Location: 1:48 + Links: 1 + Modified: XXXX-XX-XX XX:XX:XX XXX /one Group Location: 1:195 Links: 1 diff --git a/tools/testfiles/h5mkgrp_single.ls b/tools/testfiles/h5mkgrp_single.ls index 1f7e828..e9932f7 100644 --- a/tools/testfiles/h5mkgrp_single.ls +++ b/tools/testfiles/h5mkgrp_single.ls @@ -2,6 +2,9 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_single.h5' ############################# Opened "../testfiles/h5mkgrp_single.h5" with sec2 driver. +/ Group + Location: 1:96 + Links: 1 /single Group Location: 1:800 Links: 1 diff --git a/tools/testfiles/h5mkgrp_single_latest.ls b/tools/testfiles/h5mkgrp_single_latest.ls index 7f5ee72..b6e6ea4 100644 --- a/tools/testfiles/h5mkgrp_single_latest.ls +++ b/tools/testfiles/h5mkgrp_single_latest.ls @@ -2,6 +2,10 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_single_latest.h5' ############################# Opened "../testfiles/h5mkgrp_single_latest.h5" with sec2 driver. +/ Group + Location: 1:48 + Links: 1 + Modified: XXXX-XX-XX XX:XX:XX XXX /latest Group Location: 1:195 Links: 1 diff --git a/tools/testfiles/tall-2.ls b/tools/testfiles/tall-2.ls index 5513214..2e4cd37 100644 --- a/tools/testfiles/tall-2.ls +++ b/tools/testfiles/tall-2.ls @@ -1,6 +1,7 @@ ############################# output for 'h5ls -w80 -r -d tall.h5' ############################# +/ Group /g1 Group /g1/g1.1 Group /g1/g1.1/dset1.1.1 Dataset {10, 10} diff --git a/tools/testfiles/tarray1.ls b/tools/testfiles/tarray1.ls index 83a51a8..60c002d 100644 --- a/tools/testfiles/tarray1.ls +++ b/tools/testfiles/tarray1.ls @@ -1,6 +1,7 @@ ############################# output for 'h5ls -w80 -r -d tarray1.h5' ############################# +/ Group /Dataset1 Dataset {4} Data: (0) [0,1,2,3], [10,11,12,13], [20,21,22,23], [30,31,32,33] diff --git a/tools/testfiles/tattr2.ls b/tools/testfiles/tattr2.ls index 88b24cd..0448868 100644 --- a/tools/testfiles/tattr2.ls +++ b/tools/testfiles/tattr2.ls @@ -2,149 +2,6 @@ output for 'h5ls -w80 -v -S tattr2.h5' ############################# Opened "tattr2.h5" with sec2 driver. - Attribute: array {2} - Type: [3] 32-bit little-endian integer - Data: [1,2,3], [4,5,6] - Attribute: array2D {3, 2} - Type: [3] 32-bit little-endian integer - Data: - (0,0) [1,2,3], [4,5,6], [7,8,9], [10,11,12], [13,14,15], [16,17,18] - Attribute: array3D {4, 3, 2} - Type: [3] 32-bit little-endian integer - Data: - (0,0,0) [1,2,3], [4,5,6], [7,8,9], [10,11,12], [13,14,15], - (0,2,1) [16,17,18], [19,20,21], [22,23,24], [25,26,27], [28,29,30], - (1,2,0) [31,32,33], [34,35,36], [37,38,39], [40,41,42], [43,44,45], - (2,1,1) [46,47,48], [49,50,51], [52,53,54], [55,56,57], [58,59,60], - (3,1,0) [61,62,63], [64,65,66], [67,68,69], [70,71,72] - Attribute: bitfield {2} - Type: 8-bit bitfield - Data: 0x01, 0x02 - Attribute: bitfield2D {3, 2} - Type: 8-bit bitfield - Data: - (0,0) 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 - Attribute: bitfield3D {4, 3, 2} - Type: 8-bit bitfield - Data: - (0,0,0) 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, - (1,2,0) 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, - (3,1,0) 0x15, 0x16, 0x17, 0x18 - Attribute: compound {2} - Type: struct { - "a" +0 8-bit integer - "b" +4 IEEE 64-bit little-endian float - } 12 bytes - Data: {1, 2}, {3, 4} - Attribute: compound2D {3, 2} - Type: struct { - "a" +0 8-bit integer - "b" +4 IEEE 64-bit little-endian float - } 12 bytes - Data: - (0,0) {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12} - Attribute: compound3D {4, 3, 2} - Type: struct { - "a" +0 8-bit integer - "b" +4 IEEE 64-bit little-endian float - } 12 bytes - Data: - (0,0,0) {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}, {13, - (1,0,0) 14}, {15, 16}, {17, 18}, {19, 20}, {21, 22}, {23, 24}, - (2,0,0) {25, 26}, {27, 28}, {29, 30}, {31, 32}, {33, 34}, {35, 36}, - (3,0,0) {37, 38}, {39, 40}, {41, 42}, {43, 44}, {45, 46}, {47, 48} - Attribute: enum {2} - Type: enum 32-bit little-endian integer { - RED = 0 - GREEN = 1 - } - Data: RED, RED - Attribute: enum2D {3, 2} - Type: enum 32-bit little-endian integer { - RED = 0 - GREEN = 1 - } - Data: - (0,0) RED, RED, RED, RED, RED, RED - Attribute: enum3D {4, 3, 2} - Type: enum 32-bit little-endian integer { - RED = 0 - GREEN = 1 - } - Data: - (0,0,0) RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, - (2,0,0) RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, RED - Attribute: float {2} - Type: IEEE 32-bit little-endian float - Data: 1, 2 - Attribute: float2D {3, 2} - Type: IEEE 32-bit little-endian float - Data: - (0,0) 1, 2, 3, 4, 5, 6 - Attribute: float3D {4, 3, 2} - Type: IEEE 32-bit little-endian float - Data: - (0,0,0) 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - (2,2,1) 18, 19, 20, 21, 22, 23, 24 - Attribute: integer {2} - Type: 32-bit little-endian integer - Data: 1, 2 - Attribute: integer2D {3, 2} - Type: 32-bit little-endian integer - Data: - (0,0) 1, 2, 3, 4, 5, 6 - Attribute: integer3D {4, 3, 2} - Type: 32-bit little-endian integer - Data: - (0,0,0) 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - (2,2,1) 18, 19, 20, 21, 22, 23, 24 - Attribute: opaque {2} - Type: 1-byte opaque type - (tag = "1-byte opaque type") - Data: 0x01, 0x02 - Attribute: opaque2D {3, 2} - Type: 1-byte opaque type - (tag = "1-byte opaque type") - Data: - (0,0) 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 - Attribute: opaque3D {4, 3, 2} - Type: 1-byte opaque type - (tag = "1-byte opaque type") - Data: - (0,0,0) 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, - (1,2,0) 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, - (3,1,0) 0x15, 0x16, 0x17, 0x18 - Attribute: string {2} - Type: 2-byte null-terminated ASCII string - Data: "ab", "de" - Attribute: string2D {3, 2} - Type: 2-byte null-terminated ASCII string - Data: - (0,0) "ab", "cd", "ef", "gh", "ij", "kl" - Attribute: string3D {4, 3, 2} - Type: 2-byte null-terminated ASCII string - Data: - (0,0,0) "ab", "cd", "ef", "gh", "ij", "kl", "mn", "pq", "rs", "tu", - (1,2,0) "vw", "xz", "AB", "CD", "EF", "GH", "IJ", "KL", "MN", "PQ", - (3,1,0) "RS", "TU", "VW", "XZ" - Attribute: vlen {2} - Type: variable length of - 32-bit little-endian integer - Data: (1), (2,3) - Attribute: vlen2D {3, 2} - Type: variable length of - 32-bit little-endian integer - Data: - (0,0) (0), (1), (2,3), (4,5), (6,7,8), (9,10,11) - Attribute: vlen3D {4, 3, 2} - Type: variable length of - 32-bit little-endian integer - Data: - (0,0,0) (0), (1), (2), (3), (4), (5), (6,7), (8,9), (10,11), - (1,1,1) (12,13), (14,15), (16,17), (18,19,20), (21,22,23), - (2,1,0) (24,25,26), (27,28,29), (30,31,32), (33,34,35), - (3,0,0) (36,37,38,39), (40,41,42,43), (44,45,46,47), (48,49,50,51), - (3,2,0) (52,53,54,55), (56,57,58,59) dset Dataset {2/2} Attribute: array {2} Type: [3] 32-bit little-endian integer diff --git a/tools/testfiles/tcomp-1.ls b/tools/testfiles/tcomp-1.ls index 599fe68..9cfb47d 100644 --- a/tools/testfiles/tcomp-1.ls +++ b/tools/testfiles/tcomp-1.ls @@ -1,6 +1,7 @@ ############################# output for 'h5ls -w80 -r -d tcompound.h5' ############################# +/ Group /dset1 Dataset {5} Data: (0) {0, 0, 1}, {1, 1, 0.5}, {2, 4, 0.333333333333333}, {3, 9, 0.25}, diff --git a/tools/testfiles/tdset-1.ls b/tools/testfiles/tdset-1.ls index 6853429..b6e4671 100644 --- a/tools/testfiles/tdset-1.ls +++ b/tools/testfiles/tdset-1.ls @@ -1,6 +1,7 @@ ############################# output for 'h5ls -w80 -r -d tdset.h5' ############################# +/ Group /dset1 Dataset {10, 20} Data: (0,0) 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, diff --git a/tools/testfiles/textlink-1.ls b/tools/testfiles/textlink-1.ls index f92786b..87be5a7 100644 --- a/tools/testfiles/textlink-1.ls +++ b/tools/testfiles/textlink-1.ls @@ -1,5 +1,6 @@ ############################# output for 'h5ls -w80 -r textlink.h5' ############################# +/ Group /extlink1 -> file: filename path: objname /extlink2 -> file: anotherfile path: anotherobj diff --git a/tools/testfiles/tgroup-1.ls b/tools/testfiles/tgroup-1.ls index 62ebe70..0ca929d 100644 --- a/tools/testfiles/tgroup-1.ls +++ b/tools/testfiles/tgroup-1.ls @@ -1,17 +1,29 @@ ############################# output for 'h5ls -w80 -r -g tgroup.h5' ############################# -/ Group -/g1 Group -/g1/g1.1 Group -/g1/g1.2 Group -/g2 Group -/g2/g2.1 Group -/g2/g2.1/g2.1.1 Group -/g2/g2.1/g2.1.2 Group -/g2/g2.1/g2.1.3 Group -/g3 Group -/g3/g3.1 Group -/g3/g3.2 Group -/g3/g3.3 Group -/g3/g3.4 Group +Error: 'recursive' option not compatible with 'group info' option! + +usage: h5ls [OPTIONS] [OBJECTS...] + OPTIONS + -h, -?, --help Print a usage message and exit + -a, --address Print addresses for raw data + -d, --data Print the values of datasets + -e, --errors Show all HDF5 error reporting + -f, --full Print full path names instead of base names + -g, --group Show information about a group, not its contents + -l, --label Label members of compound datasets + -r, --recursive List all groups recursively, avoiding cycles + -s, --string Print 1-byte integer datasets as ASCII + -S, --simple Use a machine-readable output format + -wN, --width=N Set the number of columns of output + -v, --verbose Generate more verbose output + -V, --version Print version number and exit + --vfd=DRIVER Use the specified virtual file driver + -x, --hexdump Show raw data in hexadecimal format + + OBJECTS + Each object consists of an HDF5 file name optionally followed by a + slash and an object name within the file (if no object is specified + within the file then the contents of the root group are displayed). + The file name may include a printf(3C) integer format such as + "%05d" to open a file family. diff --git a/tools/testfiles/tgroup-2.ls b/tools/testfiles/tgroup-2.ls new file mode 100644 index 0000000..0817d93 --- /dev/null +++ b/tools/testfiles/tgroup-2.ls @@ -0,0 +1,4 @@ +############################# + output for 'h5ls -w80 -g tgroup.h5/g1' +############################# +g1 Group diff --git a/tools/testfiles/tloop-1.ls b/tools/testfiles/tloop-1.ls index b9631b7..22cb6c7 100644 --- a/tools/testfiles/tloop-1.ls +++ b/tools/testfiles/tloop-1.ls @@ -1,6 +1,7 @@ ############################# output for 'h5ls -w80 -r -d tloop.h5' ############################# +/ Group /g1 Group /g1/g1.1 Group /g1/g1.1/g2.1 Group, same as /g1 diff --git a/tools/testfiles/tnestcomp-1.ls b/tools/testfiles/tnestcomp-1.ls index eef41ef..9dc193d 100644 --- a/tools/testfiles/tnestcomp-1.ls +++ b/tools/testfiles/tnestcomp-1.ls @@ -1,6 +1,7 @@ ############################# output for 'h5ls -w80 -r -d tnestedcomp.h5' ############################# +/ Group /ArrayOfStructures Dataset {10} Data: (0) {0, 0, 1, {"A", [-100,100]}}, {1, 1, 0.5, {"B", [-100,100]}}, diff --git a/tools/testfiles/tsaf.ls b/tools/testfiles/tsaf.ls index 8efc0f2..96d4811 100644 --- a/tools/testfiles/tsaf.ls +++ b/tools/testfiles/tsaf.ls @@ -1,6 +1,7 @@ ############################# output for 'h5ls -w80 -r -d tsaf.h5' ############################# +/ Group /.DSL_METADATA Dataset {5919/Inf} Data: (0) 47, 32, 67, 79, 78, 84, 65, 73, 78, 69, 82, 10, 47, 46, 97, 116, diff --git a/tools/testfiles/tslink-1.ls b/tools/testfiles/tslink-1.ls index 05b9bca..4c16958 100644 --- a/tools/testfiles/tslink-1.ls +++ b/tools/testfiles/tslink-1.ls @@ -1,5 +1,6 @@ ############################# output for 'h5ls -w80 -r tslink.h5' ############################# +/ Group /slink1 -> somevalue /slink2 -> linkvalue diff --git a/tools/testfiles/tstr-1.ls b/tools/testfiles/tstr-1.ls index 1961fd4..8a223cc 100644 --- a/tools/testfiles/tstr-1.ls +++ b/tools/testfiles/tstr-1.ls @@ -1,6 +1,7 @@ ############################# output for 'h5ls -w80 -r -d tstr.h5' ############################# +/ Group /comp1 Dataset {3, 6} Data: (0,0) {[0,1,4,9,16,25,36,49,64,81,1,4,9,16,25,36,49,64,81,100,4,9,16, diff --git a/tools/testfiles/tudlink-1.ls b/tools/testfiles/tudlink-1.ls index e83fce7..b8578ce 100644 --- a/tools/testfiles/tudlink-1.ls +++ b/tools/testfiles/tudlink-1.ls @@ -1,5 +1,6 @@ ############################# output for 'h5ls -w80 -r tudlink.h5' ############################# +/ Group /udlink1 -> cannot follow UD links /udlink2 -> cannot follow UD links diff --git a/tools/testfiles/tvldtypes1.ls b/tools/testfiles/tvldtypes1.ls index cf1688e..4c4c162 100644 --- a/tools/testfiles/tvldtypes1.ls +++ b/tools/testfiles/tvldtypes1.ls @@ -1,6 +1,7 @@ ############################# output for 'h5ls -w80 -r -d tvldtypes1.h5' ############################# +/ Group /Dataset1.0 Dataset {4} Data: (0) (0), (10,11), (20,21,22), (30,31,32,33) -- cgit v0.12