diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2007-11-24 16:49:36 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2007-11-24 16:49:36 (GMT) |
commit | 2f36ea99d4ad1b036d377719e49eaab2dec64444 (patch) | |
tree | 63be7c282767004339c49aa0e738e6a62630c280 /src/H5Gname.c | |
parent | 083357dad3334473507a97e17593a9d68e42d69f (diff) | |
download | hdf5-2f36ea99d4ad1b036d377719e49eaab2dec64444.zip hdf5-2f36ea99d4ad1b036d377719e49eaab2dec64444.tar.gz hdf5-2f36ea99d4ad1b036d377719e49eaab2dec64444.tar.bz2 |
[svn-r14284] Description:
Add H5Lvisit_by_name() API routine to library.
Eliminated all (five!) other group traversal routines and changed them
all to use the new API routine.
Cleaned up output of h5ls & h5stat:
- Issue error when requesting recursive traversal of a file
with the "group info" flag, but no group given
- Print info about root group in all(?) appropriate situations
- Don't print "verbose" information about root group until the
root group is in the list of objects to display
(mostly because h5ls & h5stat had a different twist on traversing the
groups in a file that the other utilities)
Tested on:
FreeBSD/32 6.2 (duty) in debug mode
FreeBSD/64 6.2 (liberty) w/C++ & FORTRAN, in debug mode
Linux/32 2.6 (kagiso) w/PGI compilers, w/C++ & FORTRAN, w/threadsafe,
in debug mode
Linux/64-amd64 2.6 (smirom) w/default API=1.6.x, w/C++ & FORTRAN,
in production mode
Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN,
in production mode
Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN,
w/szip filter, in production mode
Mac OS X/32 10.4.10 (amazon) in debug mode
Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in production mode
Diffstat (limited to 'src/H5Gname.c')
-rw-r--r-- | src/H5Gname.c | 282 |
1 files changed, 94 insertions, 188 deletions
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() */ |