From 8333adf8ffc1265440aefad62e0cd9ab33175bd7 Mon Sep 17 00:00:00 2001 From: Raymond Lu Date: Mon, 25 Nov 2002 12:59:14 -0500 Subject: [svn-r6136] Purpose: new functions Description: H5Gget_num_objs, H5Gget_objname_by_idx and H5Gget_objtype_by_idx. Platforms tested: modi4, arabica, eirene Misc. update: RELEASE.txt updated. --- release_docs/RELEASE.txt | 2 + src/H5B.c | 16 ++- src/H5Bprivate.h | 11 +- src/H5Distore.c | 20 ++-- src/H5Fistore.c | 20 ++-- src/H5G.c | 261 +++++++++++++++++++++++++++++++++++++++++++++++ src/H5Gnode.c | 161 +++++++++++++++++++++++++++-- src/H5Gpkg.h | 23 ++++- src/H5Gprivate.h | 3 + src/H5Gpublic.h | 3 + test/titerate.c | 208 +++++++++++++++++++++++++++++++++++-- 11 files changed, 680 insertions(+), 48 deletions(-) diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index c50be99..a6d3194 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -239,6 +239,8 @@ Documentation New Features ============ + * New functions H5Gget_num_objs, H5Gget_objname_by_idx and H5Gget_objtype_by_idx + are added to the library. SLU - 2002/11/25 * H5Dget_offset is added to return the offset of a dataset's data relative to the beginning of the file. SLU - 2002/11/7 * Functions H5Tget_native_type and H5Tis_variable_str are added. The first diff --git a/src/H5B.c b/src/H5B.c index 4d1c328..700cf3f 100644 --- a/src/H5B.c +++ b/src/H5B.c @@ -1473,9 +1473,10 @@ H5B_iterate (H5F_t *f, const H5B_class_t *type, H5B_operator_t op, haddr_t addr, haddr_t cur_addr = HADDR_UNDEF; haddr_t *child = NULL; uint8_t *key = NULL; - int i, nchildren; + int i, nchildren; herr_t ret_value = SUCCEED; - + H5B_iterate_t ret_flag = H5B_ITER_CONT; + FUNC_ENTER_NOAPI(H5B_iterate, FAIL); /* @@ -1526,11 +1527,16 @@ H5B_iterate (H5F_t *f, const H5B_class_t *type, H5B_operator_t op, haddr_t addr, * Perform the iteration operator, which might invoke an * application callback. */ - for (i=0; isizeof_nkey, + for (i=0; isizeof_nkey, child[i], key+(i+1)*type->sizeof_nkey, udata); - if (ret_value<0) + if (ret_flag==H5B_ITER_ERROR) { HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "iterator function failed"); + } else if(ret_flag==H5B_ITER_STOP) { + HGOTO_DONE(SUCCEED); + } else { + ; + } } /* end for */ } /* end for */ } /* end else */ diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h index 9f2937c..3a59d93 100644 --- a/src/H5Bprivate.h +++ b/src/H5Bprivate.h @@ -50,9 +50,16 @@ typedef enum H5B_ins_t { H5B_INS_REMOVE = 5 /*remove current node */ } H5B_ins_t; +/* Define return values from operator callback function for H5B_iterate */ +typedef enum H5B_iterate_t { + H5B_ITER_ERROR = -1, /*error return value */ + H5B_ITER_CONT = 0, /*continue the loop */ + H5B_ITER_STOP = 1 /*stop and break the loop */ +} H5B_iterate_t; + /* Define the operator callback function pointer for H5B_iterate() */ -typedef herr_t (*H5B_operator_t)(H5F_t *f, void *_lt_key, haddr_t addr, - void *_rt_key, void *_udata); +typedef H5B_iterate_t (*H5B_operator_t)(H5F_t *f, void *_lt_key, haddr_t addr, + void *_rt_key, void *_udata); /* * Each class of object that can be pointed to by a B-link tree has a diff --git a/src/H5Distore.c b/src/H5Distore.c index 147e143..ea74165 100644 --- a/src/H5Distore.c +++ b/src/H5Distore.c @@ -122,9 +122,9 @@ static H5B_ins_t H5F_istore_insert(H5F_t *f, haddr_t addr, void *_lt_key, void *_udata, void *_rt_key, hbool_t *rt_key_changed, haddr_t *new_node/*out*/); -static herr_t H5F_istore_iter_allocated(H5F_t *f, void *left_key, haddr_t addr, +static H5B_iterate_t H5F_istore_iter_allocated(H5F_t *f, void *left_key, haddr_t addr, void *right_key, void *_udata); -static herr_t H5F_istore_iter_dump(H5F_t *f, void *left_key, haddr_t addr, +static H5B_iterate_t H5F_istore_iter_dump(H5F_t *f, void *left_key, haddr_t addr, void *right_key, void *_udata); static herr_t H5F_istore_decode_key(H5F_t *f, H5B_t *bt, uint8_t *raw, void *_key); @@ -134,7 +134,7 @@ static herr_t H5F_istore_debug_key(FILE *stream, int indent, int fwidth, const void *key, const void *udata); static haddr_t H5F_istore_get_addr(H5F_t *f, const H5O_layout_t *layout, const hssize_t offset[]); -static herr_t H5F_istore_prune_extent(H5F_t *f, void *_lt_key, haddr_t addr, +static H5B_iterate_t H5F_istore_prune_extent(H5F_t *f, void *_lt_key, haddr_t addr, void *_rt_key, void *_udata); static H5B_ins_t H5F_istore_remove( H5F_t *f, haddr_t addr, void *_lt_key, hbool_t *lt_key_changed, void *_udata, void *_rt_key, @@ -768,7 +768,7 @@ done: * Changed to callback from H5B_iterate *------------------------------------------------------------------------- */ -static herr_t +static H5B_iterate_t H5F_istore_iter_allocated (H5F_t UNUSED *f, void *_lt_key, haddr_t UNUSED addr, void UNUSED *_rt_key, void *_udata) { @@ -779,7 +779,7 @@ H5F_istore_iter_allocated (H5F_t UNUSED *f, void *_lt_key, haddr_t UNUSED addr, bt_udata->total_storage += lt_key->nbytes; - FUNC_LEAVE(SUCCEED); + FUNC_LEAVE(H5B_ITER_CONT); } /* H5F_istore_iter_allocated() */ @@ -804,7 +804,7 @@ H5F_istore_iter_allocated (H5F_t UNUSED *f, void *_lt_key, haddr_t UNUSED addr, * Changed to callback from H5B_iterate *------------------------------------------------------------------------- */ -static herr_t +static H5B_iterate_t H5F_istore_iter_dump (H5F_t UNUSED *f, void *_lt_key, haddr_t UNUSED addr, void UNUSED *_rt_key, void *_udata) { @@ -832,7 +832,7 @@ H5F_istore_iter_dump (H5F_t UNUSED *f, void *_lt_key, haddr_t UNUSED addr, bt_udata->total_storage++; } - FUNC_LEAVE(SUCCEED); + FUNC_LEAVE(H5B_ITER_CONT); } /* H5F_istore_iter_dump() */ @@ -2737,7 +2737,7 @@ done: * *------------------------------------------------------------------------- */ -static herr_t +static H5B_iterate_t H5F_istore_prune_extent(H5F_t *f, void *_lt_key, haddr_t UNUSED addr, void UNUSED *_rt_key, void *_udata) { @@ -2745,7 +2745,7 @@ H5F_istore_prune_extent(H5F_t *f, void *_lt_key, haddr_t UNUSED addr, H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key; unsigned u; H5F_istore_ud1_t udata; - herr_t ret_value=SUCCEED; /* Return value */ + H5B_iterate_t ret_value=H5B_ITER_CONT; /* Return value */ /* The LT_KEY is the left key (the one that describes the chunk). It points to a chunk of * storage that contains the beginning of the logical address space represented by UDATA. @@ -2771,7 +2771,7 @@ H5F_istore_prune_extent(H5F_t *f, void *_lt_key, haddr_t UNUSED addr, /* Remove */ if(H5B_remove(f, H5B_ISTORE, bt_udata->mesg.addr, &udata) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to remove entry"); + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5B_ITER_ERROR, "unable to remove entry"); break; } /* end if */ diff --git a/src/H5Fistore.c b/src/H5Fistore.c index 147e143..ea74165 100644 --- a/src/H5Fistore.c +++ b/src/H5Fistore.c @@ -122,9 +122,9 @@ static H5B_ins_t H5F_istore_insert(H5F_t *f, haddr_t addr, void *_lt_key, void *_udata, void *_rt_key, hbool_t *rt_key_changed, haddr_t *new_node/*out*/); -static herr_t H5F_istore_iter_allocated(H5F_t *f, void *left_key, haddr_t addr, +static H5B_iterate_t H5F_istore_iter_allocated(H5F_t *f, void *left_key, haddr_t addr, void *right_key, void *_udata); -static herr_t H5F_istore_iter_dump(H5F_t *f, void *left_key, haddr_t addr, +static H5B_iterate_t H5F_istore_iter_dump(H5F_t *f, void *left_key, haddr_t addr, void *right_key, void *_udata); static herr_t H5F_istore_decode_key(H5F_t *f, H5B_t *bt, uint8_t *raw, void *_key); @@ -134,7 +134,7 @@ static herr_t H5F_istore_debug_key(FILE *stream, int indent, int fwidth, const void *key, const void *udata); static haddr_t H5F_istore_get_addr(H5F_t *f, const H5O_layout_t *layout, const hssize_t offset[]); -static herr_t H5F_istore_prune_extent(H5F_t *f, void *_lt_key, haddr_t addr, +static H5B_iterate_t H5F_istore_prune_extent(H5F_t *f, void *_lt_key, haddr_t addr, void *_rt_key, void *_udata); static H5B_ins_t H5F_istore_remove( H5F_t *f, haddr_t addr, void *_lt_key, hbool_t *lt_key_changed, void *_udata, void *_rt_key, @@ -768,7 +768,7 @@ done: * Changed to callback from H5B_iterate *------------------------------------------------------------------------- */ -static herr_t +static H5B_iterate_t H5F_istore_iter_allocated (H5F_t UNUSED *f, void *_lt_key, haddr_t UNUSED addr, void UNUSED *_rt_key, void *_udata) { @@ -779,7 +779,7 @@ H5F_istore_iter_allocated (H5F_t UNUSED *f, void *_lt_key, haddr_t UNUSED addr, bt_udata->total_storage += lt_key->nbytes; - FUNC_LEAVE(SUCCEED); + FUNC_LEAVE(H5B_ITER_CONT); } /* H5F_istore_iter_allocated() */ @@ -804,7 +804,7 @@ H5F_istore_iter_allocated (H5F_t UNUSED *f, void *_lt_key, haddr_t UNUSED addr, * Changed to callback from H5B_iterate *------------------------------------------------------------------------- */ -static herr_t +static H5B_iterate_t H5F_istore_iter_dump (H5F_t UNUSED *f, void *_lt_key, haddr_t UNUSED addr, void UNUSED *_rt_key, void *_udata) { @@ -832,7 +832,7 @@ H5F_istore_iter_dump (H5F_t UNUSED *f, void *_lt_key, haddr_t UNUSED addr, bt_udata->total_storage++; } - FUNC_LEAVE(SUCCEED); + FUNC_LEAVE(H5B_ITER_CONT); } /* H5F_istore_iter_dump() */ @@ -2737,7 +2737,7 @@ done: * *------------------------------------------------------------------------- */ -static herr_t +static H5B_iterate_t H5F_istore_prune_extent(H5F_t *f, void *_lt_key, haddr_t UNUSED addr, void UNUSED *_rt_key, void *_udata) { @@ -2745,7 +2745,7 @@ H5F_istore_prune_extent(H5F_t *f, void *_lt_key, haddr_t UNUSED addr, H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key; unsigned u; H5F_istore_ud1_t udata; - herr_t ret_value=SUCCEED; /* Return value */ + H5B_iterate_t ret_value=H5B_ITER_CONT; /* Return value */ /* The LT_KEY is the left key (the one that describes the chunk). It points to a chunk of * storage that contains the beginning of the logical address space represented by UDATA. @@ -2771,7 +2771,7 @@ H5F_istore_prune_extent(H5F_t *f, void *_lt_key, haddr_t UNUSED addr, /* Remove */ if(H5B_remove(f, H5B_ISTORE, bt_udata->mesg.addr, &udata) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to remove entry"); + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5B_ITER_ERROR, "unable to remove entry"); break; } /* end if */ diff --git a/src/H5G.c b/src/H5G.c index d08ac5b..8980ee2 100644 --- a/src/H5G.c +++ b/src/H5G.c @@ -363,6 +363,143 @@ done: /*------------------------------------------------------------------------- + * Function: H5Gget_num_objs + * + * Purpose: Returns the number of objects in the group. It iterates + * all B-tree leaves and sum up total number of group members. + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Raymond Lu + * Nov 20, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Gget_num_objs(hid_t group_id, hsize_t *num_objs) +{ + H5G_t *group = NULL; + herr_t ret_value; + + FUNC_ENTER_API(H5Gget_num_objs, FAIL); + H5TRACE2("e","i*h",group_id,num_objs); + + /* Check args */ + if (NULL==(group = H5I_object_verify(group_id,H5I_GROUP))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group"); + if (!num_objs) + HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "nil pointer"); + + /* Call private function. */ + ret_value = H5G_get_num_objs(group, num_objs); + +done: + FUNC_LEAVE(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Gget_objname_by_idx + * + * Purpose: Returns the name of objects in the group by giving index. + * If `name' is non-NULL then write up to `size' bytes into that + * buffer and always return the length of the entry name. + * Otherwise `size' is ignored and the function does not store the name, + * just returning the number of characters required to store the name. + * If an error occurs then the buffer pointed to by `name' (NULL or non-NULL) + * is unchanged and the function returns a negative value. + * If a zero is returned for the name's length, then there is no name + * associated with the ID. + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Raymond Lu + * Nov 20, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +ssize_t +H5Gget_objname_by_idx(hid_t group_id, hsize_t idx, char* name/*out*/, size_t size) +{ + H5G_t *group = NULL; + hsize_t num_objs; + ssize_t ret_value = FAIL; + + FUNC_ENTER_API(H5Gget_objname_by_idx, FAIL); + + /* Check args */ + if (NULL==(group = H5I_object_verify(group_id,H5I_GROUP))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group"); + if (!name) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "nil pointer for name"); + + if (H5G_get_num_objs(group, &num_objs)<0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unable to retrieve number of members"); + if(idx >= num_objs) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "index out of bound"); + + /*call private function*/ + ret_value = H5G_get_objname_by_idx(group, idx, name, size); + +done: + FUNC_LEAVE(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Gget_objtype_by_idx + * + * Purpose: Returns the type of objects in the group by giving index. + * + * + * Return: Success: H5G_GROUP(1), H5G_DATASET(2), H5G_TYPE(3) + * + * Failure: H5G_UNKNOWN + * + * Programmer: Raymond Lu + * Nov 20, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +H5Gget_objtype_by_idx(hid_t group_id, hsize_t idx) +{ + H5G_t *group = NULL; + hsize_t num_objs; + int ret_value = FAIL; + + FUNC_ENTER_API(H5Gget_objtype_by_idx, FAIL); + H5TRACE2("Is","ih",group_id,idx); + + /* Check args */ + if (NULL==(group = H5I_object_verify(group_id,H5I_GROUP))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group"); + + if (H5G_get_num_objs(group, &num_objs)<0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unable to retrieve number of members"); + if(idx >= num_objs) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "index out of bound"); + + /*call private function*/ + ret_value = H5G_get_objtype_by_idx(group, idx); + +done: + FUNC_LEAVE(ret_value); + +} + + +/*------------------------------------------------------------------------- * Function: H5Gmove2 * * Purpose: Renames an object within an HDF5 file. The original name SRC @@ -2258,6 +2395,130 @@ done: /*------------------------------------------------------------------------- + * Function: H5G_get_num_objs + * + * Purpose: Private function for H5Gget_num_objs. Returns the number + * of objects in the group. It iterates all B-tree leaves + * and sum up total number of group members. + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Raymond Lu + * Nov 20, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_get_num_objs(H5G_t *grp, hsize_t *num_objs) +{ + herr_t ret_value; + + FUNC_ENTER_NOAPI(H5G_get_num_objs, FAIL); + + *num_objs = 0; + /* Iterate over the group members */ + if ((ret_value = H5B_iterate (H5G_fileof(grp), H5B_SNODE, + H5G_node_sumup, grp->ent.cache.stab.btree_addr, num_objs))<0) + HERROR (H5E_SYM, H5E_CANTINIT, "iteration operator failed"); + +done: + FUNC_LEAVE(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5G_get_objname_by_idx + * + * Purpose: Private function for H5Gget_objname_by_idx. + * Returns the name of objects in the group by giving index. + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Raymond Lu + * Nov 20, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +ssize_t +H5G_get_objname_by_idx(H5G_t *grp, hsize_t idx, char* name, size_t size) +{ + ssize_t ret_value = FAIL; + H5G_bt_ud3_t udata; + + FUNC_ENTER_NOAPI(H5G_get_objname_by_idx, FAIL); + + udata.idx = idx; + udata.num_objs = 0; + udata.group = grp; + udata.name = NULL; + + /* Iterate over the group members */ + if ((ret_value = H5B_iterate (H5G_fileof(grp), H5B_SNODE, + H5G_node_name, grp->ent.cache.stab.btree_addr, &udata))<0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "iteration operator failed"); + + ret_value = HDstrlen(udata.name); + if(name && size>0) { + HDstrncpy(name, udata.name, MIN(ret_value+1,size-1)); + if(ret_value >= size) + name[size-1]='\0'; + } + +done: + FUNC_LEAVE(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5G_get_objtype_by_idx + * + * Purpose: Private function for H5Gget_objtype_by_idx. + * Returns the type of objects in the group by giving index. + * + * Return: Success: H5G_GROUP(1), H5G_DATASET(2), H5G_TYPE(3) + * + * Failure: UNKNOWN + * + * Programmer: Raymond Lu + * Nov 20, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +H5G_get_objtype_by_idx(H5G_t *grp, hsize_t idx) +{ + int ret_value = FAIL; + H5G_bt_ud3_t udata; + + FUNC_ENTER_NOAPI(H5G_get_objname_by_idx, FAIL); + + udata.idx = idx; + udata.num_objs = 0; + udata.group = grp; + + /* Iterate over the group members */ + if ((ret_value = H5B_iterate (H5G_fileof(grp), H5B_SNODE, + H5G_node_type, grp->ent.cache.stab.btree_addr, &udata))<0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "iteration operator failed"); + + ret_value = udata.type; + +done: + FUNC_LEAVE(ret_value); +} + + +/*------------------------------------------------------------------------- * Function: H5G_linkval * * Purpose: Returns the value of a symbolic link. diff --git a/src/H5Gnode.c b/src/H5Gnode.c index ca3b973..8671a43 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -1045,7 +1045,7 @@ done: * Changed to callback from H5B_iterate *------------------------------------------------------------------------- */ -herr_t +H5B_iterate_t H5G_node_iterate (H5F_t *f, void UNUSED *_lt_key, haddr_t addr, void UNUSED *_rt_key, void *_udata) { @@ -1055,9 +1055,9 @@ H5G_node_iterate (H5F_t *f, void UNUSED *_lt_key, haddr_t addr, size_t n, *name_off=NULL; const char *name; char buf[1024], *s; - herr_t ret_value = FAIL; + H5B_iterate_t ret_value = H5B_ITER_ERROR; - FUNC_ENTER_NOAPI(H5G_node_iterate, FAIL); + FUNC_ENTER_NOAPI(H5G_node_iterate, H5B_ITER_ERROR); /* * Check arguments. @@ -1071,10 +1071,10 @@ H5G_node_iterate (H5F_t *f, void UNUSED *_lt_key, haddr_t addr, * because we're about to call an application function. */ if (NULL == (sn = H5AC_find(f, H5AC_SNODE, addr, NULL, NULL))) - HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, FAIL, "unable to load symbol table node"); + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_ITER_ERROR, "unable to load symbol table node"); nsyms = sn->nsyms; if (NULL==(name_off = H5MM_malloc (nsyms*sizeof(name_off[0])))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, H5B_ITER_ERROR, "memory allocation failed"); for (i=0; ientry[i].name_off; sn = NULL; @@ -1092,7 +1092,7 @@ H5G_node_iterate (H5F_t *f, void UNUSED *_lt_key, haddr_t addr, n = HDstrlen (name); if (n+1>sizeof(buf)) { if (NULL==(s = H5MM_malloc (n+1))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, H5B_ITER_ERROR, "memory allocation failed"); } else { s = buf; } @@ -1117,12 +1117,159 @@ done: /*------------------------------------------------------------------------- + * Function: H5G_node_sumup + * + * Purpose: This function gets called during a group iterate operation + * to return total number of members in the group. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Raymond Lu + * Nov 20, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +H5B_iterate_t +H5G_node_sumup(H5F_t *f, void UNUSED *_lt_key, haddr_t addr, + void UNUSED *_rt_key, void *_udata) +{ + hsize_t *num_objs = (hsize_t *)_udata; + H5G_node_t *sn = NULL; + H5B_iterate_t ret_value = H5B_ITER_CONT; + + FUNC_ENTER_NOAPI(H5G_node_sumup, H5B_ITER_ERROR); + + /* + * Check arguments. + */ + assert(f); + assert(H5F_addr_defined(addr)); + assert(num_objs); + + /* Find the object node and add the number of symbol entries. */ + if (NULL == (sn = H5AC_find(f, H5AC_SNODE, addr, NULL, NULL))) + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_ITER_ERROR, "unable to load symbol table node"); + *num_objs += sn->nsyms; + +done: + FUNC_LEAVE(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5G_node_name + * + * Purpose: This function gets called during a group iterate operation + * to return object name by giving idx. + * + * Return: 0 if object isn't found in this node; 1 if object is found; + * Negative on failure + * + * Programmer: Raymond Lu + * Nov 20, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +H5B_iterate_t +H5G_node_name(H5F_t *f, void UNUSED *_lt_key, haddr_t addr, + void UNUSED *_rt_key, void *_udata) +{ + H5G_bt_ud3_t *bt_udata = (H5G_bt_ud3_t *)_udata; + size_t name_off; + hsize_t loc_idx; + char *name; + H5G_node_t *sn = NULL; + H5B_iterate_t ret_value = H5B_ITER_CONT; + + FUNC_ENTER_NOAPI(H5G_node_name, H5B_ITER_ERROR); + + /* + * Check arguments. + */ + assert(f); + assert(H5F_addr_defined(addr)); + assert(bt_udata); + + + if (NULL == (sn = H5AC_find(f, H5AC_SNODE, addr, NULL, NULL))) + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_ITER_ERROR, "unable to load symbol table node"); + + /* Find the node, locate the object symbol table entry and retrieve the name */ + if(bt_udata->idx >= bt_udata->num_objs && bt_udata->idx < (bt_udata->num_objs+sn->nsyms)) { + loc_idx = bt_udata->idx - bt_udata->num_objs; + name_off = sn->entry[loc_idx].name_off; + name = (char*)H5HL_peek (f, bt_udata->group->ent.cache.stab.heap_addr, name_off); + assert (name); + bt_udata->name = HDstrdup (name); + HGOTO_DONE(H5B_ITER_STOP); + } + + bt_udata->num_objs += sn->nsyms; + +done: + FUNC_LEAVE(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5G_node_type + * + * Purpose: This function gets called during a group iterate operation + * to return object type by given idx. + * + * Return: 0 if object isn't found in this node; 1 if found; + * Negative on failure + * + * Programmer: Raymond Lu + * Nov 20, 2002 + * + * + *------------------------------------------------------------------------- + */ +H5B_iterate_t +H5G_node_type(H5F_t *f, void UNUSED *_lt_key, haddr_t addr, + void UNUSED *_rt_key, void *_udata) +{ + H5G_bt_ud3_t *bt_udata = (H5G_bt_ud3_t*)_udata; + hsize_t loc_idx; + H5G_node_t *sn = NULL; + H5B_iterate_t ret_value = H5B_ITER_CONT; + + FUNC_ENTER_NOAPI(H5G_node_name, H5B_ITER_ERROR); + + /* Check arguments. */ + assert(f); + assert(H5F_addr_defined(addr)); + assert(bt_udata); + + /* Find the node, locate the object symbol table entry and retrieve the type */ + if (NULL == (sn = H5AC_find(f, H5AC_SNODE, addr, NULL, NULL))) + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_ITER_ERROR, "unable to load symbol table node"); + + if(bt_udata->idx >= bt_udata->num_objs && bt_udata->idx < (bt_udata->num_objs+sn->nsyms)) { + loc_idx = bt_udata->idx - bt_udata->num_objs; + bt_udata->type = H5G_get_type(&(sn->entry[loc_idx])); + HGOTO_DONE(H5B_ITER_STOP); + } + + bt_udata->num_objs += sn->nsyms; + +done: + FUNC_LEAVE(ret_value); +} + + +/*------------------------------------------------------------------------- * Function: H5G_node_debug * * Purpose: Prints debugging information about a symbol table node * or a B-tree node for a symbol table B-tree. * - * Return: Non-negative on success/Negative on failure + * Return: 0(zero) on success/Negative on failure * * Programmer: Robb Matzke * matzke@llnl.gov diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h index 9d2b98c..3fc8bd3 100644 --- a/src/H5Gpkg.h +++ b/src/H5Gpkg.h @@ -110,6 +110,18 @@ typedef struct H5G_bt_ud2_t { } H5G_bt_ud2_t; /* + * Data exchange structure to pass through the B-tree layer for the + * H5B_iterate function. + */ +typedef struct H5G_bt_ud3_t { + struct H5G_t *group; /*the group to which group_id points */ + hsize_t idx; /*index of group member to be querried */ + char *name; /*member name to be returned */ + hsize_t num_objs; /*the number of objects having been traversed*/ + int type; /*member type to be returned */ +} H5G_bt_ud3_t; + +/* * This is the class identifier to give to the B-tree functions. */ H5_DLLVAR H5B_class_t H5B_SNODE[1]; @@ -140,7 +152,12 @@ H5_DLL herr_t H5G_ent_encode_vec(H5F_t *f, uint8_t **pp, /* Functions that understand symbol table nodes */ H5_DLL unsigned H5G_node_k(const H5F_t *f); -H5_DLL herr_t H5G_node_iterate (H5F_t *f, void UNUSED *_lt_key, haddr_t addr, - void UNUSED *_rt_key, void *_udata); - +H5_DLL H5B_iterate_t H5G_node_iterate (H5F_t *f, void UNUSED *_lt_key, haddr_t addr, + void UNUSED *_rt_key, void *_udata); +H5_DLL H5B_iterate_t H5G_node_sumup(H5F_t *f, void UNUSED *_lt_key, haddr_t addr, + void UNUSED *_rt_key, void *_udata); +H5_DLL H5B_iterate_t H5G_node_name(H5F_t *f, void UNUSED *_lt_key, haddr_t addr, + void UNUSED *_rt_key, void *_udata); +H5_DLL H5B_iterate_t H5G_node_type(H5F_t *f, void UNUSED *_lt_key, haddr_t addr, + void UNUSED *_rt_key, void *_udata); #endif diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index 1028764..8515b2d 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -145,6 +145,9 @@ H5_DLL H5G_t *H5G_open_oid(H5G_entry_t *ent); H5_DLL H5G_t *H5G_reopen(H5G_t *grp); H5_DLL herr_t H5G_close(H5G_t *grp); H5_DLL H5G_t *H5G_rootof(H5F_t *f); +H5_DLL herr_t H5G_get_num_objs(H5G_t *grp, hsize_t *num_objs); +H5_DLL ssize_t H5G_get_objname_by_idx(H5G_t *grp, hsize_t idx, char* name, size_t size); +H5_DLL int H5G_get_objtype_by_idx(H5G_t *grp, hsize_t idx); H5_DLL htri_t H5G_isa(H5G_entry_t *ent); H5_DLL herr_t H5G_link(H5G_entry_t *cur_loc, const char *cur_name, H5G_entry_t *new_loc, const char *new_name, diff --git a/src/H5Gpublic.h b/src/H5Gpublic.h index 96ed37f..5e40033 100644 --- a/src/H5Gpublic.h +++ b/src/H5Gpublic.h @@ -81,6 +81,9 @@ H5_DLL hid_t H5Gopen(hid_t loc_id, const char *name); H5_DLL herr_t H5Gclose(hid_t group_id); H5_DLL herr_t H5Giterate(hid_t loc_id, const char *name, int *idx, H5G_iterate_t op, void *op_data); +H5_DLL herr_t H5Gget_num_objs(hid_t loc_id, hsize_t *num_objs); +H5_DLL ssize_t H5Gget_objname_by_idx(hid_t group_id, hsize_t idx, char* name, size_t size); +H5_DLL int H5Gget_objtype_by_idx(hid_t group_id, hsize_t idx); H5_DLL herr_t H5Gmove2(hid_t src_loc, const char *src, hid_t dst_loc, const char *dst); H5_DLL herr_t H5Glink2(hid_t src_loc, const char *cur_name, H5G_link_t type, diff --git a/test/titerate.c b/test/titerate.c index eb730d9..ef291b5 100644 --- a/test/titerate.c +++ b/test/titerate.c @@ -1,13 +1,13 @@ /**************************************************************************** - * NCSA HDF * - * Software Development Group * - * National Center for Supercomputing Applications * - * University of Illinois at Urbana-Champaign * - * 605 E. Springfield, Champaign IL 61820 * - * * - * For conditions of distribution and use, see the accompanying * - * hdf/COPYING file. * - * * + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * ****************************************************************************/ /* $Id$ */ @@ -113,12 +113,15 @@ static void test_iter_group(void) hid_t dataset; /* Dataset ID */ hid_t datatype; /* Common datatype ID */ hid_t filespace; /* Common dataspace ID */ + hid_t root_group,grp; /* Root group ID */ int i; /* counting variable */ int idx; /* Index in the group */ char name[NAMELEN]; /* temporary name buffer */ char *dnames[NDATASETS];/* Names of the datasets created */ + char dataset_name[16]; /* dataset name */ iter_info info; /* Custom iteration information */ - herr_t ret; /* Generic return value */ + hsize_t num_membs; /* Number of group members */ + herr_t ret; /* Generic return value */ /* Output message about test being performed */ MESSAGE(5, ("Testing Group Iteration Functionality\n")); @@ -146,10 +149,22 @@ static void test_iter_group(void) CHECK(ret, FAIL, "H5Dclose"); } + /* Create a group and named datatype under root group for testing + * H5Gget_objtype_by_idx. + */ + grp = H5Gcreate(file, "grp", 0); + CHECK(ret, FAIL, "H5Gcreate"); + + ret = H5Tcommit(file, "dtype", datatype); + CHECK(ret, FAIL, "H5Tcommit"); + /* Close everything up */ ret=H5Tclose(datatype); CHECK(ret, FAIL, "H5Tclose"); - + + ret=H5Gclose(grp); + CHECK(ret, FAIL, "H5Gclose"); + ret=H5Sclose(filespace); CHECK(ret, FAIL, "H5Sclose"); @@ -159,10 +174,39 @@ static void test_iter_group(void) /* Sort the dataset names */ qsort(dnames,NDATASETS,sizeof(char *),iter_strcmp); + /* Iterate through the datasets in the root group in various ways */ file=H5Fopen(DATAFILE, H5F_ACC_RDONLY, H5P_DEFAULT); CHECK(file, FAIL, "H5Fopen"); + /* These twp functions, H5Gget_num_objs and H5Gget_objname_by_idx, actually + * iterate through B-tree for group members in internal library design. + */ + { + root_group = H5Gopen(file, "/"); + CHECK(root_group, FAIL, "H5Gopen"); + + ret = H5Gget_num_objs(root_group, &num_membs); + CHECK(ret, FAIL, "H5Gget_num_objs"); + VERIFY(num_membs,NDATASETS+2,"H5Gget_num_objs"); + + for(i=0; i< num_membs; i++) { + ret = H5Gget_objname_by_idx(root_group, i, dataset_name, 32); + CHECK(ret, FAIL, "H5Gget_objsname_by_idx"); + + ret = H5Gget_objtype_by_idx(root_group, i); + CHECK(ret, H5G_UNKNOWN, "H5Gget_objsname_by_idx"); + } + + H5E_BEGIN_TRY { + ret = H5Gget_objname_by_idx(root_group, NDATASETS+3, dataset_name, 16); + } H5E_END_TRY; + VERIFY(ret, FAIL, "H5Gget_objsname_by_idx"); + + ret = H5Gclose(root_group); + CHECK(ret, FAIL, "H5Gclose"); + } + /* Test all objects in group, when callback always returns 0 */ info.command=RET_ZERO; idx=0; @@ -528,6 +572,147 @@ static void test_iter_group_large(void) /**************************************************************** ** +** test_grp_memb_funcs(): Test group member information +** functionality +** +****************************************************************/ +static void test_grp_memb_funcs(void) +{ + hid_t file; /* File ID */ + hid_t dataset; /* Dataset ID */ + hid_t datatype; /* Common datatype ID */ + hid_t filespace; /* Common dataspace ID */ + hid_t root_group,grp; /* Root group ID */ + int i; /* counting variable */ + int idx; /* Index in the group */ + char name[NAMELEN]; /* temporary name buffer */ + char *dnames[NDATASETS+2];/* Names of the datasets created */ + char *obj_names[NDATASETS+2];/* Names of the objects in group */ + char dataset_name[16]; /* dataset name */ + iter_info info; /* Custom iteration information */ + hsize_t num_membs; /* Number of group members */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing Group Member Information Functionality\n")); + + /* Create the test file with the datasets */ + file = H5Fcreate(DATAFILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + CHECK(file, FAIL, "H5Fcreate"); + + datatype = H5Tcopy(H5T_NATIVE_INT); + CHECK(datatype, FAIL, "H5Tcopy"); + + filespace=H5Screate(H5S_SCALAR); + CHECK(filespace, FAIL, "H5Screate"); + + for(i=0; i< NDATASETS; i++) { + sprintf(name,"Dataset %d",i); + dataset = H5Dcreate(file, name, datatype, filespace, H5P_DEFAULT); + CHECK(dataset, FAIL, "H5Dcreate"); + + /* Keep a copy of the dataset names around for later */ + dnames[i]=HDstrdup(name); + CHECK(dnames[i], NULL, "strdup"); + + ret=H5Dclose(dataset); + CHECK(ret, FAIL, "H5Dclose"); + } + + /* Create a group and named datatype under root group for testing + * H5Gget_objtype_by_idx. + */ + grp = H5Gcreate(file, "grp", 0); + CHECK(ret, FAIL, "H5Gcreate"); + + dnames[NDATASETS]=HDstrdup("grp"); + CHECK(dnames[NDATASETS], NULL, "strdup"); + + ret = H5Tcommit(file, "dtype", datatype); + CHECK(ret, FAIL, "H5Tcommit"); + + dnames[NDATASETS+1]=HDstrdup("dtype"); + CHECK(dnames[NDATASETS], NULL, "strdup"); + + /* Close everything up */ + ret=H5Tclose(datatype); + CHECK(ret, FAIL, "H5Tclose"); + + ret=H5Gclose(grp); + CHECK(ret, FAIL, "H5Gclose"); + + ret=H5Sclose(filespace); + CHECK(ret, FAIL, "H5Sclose"); + + ret=H5Fclose(file); + CHECK(ret, FAIL, "H5Fclose"); + + /* Sort the dataset names */ + qsort(dnames,NDATASETS+2,sizeof(char *),iter_strcmp); + + + /* Iterate through the datasets in the root group in various ways */ + file=H5Fopen(DATAFILE, H5F_ACC_RDONLY, H5P_DEFAULT); + CHECK(file, FAIL, "H5Fopen"); + + /* These twp functions, H5Gget_num_objs and H5Gget_objname_by_idx, actually + * iterate through B-tree for group members in internal library design. + */ + root_group = H5Gopen(file, "/"); + CHECK(root_group, FAIL, "H5Gopen"); + + ret = H5Gget_num_objs(root_group, &num_membs); + CHECK(ret, FAIL, "H5Gget_num_objs"); + VERIFY(num_membs,NDATASETS+2,"H5Gget_num_objs"); + + for(i=0; i< num_membs; i++) { + ret = H5Gget_objname_by_idx(root_group, i, dataset_name, 32); + CHECK(ret, FAIL, "H5Gget_objsname_by_idx"); + + /* Keep a copy of the dataset names around for later */ + obj_names[i]=HDstrdup(dataset_name); + CHECK(dnames[i], NULL, "strdup"); + + ret = H5Gget_objtype_by_idx(root_group, i); + CHECK(ret, H5G_UNKNOWN, "H5Gget_objsname_by_idx"); + + if(!HDstrcmp(dataset_name, "grp")) + VERIFY(ret, H5G_GROUP, "H5Gget_objsname_by_idx"); + if(!HDstrcmp(dataset_name, "dtype")) + VERIFY(ret, H5G_TYPE, "H5Gget_objsname_by_idx"); + if(!HDstrncmp(dataset_name, "Dataset", 7)) + VERIFY(ret, H5G_DATASET, "H5Gget_objsname_by_idx"); + } + + H5E_BEGIN_TRY { + ret = H5Gget_objname_by_idx(root_group, NDATASETS+3, dataset_name, 16); + } H5E_END_TRY; + VERIFY(ret, FAIL, "H5Gget_objsname_by_idx"); + + /* Sort the dataset names */ + qsort(obj_names,NDATASETS+2,sizeof(char *),iter_strcmp); + + /* Compare object names */ + for(i=0; i< num_membs; i++) { + ret = HDstrcmp(dnames[i], obj_names[i]); + VERIFY(ret, 0, "HDstrcmp"); + } + + ret = H5Gclose(root_group); + CHECK(ret, FAIL, "H5Gclose"); + + + ret=H5Fclose(file); + CHECK(ret, FAIL, "H5Fclose"); + + /* Free the dataset names */ + for(i=0; i< NDATASETS+2; i++) + free(dnames[i]); + +} /* test_grp_memb_funcs() */ + +/**************************************************************** +** ** test_iterate(): Main iteration testing routine. ** ****************************************************************/ @@ -541,6 +726,7 @@ test_iterate(void) test_iter_group(); /* Test group iteration */ test_iter_group_large(); /* Test group iteration for large # of objects */ test_iter_attr(); /* Test attribute iteration */ + test_grp_memb_funcs(); /* Test group member information functions */ } /* test_iterate() */ -- cgit v0.12