summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2007-11-25 22:10:35 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2007-11-25 22:10:35 (GMT)
commitafd94614e0e6b527df8899470b33d2f667bb531f (patch)
treebda5a063cc3892f3b1a884d71449b6c71595e1e4
parente4f62217b88a1ad842cd5f226c2729feb3b8c559 (diff)
downloadhdf5-afd94614e0e6b527df8899470b33d2f667bb531f.zip
hdf5-afd94614e0e6b527df8899470b33d2f667bb531f.tar.gz
hdf5-afd94614e0e6b527df8899470b33d2f667bb531f.tar.bz2
[svn-r14286] Description:
Add H5Ovisit() and H5Ovisit_by_name() API routines. 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
-rw-r--r--src/H5G.c4
-rw-r--r--src/H5Gpkg.h3
-rw-r--r--src/H5Gprivate.h3
-rw-r--r--src/H5O.c392
-rw-r--r--src/H5Opublic.h9
-rw-r--r--test/links.c265
6 files changed, 667 insertions, 9 deletions
diff --git a/src/H5G.c b/src/H5G.c
index 675b166..0fa2c1c 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -135,7 +135,7 @@ 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);
+H5FL_DEFINE(H5_obj_t);
/* Private prototypes */
@@ -1933,7 +1933,7 @@ H5G_visit(hid_t loc_id, const char *group_name, H5_index_t idx_type,
udata.path_buf_size = 1;
udata.curr_path_len = 0;
- /* Create skip list to store reference path information */
+ /* Create skip list to store visited object 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")
diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h
index 2d936a9..b2cef28 100644
--- a/src/H5Gpkg.h
+++ b/src/H5Gpkg.h
@@ -342,9 +342,6 @@ H5_DLL H5G_t *H5G_open_name(const H5G_loc_t *loc, const char *name,
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
diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h
index 0ddb3e9..c54f11d 100644
--- a/src/H5Gprivate.h
+++ b/src/H5Gprivate.h
@@ -162,6 +162,9 @@ H5_DLL herr_t H5G_unmount(H5G_t *grp);
#ifndef H5_NO_DEPRECATED_SYMBOLS
H5_DLL H5G_obj_t H5G_map_obj_type(H5O_type_t obj_type);
#endif /* H5_NO_DEPRECATED_SYMBOLS */
+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);
/*
* These functions operate on symbol table nodes.
diff --git a/src/H5O.c b/src/H5O.c
index 67aa960..70b6efe 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -57,6 +57,17 @@
/* Local Typedefs */
/******************/
+/* User data for recursive traversal over objects from a group */
+typedef struct {
+ hid_t obj_id; /* The ID for the starting group */
+ H5G_loc_t *start_loc; /* Location of starting group */
+ hid_t lapl_id; /* LAPL for walking across links */
+ hid_t dxpl_id; /* DXPL for operations */
+ H5SL_t *visited; /* Skip list for tracking visited nodes */
+ H5O_iterate_t op; /* Application callback */
+ void *op_data; /* Application's op data */
+} H5O_iter_visit_ud_t;
+
/********************/
/* Package Typedefs */
@@ -70,6 +81,9 @@
static herr_t H5O_delete_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh);
static const H5O_obj_class_t *H5O_obj_class(const H5O_loc_t *loc, hid_t dxpl_id);
static herr_t H5O_obj_type_real(H5O_t *oh, H5O_type_t *obj_type);
+static herr_t H5O_visit(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
+ H5_iter_order_t order, H5O_iterate_t op, void *op_data, hid_t lapl_id,
+ hid_t dxpl_id);
/*********************/
@@ -140,6 +154,9 @@ H5FL_BLK_DEFINE(chunk_image);
/* Declare external the free list for time_t's */
H5FL_EXTERN(time_t);
+/* Declare external the free list for H5_obj_t's */
+H5FL_EXTERN(H5_obj_t);
+
/*******************/
/* Local Variables */
@@ -827,6 +844,127 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5Ovisit
+ *
+ * Purpose: Recursively visit an object and all the objects reachable
+ * from it. If the starting object is a group, all the objects
+ * linked to from that group will be visited. 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: Soft links and user-defined links are ignored during
+ * this operation.
+ *
+ * NOTE: Each _object_ reachable from the initial group will only
+ * be visited once. If multiple hard links point to the same
+ * object, the first link to the object's path (according to the
+ * iteration index and iteration order given) will be used to in
+ * the callback about the 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 25 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Ovisit(hid_t obj_id, H5_index_t idx_type, H5_iter_order_t order,
+ H5O_iterate_t op, void *op_data)
+{
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(H5Ovisit, FAIL)
+
+ /* Check args */
+ 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")
+
+ /* Call internal object visitation routine */
+ if((ret_value = H5O_visit(obj_id, ".", idx_type, order, op, op_data, H5P_LINK_ACCESS_DEFAULT, H5AC_ind_dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "object visitation failed")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Ovisit() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Ovisit_by_name
+ *
+ * Purpose: Recursively visit an object and all the objects reachable
+ * from it. If the starting object is a group, all the objects
+ * linked to from that group will be visited. 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: Soft links and user-defined links are ignored during
+ * this operation.
+ *
+ * NOTE: Each _object_ reachable from the initial group will only
+ * be visited once. If multiple hard links point to the same
+ * object, the first link to the object's path (according to the
+ * iteration index and iteration order given) will be used to in
+ * the callback about the 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 24 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Ovisit_by_name(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
+ H5_iter_order_t order, H5O_iterate_t op, void *op_data, hid_t lapl_id)
+{
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(H5Ovisit_by_name, FAIL)
+
+ /* Check args */
+ if(!obj_name || !*obj_name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
+ 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 object visitation routine */
+ if((ret_value = H5O_visit(loc_id, obj_name, idx_type, order, op, op_data, lapl_id, H5AC_ind_dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "object visitation failed")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Ovisit_by_name() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5Oclose
*
* Purpose: Close an open file object.
@@ -1124,7 +1262,7 @@ H5O_open_name(H5G_loc_t *loc, const char *name, hid_t lapl_id)
loc_found = TRUE;
/* Open the object */
- if((ret_value = H5O_open_by_loc(&obj_loc, H5AC_dxpl_id)) < 0)
+ if((ret_value = H5O_open_by_loc(&obj_loc, H5AC_ind_dxpl_id)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open object")
done:
@@ -2456,3 +2594,255 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_get_rc_and_type() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_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 25, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_free_visit_visited(void *item, void UNUSED *key, void UNUSED *operator_data/*in,out*/)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_free_visit_visited)
+
+ H5FL_FREE(H5_obj_t, item);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O_free_visit_visited() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_visit_cb
+ *
+ * Purpose: Callback function for recursively visiting objects from a group
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Nov 25, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_visit_cb(hid_t UNUSED group, const char *name, const H5L_info_t *linfo,
+ void *_udata)
+{
+ H5O_iter_visit_ud_t *udata = (H5O_iter_visit_ud_t *)_udata; /* User data for callback */
+ 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 */
+ herr_t ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_visit_cb)
+
+ /* Sanity check */
+ HDassert(name);
+ HDassert(linfo);
+ HDassert(udata);
+
+ /* Check if this is a hard link */
+ if(linfo->type == H5L_TYPE_HARD) {
+ H5_obj_t obj_pos; /* Object "position" for this 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->start_loc, name, &obj_loc/*out*/, udata->lapl_id, udata->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_OHDR, 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)) {
+ H5O_info_t oinfo; /* Object info */
+
+ /* Get the object's info */
+ if(H5O_get_info(&obj_oloc, udata->dxpl_id, TRUE, &oinfo) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5_ITER_ERROR, "unable to get object info")
+
+ /* Make the application callback */
+ ret_value = (udata->op)(udata->obj_id, name, &oinfo, udata->op_data);
+
+ /* Check for continuing to visit objects */
+ if(ret_value == H5_ITER_CONT) {
+ /* If its ref count is > 1, we add it to the list of visited objects */
+ /* (because it could come up again during traversal) */
+ if(oinfo.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_OHDR, 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_OHDR, H5E_CANTINSERT, H5_ITER_ERROR, "can't insert object node into visited list")
+ } /* end if */
+ } /* end if */
+ } /* end if */
+ } /* end if */
+
+done:
+ /* Release resources */
+ if(obj_found && H5G_loc_free(&obj_loc) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, H5_ITER_ERROR, "can't free location")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_visit_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_visit
+ *
+ * Purpose: Recursively visit an object and all the objects reachable
+ * from it. If the starting object is a group, all the objects
+ * linked to from that group will be visited. 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: Soft links and user-defined links are ignored during
+ * this operation.
+ *
+ * NOTE: Each _object_ reachable from the initial group will only
+ * be visited once. If multiple hard links point to the same
+ * object, the first link to the object's path (according to the
+ * iteration index and iteration order given) will be used to in
+ * the callback about the 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 24 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_visit(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
+ H5_iter_order_t order, H5O_iterate_t op, void *op_data, hid_t lapl_id,
+ hid_t dxpl_id)
+{
+ H5O_iter_visit_ud_t udata; /* User data for callback */
+ H5G_loc_t loc; /* Location of reference object */
+ H5G_loc_t obj_loc; /* Location used to open object */
+ H5G_name_t obj_path; /* Opened object group hier. path */
+ H5O_loc_t obj_oloc; /* Opened object object location */
+ hbool_t loc_found = FALSE; /* Entry at 'name' found */
+ H5O_info_t oinfo; /* Object info struct */
+ hid_t obj_id = (-1); /* ID of object */
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_visit, FAIL)
+
+ /* Portably initialize user data struct to zeros */
+ HDmemset(&udata, 0, sizeof(udata));
+
+ /* Check args */
+ if(H5G_loc(loc_id, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+
+ /* 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's location */
+ if(H5G_loc_find(&loc, obj_name, &obj_loc/*out*/, lapl_id, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
+ loc_found = TRUE;
+
+ /* Get the object's info */
+ if(H5O_get_info(&obj_oloc, dxpl_id, TRUE, &oinfo) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to get object info")
+
+ /* Open the object */
+ /* (Takes ownership of the obj_loc information) */
+ if((obj_id = H5O_open_by_loc(&obj_loc, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open object")
+
+ /* Make callback for starting object */
+ if((ret_value = op(obj_id, ".", &oinfo, op_data)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "can't visit objects")
+
+ /* Check for object being a group */
+ if(oinfo.type == H5O_TYPE_GROUP) {
+ H5G_loc_t start_loc; /* Location of starting group */
+
+ /* Get the location of the starting group */
+ if(H5G_loc(obj_id, &start_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+
+ /* Set up user data for visiting links */
+ udata.obj_id = obj_id;
+ udata.start_loc = &start_loc;
+ udata.lapl_id = lapl_id;
+ udata.dxpl_id = dxpl_id;
+ udata.op = op;
+ udata.op_data = op_data;
+
+ /* Create skip list to store visited object information */
+ if((udata.visited = H5SL_create(H5SL_TYPE_OBJ, 0.5, (size_t)16)) == NULL)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "can't create skip list for visited objects")
+
+ /* If its ref count is > 1, we add it to the list of visited objects */
+ /* (because it could come up again during traversal) */
+ if(oinfo.rc > 1) {
+ H5_obj_t *obj_pos; /* New object node for visited list */
+
+ /* Allocate new object "position" node */
+ if((obj_pos = H5FL_MALLOC(H5_obj_t)) == NULL)
+ HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "can't allocate object node")
+
+ /* Construct unique "position" for this object */
+ obj_pos->fileno = oinfo.fileno;
+ obj_pos->addr = oinfo.addr;
+
+ /* Add to list of visited objects */
+ if(H5SL_insert(udata.visited, obj_pos, obj_pos) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object node into visited list")
+ } /* end if */
+
+ /* Call internal group visitation routine */
+ if((ret_value = H5G_visit(obj_id, ".", idx_type, order, H5O_visit_cb, &udata, lapl_id, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "object visitation failed")
+ } /* end if */
+
+done:
+ if(obj_id > 0) {
+ if(H5I_dec_ref(obj_id) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to close object")
+ } /* end if */
+ else if(loc_found && H5G_loc_free(&obj_loc) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't free location")
+ if(udata.visited)
+ H5SL_destroy(udata.visited, H5O_free_visit_visited, NULL);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_visit() */
+
+
diff --git a/src/H5Opublic.h b/src/H5Opublic.h
index 6ddd565..64fdd07 100644
--- a/src/H5Opublic.h
+++ b/src/H5Opublic.h
@@ -124,6 +124,10 @@ typedef struct H5O_info_t {
/* Typedef for message creation indexes */
typedef uint32_t H5O_msg_crt_idx_t;
+/* Prototype for H5Ovisit/H5Ovisit_by_name() operator */
+typedef herr_t (*H5O_iterate_t)(hid_t obj, const char *name, const H5O_info_t *info,
+ void *op_data);
+
/********************/
/* Public Variables */
@@ -159,6 +163,11 @@ H5_DLL herr_t H5Oset_comment_by_name(hid_t loc_id, const char *name,
H5_DLL ssize_t H5Oget_comment(hid_t obj_id, char *comment, size_t bufsize);
H5_DLL ssize_t H5Oget_comment_by_name(hid_t loc_id, const char *name,
char *comment, size_t bufsize, hid_t lapl_id);
+H5_DLL herr_t H5Ovisit(hid_t obj_id, H5_index_t idx_type, H5_iter_order_t order,
+ H5O_iterate_t op, void *op_data);
+H5_DLL herr_t H5Ovisit_by_name(hid_t loc_id, const char *obj_name,
+ H5_index_t idx_type, H5_iter_order_t order, H5O_iterate_t op,
+ void *op_data, hid_t lapl_id);
H5_DLL herr_t H5Oclose(hid_t object_id);
/* Symbols defined for compatibility with previous versions of the HDF5 API.
diff --git a/test/links.c b/test/links.c
index 8208b2c..cef354d 100644
--- a/test/links.c
+++ b/test/links.c
@@ -165,12 +165,90 @@ static const link_visit_t lvisit2[] = {
{"hard_zero/soft_two", 1}
};
-
typedef struct {
- unsigned idx; /* Index in visit structure */
- const link_visit_t *info; /* Pointer to the visit structure to use */
+ unsigned idx; /* Index in link visit structure */
+ const link_visit_t *info; /* Pointer to the link visit structure to use */
} lvisit_ud_t;
+
+/* Object visit structs */
+typedef struct {
+ const char *path; /* Path to object */
+ H5O_type_t type; /* Type of object */
+} obj_visit_t;
+static const obj_visit_t ovisit0_old[] = {
+ {".", 0},
+ {"Dataset_zero", 1},
+ {"Group1", 0},
+ {"Group1/Dataset_one", 1},
+ {"Group1/Group2", 0},
+ {"Group1/Group2/Dataset_two", 1},
+ {"Group1/Group2/Type_two", 2},
+ {"Group1/Type_one", 2},
+ {"Type_zero", 2}
+};
+static const obj_visit_t ovisit0_new[] = {
+ {".", 0},
+ {"Dataset_zero", 1},
+ {"Group1", 0},
+ {"Group1/Dataset_one", 1},
+ {"Group1/Group2", 0},
+ {"Group1/Group2/Dataset_two", 1},
+ {"Group1/Group2/Type_two", 2},
+ {"Group1/Type_one", 2},
+ {"Type_zero", 2}
+};
+static const obj_visit_t ovisit1_old[] = {
+ {".", 0},
+ {"Dataset_one", 1},
+ {"Group2", 0},
+ {"Group2/Dataset_two", 1},
+ {"Group2/Type_two", 2},
+ {"Group2/hard_zero", 0},
+ {"Group2/hard_zero/Dataset_zero", 1},
+ {"Group2/hard_zero/Type_zero", 2},
+ {"Type_one", 2}
+};
+static const obj_visit_t ovisit1_new[] = {
+ {".", 0},
+ {"Dataset_one", 1},
+ {"Group2", 0},
+ {"Group2/Dataset_two", 1},
+ {"Group2/Type_two", 2},
+ {"Group2/hard_zero", 0},
+ {"Group2/hard_zero/Dataset_zero", 1},
+ {"Group2/hard_zero/Type_zero", 2},
+ {"Type_one", 2}
+};
+static const obj_visit_t ovisit2_old[] = {
+ {".", 0},
+ {"Dataset_two", 1},
+ {"Type_two", 2},
+ {"hard_zero", 0},
+ {"hard_zero/Dataset_zero", 1},
+ {"hard_zero/Group1", 0},
+ {"hard_zero/Group1/Dataset_one", 1},
+ {"hard_zero/Group1/Type_one", 2},
+ {"hard_zero/Type_zero", 2}
+};
+static const obj_visit_t ovisit2_new[] = {
+ {".", 0},
+ {"Dataset_two", 1},
+ {"Type_two", 2},
+ {"hard_zero", 0},
+ {"hard_zero/Dataset_zero", 1},
+ {"hard_zero/Group1", 0},
+ {"hard_zero/Group1/Dataset_one", 1},
+ {"hard_zero/Group1/Type_one", 2},
+ {"hard_zero/Type_zero", 2}
+};
+
+typedef struct {
+ unsigned idx; /* Index in object visit structure */
+ const obj_visit_t *info; /* Pointer to the object visit structure to use */
+} ovisit_ud_t;
+
+
/*-------------------------------------------------------------------------
* Function: mklinks
@@ -5530,6 +5608,185 @@ error:
/*-------------------------------------------------------------------------
+ * Function: visit_obj_cb
+ *
+ * Purpose: Callback routine for visiting objects in a file
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Quincey Koziol
+ * Sunday, November 25, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+visit_obj_cb(hid_t UNUSED group_id, const char *name, const H5O_info_t *oinfo,
+ void *_op_data)
+{
+ ovisit_ud_t *op_data = (ovisit_ud_t *)_op_data;
+
+ /* Check for correct object information */
+ if(HDstrcmp(op_data->info[op_data->idx].path, name)) return(H5_ITER_ERROR);
+ if(op_data->info[op_data->idx].type != oinfo->type) return(H5_ITER_ERROR);
+
+ /* Advance to next location in expected output */
+ op_data->idx++;
+
+ return(H5_ITER_CONT);
+} /* end visit_link_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: obj_visit
+ *
+ * Purpose: Test the object visiting routine
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Quincey Koziol
+ * Sunday, November 25, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+obj_visit(hid_t fapl, hbool_t new_format)
+{
+ ovisit_ud_t udata; /* User-data for visiting */
+ hid_t fid = -1;
+ hid_t gid = -1; /* Group ID */
+
+ if(new_format)
+ TESTING("object visiting (w/new group format)")
+ else
+ TESTING("object visiting")
+
+ /* Construct "interesting" file to visit */
+ if((fid = build_visit_file(fapl)) < 0) TEST_ERROR
+
+ /* Visit all the objects reachable from the root group (with file ID) */
+ udata.idx = 0;
+ udata.info = new_format ? ovisit0_new : ovisit0_old;
+ if(H5Ovisit(fid, H5_INDEX_NAME, H5_ITER_INC, visit_obj_cb, &udata) < 0) FAIL_STACK_ERROR
+
+ /* Visit all the objects reachable from the root group (with group ID) */
+ if((gid = H5Gopen2(fid, "/", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
+ udata.idx = 0;
+ udata.info = new_format ? ovisit0_new : ovisit0_old;
+ if(H5Ovisit(gid, H5_INDEX_NAME, H5_ITER_INC, visit_obj_cb, &udata) < 0) FAIL_STACK_ERROR
+ if(H5Gclose(gid) < 0) FAIL_STACK_ERROR
+
+
+ /* Visit all the objects reachable from each internal group */
+ if((gid = H5Gopen2(fid, "/Group1", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
+ udata.idx = 0;
+ udata.info = new_format ? ovisit1_new : ovisit1_old;
+ if(H5Ovisit(gid, H5_INDEX_NAME, H5_ITER_INC, visit_obj_cb, &udata) < 0) FAIL_STACK_ERROR
+ if(H5Gclose(gid) < 0) FAIL_STACK_ERROR
+
+ if((gid = H5Gopen2(fid, "/Group1/Group2", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
+ udata.idx = 0;
+ udata.info = new_format ? ovisit2_new : ovisit2_old;
+ if(H5Ovisit(gid, H5_INDEX_NAME, H5_ITER_INC, visit_obj_cb, &udata) < 0) FAIL_STACK_ERROR
+ if(H5Gclose(gid) < 0) FAIL_STACK_ERROR
+
+
+ /* Close file created */
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Fclose(gid);
+ H5Fclose(fid);
+ } H5E_END_TRY;
+ return -1;
+} /* end obj_visit() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: obj_visit_by_name
+ *
+ * Purpose: Test the object visiting "by name" routine
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Quincey Koziol
+ * Sunday, November 25, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+obj_visit_by_name(hid_t fapl, hbool_t new_format)
+{
+ ovisit_ud_t udata; /* User-data for visiting */
+ hid_t fid = -1;
+ hid_t gid = -1; /* Group ID */
+
+ if(new_format)
+ TESTING("object visiting by name (w/new group format)")
+ else
+ TESTING("object visiting by name")
+
+ /* Construct "interesting" file to visit */
+ if((fid = build_visit_file(fapl)) < 0) TEST_ERROR
+
+ /* Visit all the objects reachable from the root group (with file ID) */
+ udata.idx = 0;
+ udata.info = new_format ? ovisit0_new : ovisit0_old;
+ if(H5Ovisit_by_name(fid, "/", H5_INDEX_NAME, H5_ITER_INC, visit_obj_cb, &udata, H5P_DEFAULT) < 0) FAIL_STACK_ERROR
+
+ /* Visit all the objects reachable from the root group (with group ID) */
+ if((gid = H5Gopen2(fid, "/", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
+ udata.idx = 0;
+ udata.info = new_format ? ovisit0_new : ovisit0_old;
+ if(H5Ovisit_by_name(gid, ".", H5_INDEX_NAME, H5_ITER_INC, visit_obj_cb, &udata, H5P_DEFAULT) < 0) FAIL_STACK_ERROR
+ if(H5Gclose(gid) < 0) FAIL_STACK_ERROR
+
+
+ /* Visit all the objects reachable from each internal group */
+ udata.idx = 0;
+ udata.info = new_format ? ovisit1_new : ovisit1_old;
+ if(H5Ovisit_by_name(fid, "/Group1", H5_INDEX_NAME, H5_ITER_INC, visit_obj_cb, &udata, H5P_DEFAULT) < 0) FAIL_STACK_ERROR
+
+ if((gid = H5Gopen2(fid, "/Group1", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
+ udata.idx = 0;
+ udata.info = new_format ? ovisit1_new : ovisit1_old;
+ if(H5Ovisit_by_name(gid, ".", H5_INDEX_NAME, H5_ITER_INC, visit_obj_cb, &udata, H5P_DEFAULT) < 0) FAIL_STACK_ERROR
+ if(H5Gclose(gid) < 0) FAIL_STACK_ERROR
+
+
+ udata.idx = 0;
+ udata.info = new_format ? ovisit2_new : ovisit2_old;
+ if(H5Ovisit_by_name(fid, "/Group1/Group2", H5_INDEX_NAME, H5_ITER_INC, visit_obj_cb, &udata, H5P_DEFAULT) < 0) FAIL_STACK_ERROR
+
+ if((gid = H5Gopen2(fid, "/Group1/Group2", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
+ udata.idx = 0;
+ udata.info = new_format ? ovisit2_new : ovisit2_old;
+ if(H5Ovisit_by_name(gid, ".", H5_INDEX_NAME, H5_ITER_INC, visit_obj_cb, &udata, H5P_DEFAULT) < 0) FAIL_STACK_ERROR
+ if(H5Gclose(gid) < 0) FAIL_STACK_ERROR
+
+
+ /* Close file created */
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Fclose(gid);
+ H5Fclose(fid);
+ } H5E_END_TRY;
+ return -1;
+} /* end obj_visit_by_name() */
+
+
+/*-------------------------------------------------------------------------
* Function: corder_create_empty
*
* Purpose: Create an empty group with creation order indices
@@ -10023,6 +10280,8 @@ main(void)
/* Misc. extra tests, useful for both new & old format files */
nerrors += link_visit(my_fapl, new_format) < 0 ? 1 : 0;
nerrors += link_visit_by_name(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += obj_visit(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += obj_visit_by_name(my_fapl, new_format) < 0 ? 1 : 0;
/* Keep this test last, it's testing files that are used above */
nerrors += check_all_closed(my_fapl, new_format) < 0 ? 1 : 0;