summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2007-02-13 14:50:48 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2007-02-13 14:50:48 (GMT)
commit56e63bdeea4bd94b46dd3e962e457959e4fe636c (patch)
treec1dcd9332f26691c1a12eb0bdb0c025fc1c91fd5
parent46e24b92bfabd15d5cd09d2373914daa18e7bad3 (diff)
downloadhdf5-56e63bdeea4bd94b46dd3e962e457959e4fe636c.zip
hdf5-56e63bdeea4bd94b46dd3e962e457959e4fe636c.tar.gz
hdf5-56e63bdeea4bd94b46dd3e962e457959e4fe636c.tar.bz2
[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)
-rw-r--r--src/H5A.c77
-rw-r--r--src/H5Adense.c61
-rw-r--r--src/H5Aint.c158
-rw-r--r--src/H5Apkg.h10
-rw-r--r--src/H5Apublic.h3
-rw-r--r--src/H5Gdense.c51
-rw-r--r--src/H5L.c259
-rw-r--r--src/H5Oattribute.c28
-rw-r--r--src/H5Opkg.h4
-rw-r--r--test/links.c2
-rw-r--r--test/tattr.c253
-rw-r--r--test/titerate.c60
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");