mirror of
https://github.com/HDFGroup/hdf5.git
synced 2026-09-25 04:09:44 +03:00
Improve performance of H5Ovisit with deeply nested groups (#6272)
Improve performance of H5Ovisit (and H5Ocopy, and functions that retrieve and object name) by passing more information about the visited object from the underlying H5G_visit routine to these callbacks. Introduced an internal object callback for H5G_visit to facilitate this. H5Ovisit1 and potentially H5Ovisit2 are still slow with deeply nested groups due to the way these deprecated functions interact with the VOL layer.
This commit is contained in:
@@ -65,6 +65,10 @@ We would like to thank the many HDF5 community members who contributed to this r
|
||||
|
||||
## Library
|
||||
|
||||
### Improve performance of H5Ovisit() with deeply nested group structures
|
||||
|
||||
`H5Ovisit()` would previously internally traverse each object's path name from the iteration root group in order to retrieve information about that object, causing severe performance degradation with a deeply nested group structure. Modified the algorithm to instead retrieve information directly from the object. To get this benefit, users should use `H5Ovisit3()`, or use `H5Ovisit2()` with neither `H5O_INFO_HDR` nor `H5O_INFO_META_SIZE` selected in the `fields` parameter. Performance of `H5Ocopy()`, `H5Iget_name()`, and external links with a callback set should also improve in similar situations.
|
||||
|
||||
## Parallel Library
|
||||
|
||||
## Fortran Library
|
||||
|
||||
+90
-77
@@ -61,16 +61,17 @@ typedef struct {
|
||||
|
||||
/* 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 */
|
||||
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_iterate2_t op; /* Application callback */
|
||||
void *op_data; /* Application's op data */
|
||||
hid_t gid; /* The group ID for the starting group */
|
||||
H5G_loc_t *curr_loc; /* Location of starting group */
|
||||
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_iterate2_t link_op; /* Application callback for link operations */
|
||||
H5G_obj_iterate_t obj_op; /* Library internal callback for object operations */
|
||||
void *op_data; /* Application's op data */
|
||||
} H5G_iter_visit_ud_t;
|
||||
|
||||
/********************/
|
||||
@@ -981,7 +982,6 @@ 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_info2_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 */
|
||||
@@ -1016,17 +1016,22 @@ H5G__visit_cb(const H5O_link_t *lnk, void *_udata)
|
||||
strncpy(&(udata->path[old_path_len]), lnk->name, link_name_len + 1);
|
||||
udata->curr_path_len += link_name_len;
|
||||
|
||||
/* Construct the link info from the link message */
|
||||
if (H5G_link_to_info(udata->curr_loc->oloc, lnk, &info) < 0)
|
||||
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for link");
|
||||
/* Check if we're performing a link callback */
|
||||
if (udata->link_op) {
|
||||
H5L_info2_t info; /* Link info */
|
||||
|
||||
/* Prepare & restore library for user callback */
|
||||
H5_BEFORE_USER_CB(H5_ITER_ERROR)
|
||||
{
|
||||
/* Make the application callback */
|
||||
ret_value = (udata->op)(udata->gid, udata->path, &info, udata->op_data);
|
||||
}
|
||||
H5_AFTER_USER_CB(H5_ITER_ERROR)
|
||||
/* Construct the link info from the link message */
|
||||
if (H5G_link_to_info(udata->curr_loc->oloc, lnk, &info) < 0)
|
||||
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for link");
|
||||
|
||||
/* Prepare & restore library for user callback */
|
||||
H5_BEFORE_USER_CB(H5_ITER_ERROR)
|
||||
{
|
||||
/* Make the application callback */
|
||||
ret_value = (udata->link_op)(udata->gid, udata->path, &info, udata->op_data);
|
||||
}
|
||||
H5_AFTER_USER_CB(H5_ITER_ERROR)
|
||||
}
|
||||
|
||||
/* Check for doing more work */
|
||||
if (ret_value == H5_ITER_CONT && lnk->type == H5L_TYPE_HARD) {
|
||||
@@ -1051,72 +1056,79 @@ H5G__visit_cb(const H5O_link_t *lnk, void *_udata)
|
||||
if (NULL == H5SL_search(udata->visited, &obj_pos)) {
|
||||
H5O_type_t otype; /* Basic object type (group, dataset, etc.) */
|
||||
|
||||
/* Get the object's reference count and type */
|
||||
if (H5O_get_rc_and_type(&obj_oloc, NULL, &otype) < 0)
|
||||
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get object info");
|
||||
/* Make the internal library object callback if present */
|
||||
if (udata->obj_op)
|
||||
ret_value = (udata->obj_op)(udata->gid, udata->path, &obj_oloc, udata->op_data);
|
||||
|
||||
/* Add it to the list of visited objects */
|
||||
{
|
||||
H5_obj_t *new_node; /* New object node for visited list */
|
||||
/* Check if we're continuing iteration */
|
||||
if (ret_value == H5_ITER_CONT) {
|
||||
/* Get the object's type */
|
||||
if (H5O_obj_type(&obj_oloc, &otype) < 0)
|
||||
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get object type");
|
||||
|
||||
/* 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");
|
||||
/* Add this object to the list of visited objects */
|
||||
{
|
||||
H5_obj_t *new_node; /* New object node for visited list */
|
||||
|
||||
/* Set node information */
|
||||
*new_node = obj_pos;
|
||||
/* 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");
|
||||
|
||||
/* 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");
|
||||
}
|
||||
/* Set node information */
|
||||
*new_node = obj_pos;
|
||||
|
||||
/* 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 */
|
||||
htri_t linfo_exists; /* Whether the link info message exists */
|
||||
/* 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");
|
||||
}
|
||||
|
||||
/* Add the path separator to the current path */
|
||||
assert(udata->path[udata->curr_path_len] == '\0');
|
||||
strncpy(&(udata->path[udata->curr_path_len]), "/", (size_t)2);
|
||||
udata->curr_path_len++;
|
||||
/* 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 */
|
||||
htri_t linfo_exists; /* Whether the link info message exists */
|
||||
|
||||
/* Attempt to get the link info for this group */
|
||||
if ((linfo_exists = H5G__obj_get_linfo(&obj_oloc, &linfo)) < 0)
|
||||
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "can't check for link info message");
|
||||
if (linfo_exists) {
|
||||
/* 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)
|
||||
/* Add the path separator to the current path */
|
||||
assert(udata->path[udata->curr_path_len] == '\0');
|
||||
strncpy(&(udata->path[udata->curr_path_len]), "/", (size_t)2);
|
||||
udata->curr_path_len++;
|
||||
|
||||
/* Attempt to get the link info for this group */
|
||||
if ((linfo_exists = H5G__obj_get_linfo(&obj_oloc, &linfo)) < 0)
|
||||
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "can't check for link info message");
|
||||
if (linfo_exists) {
|
||||
/* 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
|
||||
assert(idx_type == H5_INDEX_NAME);
|
||||
} /* end if */
|
||||
else {
|
||||
/* 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 */
|
||||
else
|
||||
assert(idx_type == H5_INDEX_NAME);
|
||||
} /* end if */
|
||||
else {
|
||||
/* 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;
|
||||
/* 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);
|
||||
/* Iterate over links in group */
|
||||
ret_value = H5G__obj_iterate(&obj_oloc, idx_type, udata->order, (hsize_t)0, NULL,
|
||||
H5G__visit_cb, udata);
|
||||
|
||||
/* Restore location */
|
||||
udata->curr_loc = old_loc;
|
||||
} /* end if */
|
||||
} /* end if */
|
||||
} /* end if */
|
||||
/* Restore location */
|
||||
udata->curr_loc = old_loc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
/* Reset path back to incoming path */
|
||||
@@ -1157,7 +1169,7 @@ done:
|
||||
*/
|
||||
herr_t
|
||||
H5G_visit(H5G_loc_t *loc, const char *group_name, H5_index_t idx_type, H5_iter_order_t order,
|
||||
H5L_iterate2_t op, void *op_data)
|
||||
H5L_iterate2_t link_op, H5G_obj_iterate_t obj_op, void *op_data)
|
||||
{
|
||||
H5G_iter_visit_ud_t udata; /* User data for callback */
|
||||
H5O_linfo_t linfo; /* Link info message */
|
||||
@@ -1193,7 +1205,8 @@ H5G_visit(H5G_loc_t *loc, const char *group_name, H5_index_t idx_type, H5_iter_o
|
||||
udata.curr_loc = &start_loc;
|
||||
udata.idx_type = idx_type;
|
||||
udata.order = order;
|
||||
udata.op = op;
|
||||
udata.link_op = link_op;
|
||||
udata.obj_op = obj_op;
|
||||
udata.op_data = op_data;
|
||||
|
||||
/* Allocate space for the path name */
|
||||
@@ -1206,7 +1219,7 @@ H5G_visit(H5G_loc_t *loc, const char *group_name, H5_index_t idx_type, H5_iter_o
|
||||
if ((udata.visited = H5SL_create(H5SL_TYPE_OBJ, NULL)) == NULL)
|
||||
HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "can't create skip list for visited objects");
|
||||
|
||||
/* Add it to the list of visited objects */
|
||||
/* Add parent group to the list of visited objects */
|
||||
{
|
||||
H5_obj_t *obj_pos; /* New object node for visited list */
|
||||
|
||||
|
||||
+14
-47
@@ -1040,64 +1040,31 @@ done:
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5G__get_name_by_addr_cb(hid_t gid, const char *path, const H5L_info2_t *linfo, void *_udata)
|
||||
H5G__get_name_by_addr_cb(hid_t gid, const char *path, const H5O_loc_t *obj_oloc, void *_udata)
|
||||
{
|
||||
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 */
|
||||
bool obj_found = false; /* Object at 'path' found */
|
||||
herr_t ret_value = H5_ITER_CONT; /* Return value */
|
||||
H5G_gnba_iter_t *udata = (H5G_gnba_iter_t *)_udata; /* User data for iteration */
|
||||
herr_t ret_value = H5_ITER_CONT; /* Return value */
|
||||
|
||||
FUNC_ENTER_PACKAGE
|
||||
|
||||
/* Sanity check */
|
||||
assert(path);
|
||||
assert(linfo);
|
||||
assert(obj_oloc);
|
||||
assert(udata);
|
||||
assert(udata->loc);
|
||||
assert(udata->path == NULL);
|
||||
|
||||
/* Check for hard link with correct address */
|
||||
if (linfo->type == H5L_TYPE_HARD) {
|
||||
haddr_t link_addr;
|
||||
/* Check for object in same file (handles mounted files) */
|
||||
/* (re-verify address, in case we traversed a file mount) */
|
||||
if (udata->loc->addr == obj_oloc->addr && udata->loc->file == obj_oloc->file) {
|
||||
if (NULL == (udata->path = H5MM_strdup(path)))
|
||||
HGOTO_ERROR(H5E_SYM, H5E_CANTALLOC, H5_ITER_ERROR, "can't duplicate path string");
|
||||
|
||||
/* Retrieve hard link address from VOL token */
|
||||
if (H5VL_native_token_to_addr(udata->loc->file, H5I_FILE, linfo->u.token, &link_addr) < 0)
|
||||
HGOTO_ERROR(H5E_SYM, H5E_CANTUNSERIALIZE, FAIL, "can't deserialize object token into address");
|
||||
|
||||
if (udata->loc->addr == link_addr) {
|
||||
H5G_loc_t grp_loc; /* Location of group */
|
||||
|
||||
/* Get group's location */
|
||||
if (H5G_loc(gid, &grp_loc) < 0)
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5_ITER_ERROR, "bad group location");
|
||||
|
||||
/* Set up opened object location to fill in */
|
||||
obj_loc.oloc = &obj_oloc;
|
||||
obj_loc.path = &obj_path;
|
||||
H5G_loc_reset(&obj_loc);
|
||||
|
||||
/* Find the object */
|
||||
if (H5G_loc_find(&grp_loc, path, &obj_loc /*out*/) < 0)
|
||||
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5_ITER_ERROR, "object not found");
|
||||
obj_found = true;
|
||||
|
||||
/* 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) {
|
||||
if (NULL == (udata->path = H5MM_strdup(path)))
|
||||
HGOTO_ERROR(H5E_SYM, H5E_CANTALLOC, H5_ITER_ERROR, "can't duplicate path string");
|
||||
|
||||
/* We found a match so we return immediately */
|
||||
HGOTO_DONE(H5_ITER_STOP);
|
||||
} /* end if */
|
||||
} /* end if */
|
||||
} /* end if */
|
||||
/* We found a match so we return immediately */
|
||||
HGOTO_DONE(H5_ITER_STOP);
|
||||
} /* 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");
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5G__get_name_by_addr_cb() */
|
||||
|
||||
@@ -1145,7 +1112,7 @@ H5G_get_name_by_addr(H5F_t *f, const H5O_loc_t *loc, char *name, size_t size, si
|
||||
udata.path = NULL;
|
||||
|
||||
/* Visit all the links in the file */
|
||||
if ((status = H5G_visit(&root_loc, "/", H5_INDEX_NAME, H5_ITER_NATIVE, H5G__get_name_by_addr_cb,
|
||||
if ((status = H5G_visit(&root_loc, "/", H5_INDEX_NAME, H5_ITER_NATIVE, NULL, H5G__get_name_by_addr_cb,
|
||||
&udata)) < 0)
|
||||
HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "group traversal failed while looking for object name");
|
||||
else if (status > 0)
|
||||
|
||||
+5
-1
@@ -164,6 +164,10 @@ typedef herr_t (*H5G_traverse_t)(H5G_loc_t *grp_loc /*in*/, const char *name,
|
||||
const struct H5O_link_t *lnk /*in*/, H5G_loc_t *obj_loc /*out*/,
|
||||
void *operator_data /*in,out*/, H5G_own_loc_t *own_loc /*out*/);
|
||||
|
||||
/* Typedef for internal library object iteration/visit callback */
|
||||
typedef herr_t (*H5G_obj_iterate_t)(hid_t group, const char *name, const struct H5O_loc_t *obj_oloc,
|
||||
void *op_data);
|
||||
|
||||
/* Describe kind of callback to make for each link */
|
||||
typedef enum H5G_link_iterate_op_type_t {
|
||||
#ifndef H5_NO_DEPRECATED_SYMBOLS
|
||||
@@ -217,7 +221,7 @@ H5_DLL herr_t H5G_traverse(const H5G_loc_t *loc, const char *name, unsigned targ
|
||||
H5_DLL herr_t H5G_iterate(H5G_loc_t *loc, 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);
|
||||
H5_DLL herr_t H5G_visit(H5G_loc_t *loc, const char *group_name, H5_index_t idx_type, H5_iter_order_t order,
|
||||
H5L_iterate2_t op, void *op_data);
|
||||
H5L_iterate2_t link_op, H5G_obj_iterate_t obj_op, void *op_data);
|
||||
|
||||
/*
|
||||
* Functions that understand links in groups
|
||||
|
||||
+10
-31
@@ -79,7 +79,7 @@ static herr_t H5O__copy_obj(H5G_loc_t *src_loc, H5G_loc_t *dst_loc, const char *
|
||||
hid_t lcpl_id);
|
||||
static herr_t H5O__copy_free_comm_dt_cb(void *item, void *key, void *op_data);
|
||||
static int H5O__copy_comm_dt_cmp(const void *dt1, const void *dt2);
|
||||
static herr_t H5O__copy_search_comm_dt_cb(hid_t group, const char *name, const H5L_info2_t *linfo,
|
||||
static herr_t H5O__copy_search_comm_dt_cb(hid_t group, const char *name, const H5O_loc_t *obj_oloc,
|
||||
void *udata);
|
||||
static htri_t H5O__copy_search_comm_dt(H5F_t *file_src, H5O_t *oh_src, H5O_loc_t *oloc_dst /*in, out*/,
|
||||
H5O_copy_t *cpy_info);
|
||||
@@ -1229,7 +1229,7 @@ done:
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5O__copy_search_comm_dt_check(H5O_loc_t *obj_oloc, H5O_copy_search_comm_dt_ud_t *udata)
|
||||
H5O__copy_search_comm_dt_check(const H5O_loc_t *obj_oloc, H5O_copy_search_comm_dt_ud_t *udata)
|
||||
{
|
||||
H5O_copy_search_comm_dt_key_t *key = NULL; /* Skiplist key */
|
||||
haddr_t *addr = NULL; /* Destination address */
|
||||
@@ -1343,48 +1343,27 @@ done:
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5O__copy_search_comm_dt_cb(hid_t H5_ATTR_UNUSED group, const char *name, const H5L_info2_t *linfo,
|
||||
H5O__copy_search_comm_dt_cb(hid_t H5_ATTR_UNUSED group, const char *name, const H5O_loc_t *obj_oloc,
|
||||
void *_udata)
|
||||
{
|
||||
H5O_copy_search_comm_dt_ud_t *udata =
|
||||
(H5O_copy_search_comm_dt_ud_t *)_udata; /* Skip list of dtypes in dest file */
|
||||
H5G_loc_t obj_loc; /* Location of object */
|
||||
H5O_loc_t obj_oloc; /* Object's object location */
|
||||
H5G_name_t obj_path; /* Object's group hier. path */
|
||||
bool obj_found = false; /* Object at 'name' found */
|
||||
herr_t ret_value = H5_ITER_CONT; /* Return value */
|
||||
herr_t ret_value = H5_ITER_CONT; /* Return value */
|
||||
|
||||
FUNC_ENTER_PACKAGE
|
||||
|
||||
/* Sanity checks */
|
||||
assert(name);
|
||||
assert(linfo);
|
||||
assert(obj_oloc);
|
||||
assert(udata);
|
||||
assert(udata->dst_dt_list);
|
||||
assert(udata->dst_root_loc);
|
||||
|
||||
/* Check if this is a hard link */
|
||||
if (linfo->type == H5L_TYPE_HARD) {
|
||||
/* 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 */
|
||||
if (H5G_loc_find(udata->dst_root_loc, name, &obj_loc /*out*/) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, H5_ITER_ERROR, "object not found");
|
||||
obj_found = true;
|
||||
|
||||
/* Check object and add to skip list if appropriate */
|
||||
if (H5O__copy_search_comm_dt_check(&obj_oloc, udata) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5_ITER_ERROR, "can't check object");
|
||||
} /* end if */
|
||||
/* Check object and add to skip list if appropriate */
|
||||
if (H5O__copy_search_comm_dt_check(obj_oloc, udata) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5_ITER_ERROR, "can't check object");
|
||||
|
||||
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__copy_search_comm_dt_cb */
|
||||
|
||||
@@ -1541,8 +1520,8 @@ H5O__copy_search_comm_dt(H5F_t *file_src, H5O_t *oh_src, H5O_loc_t *oloc_dst /*i
|
||||
|
||||
/* Traverse the destination file, adding committed datatypes to the skip
|
||||
* list */
|
||||
if (H5G_visit(&dst_root_loc, "/", H5_INDEX_NAME, H5_ITER_NATIVE, H5O__copy_search_comm_dt_cb,
|
||||
&udata) < 0)
|
||||
if (H5G_visit(&dst_root_loc, "/", H5_INDEX_NAME, H5_ITER_NATIVE, NULL,
|
||||
H5O__copy_search_comm_dt_cb, &udata) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "object visitation failed");
|
||||
cpy_info->dst_dt_list_complete = true;
|
||||
} /* end if */
|
||||
|
||||
+23
-133
@@ -54,12 +54,10 @@
|
||||
|
||||
/* 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 */
|
||||
H5SL_t *visited; /* Skip list for tracking visited nodes */
|
||||
H5O_iterate2_t op; /* Application callback */
|
||||
void *op_data; /* Application's op data */
|
||||
unsigned fields; /* Selection of object info */
|
||||
hid_t obj_id; /* The ID for the starting group */
|
||||
H5O_iterate2_t op; /* Application callback */
|
||||
void *op_data; /* Application's op data */
|
||||
unsigned fields; /* Selection of object info */
|
||||
} H5O_iter_visit_ud_t;
|
||||
|
||||
/********************/
|
||||
@@ -73,8 +71,7 @@ typedef struct {
|
||||
static herr_t H5O__delete_oh(H5F_t *f, H5O_t *oh);
|
||||
static herr_t H5O__obj_type_real(const H5O_t *oh, H5O_type_t *obj_type);
|
||||
static herr_t H5O__get_hdr_info_real(const H5O_t *oh, H5O_hdr_info_t *hdr);
|
||||
static herr_t H5O__free_visit_visited(void *item, void *key, void *operator_data /*in,out*/);
|
||||
static herr_t H5O__visit_cb(hid_t group, const char *name, const H5L_info2_t *linfo, void *_udata);
|
||||
static herr_t H5O__visit_cb(hid_t group, const char *name, const H5O_loc_t *obj_oloc, void *_udata);
|
||||
static herr_t H5O__obj_class_real(const H5O_t *oh, const H5O_obj_class_t **cls);
|
||||
static herr_t H5O__reset_info2(H5O_info2_t *oinfo);
|
||||
|
||||
@@ -2505,25 +2502,6 @@ 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
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5O__free_visit_visited(void *item, void H5_ATTR_UNUSED *key, void H5_ATTR_UNUSED *operator_data /*in,out*/)
|
||||
{
|
||||
FUNC_ENTER_PACKAGE_NOERR
|
||||
|
||||
item = H5FL_FREE(H5_obj_t, item);
|
||||
|
||||
FUNC_LEAVE_NOAPI(SUCCEED)
|
||||
} /* end H5O__free_visit_visited() */
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O__visit_cb
|
||||
*
|
||||
@@ -2535,85 +2513,32 @@ H5O__free_visit_visited(void *item, void H5_ATTR_UNUSED *key, void H5_ATTR_UNUSE
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5O__visit_cb(hid_t H5_ATTR_UNUSED group, const char *name, const H5L_info2_t *linfo, void *_udata)
|
||||
H5O__visit_cb(hid_t H5_ATTR_UNUSED group, const char *name, const H5O_loc_t *obj_oloc, 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 */
|
||||
bool obj_found = false; /* Object at 'name' found */
|
||||
H5O_info2_t oinfo; /* Object info */
|
||||
herr_t ret_value = H5_ITER_CONT; /* Return value */
|
||||
|
||||
FUNC_ENTER_PACKAGE
|
||||
|
||||
/* Sanity check */
|
||||
assert(name);
|
||||
assert(linfo);
|
||||
assert(obj_oloc);
|
||||
assert(udata);
|
||||
|
||||
/* Check if this is a hard link */
|
||||
if (linfo->type == H5L_TYPE_HARD) {
|
||||
H5_obj_t obj_pos; /* Object "position" for this object */
|
||||
/* Get the object's info */
|
||||
if (H5O_get_info(obj_oloc, &oinfo, udata->fields) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5_ITER_ERROR, "unable to get object info");
|
||||
|
||||
/* 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*/) < 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_info2_t oinfo; /* Object info */
|
||||
|
||||
/* Get the object's info */
|
||||
if (H5O_get_info(&obj_oloc, &oinfo, udata->fields) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5_ITER_ERROR, "unable to get object info");
|
||||
|
||||
/* Prepare & restore library for user callback */
|
||||
H5_BEFORE_USER_CB(FAIL)
|
||||
{
|
||||
/* Make the application callback */
|
||||
ret_value = (udata->op)(udata->obj_id, name, &oinfo, udata->op_data);
|
||||
}
|
||||
H5_AFTER_USER_CB(FAIL)
|
||||
|
||||
/* 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 */
|
||||
/* Prepare & restore library for user callback */
|
||||
H5_BEFORE_USER_CB(FAIL)
|
||||
{
|
||||
/* Make the application callback */
|
||||
ret_value = (udata->op)(udata->obj_id, name, &oinfo, udata->op_data);
|
||||
}
|
||||
H5_AFTER_USER_CB(FAIL)
|
||||
|
||||
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() */
|
||||
|
||||
@@ -2715,51 +2640,19 @@ H5O__visit(H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type, H5_iter_or
|
||||
/* Check for object being a group */
|
||||
if (oinfop->type == H5O_TYPE_GROUP) {
|
||||
H5G_loc_t start_loc; /* Location of starting group */
|
||||
H5G_loc_t vis_loc; /* Location of visited 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.op = op;
|
||||
udata.op_data = op_data;
|
||||
udata.fields = fields;
|
||||
|
||||
/* Create skip list to store visited object information */
|
||||
if ((udata.visited = H5SL_create(H5SL_TYPE_OBJ, NULL)) == 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 (oinfop->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 = oinfop->fileno;
|
||||
|
||||
/* De-serialize object token into an object address */
|
||||
if (H5VL_native_token_to_addr(loc->oloc->file, H5I_FILE, oinfop->token, &(obj_pos->addr)) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTUNSERIALIZE, FAIL,
|
||||
"can't deserialize object token into address");
|
||||
|
||||
/* 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");
|
||||
}
|
||||
|
||||
/* Get the location of the visited group */
|
||||
if (H5G_loc(obj_id, &vis_loc) < 0)
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location");
|
||||
udata.obj_id = obj_id;
|
||||
udata.op = op;
|
||||
udata.op_data = op_data;
|
||||
udata.fields = fields;
|
||||
|
||||
/* Call internal group visitation routine */
|
||||
if ((ret_value = H5G_visit(&vis_loc, ".", idx_type, order, H5O__visit_cb, &udata)) < 0)
|
||||
if ((ret_value = H5G_visit(&start_loc, ".", idx_type, order, NULL, H5O__visit_cb, &udata)) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "object visitation failed");
|
||||
} /* end if */
|
||||
|
||||
@@ -2772,9 +2665,6 @@ done:
|
||||
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() */
|
||||
|
||||
|
||||
@@ -356,7 +356,7 @@ H5VL__native_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_
|
||||
if (iter_args->recursive) {
|
||||
/* H5Lvisit */
|
||||
if ((ret_value = H5G_visit(&loc, ".", iter_args->idx_type, iter_args->order,
|
||||
iter_args->op, iter_args->op_data)) < 0)
|
||||
iter_args->op, NULL, iter_args->op_data)) < 0)
|
||||
HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "link visitation failed");
|
||||
} /* end if */
|
||||
else {
|
||||
@@ -371,7 +371,7 @@ H5VL__native_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_
|
||||
/* H5Lvisit_by_name */
|
||||
if ((ret_value =
|
||||
H5G_visit(&loc, loc_params->loc_data.loc_by_name.name, iter_args->idx_type,
|
||||
iter_args->order, iter_args->op, iter_args->op_data)) < 0)
|
||||
iter_args->order, iter_args->op, NULL, iter_args->op_data)) < 0)
|
||||
HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "link visitation failed");
|
||||
} /* end if */
|
||||
else {
|
||||
|
||||
Reference in New Issue
Block a user