summaryrefslogtreecommitdiffstats
path: root/src/H5Gname.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Gname.c')
-rw-r--r--src/H5Gname.c399
1 files changed, 129 insertions, 270 deletions
diff --git a/src/H5Gname.c b/src/H5Gname.c
index faec337..ffcb530 100644
--- a/src/H5Gname.c
+++ b/src/H5Gname.c
@@ -47,19 +47,19 @@ typedef struct H5G_names_t {
H5RS_str_t *dst_name; /* Name of object relative to destination location */
} H5G_names_t;
-/* Info to pass to the iteration functions */
-typedef struct H5G_name_iter_t {
- char *container; /* full name of the container object */
+/* Info to pass to the iteration function when building name */
+typedef struct H5G_ref_path_iter_t {
+ /* In */
hid_t file; /* File id where it came from */
+ hid_t dxpl_id; /* DXPL for operations */
haddr_t obj; /* The address what we're looking for */
-} H5G_ref_path_iter_t;
-typedef struct {
- haddr_t objno; /* Object ID (i.e. address) */
- char *path; /* Object path */
-} H5G_ref_path_node_t;
+ /* In/Out */
+ H5SL_t *ref_path_table; /* Skip list for tracking visited nodes */
-H5SL_t *ref_path_table = NULL; /* the "table" for path nodes */
+ /* Out */
+ char *container; /* full name of the container object */
+} H5G_ref_path_iter_t;
/* Private macros */
@@ -68,6 +68,9 @@ H5SL_t *ref_path_table = NULL; /* the "table" for path nodes */
/* Declare extern the PQ free list for the wrapped strings */
H5FL_BLK_EXTERN(str_buf);
+/* Declare the free list to manage haddr_t's */
+H5FL_DEFINE_STATIC(haddr_t);
+
/* PRIVATE PROTOTYPES */
static htri_t H5G_common_path(const H5RS_str_t *fullpath_r, const H5RS_str_t *prefix_r);
static H5RS_str_t *H5G_build_fullpath(const char *prefix, const char *name);
@@ -76,13 +79,10 @@ static H5RS_str_t *H5G_build_fullpath_refstr_str(H5RS_str_t *path_r, const char
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 ssize_t H5G_get_refobj_name(haddr_t id, hid_t file, char* name, size_t size);
static herr_t H5G_refname_iterator(hid_t group, const char *name, void *_iter);
-static herr_t H5G_init_ref_path_table(hid_t fid);
-static hbool_t H5G_ref_path_table_find(haddr_t objno);
-static herr_t H5G_ref_path_table_put(char *path, haddr_t objno);
-static herr_t H5G_free_ref_path_info(void *item, void UNUSED *key, void UNUSED *operator_data/*in,out*/);
-static herr_t H5G_term_ref_path_table(void);
+static herr_t H5G_free_ref_path_node(void *item, void *key, void *operator_data/*in,out*/);
+static ssize_t H5G_get_refobj_name(haddr_t id, hid_t file, char* name,
+ size_t size, hid_t dxpl_it);
/*-------------------------------------------------------------------------
@@ -431,7 +431,7 @@ H5G_name_copy(H5G_name_t *dst, const H5G_name_t *src, H5_copy_depth_t depth)
*-------------------------------------------------------------------------
*/
ssize_t
-H5G_get_name(hid_t id, char *name/*out*/, size_t size)
+H5G_get_name(hid_t id, char *name/*out*/, size_t size, hid_t dxpl_id)
{
H5G_loc_t loc; /* Object location */
ssize_t ret_value = FAIL;
@@ -442,6 +442,7 @@ H5G_get_name(hid_t id, char *name/*out*/, size_t size)
if(H5G_loc(id, &loc) >= 0) {
ssize_t len;
+ /* If the user path is available and it's not "hidden", use it */
if(loc.path->user_path_r != NULL && loc.path->obj_hidden == 0) {
len = H5RS_len(loc.path->user_path_r);
@@ -459,7 +460,7 @@ H5G_get_name(hid_t id, char *name/*out*/, size_t size)
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve file ID")
/* Search for name of object */
- if((len = H5G_get_refobj_name((loc.oloc)->addr, file, name, size)) < 0)
+ if((len = H5G_get_refobj_name((loc.oloc)->addr, file, name, size, dxpl_id)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't determine name")
/* Close file ID used for search */
@@ -1031,104 +1032,100 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5G_ref_path_table_put
- *
- * Purpose: Enter the 'obj' with 'path' in the table (assumes its not
- * already there)
- *
- * Create an object reference, pte, and store them
- * in the table.
+ * Function: H5G_refname_iterator
*
- * NOTE: Takes ownership of the path name string passed in!
+ * Purpose: The iterator which traverses all objects in a file looking for
+ * one that matches the object that is being looked for.
*
- * Return: Non-negative on success, negative on failure
+ * Return: 1 on success, 0 to continue searching, negative on failure.
*
- * Programmer: REMcG
+ * Programmer: Leon Arber, Nov 1, 2006.
*
* 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_ref_path_table_put(char *path, haddr_t objno)
+H5G_refname_iterator(hid_t group, const char *name, void *_udata)
{
- H5G_ref_path_node_t *new_node; /* New path node for table */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5G_ref_path_table_put)
-
- /* Sanity check */
- HDassert(ref_path_table);
- HDassert(H5F_addr_defined(objno));
- HDassert(path);
+ H5G_ref_path_iter_t *udata = (H5G_ref_path_iter_t*)_udata;
+ H5G_stat_t sb; /* Stat buffer for object */
+ H5G_loc_t loc; /* Group location of parent */
+ haddr_t objno; /* Address of current object */
+ herr_t ret_value = 0; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5G_refname_iterator)
+
+ /* Look up group location info */
+ if(H5G_loc(group, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
- /* Allocate new path node */
- if((new_node = H5MM_malloc(sizeof(H5G_ref_path_node_t))) == NULL)
- HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate path node")
+ /* Get information for object in group */
+ if(H5G_get_objinfo(&loc, name, 0, &sb, udata->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "cannot stat object")
+ objno = (haddr_t)sb.objno[0] | ((haddr_t)sb.objno[1] << (8 * sizeof(long)));
- /* Set node information */
- new_node->objno = objno;
- new_node->path = path;
+ /* Check for finding the object */
+ if(udata->obj == objno) {
+ /* Build the object's full name */
+ if(NULL == (udata->container = H5MM_realloc(udata->container, HDstrlen(udata->container) + HDstrlen(name) + 2)))
+ HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate path string")
+ HDstrcat(udata->container, name);
- /* Insert into skip list */
- if(H5SL_insert(ref_path_table, new_node, &(new_node->objno)) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "can't insert path node into table")
+ /* We found a match so we return immediately */
+ HGOTO_DONE(1)
+ } /* end if */
+ else {
+ /* See if we've seen this object before */
+ if(H5SL_search(udata->ref_path_table, &objno))
+ HGOTO_DONE(0)
+ else {
+ /* If not, we add it to the list of visited objects if it's ref count is > 1 */
+ if(sb.nlink > 1) {
+ haddr_t *new_node; /* New path node for table */
+
+ /* Allocate new path node */
+ if((new_node = H5FL_MALLOC(haddr_t)) == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate path node")
+
+ /* Set node information */
+ *new_node = objno;
+
+ /* Insert into skip list */
+ if(H5SL_insert(udata->ref_path_table, new_node, new_node) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "can't insert path node into table")
+ } /* end if */
+ } /* end else */
+
+ /* If it's a group, we recurse into it */
+ if(sb.type == H5G_GROUP) {
+ int last_obj;
+ size_t len;
+
+ /* Build full path name of group to recurse into */
+ len = HDstrlen(udata->container);
+ if(NULL == (udata->container = H5MM_realloc(udata->container, HDstrlen(udata->container) + HDstrlen(name) + 2)))
+ HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate path string")
+ HDstrcat(udata->container, name);
+ HDstrcat(udata->container, "/");
+
+ ret_value = H5G_obj_iterate(udata->file, udata->container, H5_ITER_INC, 0, &last_obj, H5G_refname_iterator, udata, 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 */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5G_ref_path_table_put() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G_init_ref_path_table
- *
- * Purpose: Enter the root group ("/") into the path table
- *
- * Return: Non-negative on success, negative on failure
- *
- * Programmer: Quincey Koziol
- *
- * Modifications:
- * Leon Arber, Oct. 25, 2006. Moved into H5G from h5ls
- * tools lib for looking up path to reference.
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5G_init_ref_path_table(hid_t fid)
-{
- H5G_stat_t sb;
- haddr_t objno; /* Compact form of object's location */
- char *root_path;
- herr_t ret_value = 0;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_init_ref_path_table)
-
- /* Create skip list to store reference path information */
- if((ref_path_table = H5SL_create(H5SL_TYPE_HADDR, 0.5, (size_t)16))==NULL)
- ret_value = -1;
-
- if((root_path = HDstrdup("/")) == NULL)
- ret_value = -1;
-
- if(H5Gget_objinfo(fid, "/", TRUE, &sb)<0) {
- /* fatal error? */
- HDfree(root_path);
- ret_value = -1;
- }
- objno = (haddr_t)sb.objno[0] | ((haddr_t)sb.objno[1] << (8 * sizeof(long)));
-
- /* Insert into table (takes ownership of path) */
- H5G_ref_path_table_put(root_path, objno);
-
- FUNC_LEAVE_NOAPI(ret_value);
-}
+} /* end H5G_refname_iterator() */
/*-------------------------------------------------------------------------
- * Function: H5G_free_ref_path_info
+ * Function: H5G_free_ref_path_node
*
* Purpose: Free the key for a reference path table node
*
@@ -1140,167 +1137,20 @@ H5G_init_ref_path_table(hid_t fid)
* Leon Arber, Oct. 25, 2006. Moved into H5G from h5ls
* tools lib for looking up path to reference.
*
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5G_free_ref_path_info(void *item, void UNUSED *key, void UNUSED *operator_data/*in,out*/)
-{
- H5G_ref_path_node_t *node = (H5G_ref_path_node_t *)item;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_free_ref_path_info)
-
- H5MM_xfree(node->path);
- H5MM_xfree(node);
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G_term_ref_path_table
- *
- * Purpose: Terminate the reference path table
- *
- * Return: Non-negative on success, negative on failure
- *
- * 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_term_ref_path_table(void)
+H5G_free_ref_path_node(void *item, void UNUSED *key, void UNUSED *operator_data/*in,out*/)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_term_ref_path_table)
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_free_ref_path_node)
- /* Destroy reference path table, freeing all memory */
- if(ref_path_table)
- H5SL_destroy(ref_path_table, H5G_free_ref_path_info, NULL);
+ H5FL_FREE(haddr_t, item);
FUNC_LEAVE_NOAPI(SUCCEED)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G_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:
- * Leon Arber, Oct. 25, 2006. Moved into H5G from h5ls
- * tools lib for looking up path to reference.
- *
- *-------------------------------------------------------------------------
- */
-static hbool_t
-H5G_ref_path_table_find(haddr_t objno)
-{
- hbool_t ret_value;
-
- HDassert(ref_path_table);
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_ref_path_table_find)
-
- if(H5SL_search(ref_path_table, &objno) == NULL)
- ret_value = FALSE;
- else
- ret_value = TRUE;
-
- FUNC_LEAVE_NOAPI(ret_value);
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G_refname_iterator
- *
- * Purpose: The iterator which traverses all objects in a file looking for
- * one that matches the object that is being looked for.
- *
- * Return: 1 on success, 0 to continue searching, negative on failure.
- *
- * Programmer: Leon Arber, Nov 1, 2006.
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5G_refname_iterator(hid_t group, const char *name, void *_iter)
-{
- H5G_stat_t sb;
- H5G_ref_path_iter_t *iter = (H5G_ref_path_iter_t*)_iter;
- H5G_loc_t loc;
- int ret_value = 0, last_obj;
-
- FUNC_ENTER_NOAPI_NOINIT(H5G_refname_iterator)
-
- if(H5G_loc(group, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
-
- if(H5G_get_objinfo(&loc, name, 0, &sb, H5AC_ind_dxpl_id) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "cannot stat object")
-
- /* We hit an unknown type during iteration. Let's continue anyway */
- if(sb.type < 0 || sb.type >= H5G_NTYPES)
- ret_value = 0;
- else
- {
- haddr_t objno = (haddr_t)sb.objno[0] | ((haddr_t)sb.objno[1] << (8 * sizeof(long)));
-
- /* See if we've seen this object before */
- if (H5G_ref_path_table_find(objno))
- HGOTO_DONE(ret_value)
- else
- {
- /* If not, we add it to the list of visited objects if it's ref count is > 1*/
- if(H5I_get_ref(group) > 1)
- {
- /* We don't really care about the path to this object in the table, since we're only going
- * to be matching on objno */
- if(H5G_ref_path_table_put(NULL, objno) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "couldn't insert object into ref path table")
- }
-
- ret_value = 0;
- }
-
- if(iter->obj == objno)
- {
- /* We found a match so we return immediately */
- iter->container = H5MM_realloc(iter->container, HDstrlen(iter->container)+HDstrlen(name)+2);
- iter->container = HDstrcat(iter->container,name);
-
- ret_value = 1;
- }
- else if(sb.type == H5G_GROUP)
- {
- /* It's a group, so we recurse into it */
- int len = HDstrlen(iter->container);
- iter->container = H5MM_realloc(iter->container, HDstrlen(iter->container)+HDstrlen(name)+2);
- iter->container = HDstrcat(iter->container,name);
- HDstrcpy(iter->container+HDstrlen(iter->container), "/");
-
- ret_value = H5G_obj_iterate(iter->file, iter->container, H5_ITER_INC, 0, &last_obj, H5G_refname_iterator, _iter, H5AC_ind_dxpl_id);
-
- /* If we didn't find the object, truncate the name to not include it anymore */
- if(!ret_value)
- iter->container[len] = '\0';
- }
- }
-
- /* Close the object. */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5G_free_ref_path_node() */
/*-------------------------------------------------------------------------
@@ -1316,41 +1166,50 @@ done:
* Programmer: Leon Arber, Nov 1, 2006.
*
* Modifications:
+ * Quincey Koziol, Nov. 3, 2006
+ * Cleaned up code.
*
*-------------------------------------------------------------------------
*/
static ssize_t
-H5G_get_refobj_name(haddr_t id, hid_t file, char* name, size_t size)
+H5G_get_refobj_name(haddr_t addr, hid_t file, char *name, size_t size, hid_t dxpl_id)
{
- const char *oname = "/";
- H5G_ref_path_iter_t udata;
- int last_obj = 0;
- ssize_t ret_value = 0;
+ H5G_ref_path_iter_t udata; /* User data for iteration */
+ int last_obj = 0; /* Start object for iteration */
+ ssize_t ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5G_get_refobj_name)
- /* Initialize the ref path table for tracking visited objects */
- H5G_init_ref_path_table(file);
-
- udata.container = H5MM_malloc(strlen(oname)+1);
- HDstrcpy(udata.container, oname);
+ /* Set up user data for iterator */
udata.file = file;
- udata.obj = id;
+ udata.dxpl_id = dxpl_id;
+ if(NULL == (udata.container = H5MM_strdup("/")))
+ HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate root group name")
+ udata.obj = addr;
- if((ret_value = H5G_obj_iterate(file, oname, H5_ITER_INC, 0, &last_obj, H5G_refname_iterator, &udata, H5AC_ind_dxpl_id))< 0)
+ /* 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((ret_value = H5G_obj_iterate(file, "/", H5_ITER_INC, 0, &last_obj, H5G_refname_iterator, &udata, dxpl_id)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "group iteration failed while looking for object name")
- else if(ret_value == 0)
- HGOTO_DONE(ret_value)
- else if(HDstrlen(udata.container) >= size)
- ret_value = HDstrlen(udata.container) + 1;
- else {
- HDstrncpy(name, udata.container, size);
- ret_value = HDstrlen(udata.container) + 1;
- } /* end else */
+ else if(ret_value > 0) {
+ /* Set the length of the full path */
+ ret_value = HDstrlen(udata.container) + 1;
+
+ /* If there's a buffer provided, copy into it, up to the limit of its size */
+ if(name) {
+ HDstrncpy(name, udata.container, size);
+ if((size_t)ret_value >= size)
+ name[size - 1] = '\0';
+ } /* end if */
+ } /* end if */
done:
- H5G_term_ref_path_table();
H5MM_xfree(udata.container);
+ if(udata.ref_path_table)
+ H5SL_destroy(udata.ref_path_table, H5G_free_ref_path_node, NULL);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5G_get_refobj_name() */