From 56e63bdeea4bd94b46dd3e962e457959e4fe636c Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Tue, 13 Feb 2007 09:50:48 -0500 Subject: [svn-r13287] Description: Add H5Aget_info_by_idx & H5Aget_name_by_idx routines, along with refactoring underlying indices code to handle those sort of queries. Simplify the link callback routines a bit. Minor other cleanups. Tested on: Mac OS X/32 10.4.8 (amazon) FreeBSD/32 6.2 (duty) --- src/H5A.c | 77 ++++++++++++++-- src/H5Adense.c | 61 ++++++++----- src/H5Aint.c | 158 ++++++++++++++++++++++++++------ src/H5Apkg.h | 10 +-- src/H5Apublic.h | 3 + src/H5Gdense.c | 51 ++++++----- src/H5L.c | 259 ++++++++++++----------------------------------------- src/H5Oattribute.c | 28 +++--- src/H5Opkg.h | 4 +- test/links.c | 2 +- test/tattr.c | 253 +++++++++++++++++++++++++++++++++++++++++++++------ test/titerate.c | 60 ++++++------- 12 files changed, 605 insertions(+), 361 deletions(-) diff --git a/src/H5A.c b/src/H5A.c index 116ee9e..35773df 100644 --- a/src/H5A.c +++ b/src/H5A.c @@ -1182,10 +1182,10 @@ H5Aget_name(hid_t attr_id, size_t buf_size, char *buf) /* get the real attribute length */ nbytes = HDstrlen(attr->name); - assert((ssize_t)nbytes>=0); /*overflow, pretty unlikey --rpm*/ + HDassert((ssize_t)nbytes >= 0); /*overflow, pretty unlikely --rpm*/ /* compute the string length which will fit into the user's buffer */ - copy_len = MIN(buf_size-1, nbytes); + copy_len = MIN(buf_size - 1, nbytes); /* Copy all/some of the name */ if(buf && copy_len > 0) { @@ -1204,6 +1204,66 @@ done: /*------------------------------------------------------------------------- + * Function: H5Aget_name_by_idx + * + * Purpose: Retrieve name of an attribute, according to the + * order within an index. + * + * Same pattern of behavior as H5Iget_name. + * + * Return: Success: Non-negative length of name, with information + * in NAME buffer + * Failure: Negative + * + * Programmer: Quincey Koziol + * February 8, 2007 + * + *------------------------------------------------------------------------- + */ +ssize_t +H5Aget_name_by_idx(hid_t loc_id, H5_index_t idx_type, H5_iter_order_t order, + hsize_t n, char *name /*out*/, size_t size) +{ + H5G_loc_t loc; /* Object location */ + H5A_t *attr = NULL; /* Attribute object for name */ + ssize_t ret_value; /* Return value */ + + FUNC_ENTER_API(H5Aget_name_by_idx, FAIL) + + /* Check args */ + if(H5I_ATTR == H5I_get_type(loc_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") + if(H5G_loc(loc_id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + 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") + + /* Open the attribute on the object header */ + if(NULL == (attr = H5A_open_by_idx(&loc, idx_type, order, n, H5AC_ind_dxpl_id))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "can't open attribute") + + /* Get the length of the name */ + ret_value = (ssize_t)HDstrlen(attr->name); + + /* Copy the name into the user's buffer, if given */ + if(name) { + HDstrncpy(name, attr->name, MIN((size_t)(ret_value + 1), size)); + if((size_t)ret_value >= size) + name[size - 1]='\0'; + } /* end if */ + +done: + /* Release resources */ + if(attr && H5A_close(attr) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "can't close attribute") + + FUNC_LEAVE_API(ret_value) +} /* end H5Aget_name_by_idx() */ + + +/*------------------------------------------------------------------------- * Function: H5Aget_storage_size * * Purpose: Returns the amount of storage size that is required for this @@ -1367,7 +1427,7 @@ H5Aget_info_by_idx(hid_t loc_id, H5_index_t idx_type, H5_iter_order_t order, HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to get attribute info") done: - /* Cleanup on failure */ + /* Release resources */ if(attr && H5A_close(attr) < 0) HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "can't close attribute") @@ -1494,7 +1554,8 @@ H5Aiterate(hid_t loc_id, unsigned *attr_num, H5A_operator_t op, void *op_data) { H5G_loc_t loc; /* Object location */ H5A_attr_iter_op_t attr_op; /* Attribute operator */ - unsigned start_idx; /* Index of attribute to start iterating at */ + hsize_t start_idx; /* Index of attribute to start iterating at */ + hsize_t last_attr; /* Index of last attribute examined */ herr_t ret_value; /* Return value */ FUNC_ENTER_API(H5Aiterate, FAIL) @@ -1511,11 +1572,13 @@ H5Aiterate(hid_t loc_id, unsigned *attr_num, H5A_operator_t op, void *op_data) attr_op.u.app_op = op; /* Call attribute iteration routine */ - start_idx = (attr_num ? (unsigned)*attr_num : 0); -/* XXX: Uses "native" name index order currently - should use creation order */ - if((ret_value = H5O_attr_iterate(loc_id, loc.oloc, H5AC_ind_dxpl_id, H5_ITER_NATIVE, start_idx, attr_num, &attr_op, op_data)) < 0) + last_attr = start_idx = (hsize_t)(attr_num ? *attr_num : 0); + if((ret_value = H5O_attr_iterate(loc_id, loc.oloc, H5AC_ind_dxpl_id, H5_INDEX_CRT_ORDER, H5_ITER_INC, start_idx, &last_attr, &attr_op, op_data)) < 0) HERROR(H5E_ATTR, H5E_BADITER, "error iterating over attributes"); + /* Set the last attribute information */ + *attr_num = (unsigned)last_attr; + done: FUNC_LEAVE_API(ret_value) } /* H5Aiterate() */ diff --git a/src/H5Adense.c b/src/H5Adense.c index e56b0cb..78cdcc8 100644 --- a/src/H5Adense.c +++ b/src/H5Adense.c @@ -87,13 +87,13 @@ typedef struct { /* downward (internal) */ H5F_t *f; /* Pointer to file that fractal heap is in */ hid_t dxpl_id; /* DXPL for operation */ - H5HF_t *fheap; /* Fractal heap handle */ + H5HF_t *fheap; /* Fractal heap handle */ H5HF_t *shared_fheap; /* Fractal heap handle for shared messages */ + hsize_t count; /* # of attributes examined */ /* downward (from application) */ hid_t loc_id; /* Object ID for application callback */ - unsigned skip; /* Number of attributes to skip */ - unsigned count; /* The # of attributes visited */ + hsize_t skip; /* Number of attributes to skip */ const H5A_attr_iter_op_t *attr_op; /* Callback for each attribute */ void *op_data; /* Callback data for each attribute */ @@ -965,14 +965,15 @@ done: */ herr_t H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id, haddr_t attr_fheap_addr, - haddr_t name_bt2_addr, H5_iter_order_t order, unsigned skip, - unsigned *last_attr, const H5A_attr_iter_op_t *attr_op, void *op_data) + haddr_t name_bt2_addr, haddr_t corder_bt2_addr, H5_index_t idx_type, + H5_iter_order_t order, hsize_t skip, hsize_t *last_attr, + const H5A_attr_iter_op_t *attr_op, void *op_data) { - H5A_bt2_ud_it_t udata; /* User data for iterator callback */ H5HF_t *fheap = NULL; /* Fractal heap handle */ H5HF_t *shared_fheap = NULL; /* Fractal heap handle for shared header messages */ H5A_attr_table_t atable = {0, NULL}; /* Table of attributes */ - hsize_t nrec; /* # of records in v2 B-tree */ + const H5B2_class_t *bt2_class = NULL; /* Class of v2 B-tree */ + haddr_t bt2_addr; /* Address of v2 B-tree to use for lookup */ herr_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5A_dense_iterate, FAIL) @@ -985,21 +986,34 @@ H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id, haddr_t attr_fheap_addr HDassert(H5F_addr_defined(name_bt2_addr)); HDassert(attr_op); - /* Retrieve # of records in name index */ - /* (# of records in all indices the same) */ - if(H5B2_get_nrec(f, dxpl_id, H5A_BT2_NAME, name_bt2_addr, &nrec) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve # of records in index") - - /* Check for skipping too many attributes */ - if(skip > 0) { - /* Check for bad starting index */ - if((hsize_t)skip >= nrec) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified") + /* Determine the address of the index to use */ + if(idx_type == H5_INDEX_NAME) { + /* Check if "native" order is OK - since names are hashed, getting them + * in strictly increasing or decreasing order requires building a + * table and sorting it. + */ + if(order == H5_ITER_NATIVE) { + HDassert(H5F_addr_defined(name_bt2_addr)); + bt2_addr = name_bt2_addr; + bt2_class = H5A_BT2_NAME; + } /* end if */ + else + bt2_addr = HADDR_UNDEF; } /* end if */ + else { + HDassert(idx_type == H5_INDEX_CRT_ORDER); + + /* This address may not be defined if creation order is tracked, but + * there's no index on it. If there's no v2 B-tree that indexes + * the links, a table will be built. + */ + bt2_addr = corder_bt2_addr; + bt2_class = H5A_BT2_CORDER; + } /* end else */ /* Check on iteration order */ - /* ("native" iteration order is unordered for this attribute storage mechanism) */ - if(order == H5_ITER_NATIVE) { + if(order == H5_ITER_NATIVE && H5F_addr_defined(bt2_addr)) { + H5A_bt2_ud_it_t udata; /* User data for iterator callback */ htri_t attr_sharable; /* Flag indicating attributes are sharable */ /* Open the fractal heap */ @@ -1039,18 +1053,17 @@ H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id, haddr_t attr_fheap_addr /* Iterate over the records in the v2 B-tree's "native" order */ /* (by hash of name) */ - if((ret_value = H5B2_iterate(f, dxpl_id, H5A_BT2_NAME, name_bt2_addr, - H5A_dense_iterate_bt2_cb, &udata)) < 0) + if((ret_value = H5B2_iterate(f, dxpl_id, bt2_class, bt2_addr, H5A_dense_iterate_bt2_cb, &udata)) < 0) HERROR(H5E_ATTR, H5E_BADITER, "attribute iteration failed"); - /* Update last attribute looked at */ + /* Update the last attribute examined, if requested */ if(last_attr) *last_attr = udata.count; } /* end if */ else { /* Build the table of attributes for this object */ - if(H5A_dense_build_table(f, dxpl_id, nrec, attr_fheap_addr, name_bt2_addr, - H5_INDEX_NAME, order, &atable) < 0) + /* (build table using the name index, but sort according to idx_type) */ + if(H5A_dense_build_table(f, dxpl_id, attr_fheap_addr, name_bt2_addr, idx_type, order, &atable) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "error building table of attributes") /* Iterate over attributes in table */ diff --git a/src/H5Aint.c b/src/H5Aint.c index a3d895c..8b4f92a 100644 --- a/src/H5Aint.c +++ b/src/H5Aint.c @@ -57,6 +57,7 @@ typedef struct { hid_t dxpl_id; /* DXPL for operation */ H5A_attr_table_t *atable; /* Pointer to attribute table to build */ size_t curr_attr; /* Current attribute to operate on */ + hbool_t bogus_crt_idx; /* Whether bogus creation index values need to be set */ } H5A_compact_bt_ud_t; /* Data exchange structure to use when building table of dense attributes for an object */ @@ -114,7 +115,7 @@ static herr_t H5A_attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type, */ static herr_t H5A_compact_build_table_cb(H5O_t UNUSED *oh, H5O_mesg_t *mesg/*in,out*/, - unsigned UNUSED sequence, unsigned UNUSED *oh_flags_ptr, void *_udata/*in,out*/) + unsigned sequence, unsigned UNUSED *oh_flags_ptr, void *_udata/*in,out*/) { H5A_compact_bt_ud_t *udata = (H5A_compact_bt_ud_t *)_udata; /* Operator user data */ herr_t ret_value = H5_ITER_CONT; /* Return value */ @@ -140,6 +141,10 @@ H5A_compact_build_table_cb(H5O_t UNUSED *oh, H5O_mesg_t *mesg/*in,out*/, if(NULL == H5A_copy(&udata->atable->attrs[udata->curr_attr], (const H5A_t *)mesg->native)) HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute") + /* Assign [somewhat arbitrary] creation order value, if requested */ + if(udata->bogus_crt_idx) + udata->atable->attrs[udata->curr_attr].crt_idx = sequence; + /* Increment current attribute */ udata->curr_attr++; @@ -166,9 +171,8 @@ done: *------------------------------------------------------------------------- */ herr_t -H5A_compact_build_table(H5F_t *f, hid_t dxpl_id, H5O_t *oh, - H5_index_t UNUSED idx_type, H5_iter_order_t order, - H5A_attr_table_t *atable, unsigned *oh_flags) +H5A_compact_build_table(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5_index_t idx_type, + H5_iter_order_t order, H5A_attr_table_t *atable, unsigned *oh_flags) { H5A_compact_bt_ud_t udata; /* User data for iteration callback */ H5O_mesg_operator_t op; /* Wrapper for operator */ @@ -190,6 +194,7 @@ H5A_compact_build_table(H5F_t *f, hid_t dxpl_id, H5O_t *oh, udata.dxpl_id = dxpl_id; udata.atable = atable; udata.curr_attr = 0; + udata.bogus_crt_idx = (oh->version == H5O_VERSION_1) ? TRUE : FALSE; /* Iterate over existing attributes, checking for attribute with same name */ op.lib_op = H5A_compact_build_table_cb; @@ -200,7 +205,7 @@ H5A_compact_build_table(H5F_t *f, hid_t dxpl_id, H5O_t *oh, atable->nattrs = udata.curr_attr; /* Sort attribute table in correct iteration order */ - if(H5A_attr_sort_table(atable, H5_INDEX_NAME, order) < 0) + if(H5A_attr_sort_table(atable, idx_type, order) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTSORT, FAIL, "error sorting attribute table") done: @@ -255,7 +260,8 @@ done: * an object * * Note: Used for building table of attributes in non-native iteration - * order for an index + * order for an index. Uses the "name" index to retrieve records, + * but the 'idx_type' index for sorting them. * * Return: Success: Non-negative * Failure: Negative @@ -266,11 +272,12 @@ done: *------------------------------------------------------------------------- */ herr_t -H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, hsize_t nattrs, haddr_t attr_fheap_addr, - haddr_t name_bt2_addr, H5_index_t UNUSED idx_type, H5_iter_order_t order, +H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, haddr_t attr_fheap_addr, + haddr_t name_bt2_addr, H5_index_t idx_type, H5_iter_order_t order, H5A_attr_table_t *atable) { - herr_t ret_value = SUCCEED; /* Return value */ + hsize_t nrec; /* # of records in v2 B-tree */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5A_dense_build_table) @@ -280,9 +287,14 @@ H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, hsize_t nattrs, haddr_t attr_fhea HDassert(H5F_addr_defined(name_bt2_addr)); HDassert(atable); + /* Retrieve # of records in "name" B-tree */ + /* (should be same # of records in all indices) */ + if(H5B2_get_nrec(f, dxpl_id, H5A_BT2_NAME, name_bt2_addr, &nrec) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve # of records in index") + /* Set size of table */ - H5_CHECK_OVERFLOW(nattrs, /* From: */ hsize_t, /* To: */ size_t); - atable->nattrs = (size_t)nattrs; + H5_CHECK_OVERFLOW(nrec, /* From: */ hsize_t, /* To: */ size_t); + atable->nattrs = (size_t)nrec; /* Allocate space for the table entries */ if(atable->nattrs > 0) { @@ -303,11 +315,12 @@ H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, hsize_t nattrs, haddr_t attr_fhea /* Iterate over the links in the group, building a table of the link messages */ if(H5A_dense_iterate(f, dxpl_id, (hid_t)0, attr_fheap_addr, name_bt2_addr, - H5_ITER_NATIVE, (unsigned)0, NULL, &attr_op, &udata) < 0) + HADDR_UNDEF, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, NULL, + &attr_op, &udata) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table") /* Sort attribute table in correct iteration order */ - if(H5A_attr_sort_table(atable, H5_INDEX_NAME, order) < 0) + if(H5A_attr_sort_table(atable, idx_type, order) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTSORT, FAIL, "error sorting attribute table") } /* end if */ else @@ -332,7 +345,7 @@ done: * * Programmer: Quincey Koziol * koziol@hdfgroup.org - * Dec 11 2005 + * Dec 11 2006 * *------------------------------------------------------------------------- */ @@ -346,6 +359,103 @@ H5A_attr_cmp_name_inc(const void *attr1, const void *attr2) /*------------------------------------------------------------------------- + * Function: H5A_attr_cmp_name_dec + * + * Purpose: Callback routine for comparing two attribute names, in + * decreasing alphabetic order + * + * Return: An integer less than, equal to, or greater than zero if the + * second argument is considered to be respectively less than, + * equal to, or greater than the first. If two members compare + * as equal, their order in the sorted array is undefined. + * (i.e. opposite of strcmp()) + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Feb 8 2007 + * + *------------------------------------------------------------------------- + */ +static int +H5A_attr_cmp_name_dec(const void *attr1, const void *attr2) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_attr_cmp_name_dec) + + FUNC_LEAVE_NOAPI(HDstrcmp(((const H5A_t *)attr2)->name, ((const H5A_t *)attr1)->name)) +} /* end H5A_attr_cmp_name_dec() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_attr_cmp_corder_inc + * + * Purpose: Callback routine for comparing two attributes, in + * increasing creation order + * + * Return: An integer less than, equal to, or greater than zero if the + * first argument is considered to be respectively less than, + * equal to, or greater than the second. If two members compare + * as equal, their order in the sorted array is undefined. + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Feb 8 2007 + * + *------------------------------------------------------------------------- + */ +static int +H5A_attr_cmp_corder_inc(const void *attr1, const void *attr2) +{ + int ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_attr_cmp_corder_inc) + + if(((const H5A_t *)attr1)->crt_idx < ((const H5A_t *)attr2)->crt_idx) + ret_value = -1; + else if(((const H5A_t *)attr1)->crt_idx > ((const H5A_t *)attr2)->crt_idx) + ret_value = 1; + else + ret_value = 0; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_attr_cmp_corder_inc() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_attr_cmp_corder_dec + * + * Purpose: Callback routine for comparing two attributes, in + * decreasing creation order + * + * Return: An integer less than, equal to, or greater than zero if the + * second argument is considered to be respectively less than, + * equal to, or greater than the first. If two members compare + * as equal, their order in the sorted array is undefined. + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Feb 8 2007 + * + *------------------------------------------------------------------------- + */ +static int +H5A_attr_cmp_corder_dec(const void *attr1, const void *attr2) +{ + int ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_attr_cmp_corder_dec) + + if(((const H5A_t *)attr1)->crt_idx < ((const H5A_t *)attr2)->crt_idx) + ret_value = 1; + else if(((const H5A_t *)attr1)->crt_idx > ((const H5A_t *)attr2)->crt_idx) + ret_value = -1; + else + ret_value = 0; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_attr_cmp_corder_dec() */ + + +/*------------------------------------------------------------------------- * Function: H5A_attr_sort_table * * Purpose: Sort table containing a list of attributes for an object @@ -368,31 +478,23 @@ H5A_attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type, HDassert(atable); /* Pick appropriate comparison routine */ -#ifdef NOT_YET if(idx_type == H5_INDEX_NAME) { -#else /* NOT_YET */ -HDassert(idx_type == H5_INDEX_NAME); -#endif /* NOT_YET */ if(order == H5_ITER_INC) HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t), H5A_attr_cmp_name_inc); -#ifdef NOT_YET else if(order == H5_ITER_DEC) - HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_link_cmp_name_dec); -#endif /* NOT_YET */ + HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t), H5A_attr_cmp_name_dec); else HDassert(order == H5_ITER_NATIVE); -#ifdef NOT_YET } /* end if */ else { HDassert(idx_type == H5_INDEX_CRT_ORDER); if(order == H5_ITER_INC) - HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_link_cmp_corder_inc); + HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t), H5A_attr_cmp_corder_inc); else if(order == H5_ITER_DEC) - HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_link_cmp_corder_dec); + HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t), H5A_attr_cmp_corder_dec); else HDassert(order == H5_ITER_NATIVE); } /* end else */ -#endif /* NOT_YET */ FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5A_attr_sort_table() */ @@ -413,8 +515,8 @@ HDassert(idx_type == H5_INDEX_NAME); *------------------------------------------------------------------------- */ herr_t -H5A_attr_iterate_table(const H5A_attr_table_t *atable, unsigned skip, - unsigned *last_attr, hid_t loc_id, const H5A_attr_iter_op_t *attr_op, +H5A_attr_iterate_table(const H5A_attr_table_t *atable, hsize_t skip, + hsize_t *last_attr, hid_t loc_id, const H5A_attr_iter_op_t *attr_op, void *op_data) { size_t u; /* Local index variable */ @@ -431,7 +533,7 @@ H5A_attr_iterate_table(const H5A_attr_table_t *atable, unsigned skip, *last_attr = skip; /* Iterate over attribute messages */ - H5_ASSIGN_OVERFLOW(/* To: */ u, /* From: */ skip, /* From: */ unsigned, /* To: */ size_t) + H5_ASSIGN_OVERFLOW(/* To: */ u, /* From: */ skip, /* From: */ hsize_t, /* To: */ size_t) for(; u < atable->nattrs && !ret_value; u++) { /* Check which type of callback to make */ switch(attr_op->op_type) { diff --git a/src/H5Apkg.h b/src/H5Apkg.h index 708672a..fda8a02 100644 --- a/src/H5Apkg.h +++ b/src/H5Apkg.h @@ -194,9 +194,9 @@ H5_DLL herr_t H5A_dense_write(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, H5_DLL herr_t H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *old_name, const char *new_name); H5_DLL herr_t H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id, - haddr_t attr_fheap_addr, haddr_t name_bt2_addr, H5_iter_order_t order, - unsigned skip, unsigned *last_attr, const H5A_attr_iter_op_t *attr_op, - void *op_data); + haddr_t attr_fheap_addr, haddr_t name_bt2_addr, haddr_t corder_bt2_addr, + H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, + hsize_t *last_attr, const H5A_attr_iter_op_t *attr_op, void *op_data); H5_DLL herr_t H5A_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *name); H5_DLL htri_t H5A_dense_exists(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, @@ -206,11 +206,11 @@ H5_DLL htri_t H5A_dense_exists(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, H5_DLL herr_t H5A_compact_build_table(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5_index_t idx_type, H5_iter_order_t order, H5A_attr_table_t *atable, unsigned *oh_flags); -H5_DLL herr_t H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, hsize_t nattrs, +H5_DLL herr_t H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, haddr_t attr_fheap_addr, haddr_t name_bt2_addr, H5_index_t idx_type, H5_iter_order_t order, H5A_attr_table_t *atable); H5_DLL herr_t H5A_attr_iterate_table(const H5A_attr_table_t *atable, - unsigned skip, unsigned *last_attr, hid_t loc_id, + hsize_t skip, hsize_t *last_attr, hid_t loc_id, const H5A_attr_iter_op_t *attr_op, void *op_data); H5_DLL herr_t H5A_attr_release_table(H5A_attr_table_t *atable); diff --git a/src/H5Apublic.h b/src/H5Apublic.h index 0bcf8d6..bec794c 100644 --- a/src/H5Apublic.h +++ b/src/H5Apublic.h @@ -56,6 +56,9 @@ H5_DLL hsize_t H5Aget_storage_size(hid_t attr_id); H5_DLL herr_t H5Aget_info(hid_t loc_id, const char *name, H5A_info_t *ainfo /*out*/); H5_DLL herr_t H5Aget_info_by_idx(hid_t loc_id, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, H5A_info_t *ainfo /*out*/); +H5_DLL ssize_t H5Aget_name_by_idx(hid_t loc_id, + H5_index_t idx_type, H5_iter_order_t order, hsize_t n, + char *name /*out*/, size_t size); H5_DLL herr_t H5Arename(hid_t loc_id, const char *old_name, const char *new_name); H5_DLL herr_t H5Aiterate(hid_t loc_id, unsigned *attr_num, H5A_operator_t op, void *op_data); diff --git a/src/H5Gdense.c b/src/H5Gdense.c index 865c93f..5cea19c 100644 --- a/src/H5Gdense.c +++ b/src/H5Gdense.c @@ -86,12 +86,12 @@ typedef struct { /* downward (internal) */ H5F_t *f; /* Pointer to file that fractal heap is in */ hid_t dxpl_id; /* DXPL for operation */ - H5HF_t *fheap; /* Fractal heap handle */ + H5HF_t *fheap; /* Fractal heap handle */ + hsize_t count; /* # of links examined */ /* downward (from application) */ hid_t gid; /* Group ID for application callback */ hsize_t skip; /* Number of links to skip */ - hsize_t count; /* Count of records operated on */ const H5G_link_iterate_t *lnk_op; /* Callback for each link */ void *op_data; /* Callback data for each link */ @@ -858,7 +858,7 @@ H5G_dense_iterate_fh_cb(const void *obj, size_t UNUSED obj_len, void *_udata) * this routine because this fractal heap 'op' callback routine is called * with the direct block protected and if the callback routine invokes an * HDF5 routine, it could attempt to re-protect that direct block for the - * heap, causing the HDF5 routine called to fail) + * heap, causing the HDF5 routine called to fail - QAK) */ if(NULL == (udata->lnk = H5O_msg_decode(udata->f, udata->dxpl_id, H5O_LINK_ID, obj))) HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode link") @@ -968,6 +968,8 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, { H5HF_t *fheap = NULL; /* Fractal heap handle */ H5G_link_table_t ltable = {0, NULL}; /* Table of links */ + const H5B2_class_t *bt2_class = NULL; /* Class of v2 B-tree */ + haddr_t bt2_addr; /* Address of v2 B-tree to use for lookup */ herr_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5G_dense_iterate, FAIL) @@ -979,23 +981,33 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, HDassert(linfo); HDassert(lnk_op && lnk_op->u.lib_op); - /* Check for skipping too many links */ - if(skip > 0) { - hsize_t nrec; /* # of records in v2 B-tree */ - - /* Retrieve # of records in name index */ - /* (# of records in all indices the same) */ - if(H5B2_get_nrec(f, dxpl_id, H5G_BT2_NAME, linfo->name_bt2_addr, &nrec) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve # of records in index") - - /* Check for bad starting index */ - if(skip >= nrec) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified") + /* Determine the address of the index to use */ + if(idx_type == H5_INDEX_NAME) { + /* Check if "native" order is OK - since names are hashed, getting them + * in strictly increasing or decreasing order requires building a + * table and sorting it. + */ + if(order == H5_ITER_NATIVE) { + HDassert(H5F_addr_defined(linfo->name_bt2_addr)); + bt2_addr = linfo->name_bt2_addr; + bt2_class = H5G_BT2_NAME; + } /* end if */ + else + bt2_addr = HADDR_UNDEF; } /* end if */ + else { + HDassert(idx_type == H5_INDEX_CRT_ORDER); + + /* This address may not be defined if creation order is tracked, but + * there's no index on it. If there's no v2 B-tree that indexes + * the links, a table will be built. + */ + bt2_addr = linfo->corder_bt2_addr; + bt2_class = H5G_BT2_CORDER; + } /* end else */ /* Check on iteration order */ - /* ("native" iteration order is unordered for this link storage mechanism) */ - if(order == H5_ITER_NATIVE) { + if(order == H5_ITER_NATIVE && H5F_addr_defined(bt2_addr)) { H5G_bt2_ud_it_t udata; /* User data for iterator callback */ /* Open the fractal heap */ @@ -1014,11 +1026,10 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, /* Iterate over the records in the v2 B-tree's "native" order */ /* (by hash of name) */ - if((ret_value = H5B2_iterate(f, dxpl_id, H5G_BT2_NAME, linfo->name_bt2_addr, - H5G_dense_iterate_bt2_cb, &udata)) < 0) + if((ret_value = H5B2_iterate(f, dxpl_id, bt2_class, bt2_addr, H5G_dense_iterate_bt2_cb, &udata)) < 0) HERROR(H5E_SYM, H5E_BADITER, "link iteration failed"); - /* Update last link looked at */ + /* Update the last link examined, if requested */ if(last_lnk) *last_lnk = udata.count; } /* end if */ diff --git a/src/H5L.c b/src/H5L.c index e39e787..5943ec0 100644 --- a/src/H5L.c +++ b/src/H5L.c @@ -130,14 +130,15 @@ typedef struct { /* User data for path traversal routine for getting name by index */ typedef struct { /* In */ - H5_index_t idx_type; /* Index to use */ + H5_index_t idx_type; /* Index to use */ H5_iter_order_t order; /* Order to iterate in index */ hsize_t n; /* Offset of link within index */ size_t size; /* Size of name buffer */ hid_t dxpl_id; /* DXPL to use in callback */ /* Out */ - char *name; /* Buffer to return name to user */ + char *name; /* Buffer to return name to user */ + ssize_t name_len; /* Length of full name */ } H5L_trav_gnbi_t; /********************/ @@ -158,18 +159,12 @@ static herr_t H5L_get_val_cb(H5G_loc_t *grp_loc/*in*/, const char *name, static herr_t H5L_get_val_by_idx_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/, H5G_own_loc_t *own_loc/*out*/); -static herr_t H5L_get_val_by_idx(H5G_loc_t *loc, const char *group_name, - H5_index_t idx_type, H5_iter_order_t order, hsize_t n, void *buf/*out*/, - size_t size, hid_t lapl_id, hid_t dxpl_id); static herr_t H5L_delete_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/, H5G_own_loc_t *own_loc/*out*/); static herr_t H5L_delete_by_idx_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/, H5G_own_loc_t *own_loc/*out*/); -static herr_t H5L_delete_by_idx(H5G_loc_t *loc, const char *group_name, - H5_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t lapl_id, - hid_t dxpl_id); static herr_t H5L_move_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/, H5G_own_loc_t *own_loc/*out*/); @@ -182,15 +177,9 @@ static herr_t H5L_get_info_cb(H5G_loc_t *grp_loc/*in*/, const char *name, static herr_t H5L_get_info_by_idx_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/, H5G_own_loc_t *own_loc/*out*/); -static herr_t H5L_get_info_by_idx(const H5G_loc_t *loc, const char *group_name, - H5_index_t idx_type, H5_iter_order_t order, hsize_t n, - H5L_info_t *linfo/*out*/, hid_t lapl_id, hid_t dxpl_id); static herr_t H5L_get_name_by_idx_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/, H5G_own_loc_t *own_loc/*out*/); -static herr_t H5L_get_name_by_idx(const H5G_loc_t *loc, const char *group_name, - H5_index_t idx_type, H5_iter_order_t order, hsize_t n, - char *name/*out*/, size_t size, hid_t lapl_id, hid_t dxpl_id); /*********************/ /* Package Variables */ @@ -693,6 +682,7 @@ H5Ldelete_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t lapl_id) { H5G_loc_t loc; /* Group's location */ + H5L_trav_rmbi_t udata; /* User data for callback */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(H5Ldelete_by_idx, FAIL) @@ -713,9 +703,15 @@ H5Ldelete_by_idx(hid_t loc_id, const char *group_name, if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID") - /* Unlink */ - if(H5L_delete_by_idx(&loc, group_name, idx_type, order, n, lapl_id, H5AC_dxpl_id) < 0) - HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to delete link") + /* Set up user data for unlink operation */ + udata.idx_type = idx_type; + udata.order = order; + udata.n = n; + udata.dxpl_id = H5AC_dxpl_id; + + /* Traverse the group hierarchy to remove the link */ + if(H5G_traverse(&loc, group_name, H5G_TARGET_SLINK|H5G_TARGET_UDLINK|H5G_TARGET_MOUNT, H5L_delete_by_idx_cb, &udata, lapl_id, H5AC_dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "name doesn't exist") done: FUNC_LEAVE_API(ret_value) @@ -795,6 +791,7 @@ H5Lget_val_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type, hid_t lapl_id) { H5G_loc_t loc; /* Group location for location to query */ + H5L_trav_gvbi_t udata; /* User data for callback */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(H5Lget_val_by_idx, FAIL) @@ -816,9 +813,18 @@ H5Lget_val_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type, if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID") - /* Get the link value */ - if(H5L_get_val_by_idx(&loc, group_name, idx_type, order, n, buf, size, lapl_id, H5AC_ind_dxpl_id) < 0) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to get link value") + /* Set up user data for retrieving information */ + udata.idx_type = idx_type; + udata.order = order; + udata.n = n; + udata.dxpl_id = H5AC_ind_dxpl_id; + udata.buf = buf; + udata.size = size; + + /* Traverse the group hierarchy to locate the object to get info about */ + if(H5G_traverse(&loc, group_name, H5G_TARGET_SLINK | H5G_TARGET_UDLINK, H5L_get_val_by_idx_cb, &udata, lapl_id, H5AC_ind_dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist") + done: FUNC_LEAVE_API(ret_value) @@ -889,6 +895,7 @@ H5Lget_info_by_idx(hid_t loc_id, const char *group_name, H5L_info_t *linfo /*out*/, hid_t lapl_id) { H5G_loc_t loc; /* Group location for group to query */ + H5L_trav_gibi_t udata; /* User data for callback */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(H5Lget_info_by_idx, FAIL) @@ -910,10 +917,18 @@ H5Lget_info_by_idx(hid_t loc_id, const char *group_name, if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID") - /* Get the link information */ - if(H5L_get_info_by_idx(&loc, group_name, idx_type, order, n, linfo, lapl_id, H5AC_ind_dxpl_id) < 0) + /* Set up user data for callback */ + udata.idx_type = idx_type; + udata.order = order; + udata.n = n; + udata.dxpl_id = H5AC_ind_dxpl_id; + udata.linfo = linfo; + + /* Traverse the group hierarchy to locate the object to get info about */ + if(H5G_traverse(&loc, group_name, H5G_TARGET_SLINK|H5G_TARGET_UDLINK, H5L_get_info_by_idx_cb, &udata, lapl_id, H5AC_ind_dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to get link info") + done: FUNC_LEAVE_API(ret_value) } /* end H5Lget_info_by_idx() */ @@ -1054,7 +1069,8 @@ done: * * Same pattern of behavior as H5Iget_name. * - * Return: Success: Non-negative with information in NAME buffer + * Return: Success: Non-negative length of name, with information + * in NAME buffer * Failure: Negative * * Programmer: Quincey Koziol @@ -1068,6 +1084,7 @@ H5Lget_name_by_idx(hid_t loc_id, const char *group_name, char *name /*out*/, size_t size, hid_t lapl_id) { H5G_loc_t loc; /* Location of group */ + H5L_trav_gnbi_t udata; /* User data for callback */ ssize_t ret_value; /* Return value */ FUNC_ENTER_API(H5Lget_name_by_idx, FAIL) @@ -1089,9 +1106,21 @@ H5Lget_name_by_idx(hid_t loc_id, const char *group_name, if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID") - /* Get the link's name */ - if((ret_value = H5L_get_name_by_idx(&loc, group_name, idx_type, order, n, name, size, lapl_id, H5AC_ind_dxpl_id)) < 0) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to get link's name") + /* Set up user data for callback */ + udata.idx_type = idx_type; + udata.order = order; + udata.n = n; + udata.dxpl_id = H5AC_ind_dxpl_id; + udata.name = name; + udata.size = size; + udata.name_len = -1; + + /* Traverse the group hierarchy to locate the link to get name of */ + if(H5G_traverse(&loc, group_name, H5G_TARGET_SLINK|H5G_TARGET_UDLINK, H5L_get_name_by_idx_cb, &udata, lapl_id, H5AC_ind_dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "name doesn't exist") + + /* Set the return value */ + ret_value = udata.name_len; done: FUNC_LEAVE_API(ret_value) @@ -1970,56 +1999,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5L_get_val_by_idx - * - * Purpose: Returns the value of a symbolic link or the udata for a - * user-defined link. - * - * Return: Success: Non-negative, with at most SIZE bytes of the - * link value copied into the BUF buffer. If the - * link value is larger than SIZE characters - * counting the null terminator then the BUF - * result will not be null terminated. - * - * Failure: Negative - * - * Programmer: Quincey Koziol - * Monday, November 13, 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5L_get_val_by_idx(H5G_loc_t *loc, const char *group_name, H5_index_t idx_type, - H5_iter_order_t order, hsize_t n, void *buf/*out*/, size_t size, - hid_t lapl_id, hid_t dxpl_id) -{ - H5L_trav_gvbi_t udata; /* User data for callback */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5L_get_val_by_idx) - - /* Sanity check */ - HDassert(loc); - HDassert(group_name && *group_name); - - /* Set up user data for retrieving information */ - udata.idx_type = idx_type; - udata.order = order; - udata.n = n; - udata.dxpl_id = dxpl_id; - udata.buf = buf; - udata.size = size; - - /* Traverse the group hierarchy to locate the object to get info about */ - if(H5G_traverse(loc, group_name, H5G_TARGET_SLINK | H5G_TARGET_UDLINK, H5L_get_val_by_idx_cb, &udata, lapl_id, dxpl_id) < 0) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5L_get_val_by_idx() */ - - -/*------------------------------------------------------------------------- * Function: H5L_delete_cb * * Purpose: Callback for deleting a link. This routine @@ -2150,47 +2129,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5L_delete_by_idx - * - * Purpose: Delete a link from a group, according to the order within an - * index. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * Monday, November 13, 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5L_delete_by_idx(H5G_loc_t *loc, const char *group_name, H5_index_t idx_type, - H5_iter_order_t order, hsize_t n, hid_t lapl_id, hid_t dxpl_id) -{ - H5L_trav_rmbi_t udata; /* User data for callback */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5L_delete_by_idx) - - /* Sanity check */ - HDassert(loc); - HDassert(group_name && *group_name); - - /* Set up user data for unlink operation */ - udata.idx_type = idx_type; - udata.order = order; - udata.n = n; - udata.dxpl_id = dxpl_id; - - /* Traverse the group hierarchy to remove the link */ - if(H5G_traverse(loc, group_name, H5G_TARGET_SLINK|H5G_TARGET_UDLINK|H5G_TARGET_MOUNT, H5L_delete_by_idx_cb, &udata, lapl_id, dxpl_id) < 0) - HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "name doesn't exist") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5L_delete_by_idx() */ - - -/*------------------------------------------------------------------------- * Function: H5L_move_dest_cb * * Purpose: Second callback for moving and renaming an object. This routine @@ -2650,49 +2588,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5L_get_info_by_idx - * - * Purpose: Returns metadata about a link, according to an order within - * an index. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * Monday, November 6 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5L_get_info_by_idx(const H5G_loc_t *loc, const char *group_name, - H5_index_t idx_type, H5_iter_order_t order, hsize_t n, - H5L_info_t *linfo/*out*/, hid_t lapl_id, hid_t dxpl_id) -{ - H5L_trav_gibi_t udata; /* User data for callback */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5L_get_info_by_idx) - - /* Sanity check */ - HDassert(loc); - HDassert(group_name && *group_name); - - /* Set up user data for callback */ - udata.idx_type = idx_type; - udata.order = order; - udata.n = n; - udata.dxpl_id = dxpl_id; - udata.linfo = linfo; - - /* Traverse the group hierarchy to locate the object to get info about */ - if(H5G_traverse(loc, group_name, H5G_TARGET_SLINK|H5G_TARGET_UDLINK, H5L_get_info_by_idx_cb, &udata, lapl_id, dxpl_id) < 0) - HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "name doesn't exist") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5L_get_info_by_idx() */ - - -/*------------------------------------------------------------------------- * Function: H5L_get_default_lcpl * * Purpose: Accessor for the default Link Creation Property List @@ -2748,8 +2643,8 @@ H5L_get_name_by_idx_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group doesn't exist") /* Query link */ - if(H5G_obj_get_name_by_idx(obj_loc->oloc, udata->idx_type, udata->order, - udata->n, udata->name, udata->size, udata->dxpl_id) < 0) + if((udata->name_len = H5G_obj_get_name_by_idx(obj_loc->oloc, udata->idx_type, udata->order, + udata->n, udata->name, udata->size, udata->dxpl_id)) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "link not found") done: @@ -2760,43 +2655,3 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5L_get_name_by_idx_cb() */ - -/*------------------------------------------------------------------------- - * Function: H5L_get_name_by_idx - * - * Purpose: Returns name of a link, according to an order within - * an index. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * Saturday, November 11 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5L_get_name_by_idx(const H5G_loc_t *loc, const char *group_name, - H5_index_t idx_type, H5_iter_order_t order, hsize_t n, - char *name/*out*/, size_t size, hid_t lapl_id, hid_t dxpl_id) -{ - H5L_trav_gnbi_t udata; /* User data for callback */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5L_get_name_by_idx) - - /* Set up user data for callback */ - udata.idx_type = idx_type; - udata.order = order; - udata.n = n; - udata.dxpl_id = dxpl_id; - udata.name = name; - udata.size = size; - - /* Traverse the group hierarchy to locate the object to get info about */ - if(H5G_traverse(loc, group_name, H5G_TARGET_SLINK|H5G_TARGET_UDLINK, H5L_get_name_by_idx_cb, &udata, lapl_id, dxpl_id) < 0) - HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "name doesn't exist") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5L_get_name_by_idx() */ - diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c index 781572b..2f8a1ea 100644 --- a/src/H5Oattribute.c +++ b/src/H5Oattribute.c @@ -427,7 +427,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5O_attr_open_by_idx + * Function: H5O_attr_open_by_idx_cb * * Purpose: Callback routine opening an attribute by index * @@ -491,7 +491,7 @@ H5O_attr_open_by_idx(const H5O_loc_t *loc, H5_index_t idx_type, attr_op.u.lib_op = H5O_attr_open_by_idx_cb; /* Iterate over attributes to locate correct one */ - if(H5O_attr_iterate((hid_t)-1, loc, dxpl_id, H5_ITER_INC, (unsigned)n, NULL, &attr_op, &ret_value) < 0) + if(H5O_attr_iterate((hid_t)-1, loc, dxpl_id, idx_type, order, n, NULL, &attr_op, &ret_value) < 0) HGOTO_ERROR(H5E_ATTR, H5E_BADITER, NULL, "can't locate attribute") done: @@ -950,8 +950,8 @@ done: */ herr_t H5O_attr_iterate(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id, - H5_iter_order_t order, unsigned skip, unsigned *last_attr, - const H5A_attr_iter_op_t *attr_op, void *op_data) + H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, + hsize_t *last_attr, const H5A_attr_iter_op_t *attr_op, void *op_data) { H5O_t *oh = NULL; /* Pointer to actual object header */ unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */ @@ -972,10 +972,16 @@ H5O_attr_iterate(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id, if(oh->version > H5O_VERSION_1 && H5F_addr_defined(oh->attr_fheap_addr)) { haddr_t attr_fheap_addr; /* Address of fractal heap for dense attribute storage */ haddr_t name_bt2_addr; /* Address of v2 B-tree for name index on dense attribute storage */ + haddr_t corder_bt2_addr; /* Address of v2 B-tree for creation order index on dense attribute storage */ + + /* Check for skipping too many attributes */ + if(skip > 0 && skip >= oh->nattrs) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified") /* Retrieve the information about dense attribute storage */ attr_fheap_addr = oh->attr_fheap_addr; name_bt2_addr = oh->name_bt2_addr; + corder_bt2_addr = oh->corder_bt2_addr; /* Release the object header */ if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0) @@ -984,12 +990,13 @@ H5O_attr_iterate(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id, /* Iterate over attributes in dense storage */ if((ret_value = H5A_dense_iterate(loc->file, dxpl_id, loc_id, attr_fheap_addr, - name_bt2_addr, order, skip, last_attr, attr_op, op_data)) < 0) + name_bt2_addr, corder_bt2_addr, idx_type, order, skip, + last_attr, attr_op, op_data)) < 0) HERROR(H5E_ATTR, H5E_BADITER, "error iterating over attributes"); } /* end if */ else { /* Build table of attributes for compact storage */ - if(H5A_compact_build_table(loc->file, dxpl_id, oh, H5_INDEX_NAME, H5_ITER_INC, &atable, &oh_flags) < 0) + if(H5A_compact_build_table(loc->file, dxpl_id, oh, idx_type, order, &atable, &oh_flags) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "error building attribute table") /* Release the object header */ @@ -998,11 +1005,8 @@ H5O_attr_iterate(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id, oh = NULL; /* Check for skipping too many attributes */ - if(skip > 0) { - /* Check for bad starting index */ - if(skip >= atable.nattrs) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified") - } /* end if */ + if(skip > 0 && skip >= atable.nattrs) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified") /* Iterate over attributes in table */ if((ret_value = H5A_attr_iterate_table(&atable, skip, last_attr, loc_id, attr_op, op_data)) < 0) @@ -1148,7 +1152,7 @@ H5O_attr_remove(const H5O_loc_t *loc, const char *name, hid_t dxpl_id) size_t u; /* Local index */ /* Build the table of attributes for this object */ - if(H5A_dense_build_table(loc->file, dxpl_id, oh->nattrs, oh->attr_fheap_addr, oh->name_bt2_addr, H5_INDEX_NAME, H5_ITER_NATIVE, &atable) < 0) + if(H5A_dense_build_table(loc->file, dxpl_id, oh->attr_fheap_addr, oh->name_bt2_addr, H5_INDEX_NAME, H5_ITER_NATIVE, &atable) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "error building attribute table") /* Inspect attributes in table for ones that can't be converted back diff --git a/src/H5Opkg.h b/src/H5Opkg.h index 2d106da..d3ff9c9 100644 --- a/src/H5Opkg.h +++ b/src/H5Opkg.h @@ -482,8 +482,8 @@ H5_DLL herr_t H5O_attr_write(const H5O_loc_t *loc, hid_t dxpl_id, H5_DLL herr_t H5O_attr_rename(const H5O_loc_t *loc, hid_t dxpl_id, const char *old_name, const char *new_name); H5_DLL herr_t H5O_attr_iterate(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id, - H5_iter_order_t order, unsigned skip, unsigned *last_attr, - const H5A_attr_iter_op_t *op, void *op_data); + H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, + hsize_t *last_attr, const H5A_attr_iter_op_t *op, void *op_data); H5_DLL herr_t H5O_attr_remove(const H5O_loc_t *loc, const char *name, hid_t dxpl_id); H5_DLL int H5O_attr_count(const H5O_loc_t *loc, hid_t dxpl_id); diff --git a/test/links.c b/test/links.c index 9548f4a..7696309 100644 --- a/test/links.c +++ b/test/links.c @@ -6087,7 +6087,7 @@ link_info_by_idx(hid_t fapl) char objname[NAME_BUF_SIZE]; /* Object name */ char valname[NAME_BUF_SIZE]; /* Link value name */ char filename[NAME_BUF_SIZE];/* File name */ - char tmpname[NAME_BUF_SIZE]; /* Temporary link name */ + char tmpname[NAME_BUF_SIZE]; /* Temporary link name */ unsigned u; /* Local index variable */ herr_t ret; /* Generic return value */ diff --git a/test/tattr.c b/test/tattr.c index a444ea5..0c9e06d 100644 --- a/test/tattr.c +++ b/test/tattr.c @@ -1395,9 +1395,9 @@ test_attr_iterate(hid_t fapl) VERIFY(ret, 0, "H5Aget_num_attrs"); /* Iterate over attributes on dataset */ - start=0; - count=0; - ret = H5Aiterate(dataset,&start,attr_op1,&count); + start = 0; + count = 0; + ret = H5Aiterate(dataset, &start, attr_op1, &count); VERIFY(ret, 0, "H5Aiterate"); /* Close dataset */ @@ -3800,6 +3800,153 @@ test_attr_corder_delete(hid_t fcpl, hid_t fapl) CHECK(ret, FAIL, "H5Sclose"); } /* test_attr_corder_delete() */ + +/*------------------------------------------------------------------------- + * Function: attr_info_by_idx_check + * + * Purpose: Support routine for attr_info_by_idx, to verify the attribute + * info is correct for a attribute + * + * Note: This routine assumes that the attributes have been added to the + * object in alphabetical order. + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Quincey Koziol + * Tuesday, Februrary 13, 2007 + * + *------------------------------------------------------------------------- + */ +static int +attr_info_by_idx_check(hid_t obj_id, const char *attrname, hsize_t n, + hbool_t use_index) +{ + char tmpname[NAME_BUF_SIZE]; /* Temporary attribute name */ + H5A_info_t ainfo; /* Attribute info struct */ + int old_nerrs; /* Number of errors when entering this check */ + herr_t ret; /* Generic return value */ + + /* Retrieve the current # of reported errors */ + old_nerrs = GetTestNumErrs(); + + /* Verify the information for first attribute, in increasing creation order */ + HDmemset(&ainfo, 0, sizeof(ainfo)); + ret = H5Aget_info_by_idx(obj_id, H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)0, &ainfo); + CHECK(ret, FAIL, "H5Aget_info_by_idx"); + VERIFY(ainfo.corder, 0, "H5Aget_info_by_idx"); + + /* Verify the information for new attribute, in increasing creation order */ + HDmemset(&ainfo, 0, sizeof(ainfo)); + ret = H5Aget_info_by_idx(obj_id, H5_INDEX_CRT_ORDER, H5_ITER_INC, n, &ainfo); + CHECK(ret, FAIL, "H5Aget_info_by_idx"); + VERIFY(ainfo.corder, n, "H5Aget_info_by_idx"); + + /* Verify the name for new link, in increasing creation order */ + HDmemset(tmpname, 0, (size_t)NAME_BUF_SIZE); + ret = H5Aget_name_by_idx(obj_id, H5_INDEX_CRT_ORDER, H5_ITER_INC, n, tmpname, (size_t)NAME_BUF_SIZE); + CHECK(ret, FAIL, "H5Aget_name_by_idx"); + if(HDstrcmp(attrname, tmpname)) + TestErrPrintf("Line %d: attribute name size wrong!\n", __LINE__); + + + /* Don't test "native" order if there is no creation order index, since + * there's not a good way to easily predict the attribute's order in the name + * index. + */ + if(use_index) { + /* Verify the information for first attribute, in native creation order */ + HDmemset(&ainfo, 0, sizeof(ainfo)); + ret = H5Aget_info_by_idx(obj_id, H5_INDEX_CRT_ORDER, H5_ITER_NATIVE, (hsize_t)0, &ainfo); + CHECK(ret, FAIL, "H5Aget_info_by_idx"); + VERIFY(ainfo.corder, 0, "H5Aget_info_by_idx"); + + /* Verify the information for new attribute, in native creation order */ + HDmemset(&ainfo, 0, sizeof(ainfo)); + ret = H5Aget_info_by_idx(obj_id, H5_INDEX_CRT_ORDER, H5_ITER_NATIVE, n, &ainfo); + CHECK(ret, FAIL, "H5Aget_info_by_idx"); + VERIFY(ainfo.corder, n, "H5Aget_info_by_idx"); + + /* Verify the name for new link, in increasing native order */ + HDmemset(tmpname, 0, (size_t)NAME_BUF_SIZE); + ret = H5Aget_name_by_idx(obj_id, H5_INDEX_CRT_ORDER, H5_ITER_NATIVE, n, tmpname, (size_t)NAME_BUF_SIZE); + CHECK(ret, FAIL, "H5Aget_name_by_idx"); + if(HDstrcmp(attrname, tmpname)) + TestErrPrintf("Line %d: attribute name size wrong!\n", __LINE__); + } /* end if */ + + + /* Verify the information for first attribute, in decreasing creation order */ + HDmemset(&ainfo, 0, sizeof(ainfo)); + ret = H5Aget_info_by_idx(obj_id, H5_INDEX_CRT_ORDER, H5_ITER_DEC, n, &ainfo); + CHECK(ret, FAIL, "H5Aget_info_by_idx"); + VERIFY(ainfo.corder, 0, "H5Aget_info_by_idx"); + + /* Verify the information for new attribute, in increasing creation order */ + HDmemset(&ainfo, 0, sizeof(ainfo)); + ret = H5Aget_info_by_idx(obj_id, H5_INDEX_CRT_ORDER, H5_ITER_DEC, (hsize_t)0, &ainfo); + CHECK(ret, FAIL, "H5Aget_info_by_idx"); + VERIFY(ainfo.corder, n, "H5Aget_info_by_idx"); + + /* Verify the name for new link, in increasing creation order */ + HDmemset(tmpname, 0, (size_t)NAME_BUF_SIZE); + ret = H5Aget_name_by_idx(obj_id, H5_INDEX_CRT_ORDER, H5_ITER_DEC, (hsize_t)0, tmpname, (size_t)NAME_BUF_SIZE); + CHECK(ret, FAIL, "H5Aget_name_by_idx"); + if(HDstrcmp(attrname, tmpname)) + TestErrPrintf("Line %d: attribute name size wrong!\n", __LINE__); + + + /* Verify the information for first attribute, in increasing name order */ + HDmemset(&ainfo, 0, sizeof(ainfo)); + ret = H5Aget_info_by_idx(obj_id, H5_INDEX_NAME, H5_ITER_INC, (hsize_t)0, &ainfo); + CHECK(ret, FAIL, "H5Aget_info_by_idx"); + VERIFY(ainfo.corder, 0, "H5Aget_info_by_idx"); + + /* Verify the information for new attribute, in increasing name order */ + HDmemset(&ainfo, 0, sizeof(ainfo)); + ret = H5Aget_info_by_idx(obj_id, H5_INDEX_NAME, H5_ITER_INC, n, &ainfo); + CHECK(ret, FAIL, "H5Aget_info_by_idx"); + VERIFY(ainfo.corder, n, "H5Aget_info_by_idx"); + + /* Verify the name for new link, in increasing name order */ + HDmemset(tmpname, 0, (size_t)NAME_BUF_SIZE); + ret = H5Aget_name_by_idx(obj_id, H5_INDEX_NAME, H5_ITER_INC, n, tmpname, (size_t)NAME_BUF_SIZE); + CHECK(ret, FAIL, "H5Aget_name_by_idx"); + if(HDstrcmp(attrname, tmpname)) + TestErrPrintf("Line %d: attribute name size wrong!\n", __LINE__); + + + /* Don't test "native" order queries on link name order, since there's not + * a good way to easily predict the order of the links in the name index. + */ + + + /* Verify the information for first attribute, in decreasing name order */ + HDmemset(&ainfo, 0, sizeof(ainfo)); + ret = H5Aget_info_by_idx(obj_id, H5_INDEX_NAME, H5_ITER_DEC, n, &ainfo); + CHECK(ret, FAIL, "H5Aget_info_by_idx"); + VERIFY(ainfo.corder, 0, "H5Aget_info_by_idx"); + + /* Verify the information for new attribute, in increasing name order */ + HDmemset(&ainfo, 0, sizeof(ainfo)); + ret = H5Aget_info_by_idx(obj_id, H5_INDEX_NAME, H5_ITER_DEC, (hsize_t)0, &ainfo); + CHECK(ret, FAIL, "H5Aget_info_by_idx"); + VERIFY(ainfo.corder, n, "H5Aget_info_by_idx"); + + /* Verify the name for new link, in increasing name order */ + HDmemset(tmpname, 0, (size_t)NAME_BUF_SIZE); + ret = H5Aget_name_by_idx(obj_id, H5_INDEX_NAME, H5_ITER_DEC, (hsize_t)0, tmpname, (size_t)NAME_BUF_SIZE); + CHECK(ret, FAIL, "H5Aget_name_by_idx"); + if(HDstrcmp(attrname, tmpname)) + TestErrPrintf("Line %d: attribute name size wrong!\n", __LINE__); + + /* Retrieve current # of errors */ + if(old_nerrs == GetTestNumErrs()) + return(0); + else + return(-1); +} /* end attr_info_by_idx_check() */ + /**************************************************************** ** ** test_attr_info_by_idx(): Test basic H5A (attribute) code. @@ -3807,7 +3954,7 @@ test_attr_corder_delete(hid_t fcpl, hid_t fapl) ** ****************************************************************/ static void -test_attr_info_by_idx(hid_t fcpl, hid_t fapl) +test_attr_info_by_idx(hbool_t new_format, hid_t fcpl, hid_t fapl) { hid_t fid; /* HDF5 File ID */ hid_t dset1, dset2, dset3; /* Dataset IDs */ @@ -3824,7 +3971,8 @@ test_attr_info_by_idx(hid_t fcpl, hid_t fapl) hsize_t name_count; /* # of records in name index */ hsize_t corder_count; /* # of records in creation order index */ hbool_t use_index; /* Use index on creation order values */ - char attrname[NAME_BUF_SIZE]; /* Name of attribute */ + char attrname[NAME_BUF_SIZE]; /* Name of attribute */ + char tmpname[NAME_BUF_SIZE]; /* Temporary attribute name */ unsigned curr_dset; /* Current dataset to work on */ unsigned u; /* Local index variable */ herr_t ret; /* Generic return value */ @@ -3896,15 +4044,16 @@ test_attr_info_by_idx(hid_t fcpl, hid_t fapl) /* Check for query on non-existant attribute */ ret = H5Aget_info_by_idx(my_dataset, H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)0, &ainfo); - VERIFY(ret, FALSE, "H5Aget_info_by_idx"); + VERIFY(ret, FAIL, "H5Aget_info_by_idx"); + ret = H5Aget_name_by_idx(my_dataset, H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)0, tmpname, (size_t)NAME_BUF_SIZE); + VERIFY(ret, FAIL, "H5Aget_name_by_idx"); } /* end for */ -#ifdef NOT_YET - /* Create attributes, until attribute storage is in dense form */ - for(u = 0; u < max_compact * 2; u++) { + /* Create attributes, up to limit of compact form */ + for(u = 0; u < max_compact; u++) { /* Create attribute */ sprintf(attrname, "attr %02u", u); - attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT); + attr = H5Acreate(my_dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT); CHECK(attr, FAIL, "H5Acreate"); /* Write data into the attribute */ @@ -3914,22 +4063,78 @@ test_attr_info_by_idx(hid_t fcpl, hid_t fapl) /* Close attribute */ ret = H5Aclose(attr); CHECK(ret, FAIL, "H5Aclose"); + + /* Verify information for new attribute */ + ret = attr_info_by_idx_check(my_dataset, attrname, (hsize_t)u, use_index); + CHECK(ret, FAIL, "attr_info_by_idx_check"); } /* end for */ /* Verify state of object */ - ret = H5O_num_attrs_test(dataset, &nattrs); + ret = H5O_num_attrs_test(my_dataset, &nattrs); + CHECK(ret, FAIL, "H5O_num_attrs_test"); + VERIFY(nattrs, max_compact, "H5O_num_attrs_test"); + is_empty = H5O_is_attr_empty_test(my_dataset); + VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test"); + is_dense = H5O_is_attr_dense_test(my_dataset); + VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test"); + + /* Check for out of bound offset queries */ + ret = H5Aget_info_by_idx(my_dataset, H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)u, &ainfo); + VERIFY(ret, FAIL, "H5Aget_info_by_idx"); + ret = H5Aget_info_by_idx(my_dataset, H5_INDEX_CRT_ORDER, H5_ITER_DEC, (hsize_t)u, &ainfo); + VERIFY(ret, FAIL, "H5Aget_info_by_idx"); + ret = H5Aget_name_by_idx(my_dataset, H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)u, tmpname, (size_t)NAME_BUF_SIZE); + VERIFY(ret, FAIL, "H5Aget_name_by_idx"); + + /* Create more attributes, to push into dense form */ + for(; u < (max_compact * 2); u++) { + /* Create attribute */ + sprintf(attrname, "attr %02u", u); + attr = H5Acreate(my_dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT); + CHECK(attr, FAIL, "H5Acreate"); + + /* Write data into the attribute */ + ret = H5Awrite(attr, H5T_NATIVE_UINT, &u); + CHECK(ret, FAIL, "H5Awrite"); + + /* Close attribute */ + ret = H5Aclose(attr); + CHECK(ret, FAIL, "H5Aclose"); + + /* Verify state of object */ + is_dense = H5O_is_attr_dense_test(my_dataset); + VERIFY(is_dense, (new_format ? TRUE : FALSE), "H5O_is_attr_dense_test"); + + /* Verify information for new attribute */ + ret = attr_info_by_idx_check(my_dataset, attrname, (hsize_t)u, use_index); + CHECK(ret, FAIL, "attr_info_by_idx_check"); + } /* end for */ + + /* Verify state of object */ + ret = H5O_num_attrs_test(my_dataset, &nattrs); CHECK(ret, FAIL, "H5O_num_attrs_test"); VERIFY(nattrs, (max_compact * 2), "H5O_num_attrs_test"); - is_empty = H5O_is_attr_empty_test(dataset); + is_empty = H5O_is_attr_empty_test(my_dataset); VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test"); - is_dense = H5O_is_attr_dense_test(dataset); - VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test"); + is_dense = H5O_is_attr_dense_test(my_dataset); + VERIFY(is_dense, (new_format ? TRUE : FALSE), "H5O_is_attr_dense_test"); - /* Retrieve & verify # of records in the name & creation order indices */ - ret = H5O_attr_dense_info_test(dataset, &name_count, &corder_count); - CHECK(ret, FAIL, "H5O_attr_dense_info_test"); - VERIFY(name_count, corder_count, "H5O_attr_dense_info_test"); -#endif /* NOT_YET */ + if(new_format) { + /* Retrieve & verify # of records in the name & creation order indices */ + ret = H5O_attr_dense_info_test(my_dataset, &name_count, &corder_count); + CHECK(ret, FAIL, "H5O_attr_dense_info_test"); + if(use_index) + VERIFY(name_count, corder_count, "H5O_attr_dense_info_test"); + VERIFY(name_count, (max_compact * 2), "H5O_attr_dense_info_test"); + } /* end if */ + + /* Check for out of bound offset queries */ + ret = H5Aget_info_by_idx(my_dataset, H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)u, &ainfo); + VERIFY(ret, FAIL, "H5Aget_info_by_idx"); + ret = H5Aget_info_by_idx(my_dataset, H5_INDEX_CRT_ORDER, H5_ITER_DEC, (hsize_t)u, &ainfo); + VERIFY(ret, FAIL, "H5Aget_info_by_idx"); + ret = H5Aget_name_by_idx(my_dataset, H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)u, tmpname, (size_t)NAME_BUF_SIZE); + VERIFY(ret, FAIL, "H5Aget_name_by_idx"); /* Close Datasets */ ret = H5Dclose(dset1); @@ -3942,9 +4147,8 @@ test_attr_info_by_idx(hid_t fcpl, hid_t fapl) /* Close file */ ret = H5Fclose(fid); CHECK(ret, FAIL, "H5Fclose"); - } /* end for */ -} /* test_attr_corder_delete() */ +} /* test_attr_info_by_idx() */ /**************************************************************** ** @@ -5556,10 +5760,8 @@ test_attr(void) test_attr_corder_transition(my_fcpl, my_fapl); /* Test attribute storage transitions on an object w/attribute creation order info */ test_attr_corder_delete(my_fcpl, my_fapl); /* Test deleting object using dense storage w/attribute creation order info */ -#ifdef NOT_YET /* New attribute API routine tests */ - test_attr_info_by_idx(my_fcpl, my_fapl); /* Test querying attribute info by index */ -#endif /* NOT_YET */ + test_attr_info_by_idx(new_format, my_fcpl, my_fapl); /* Test querying attribute info by index */ /* More complex tests with both "new format" and "shared" attributes */ if(use_shared == TRUE) { @@ -5571,7 +5773,8 @@ test_attr(void) } /* end for */ } /* end if */ else { - /* New attribute API routine tests */ + /* New attribute API routine tests, on old-format storage */ + test_attr_info_by_idx(new_format, fcpl, my_fapl); /* Test querying attribute info by index */ } /* end else */ } /* end for */ diff --git a/test/titerate.c b/test/titerate.c index 571f351..10ddf17 100644 --- a/test/titerate.c +++ b/test/titerate.c @@ -304,7 +304,7 @@ static void test_iter_group(hid_t fapl, hbool_t new_format) VERIFY(ret, -1, "H5Giterate"); if(i != (NDATASETS + 2)) - TestErrPrintf("Group iteration function didn't perform multiple iterations correctly!\n"); + TestErrPrintf("%u: Group iteration function didn't perform multiple iterations correctly!\n", __LINE__); /* Test all objects in group, when callback changes return value */ /* This also tests the "restarting" ability, because the index changes */ @@ -329,7 +329,7 @@ static void test_iter_group(hid_t fapl, hbool_t new_format) VERIFY(ret, -1, "H5Giterate"); if(i != 42 || idx != 52) - TestErrPrintf("Group iteration function didn't perform multiple iterations correctly!\n"); + TestErrPrintf("%u: Group iteration function didn't perform multiple iterations correctly!\n", __LINE__); ret = H5Fclose(file); CHECK(ret, FAIL, "H5Fclose"); @@ -454,65 +454,55 @@ static void test_iter_attr(hid_t fapl, hbool_t new_format) VERIFY(ret, FAIL, "H5Aiterate"); /* Test all attributes on dataset, when callback always returns 0 */ - info.command=RET_ZERO; - idx=0; - if((ret=H5Aiterate(dataset,&idx,aiter_cb,&info))>0) + info.command = RET_ZERO; + idx = 0; + if((ret = H5Aiterate(dataset, &idx, aiter_cb, &info)) > 0) TestErrPrintf("Attribute iteration function didn't return zero correctly!\n"); /* Test all attributes on dataset, when callback always returns 1 */ /* This also tests the "restarting" ability, because the index changes */ - info.command=RET_TWO; - idx=i=0; - while((ret=H5Aiterate(dataset,&idx,aiter_cb,&info))>0) { + info.command = RET_TWO; + idx = i = 0; + while((ret = H5Aiterate(dataset, &idx, aiter_cb, &info)) > 0) { /* Verify return value from iterator gets propagated correctly */ - VERIFY(ret,2,"H5Aiterate"); + VERIFY(ret, 2, "H5Aiterate"); /* Increment the number of times "2" is returned */ i++; /* Verify that the index is the correct value */ - VERIFY(idx,(unsigned)i,"H5Aiterate"); + VERIFY(idx, (unsigned)i, "H5Aiterate"); /* Verify that the correct name is retrieved */ -#ifdef LATER - if(HDstrcmp(info.name,anames[idx-1])!=0) - TestErrPrintf("Attribute iteration function didn't return two correctly!\n"); -#endif /* LATER */ - } -#ifndef LATER -HDfprintf(stderr, "Check skipped - fix after creation order for attributes implemented\n"); -#endif /* LATER */ - VERIFY(ret,-1,"H5Aiterate"); - if(i!=50 || idx!=50) - TestErrPrintf("Attribute iteration function didn't perform multiple iterations correctly!\n"); + if(HDstrcmp(info.name, anames[idx - 1]) != 0) + TestErrPrintf("%u: Attribute iteration function didn't return 'two' correctly!\n", __LINE__); + } /* end while */ + VERIFY(ret, -1, "H5Aiterate"); + if(i != 50 || idx != 50) + TestErrPrintf("%u: Attribute iteration function didn't perform multiple iterations correctly!\n", __LINE__); /* Test all attributes on dataset, when callback changes return value */ /* This also tests the "restarting" ability, because the index changes */ info.command = new_format ? RET_CHANGE2 : RET_CHANGE; - idx=i=0; - while((ret=H5Aiterate(dataset,&idx,aiter_cb,&info))>0) { + idx = i = 0; + while((ret = H5Aiterate(dataset, &idx, aiter_cb, &info)) > 0) { /* Verify return value from iterator gets propagated correctly */ - VERIFY(ret,1,"H5Aiterate"); + VERIFY(ret, 1, "H5Aiterate"); /* Increment the number of times "1" is returned */ i++; /* Verify that the index is the correct value */ - VERIFY(idx,(unsigned)i+10,"H5Aiterate"); + VERIFY(idx, (unsigned)i + 10, "H5Aiterate"); /* Verify that the correct name is retrieved */ -#ifdef LATER - if(HDstrcmp(info.name,anames[idx-1])!=0) + if(HDstrcmp(info.name, anames[idx - 1]) != 0) TestErrPrintf("Attribute iteration function didn't return changing correctly!\n"); -#endif /* LATER */ - } -#ifndef LATER -HDfprintf(stderr, "Check skipped - fix after creation order for attributes implemented\n"); -#endif /* LATER */ - VERIFY(ret,-1,"H5Aiterate"); - if(i!=40 || idx!=50) - TestErrPrintf("Attribute iteration function didn't perform multiple iterations correctly!\n"); + } /* end while */ + VERIFY(ret, -1, "H5Aiterate"); + if(i != 40 || idx != 50) + TestErrPrintf("%u: Attribute iteration function didn't perform multiple iterations correctly!\n", __LINE__); ret=H5Fclose(file); CHECK(ret, FAIL, "H5Fclose"); -- cgit v0.12