From 0c9c34fab681a559633cbae215cb49ca812f4a3d Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Sat, 30 Jul 2005 13:53:01 -0500 Subject: [svn-r11176] Purpose: Bug fix Description: Correct problems when querying information about a group that was opened by dereferencing an object reference. Solution: Read in symbol table information instead of rely on it being cached. Platforms tested: FreeBSD 4.11 (sleipnir) Too minor to require h5committest --- release_docs/RELEASE.txt | 2 + src/H5G.c | 69 +++++++++++------------------- src/H5Gnode.c | 4 +- src/H5Gpkg.h | 3 +- test/trefer.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 138 insertions(+), 47 deletions(-) diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index ed5c1cf..67dd598 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -305,6 +305,8 @@ Bug Fixes since HDF5-1.6.0 release Library ------- + - Corrected errors when querying information about a group opened + by dereferencing an object reference. QAK - 2005/07/30 - Fixed a bug with named datatypes where a copy of a named datatype used to create a dataset would accidentally use the original named datatype for the dataset's datatype. QAK - 2005/07/23 diff --git a/src/H5G.c b/src/H5G.c index c2305c5..d1c5ac9 100644 --- a/src/H5G.c +++ b/src/H5G.c @@ -104,7 +104,6 @@ #include "H5HLprivate.h" /* Local Heaps */ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ -#include "H5Oprivate.h" /* Object headers */ #include "H5Pprivate.h" /* Property lists */ /* Local macros */ @@ -592,11 +591,8 @@ ssize_t H5Gget_objname_by_idx(hid_t loc_id, hsize_t idx, char *name, size_t size) { H5G_entry_t *loc = NULL; /* Pointer to symbol table entry */ -#ifdef OLD_WAY - hsize_t num_objs; -#endif /* OLD_WAY */ ssize_t ret_value = FAIL; - + FUNC_ENTER_API(H5Gget_objname_by_idx, FAIL); H5TRACE4("Zs","ihsz",loc_id,idx,name,size); @@ -605,19 +601,7 @@ H5Gget_objname_by_idx(hid_t loc_id, hsize_t idx, char *name, size_t size) HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location ID"); if(H5G_get_type(loc,H5AC_ind_dxpl_id)!=H5G_GROUP) HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a group"); - -#ifdef OLD_WAY -/* Don't check for the number of objects in the group currently, because this - * has to iterate through the group in order to find out the information. - * We might as well just iterate through all the group entries and error out - * if we didn't find the index we are looking for. -QAK - */ - if (H5G_get_num_objs(loc, &num_objs, H5AC_ind_dxpl_id)<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"); -#endif /* OLD_WAY */ - + /*call private function*/ ret_value = H5G_get_objname_by_idx(loc, idx, name, size, H5AC_ind_dxpl_id); @@ -647,9 +631,6 @@ H5G_obj_t H5Gget_objtype_by_idx(hid_t loc_id, hsize_t idx) { H5G_entry_t *loc = NULL; /* Pointer to symbol table entry */ -#ifdef OLD_WAY - hsize_t num_objs; -#endif /* OLD_WAY */ H5G_obj_t ret_value; FUNC_ENTER_API(H5Gget_objtype_by_idx, H5G_UNKNOWN); @@ -660,19 +641,7 @@ H5Gget_objtype_by_idx(hid_t loc_id, hsize_t idx) HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "not a location ID"); if(H5G_get_type(loc,H5AC_ind_dxpl_id)!=H5G_GROUP) HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "not a group"); - -#ifdef OLD_WAY -/* Don't check for the number of objects in the group currently, because this - * has to iterate through the group in order to find out the information. - * We might as well just iterate through all the group entries and error out - * if we didn't find the index we are looking for. -QAK - */ - if (H5G_get_num_objs(loc, &num_objs, H5AC_ind_dxpl_id)<0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "unable to retrieve number of members"); - if(idx >= num_objs) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "index out of bound"); -#endif /* OLD_WAY */ - + /*call private function*/ ret_value = H5G_get_objtype_by_idx(loc, idx, H5AC_ind_dxpl_id); @@ -2912,21 +2881,25 @@ done: static herr_t H5G_get_num_objs(H5G_entry_t *loc, hsize_t *num_objs, hid_t dxpl_id) { + H5O_stab_t stab_mesg; /*info about B-tree */ herr_t ret_value; FUNC_ENTER_NOAPI(H5G_get_num_objs, FAIL); /* Sanity check */ assert(loc); - assert(loc->type==H5G_CACHED_STAB); assert(num_objs); /* Reset the number of objects in the group */ *num_objs = 0; + /* Get the B-tree info */ + if (NULL==H5O_read (loc, H5O_STAB_ID, 0, &stab_mesg, dxpl_id)) + HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address"); + /* Iterate over the group members */ if ((ret_value = H5B_iterate (loc->file, dxpl_id, H5B_SNODE, - H5G_node_sumup, loc->cache.stab.btree_addr, num_objs))<0) + H5G_node_sumup, stab_mesg.btree_addr, num_objs))<0) HERROR (H5E_SYM, H5E_CANTINIT, "iteration operator failed"); done: @@ -2954,6 +2927,7 @@ done: static ssize_t H5G_get_objname_by_idx(H5G_entry_t *loc, hsize_t idx, char* name, size_t size, hid_t dxpl_id) { + H5O_stab_t stab_mesg; /*info about local heap & B-tree */ H5G_bt_ud3_t udata; /* Iteration information */ ssize_t ret_value; /* Return value */ @@ -2961,17 +2935,20 @@ H5G_get_objname_by_idx(H5G_entry_t *loc, hsize_t idx, char* name, size_t size, h /* Sanity check */ assert(loc); - assert(loc->type==H5G_CACHED_STAB); + + /* Get the B-tree & local heap info */ + if (NULL==H5O_read (loc, H5O_STAB_ID, 0, &stab_mesg, dxpl_id)) + HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address"); /* Set iteration information */ udata.idx = idx; udata.num_objs = 0; - udata.ent = loc; + udata.mesg = &stab_mesg; udata.name = NULL; /* Iterate over the group members */ if ((ret_value = H5B_iterate (loc->file, dxpl_id, H5B_SNODE, - H5G_node_name, loc->cache.stab.btree_addr, &udata))<0) + H5G_node_name, stab_mesg.btree_addr, &udata))<0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "iteration operator failed"); /* If we don't know the name now, we almost certainly went out of bounds */ @@ -3016,24 +2993,28 @@ done: static H5G_obj_t H5G_get_objtype_by_idx(H5G_entry_t *loc, hsize_t idx, hid_t dxpl_id) { - H5G_bt_ud3_t udata; /* User data for B-tree callback */ - H5G_obj_t ret_value; /* Return value */ + H5O_stab_t stab_mesg; /*info about local heap & B-tree */ + H5G_bt_ud3_t udata; /* User data for B-tree callback */ + H5G_obj_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5G_get_objtype_by_idx, H5G_UNKNOWN); /* Sanity check */ assert(loc); - assert(loc->type==H5G_CACHED_STAB); + + /* Get the B-tree & local heap info */ + if (NULL==H5O_read (loc, H5O_STAB_ID, 0, &stab_mesg, dxpl_id)) + HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address"); /* Set iteration information */ udata.idx = idx; udata.num_objs = 0; - udata.ent = loc; + udata.mesg = &stab_mesg; udata.type = H5G_UNKNOWN; /* Iterate over the group members */ if (H5B_iterate (loc->file, dxpl_id, H5B_SNODE, - H5G_node_type, loc->cache.stab.btree_addr, &udata)<0) + H5G_node_type, stab_mesg.btree_addr, &udata)<0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "iteration operator failed"); /* If we don't know the type now, we almost certainly went out of bounds */ diff --git a/src/H5Gnode.c b/src/H5Gnode.c index f88c89c..dfa607e 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -1679,7 +1679,7 @@ H5G_node_name(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t addr, loc_idx = bt_udata->idx - bt_udata->num_objs; name_off = sn->entry[loc_idx].name_off; - if (NULL == (heap = H5HL_protect(f, dxpl_id, bt_udata->ent->cache.stab.heap_addr))) + if (NULL == (heap = H5HL_protect(f, dxpl_id, bt_udata->mesg->heap_addr))) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5B_ITER_ERROR, "unable to protect symbol name"); name = H5HL_offset_into(f, heap, name_off); @@ -1687,7 +1687,7 @@ H5G_node_name(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t addr, bt_udata->name = H5MM_strdup (name); assert(bt_udata->name); - if (H5HL_unprotect(f, dxpl_id, heap, bt_udata->ent->cache.stab.heap_addr, H5AC__NO_FLAGS_SET) < 0) + if (H5HL_unprotect(f, dxpl_id, heap, bt_udata->mesg->heap_addr, H5AC__NO_FLAGS_SET) < 0) HGOTO_ERROR(H5E_SYM, H5E_PROTECT, H5B_ITER_ERROR, "unable to unprotect symbol name"); heap=NULL; name=NULL; diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h index 36a18f9..f970b2d 100644 --- a/src/H5Gpkg.h +++ b/src/H5Gpkg.h @@ -32,6 +32,7 @@ /* Other private headers needed by this file */ #include "H5ACprivate.h" /* Metadata cache */ +#include "H5Oprivate.h" /* Object headers */ /* * A symbol table node is a collection of symbol table entries. It can @@ -113,7 +114,7 @@ typedef struct H5G_bt_ud2_t { */ typedef struct H5G_bt_ud3_t { /* downward */ - H5G_entry_t *ent; /*the entry of group being queried */ + const H5O_stab_t *mesg; /*the symbol table message of group being queried */ hsize_t idx; /*index of group member to be queried */ hsize_t num_objs; /*the number of objects having been traversed*/ diff --git a/test/trefer.c b/test/trefer.c index e5d6e9e..cf2e99b 100644 --- a/test/trefer.c +++ b/test/trefer.c @@ -54,6 +54,11 @@ typedef struct s1_t { float c; } s1_t; +#define GROUPNAME "/group" +#define GROUPNAME2 "group2" +#define DSETNAME "/dset" +#define NAME_SIZE 16 + /**************************************************************** ** @@ -910,6 +915,107 @@ test_reference_obj_deleted(void) /**************************************************************** ** +** test_reference_group_query(): Test H5R (reference) object reference code. +** Tests for correct behavior of query routines on dereferenced group +** +****************************************************************/ +static void +test_reference_group_query(void) +{ + hid_t fid = -1; /* File ID */ + hid_t gid = -1, gid2 = -1; /* Group IDs */ + hid_t did; /* Dataset ID */ + hid_t sid; /* Dataspace ID */ + hsize_t nobjs; + hobj_ref_t wref; /* Reference to write */ + hobj_ref_t rref; /* Reference to read */ + char objname[NAME_SIZE]; /* Buffer to store name */ + H5G_obj_t objtype; /* Object type */ + herr_t ret; + + /* Create file with a group and a dataset containing an object reference to the group */ + fid = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + CHECK(fid, FAIL, "H5Fcreate"); + + /* Create group to refer to */ + gid = H5Gcreate(fid, GROUPNAME, (size_t)0); + CHECK(gid, FAIL, "H5Gcreate"); + + /* Create nested group */ + gid2 = H5Gcreate(gid, GROUPNAME2, (size_t)0); + CHECK(gid2, FAIL, "H5Gcreate"); + ret = H5Gclose(gid2); + CHECK(ret, FAIL, "H5Gclose"); + + ret = H5Gclose(gid); + CHECK(ret, FAIL, "H5Gclose"); + + /* Create dataspace to use for dataset */ + sid = H5Screate(H5S_SCALAR); + CHECK(sid, FAIL, "H5Screate"); + + /* Create dataset */ + did = H5Dcreate(fid, DSETNAME, H5T_STD_REF_OBJ, sid, H5P_DEFAULT); + CHECK(did, FAIL, "H5Dcreate"); + + /* Create reference to group */ + ret = H5Rcreate(&wref, fid, GROUPNAME, H5R_OBJECT, -1); + CHECK(ret, FAIL, "H5Rcreate"); + + /* Write reference to disk */ + ret = H5Dwrite(did, H5T_STD_REF_OBJ, H5S_ALL, H5S_ALL, H5P_DEFAULT, &wref); + CHECK(ret, FAIL, "H5Dwrite"); + + /* Close objects */ + ret = H5Dclose(did); + CHECK(ret, FAIL, "H5Dclose"); + ret = H5Sclose(sid); + CHECK(ret, FAIL, "H5Sclose"); + ret = H5Fclose(fid); + CHECK(ret, FAIL, "H5Fclose"); + + + /* Re-open file */ + fid = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT); + CHECK(fid, FAIL, "H5Fopen"); + + /* Re-open dataset */ + did = H5Dopen(fid, DSETNAME); + CHECK(did, FAIL, "H5Dopen"); + + /* Read in the reference */ + ret = H5Dread(did, H5T_STD_REF_OBJ, H5S_ALL, H5S_ALL, H5P_DEFAULT, &rref); + CHECK(ret, FAIL, "H5Dread"); + + /* Dereference to get the group */ + gid = H5Rdereference(did, H5R_OBJECT, &rref); + CHECK(gid, FAIL, "H5Rdereference"); + + /* Various queries on the group opened */ + ret = H5Gget_num_objs(gid, &nobjs); + CHECK(ret, FAIL, "H5Gget_num_objs"); + + VERIFY(nobjs, 1, "H5Gget_num_objs"); + + ret = H5Gget_objname_by_idx(gid, (hsize_t)0, objname, NAME_SIZE); + CHECK(ret, FAIL, "H5Gget_objname_by_idx"); + + VERIFY_STR(objname, "group2", "H5Gget_objname_by_idx"); + + objtype = H5Gget_objtype_by_idx(gid, (hsize_t)0); + VERIFY(objtype, H5G_GROUP, "H5Gget_objtype_by_idx"); + + /* Close objects */ + ret = H5Dclose(did); + CHECK(ret, FAIL, "H5Dclose"); + ret = H5Gclose(gid); + CHECK(ret, FAIL, "H5Gclose"); + ret = H5Fclose(fid); + CHECK(ret, FAIL, "H5Fclose"); +} /* test_reference_group_query() */ + +/**************************************************************** +** ** test_reference(): Main H5R reference testing routine. ** ****************************************************************/ @@ -923,6 +1029,7 @@ test_reference(void) test_reference_region(); /* Test basic H5R dataset region reference code */ test_reference_region_1D(); /* Test H5R dataset region reference code for 1-D datasets */ test_reference_obj_deleted(); /* Test H5R object reference code for deleted objects */ + test_reference_group_query(); /* Test queries on dereferenced groups */ } /* test_reference() */ -- cgit v0.12