summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MANIFEST1
-rw-r--r--src/H5A.c137
-rw-r--r--src/H5Adense.c363
-rw-r--r--src/H5Aint.c511
-rw-r--r--src/H5Apkg.h24
-rw-r--r--src/H5Aprivate.h1
-rw-r--r--src/H5Gdense.c27
-rw-r--r--src/H5Oattr.c8
-rw-r--r--src/H5Oattribute.c194
-rw-r--r--src/H5Opkg.h7
-rwxr-xr-xsrc/H5SM.c30
-rwxr-xr-xsrc/H5SMprivate.h1
-rwxr-xr-xsrc/Makefile.am3
-rw-r--r--src/Makefile.in5
-rw-r--r--test/tattr.c94
-rw-r--r--test/titerate.c4
16 files changed, 948 insertions, 462 deletions
diff --git a/MANIFEST b/MANIFEST
index 2fd9b74..811290f 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -413,6 +413,7 @@
./src/H5Abtree2.c
./src/H5Adense.c
./src/H5Adeprec.c
+./src/H5Aint.c
./src/H5Apkg.h
./src/H5Aprivate.h
./src/H5Apublic.h
diff --git a/src/H5A.c b/src/H5A.c
index 826c8a0..072fc99 100644
--- a/src/H5A.c
+++ b/src/H5A.c
@@ -67,7 +67,8 @@ typedef struct H5A_iter_cb1 {
static hid_t H5A_create(const H5G_loc_t *loc, const char *name,
const H5T_t *type, const H5S_t *space, hid_t acpl_id, hid_t dxpl_id);
-static hid_t H5A_open(H5G_loc_t *loc, unsigned idx, hid_t dxpl_id);
+static herr_t H5A_open_common(const H5G_loc_t *loc, H5A_t *attr);
+static H5A_t *H5A_open_by_idx(H5G_loc_t *loc, unsigned idx, hid_t dxpl_id);
static H5A_t *H5A_open_by_name(const H5G_loc_t *loc, const char *name,
hid_t dxpl_id);
static herr_t H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id);
@@ -515,6 +516,7 @@ hid_t
H5Aopen_idx(hid_t loc_id, unsigned idx)
{
H5G_loc_t loc; /* Object location */
+ H5A_t *attr = NULL; /* Attribute opened */
hid_t ret_value;
FUNC_ENTER_API(H5Aopen_idx, FAIL)
@@ -526,49 +528,51 @@ H5Aopen_idx(hid_t loc_id, unsigned idx)
if(H5G_loc(loc_id, &loc) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
- /* Go do the real work for opening the attribute */
-/* XXX: Add support & tests for attributes in dense storage */
- if((ret_value = H5A_open(&loc, idx, H5AC_dxpl_id)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to open attribute")
+ /* Open the attribute in the object header */
+ if(NULL == (attr = H5A_open_by_idx(&loc, idx, H5AC_ind_dxpl_id)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open attribute")
+
+ /* Register the attribute and get an ID for it */
+ if((ret_value = H5I_register(H5I_ATTR, attr)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID")
done:
+ /* Cleanup on failure */
+ if(ret_value < 0 && attr)
+ (void)H5A_close(attr);
+
FUNC_LEAVE_API(ret_value)
} /* H5Aopen_idx() */
/*-------------------------------------------------------------------------
- * Function: H5A_open
+ * Function: H5A_open_common
*
* Purpose:
- * This is the guts of the H5Aopen_xxx functions
+ * Finishes initializing an attributes the open
+ *
* Usage:
- * herr_t H5A_open (ent, idx)
- * const H5G_entry_t *ent; IN: Pointer to symbol table entry for object to attribute
- * unsigned idx; IN: index of attribute to open (0-based)
+ * herr_t H5A_open_common(loc, name, dxpl_id)
+ * const H5G_loc_t *loc; IN: Pointer to group location for object
+ * H5A_t *attr; IN/OUT: Pointer to attribute to initialize
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * April 2, 1998
+ * December 18, 2006
*
*-------------------------------------------------------------------------
*/
-static hid_t
-H5A_open(H5G_loc_t *loc, unsigned idx, hid_t dxpl_id)
+static herr_t
+H5A_open_common(const H5G_loc_t *loc, H5A_t *attr)
{
- H5A_t *attr = NULL;
- hid_t ret_value;
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5A_open)
+ FUNC_ENTER_NOAPI_NOINIT(H5A_open_common)
/* check args */
HDassert(loc);
-
- /* Read in attribute with H5O_msg_read() */
- H5_CHECK_OVERFLOW(idx, unsigned, int);
- if(NULL == (attr = (H5A_t *)H5O_msg_read(loc->oloc, H5O_ATTR_ID, (int)idx, NULL, dxpl_id)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to load attribute info from dataset header")
- attr->initialized = TRUE;
+ HDassert(attr);
#if defined(H5_USING_PURIFY) || !defined(NDEBUG)
/* Clear object location */
@@ -593,17 +597,59 @@ H5A_open(H5G_loc_t *loc, unsigned idx, hid_t dxpl_id)
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open")
attr->obj_opened = TRUE;
- /* Register the attribute and get an ID for it */
- if((ret_value = H5I_register(H5I_ATTR, attr)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID")
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5A_open_common() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_open_by_idx
+ *
+ * Purpose:
+ * Open an attribute according to its index order
+ * Usage:
+ * herr_t H5A_open (loc, idx)
+ * const H5G_loc_t *loc; IN: Pointer to group location for object to open attribute
+ * unsigned idx; IN: index of attribute to open (0-based)
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * April 2, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5A_t *
+H5A_open_by_idx(H5G_loc_t *loc, unsigned idx, hid_t dxpl_id)
+{
+ H5A_t *attr = NULL;
+ H5A_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_open_by_idx)
+
+ /* check args */
+ HDassert(loc);
+
+ /* Read in attribute from object header */
+/* XXX: This uses name index order currently, but should use creation order, once it's implemented */
+ if(NULL == (attr = H5O_attr_open_by_idx(loc->oloc, (hsize_t)idx, dxpl_id)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to load attribute info from object header")
+ attr->initialized = TRUE;
+
+ /* Finish initializing attribute */
+ if(H5A_open_common(loc, attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to initialize attribute")
+
+ /* Set return value */
+ ret_value = attr;
done:
/* Cleanup on failure */
- if(ret_value < 0 && attr)
+ if(ret_value == NULL && attr)
(void)H5A_close(attr);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5A_open() */
+} /* H5A_open_by_idx() */
/*-------------------------------------------------------------------------
@@ -638,32 +684,13 @@ H5A_open_by_name(const H5G_loc_t *loc, const char *name, hid_t dxpl_id)
HDassert(name);
/* Read in attribute from object header */
- if(NULL == (attr = H5O_attr_open(loc->oloc, name, dxpl_id)))
+ if(NULL == (attr = H5O_attr_open_by_name(loc->oloc, name, dxpl_id)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to load attribute info from object header")
attr->initialized = TRUE;
-#if defined(H5_USING_PURIFY) || !defined(NDEBUG)
- /* Clear object location */
- if(H5O_loc_reset(&(attr->oloc)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to reset location")
-
- /* Clear path name */
- if(H5G_name_reset(&(attr->path)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to reset path")
-#endif /* H5_USING_PURIFY */
-
- /* Deep copy of the symbol table entry */
- if(H5O_loc_copy(&(attr->oloc), loc->oloc, H5_COPY_DEEP) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to copy entry")
-
- /* Deep copy of the group hier. path */
- if(H5G_name_copy(&(attr->path), loc->path, H5_COPY_DEEP) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to copy entry")
-
- /* Hold the symbol table entry (and file) open */
- if(H5O_open(&(attr->oloc)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to open")
- attr->obj_opened = TRUE;
+ /* Finish initializing attribute */
+ if(H5A_open_common(loc, attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to initialize attribute")
/* Set return value */
ret_value = attr;
@@ -1345,6 +1372,7 @@ herr_t
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 */
herr_t ret_value; /* Return value */
@@ -1357,9 +1385,14 @@ H5Aiterate(hid_t loc_id, unsigned *attr_num, H5A_operator_t op, void *op_data)
if(H5G_loc(loc_id, &loc) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+ /* Build attribute operator info */
+ attr_op.op_type = H5A_ATTR_OP_APP;
+ attr_op.u.app_op = op;
+
/* Call attribute iteration routine */
start_idx = (attr_num ? (unsigned)*attr_num : 0);
- if((ret_value = H5O_attr_iterate(loc_id, loc.oloc, H5AC_ind_dxpl_id, start_idx, attr_num, op, op_data)) < 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)
HERROR(H5E_ATTR, H5E_BADITER, "error iterating over attributes");
done:
@@ -1475,7 +1508,7 @@ H5A_copy(H5A_t *_new_attr, const H5A_t *old_attr)
/* Allocate attribute structure */
if(_new_attr == NULL) {
- if(NULL == (new_attr = H5FL_MALLOC(H5A_t)))
+ if(NULL == (new_attr = H5FL_CALLOC(H5A_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
allocated_attr = TRUE;
} /* end if */
diff --git a/src/H5Adense.c b/src/H5Adense.c
index c5de1a9..d6231cf 100644
--- a/src/H5Adense.c
+++ b/src/H5Adense.c
@@ -38,7 +38,6 @@
#include "H5private.h" /* Generic Functions */
#include "H5Apkg.h" /* Attributes */
#include "H5Eprivate.h" /* Error handling */
-#include "H5MMprivate.h" /* Memory management */
#include "H5Opkg.h" /* Object headers */
#include "H5SMprivate.h" /* Shared object header messages */
@@ -74,12 +73,6 @@
/* Local Typedefs */
/******************/
-/* Data exchange structure to use when building table of attributes for an object */
-typedef struct {
- H5A_attr_table_t *atable; /* Pointer to attribute table to build */
- size_t curr_attr; /* Current attribute to operate on */
-} H5A_dense_bt_ud_t;
-
/*
* Data exchange structure for dense attribute storage. This structure is
* passed through the v2 B-tree layer when modifying attributes.
@@ -108,7 +101,7 @@ typedef struct {
hid_t loc_id; /* Object ID for application callback */
unsigned skip; /* Number of attributes to skip */
unsigned count; /* The # of attributes visited */
- const H5A_attr_iterate_t *attr_op; /* Callback for each attribute */
+ const H5A_attr_iter_op_t *attr_op; /* Callback for each attribute */
void *op_data; /* Callback data for each attribute */
/* upward */
@@ -140,7 +133,6 @@ typedef struct {
} H5A_fh_ud_rm_t;
-
/********************/
/* Package Typedefs */
/********************/
@@ -150,8 +142,6 @@ typedef struct {
/* Local Prototypes */
/********************/
-static herr_t H5A_attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type,
- H5_iter_order_t order);
/*********************/
/* Package Variables */
@@ -173,240 +163,6 @@ H5FL_BLK_DEFINE(ser_attr);
/*-------------------------------------------------------------------------
- * Function: H5A_dense_build_table_cb
- *
- * Purpose: Callback routine for building table of attributes from dense
- * attribute storage.
- *
- * Return: Success: Non-negative
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Dec 11 2006
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5A_dense_build_table_cb(const H5A_t *attr, unsigned mesg_flags, void *_udata)
-{
- H5A_dense_bt_ud_t *udata = (H5A_dense_bt_ud_t *)_udata; /* 'User data' passed in */
- herr_t ret_value = H5_ITER_CONT; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5A_dense_build_table_cb)
-
- /* check arguments */
- HDassert(attr);
- HDassert(udata);
- HDassert(udata->curr_attr < udata->atable->nattrs);
-
- /* Copy attribute information */
- if(NULL == H5A_copy(&udata->atable->attrs[udata->curr_attr], attr))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute")
- udata->atable->flags[udata->curr_attr] = mesg_flags;
-
- /* Increment number of attributes stored */
- udata->curr_attr++;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5A_dense_build_table_cb() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5A_dense_build_table
- *
- * Purpose: Builds a table containing a sorted list of attributes for
- * an object
- *
- * Note: Used for building table of attributes in non-native iteration
- * order for an index
- *
- * Return: Success: Non-negative
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * Dec 11, 2006
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
- H5_index_t UNUSED idx_type, H5_iter_order_t UNUSED order,
- H5A_attr_table_t *atable)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5A_dense_build_table)
-
- /* Sanity check */
- HDassert(f);
- HDassert(oh);
- HDassert(atable);
-
- /* Set size of table */
- H5_CHECK_OVERFLOW(oh->nattrs, /* From: */ hsize_t, /* To: */ size_t);
- atable->nattrs = (size_t)oh->nattrs;
-
- /* Allocate space for the table entries */
- if(atable->nattrs > 0) {
- H5A_dense_bt_ud_t udata; /* User data for iteration callback */
- H5A_attr_iterate_t attr_op; /* Attribute operator */
-
- /* Allocate the table to store the attributes */
- if((atable->attrs = H5MM_malloc(sizeof(H5A_t) * atable->nattrs)) == NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- if((atable->flags = H5MM_malloc(sizeof(uint8_t) * atable->nattrs)) == NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
-
- /* Set up user data for iteration */
- udata.atable = atable;
- udata.curr_attr = 0;
-
- /* Build iterator operator */
- attr_op.op_type = H5A_ATTR_OP_LIB;
- attr_op.u.lib_op = H5A_dense_build_table_cb;
-
- /* Iterate over the links in the group, building a table of the link messages */
- if(H5A_dense_iterate(f, dxpl_id, (hid_t)0, oh->attr_fheap_addr, oh->name_bt2_addr,
- (unsigned)0, NULL, &attr_op, &udata) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "error building attribute table")
-
- /* Sort attribute table in correct iteration order */
- if(H5A_attr_sort_table(atable, H5_INDEX_NAME, H5_ITER_INC) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTSORT, FAIL, "error sorting attribute table")
- } /* end if */
- else
- atable->attrs = NULL;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5A_dense_build_table() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5A_attr_cmp_name_inc
- *
- * Purpose: Callback routine for comparing two attribute names, in
- * increasing alphabetic 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.
- * (i.e. same as strcmp())
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Dec 11 2005
- *
- *-------------------------------------------------------------------------
- */
-static int
-H5A_attr_cmp_name_inc(const void *attr1, const void *attr2)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_attr_cmp_name_inc)
-
- FUNC_LEAVE_NOAPI(HDstrcmp(((const H5A_t *)attr1)->name, ((const H5A_t *)attr2)->name))
-} /* end H5A_attr_cmp_name_inc() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5A_attr_sort_table
- *
- * Purpose: Sort table containing a list of attributes for an object
- *
- * Return: Success: Non-negative
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * Dec 11, 2006
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5A_attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type,
- H5_iter_order_t order)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_attr_sort_table)
-
- /* Sanity check */
- HDassert(atable);
-
- /* Pick appropriate sorting routine */
-#ifdef NOT_YET
- if(idx_type == H5_INDEX_NAME) {
- if(order == H5_ITER_INC)
-#else /* NOT_YET */
-HDassert(idx_type == H5_INDEX_NAME);
-HDassert(order == H5_ITER_INC);
-#endif /* NOT_YET */
- 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);
- else
- HDassert(order == H5_ITER_NATIVE);
- } /* 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);
- else if(order == H5_ITER_DEC)
- HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_link_cmp_corder_dec);
- else
- HDassert(order == H5_ITER_NATIVE);
- } /* end else */
-#endif /* NOT_YET */
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5A_attr_sort_table() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5A_attr_release_table
- *
- * Purpose: Release table containing a list of attributes for an object
- *
- * Return: Success: Non-negative
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * Dec 11, 2006
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5A_attr_release_table(H5A_attr_table_t *atable)
-{
- size_t u; /* Local index variable */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5A_attr_release_table)
-
- /* Sanity check */
- HDassert(atable);
-
- /* Release attribute info, if any */
- if(atable->nattrs > 0) {
- /* Free attribute message information */
- for(u = 0; u < atable->nattrs; u++)
- if(H5A_free(&(atable->attrs[u])) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release attribute")
-
- /* Free table of attributes */
- H5MM_xfree(atable->attrs);
- H5MM_xfree(atable->flags);
- } /* end if */
- else
- HDassert(atable->attrs == NULL);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5A_attr_release_table() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5A_dense_create
*
* Purpose: Creates dense attribute storage structures for an object
@@ -996,6 +752,10 @@ H5A_dense_iterate_bt2_cb(const void *_record, void *_bt2_udata)
H5A_dense_copy_fh_cb, &fh_udata) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPERATE, H5_ITER_ERROR, "heap op callback failed")
+ /* Check whether we should "reconstitute" the shared message info */
+ if(record->flags & H5O_MSG_FLAG_SHARED)
+ H5SM_reconstitute(&(fh_udata.attr->sh_loc), record->id);
+
/* Check which type of callback to make */
switch(bt2_udata->attr_op->op_type) {
case H5A_ATTR_OP_APP:
@@ -1005,7 +765,7 @@ H5A_dense_iterate_bt2_cb(const void *_record, void *_bt2_udata)
case H5A_ATTR_OP_LIB:
/* Call the library's callback */
- ret_value = (bt2_udata->attr_op->u.lib_op)(fh_udata.attr, record->flags, bt2_udata->op_data);
+ ret_value = (bt2_udata->attr_op->u.lib_op)(fh_udata.attr, bt2_udata->op_data);
} /* end switch */
/* Release the space allocated for the attribute */
@@ -1040,13 +800,14 @@ 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, unsigned skip, unsigned *last_attr,
- const H5A_attr_iterate_t *attr_op, void *op_data)
+ 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)
{
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 */
- htri_t attr_sharable; /* Flag indicating attributes are sharable */
+ H5A_attr_table_t atable = {0, NULL}; /* Table of attributes */
+ hsize_t nrec; /* # of records in v2 B-tree */
herr_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5A_dense_iterate, FAIL)
@@ -1059,61 +820,75 @@ 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);
- /* 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, H5A_BT2_NAME, name_bt2_addr, &nrec) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve # of records in index")
+ /* 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")
} /* end if */
- /* Open the fractal heap */
- if(NULL == (fheap = H5HF_open(f, dxpl_id, attr_fheap_addr)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
+ /* Check on iteration order */
+ /* ("native" iteration order is unordered for this attribute storage mechanism) */
+ if(order == H5_ITER_NATIVE) {
+ htri_t attr_sharable; /* Flag indicating attributes are sharable */
- /* Check if attributes are shared in this file */
- if((attr_sharable = H5SM_type_shared(f, H5O_ATTR_ID, dxpl_id)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't determine if attributes are shared")
+ /* Open the fractal heap */
+ if(NULL == (fheap = H5HF_open(f, dxpl_id, attr_fheap_addr)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
- /* Get handle for shared object heap, if attributes are sharable */
- if(attr_sharable) {
- haddr_t shared_fheap_addr; /* Address of fractal heap to use */
+ /* Check if attributes are shared in this file */
+ if((attr_sharable = H5SM_type_shared(f, H5O_ATTR_ID, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't determine if attributes are shared")
- /* Retrieve the address of the shared object's fractal heap */
- if(HADDR_UNDEF == (shared_fheap_addr = H5SM_get_fheap_addr(f, H5O_ATTR_ID, dxpl_id)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get shared object heap address")
+ /* Get handle for shared object heap, if attributes are sharable */
+ if(attr_sharable) {
+ haddr_t shared_fheap_addr; /* Address of fractal heap to use */
- /* Open the fractal heap for shared header messages */
- if(NULL == (shared_fheap = H5HF_open(f, dxpl_id, shared_fheap_addr)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
- } /* end if */
+ /* Retrieve the address of the shared object's fractal heap */
+ if(HADDR_UNDEF == (shared_fheap_addr = H5SM_get_fheap_addr(f, H5O_ATTR_ID, dxpl_id)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get shared object heap address")
- /* Construct the user data for v2 B-tree iterator callback */
- udata.f = f;
- udata.dxpl_id = dxpl_id;
- udata.fheap = fheap;
- udata.shared_fheap = shared_fheap;
- udata.loc_id = loc_id;
- udata.skip = skip;
- udata.count = 0;
- udata.attr_op = attr_op;
- udata.op_data = op_data;
-
- /* 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)
- HERROR(H5E_ATTR, H5E_BADITER, "attribute iteration failed");
-
- /* Update last attribute looked at */
- if(last_attr)
- *last_attr = udata.count;
+ /* Open the fractal heap for shared header messages */
+ if(NULL == (shared_fheap = H5HF_open(f, dxpl_id, shared_fheap_addr)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
+ } /* end if */
+
+ /* Construct the user data for v2 B-tree iterator callback */
+ udata.f = f;
+ udata.dxpl_id = dxpl_id;
+ udata.fheap = fheap;
+ udata.shared_fheap = shared_fheap;
+ udata.loc_id = loc_id;
+ udata.skip = skip;
+ udata.count = 0;
+ udata.attr_op = attr_op;
+ udata.op_data = op_data;
+
+ /* 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)
+ HERROR(H5E_ATTR, H5E_BADITER, "attribute iteration failed");
+
+ /* Update last attribute looked at */
+ 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)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "error building table of attributes")
+
+ /* Iterate over attributes in table */
+ if((ret_value = H5A_attr_iterate_table(&atable, skip, last_attr, loc_id, attr_op, op_data)) < 0)
+ HERROR(H5E_ATTR, H5E_CANTNEXT, "iteration operator failed");
+ } /* end else */
done:
/* Release resources */
@@ -1121,6 +896,8 @@ done:
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
if(fheap && H5HF_close(fheap, dxpl_id) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
+ if(atable.attrs && H5A_attr_release_table(&atable) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute table")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A_dense_iterate() */
diff --git a/src/H5Aint.c b/src/H5Aint.c
new file mode 100644
index 0000000..1d6e9ab
--- /dev/null
+++ b/src/H5Aint.c
@@ -0,0 +1,511 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Aint.c
+ * Dec 18 2006
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Internal routines for managing attributes.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5A_PACKAGE /*suppress error about including H5Apkg */
+#define H5O_PACKAGE /*suppress error about including H5Opkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Apkg.h" /* Attributes */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Opkg.h" /* Object headers */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/* Data exchange structure to use when building table of compact attributes for an object */
+typedef struct {
+ H5F_t *f; /* Pointer to file that fractal heap is in */
+ 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 */
+} H5A_compact_bt_ud_t;
+
+/* Data exchange structure to use when building table of dense attributes for an object */
+typedef struct {
+ H5A_attr_table_t *atable; /* Pointer to attribute table to build */
+ size_t curr_attr; /* Current attribute to operate on */
+} H5A_dense_bt_ud_t;
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+static herr_t H5A_compact_build_table_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
+ unsigned sequence, unsigned *oh_flags_ptr, void *_udata/*in,out*/);
+static herr_t H5A_dense_build_table_cb(const H5A_t *attr, void *_udata);
+static int H5A_attr_cmp_name_inc(const void *attr1, const void *attr2);
+static herr_t H5A_attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type,
+ H5_iter_order_t order);
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_compact_build_table_cb
+ *
+ * Purpose: Object header iterator callback routine to copy attribute
+ * into table.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 18 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+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*/)
+{
+ H5A_compact_bt_ud_t *udata = (H5A_compact_bt_ud_t *)_udata; /* Operator user data */
+ herr_t ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_compact_build_table_cb)
+
+ /* check args */
+ HDassert(mesg);
+
+ /* Check for re-allocating table */
+ if(udata->curr_attr == udata->atable->nattrs) {
+ size_t n = MAX(1, 2 * udata->atable->nattrs);
+ H5A_t *table = H5MM_realloc(udata->atable->attrs,
+ n * sizeof(H5A_t));
+
+ if(!table)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "unable to extend attribute table")
+ udata->atable->attrs = table;
+ udata->atable->nattrs = n;
+ } /* end if */
+
+ /* Check for shared message */
+ if(mesg->flags & H5O_MSG_FLAG_SHARED) {
+ /*
+ * If the message is shared then then the native pointer points to an
+ * H5O_MSG_SHARED message. We use that information to look up the real
+ * message in the global heap or some other object header.
+ */
+ if(NULL == H5O_shared_read(udata->f, udata->dxpl_id, mesg->native, H5O_MSG_ATTR, &udata->atable->attrs[udata->curr_attr]))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "unable to read shared attribute")
+ } /* end if */
+ else {
+ if(NULL == H5A_copy(&udata->atable->attrs[udata->curr_attr], mesg->native))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute")
+ } /* end else */
+
+ /* Increment current attribute */
+ udata->curr_attr++;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_compact_build_table_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_compact_build_table
+ *
+ * Purpose: Builds a table containing a sorted list of attributes for
+ * an object
+ *
+ * Note: Used for building table of attributes in non-native iteration
+ * order for an index
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Dec 18, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+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_bt_ud_t udata; /* User data for iteration callback */
+ H5O_mesg_operator_t op; /* Wrapper for operator */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_compact_build_table)
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(oh);
+ HDassert(atable);
+
+ /* Initialize table */
+ atable->attrs = NULL;
+ atable->nattrs = 0;
+
+ /* Set up user data for iteration */
+ udata.f = f;
+ udata.dxpl_id = dxpl_id;
+ udata.atable = atable;
+ udata.curr_attr = 0;
+
+ /* Iterate over existing attributes, checking for attribute with same name */
+ op.lib_op = H5A_compact_build_table_cb;
+ if(H5O_msg_iterate_real(f, oh, H5O_MSG_ATTR, TRUE, op, &udata, dxpl_id, oh_flags) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error building attribute table")
+
+ /* Correct # of attributes in table */
+ atable->nattrs = udata.curr_attr;
+
+ /* Sort attribute table in correct iteration order */
+ if(H5A_attr_sort_table(atable, H5_INDEX_NAME, order) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTSORT, FAIL, "error sorting attribute table")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_compact_build_table() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_build_table_cb
+ *
+ * Purpose: Callback routine for building table of attributes from dense
+ * attribute storage.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 11 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5A_dense_build_table_cb(const H5A_t *attr, void *_udata)
+{
+ H5A_dense_bt_ud_t *udata = (H5A_dense_bt_ud_t *)_udata; /* 'User data' passed in */
+ herr_t ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_dense_build_table_cb)
+
+ /* check arguments */
+ HDassert(attr);
+ HDassert(udata);
+ HDassert(udata->curr_attr < udata->atable->nattrs);
+
+ /* Copy attribute information */
+ if(NULL == H5A_copy(&udata->atable->attrs[udata->curr_attr], attr))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute")
+
+ /* Increment number of attributes stored */
+ udata->curr_attr++;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_dense_build_table_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_build_table
+ *
+ * Purpose: Builds a table containing a sorted list of attributes for
+ * an object
+ *
+ * Note: Used for building table of attributes in non-native iteration
+ * order for an index
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Dec 11, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+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_attr_table_t *atable)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_dense_build_table)
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(H5F_addr_defined(attr_fheap_addr));
+ HDassert(H5F_addr_defined(name_bt2_addr));
+ HDassert(atable);
+
+ /* Set size of table */
+ H5_CHECK_OVERFLOW(nattrs, /* From: */ hsize_t, /* To: */ size_t);
+ atable->nattrs = (size_t)nattrs;
+
+ /* Allocate space for the table entries */
+ if(atable->nattrs > 0) {
+ H5A_dense_bt_ud_t udata; /* User data for iteration callback */
+ H5A_attr_iter_op_t attr_op; /* Attribute operator */
+
+ /* Allocate the table to store the attributes */
+ if((atable->attrs = H5MM_malloc(sizeof(H5A_t) * atable->nattrs)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Set up user data for iteration */
+ udata.atable = atable;
+ udata.curr_attr = 0;
+
+ /* Build iterator operator */
+ attr_op.op_type = H5A_ATTR_OP_LIB;
+ attr_op.u.lib_op = H5A_dense_build_table_cb;
+
+ /* 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)
+ 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)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTSORT, FAIL, "error sorting attribute table")
+ } /* end if */
+ else
+ atable->attrs = NULL;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_dense_build_table() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_attr_cmp_name_inc
+ *
+ * Purpose: Callback routine for comparing two attribute names, in
+ * increasing alphabetic 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.
+ * (i.e. same as strcmp())
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 11 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5A_attr_cmp_name_inc(const void *attr1, const void *attr2)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_attr_cmp_name_inc)
+
+ FUNC_LEAVE_NOAPI(HDstrcmp(((const H5A_t *)attr1)->name, ((const H5A_t *)attr2)->name))
+} /* end H5A_attr_cmp_name_inc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_attr_sort_table
+ *
+ * Purpose: Sort table containing a list of attributes for an object
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Dec 11, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5A_attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type,
+ H5_iter_order_t order)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_attr_sort_table)
+
+ /* Sanity check */
+ 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 */
+ 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);
+ else if(order == H5_ITER_DEC)
+ HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_link_cmp_corder_dec);
+ else
+ HDassert(order == H5_ITER_NATIVE);
+ } /* end else */
+#endif /* NOT_YET */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5A_attr_sort_table() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_attr_iterate_table
+ *
+ * Purpose: Iterate over table containing a list of attributes for an object,
+ * making appropriate callbacks
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Dec 18, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+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,
+ void *op_data)
+{
+ size_t u; /* Local index variable */
+ herr_t ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5A_attr_iterate_table, FAIL)
+
+ /* Sanity check */
+ HDassert(atable);
+ HDassert(attr_op);
+
+ /* Skip over attributes, if requested */
+ if(last_attr)
+ *last_attr = skip;
+
+ /* Iterate over attribute messages */
+ H5_ASSIGN_OVERFLOW(/* To: */ u, /* From: */ skip, /* From: */ unsigned, /* To: */ size_t)
+ for(; u < atable->nattrs && !ret_value; u++) {
+ /* Check which type of callback to make */
+ switch(attr_op->op_type) {
+ case H5A_ATTR_OP_APP:
+ /* Make the application callback */
+ ret_value = (attr_op->u.app_op)(loc_id, atable->attrs[u].name, op_data);
+ break;
+
+ case H5A_ATTR_OP_LIB:
+ /* Call the library's callback */
+ ret_value = (attr_op->u.lib_op)(&(atable->attrs[u]), op_data);
+ } /* end switch */
+
+ /* Increment the number of entries passed through */
+ if(last_attr)
+ (*last_attr)++;
+ } /* end for */
+
+ /* Check for callback failure and pass along return value */
+ if(ret_value < 0)
+ HERROR(H5E_ATTR, H5E_CANTNEXT, "iteration operator failed");
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_attr_iterate_table() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_attr_release_table
+ *
+ * Purpose: Release table containing a list of attributes for an object
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Dec 11, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5A_attr_release_table(H5A_attr_table_t *atable)
+{
+ size_t u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_attr_release_table)
+
+ /* Sanity check */
+ HDassert(atable);
+
+ /* Release attribute info, if any */
+ if(atable->nattrs > 0) {
+ /* Free attribute message information */
+ for(u = 0; u < atable->nattrs; u++)
+ if(H5A_free(&(atable->attrs[u])) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute")
+
+ /* Free table of attributes */
+ H5MM_xfree(atable->attrs);
+ } /* end if */
+ else
+ HDassert(atable->attrs == NULL);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_attr_release_table() */
+
diff --git a/src/H5Apkg.h b/src/H5Apkg.h
index 5f8d477..ca7983f 100644
--- a/src/H5Apkg.h
+++ b/src/H5Apkg.h
@@ -119,15 +119,13 @@ typedef struct H5A_bt2_ud_ins_t {
typedef struct {
size_t nattrs; /* # of attributes in table */
H5A_t *attrs; /* Pointer to array of attributes */
- uint8_t *flags; /* Pointer to array of message flags for attributes */
} H5A_attr_table_t;
/* Attribute iteration operator for internal library callbacks */
-typedef herr_t (*H5A_lib_iterate_t)(const H5A_t *attr, unsigned mesg_flags,
- void *op_data);
+typedef herr_t (*H5A_lib_iterate_t)(const H5A_t *attr, void *op_data);
/* Describe kind of callback to make for each attribute */
-typedef struct {
+struct H5A_attr_iter_op_t {
enum {
H5A_ATTR_OP_APP, /* Application callback */
H5A_ATTR_OP_LIB /* Library internal callback */
@@ -136,7 +134,7 @@ typedef struct {
H5A_operator_t app_op; /* Application callback for each attribute */
H5A_lib_iterate_t lib_op; /* Library internal callback for each attribute */
} u;
-} H5A_attr_iterate_t;
+};
/*****************************/
@@ -169,16 +167,24 @@ H5_DLL H5A_t *H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
H5_DLL herr_t H5A_dense_write(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
const H5A_t *attr);
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, unsigned skip,
- unsigned *last_attr, const H5A_attr_iterate_t *attr_op, void *op_data);
+ 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);
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,
const char *name);
/* Attribute table operations */
-H5_DLL herr_t H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
- H5_index_t idx_type, H5_iter_order_t order, H5A_attr_table_t *atable);
+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,
+ 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,
+ const H5A_attr_iter_op_t *attr_op, void *op_data);
H5_DLL herr_t H5A_attr_release_table(H5A_attr_table_t *atable);
/* Attribute object header routines */
diff --git a/src/H5Aprivate.h b/src/H5Aprivate.h
index 75ccafd..ca14ebc 100644
--- a/src/H5Aprivate.h
+++ b/src/H5Aprivate.h
@@ -36,6 +36,7 @@
/* Forward references of package typedefs */
typedef struct H5A_t H5A_t;
+typedef struct H5A_attr_iter_op_t H5A_attr_iter_op_t;
/*****************************/
diff --git a/src/H5Gdense.c b/src/H5Gdense.c
index b0924ba..aaa2ea3 100644
--- a/src/H5Gdense.c
+++ b/src/H5Gdense.c
@@ -90,7 +90,7 @@ typedef struct {
/* downward (from application) */
hid_t gid; /* Group ID for application callback */
hsize_t skip; /* Number of links to skip */
- hsize_t *last_lnk; /* Pointer to the last link operated on */
+ 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 */
@@ -722,7 +722,7 @@ done:
if(fheap && H5HF_close(fheap, dxpl_id) < 0)
HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
if(ltable.lnks && H5G_link_release_table(&ltable) < 0)
- HDONE_ERROR(H5E_SYM, H5E_CANTFREE, H5G_UNKNOWN, "unable to release link table")
+ HDONE_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5G_dense_lookup_by_idx() */
@@ -940,8 +940,7 @@ H5G_dense_iterate_bt2_cb(const void *_record, void *_bt2_udata)
/* Increment the number of entries passed through */
/* (whether we skipped them or not) */
- if(bt2_udata->last_lnk)
- (*bt2_udata->last_lnk)++;
+ bt2_udata->count++;
/* Check for callback failure and pass along return value */
if(ret_value < 0)
@@ -983,10 +982,6 @@ 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);
- /* Open the fractal heap */
- if(NULL == (fheap = H5HF_open(f, dxpl_id, linfo->link_fheap_addr)))
- HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
-
/* Check for skipping too many links */
if(skip > 0) {
hsize_t nrec; /* # of records in v2 B-tree */
@@ -1006,13 +1001,17 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
if(order == H5_ITER_NATIVE) {
H5G_bt2_ud_it_t udata; /* User data for iterator callback */
+ /* Open the fractal heap */
+ if(NULL == (fheap = H5HF_open(f, dxpl_id, linfo->link_fheap_addr)))
+ HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
+
/* Construct the user data for v2 B-tree iterator callback */
udata.f = f;
udata.dxpl_id = dxpl_id;
udata.fheap = fheap;
udata.gid = gid;
udata.skip = skip;
- udata.last_lnk = last_lnk;
+ udata.count = 0;
udata.lnk_op = lnk_op;
udata.op_data = op_data;
@@ -1021,6 +1020,10 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
if((ret_value = H5B2_iterate(f, dxpl_id, H5G_BT2_NAME, linfo->name_bt2_addr,
H5G_dense_iterate_bt2_cb, &udata)) < 0)
HERROR(H5E_SYM, H5E_BADITER, "link iteration failed");
+
+ /* Update last link looked at */
+ if(last_lnk)
+ *last_lnk = udata.count;
} /* end if */
else {
/* Build the table of links for this group */
@@ -1037,7 +1040,7 @@ done:
if(fheap && H5HF_close(fheap, dxpl_id) < 0)
HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
if(ltable.lnks && H5G_link_release_table(&ltable) < 0)
- HDONE_ERROR(H5E_SYM, H5E_CANTFREE, H5G_UNKNOWN, "unable to release link table")
+ HDONE_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5G_dense_iterate() */
@@ -1236,7 +1239,7 @@ done:
if(fheap && H5HF_close(fheap, dxpl_id) < 0)
HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
if(ltable.lnks && H5G_link_release_table(&ltable) < 0)
- HDONE_ERROR(H5E_SYM, H5E_CANTFREE, H5G_UNKNOWN, "unable to release link table")
+ HDONE_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5G_dense_get_name_by_idx() */
@@ -1726,7 +1729,7 @@ done:
if(fheap && H5HF_close(fheap, dxpl_id) < 0)
HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
if(ltable.lnks && H5G_link_release_table(&ltable) < 0)
- HDONE_ERROR(H5E_SYM, H5E_CANTFREE, H5G_UNKNOWN, "unable to release link table")
+ HDONE_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5G_dense_remove_by_idx() */
diff --git a/src/H5Oattr.c b/src/H5Oattr.c
index 8b8edc5..75b7d3a 100644
--- a/src/H5Oattr.c
+++ b/src/H5Oattr.c
@@ -1092,7 +1092,7 @@ H5O_attr_get_share(const void *_mesg, H5O_shared_t *sh /*out*/)
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_attr_get_share)
- HDassert (mesg);
+ HDassert(mesg);
ret_value = H5O_msg_copy(H5O_SHARED_ID, &(mesg->sh_loc), sh);
@@ -1120,8 +1120,8 @@ H5O_attr_set_share(void *_mesg/*in,out*/, const H5O_shared_t *sh)
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_attr_set_share)
- HDassert (mesg);
- HDassert (sh);
+ HDassert(mesg);
+ HDassert(sh);
if(NULL == H5O_msg_copy(H5O_SHARED_ID, sh, &(mesg->sh_loc)))
ret_value = FAIL;
@@ -1159,7 +1159,7 @@ H5O_attr_is_shared(const void *_mesg)
* library read a "committed attribute" if we ever create one in
* the future.
*/
- if(mesg->sh_loc.flags & (H5O_COMMITTED_FLAG | H5O_SHARED_IN_HEAP_FLAG))
+ if(H5O_IS_SHARED(mesg->sh_loc.flags))
ret_value = TRUE;
else
ret_value = FALSE;
diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c
index 4e1532c..2d43d9b 100644
--- a/src/H5Oattribute.c
+++ b/src/H5Oattribute.c
@@ -374,7 +374,7 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5O_attr_open
+ * Function: H5O_attr_open_by_name
*
* Purpose: Open an existing attribute in an object header.
*
@@ -386,13 +386,13 @@ done:
*-------------------------------------------------------------------------
*/
H5A_t *
-H5O_attr_open(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
+H5O_attr_open_by_name(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
{
H5O_t *oh = NULL; /* Pointer to actual object header */
unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
H5A_t *ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5O_attr_open)
+ FUNC_ENTER_NOAPI_NOINIT(H5O_attr_open_by_name)
/* Check arguments */
HDassert(loc);
@@ -443,7 +443,79 @@ done:
HDONE_ERROR(H5E_ATTR, H5E_PROTECT, NULL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_attr_open */
+} /* end H5O_attr_open_by_name() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_attr_open_by_idx
+ *
+ * Purpose: Callback routine opening an attribute by index
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 18 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_attr_open_by_idx_cb(const H5A_t *attr, void *_ret_attr)
+{
+ H5A_t **ret_attr = (H5A_t **)_ret_attr; /* 'User data' passed in */
+ herr_t ret_value = H5_ITER_STOP; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_attr_open_by_idx_cb)
+
+ /* check arguments */
+ HDassert(attr);
+ HDassert(ret_attr);
+
+ /* Copy attribute information */
+ if(NULL == (*ret_attr = H5A_copy(NULL, attr)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_attr_open_by_idx_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_attr_open_by_idx
+ *
+ * Purpose: Open an existing attribute in an object header according to
+ * an index.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Monday, December 18, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+H5A_t *
+H5O_attr_open_by_idx(const H5O_loc_t *loc, hsize_t n, hid_t dxpl_id)
+{
+ H5A_attr_iter_op_t attr_op; /* Attribute operator */
+ H5A_t *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_attr_open_by_idx)
+
+ /* Check arguments */
+ HDassert(loc);
+
+ /* Build attribute operator info */
+ attr_op.op_type = H5A_ATTR_OP_LIB;
+ 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)
+ HGOTO_ERROR(H5E_ATTR, H5E_BADITER, NULL, "can't locate attribute")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_attr_open_by_idx() */
/*-------------------------------------------------------------------------
@@ -613,7 +685,7 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5O_attr_rename_dup_cb
+ * Function: H5O_attr_rename_chk_cb
*
* Purpose: Object header iterator callback routine to check for
* duplicate name during rename
@@ -627,13 +699,13 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_attr_rename_dup_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
+H5O_attr_rename_chk_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
unsigned UNUSED sequence, unsigned UNUSED *oh_flags_ptr, void *_udata/*in,out*/)
{
H5O_iter_ren_t *udata = (H5O_iter_ren_t *)_udata; /* Operator user data */
herr_t ret_value = H5_ITER_CONT; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5O_attr_rename_dup_cb)
+ FUNC_ENTER_NOAPI_NOINIT(H5O_attr_rename_chk_cb)
/* check args */
HDassert(oh);
@@ -677,7 +749,7 @@ H5O_attr_rename_dup_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_attr_rename_dup_cb() */
+} /* end H5O_attr_rename_chk_cb() */
/*-------------------------------------------------------------------------
@@ -804,7 +876,7 @@ HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "renaming attributes in dense stora
udata.found = FALSE;
/* Iterate over attributes, to check if "new name" exists already */
- op.lib_op = H5O_attr_rename_dup_cb;
+ op.lib_op = H5O_attr_rename_chk_cb;
if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, TRUE, op, &udata, dxpl_id, &oh_flags) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "error updating attribute")
@@ -844,87 +916,72 @@ done:
*/
herr_t
H5O_attr_iterate(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id,
- unsigned skip, unsigned *last_attr, H5A_operator_t op, void *op_data)
+ H5_iter_order_t order, unsigned skip, unsigned *last_attr,
+ const H5A_attr_iter_op_t *attr_op, void *op_data)
{
H5O_t *oh = NULL; /* Pointer to actual object header */
- 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 */
+ unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
+ H5A_attr_table_t atable = {0, NULL}; /* Table of attributes */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_iterate)
/* Check arguments */
HDassert(loc);
- HDassert(op);
+ HDassert(attr_op);
/* Protect the object header to iterate over */
if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
- /* Retrieve the information about dense attribute storage */
+ /* Check for attributes stored densely */
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 */
+
+ /* Retrieve the information about dense attribute storage */
attr_fheap_addr = oh->attr_fheap_addr;
name_bt2_addr = oh->name_bt2_addr;
- } /* end if */
- else
- attr_fheap_addr = name_bt2_addr = HADDR_UNDEF;
- /* Release the object header */
- if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_PROTECT, FAIL, "unable to release object header")
- oh = NULL;
-
- /* Check for attributes stored densely */
- if(H5F_addr_defined(attr_fheap_addr)) {
- H5A_attr_iterate_t attr_op; /* Attribute operator */
-
- /* Build attribute operator info */
- attr_op.op_type = H5A_ATTR_OP_APP;
- attr_op.u.app_op = op;
+ /* Release the object header */
+ if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_PROTECT, FAIL, "unable to release object header")
+ oh = NULL;
+ /* Iterate over attributes in dense storage */
if((ret_value = H5A_dense_iterate(loc->file, dxpl_id, loc_id, attr_fheap_addr,
- name_bt2_addr, skip, last_attr, &attr_op, op_data)) < 0)
+ name_bt2_addr, order, skip, last_attr, attr_op, op_data)) < 0)
HERROR(H5E_ATTR, H5E_BADITER, "error iterating over attributes");
} /* end if */
else {
- unsigned idx; /* Current attribute to operate on */
-
- /* Check for skipping over too many attributes */
- if((int)skip < H5O_msg_count(loc, H5O_ATTR_ID, dxpl_id)) {
- H5A_t found_attr; /* Copy of attribute for callback */
-
- /* Read each attribute and call application's callback */
- /* (this could be made more efficient by iterating over the
- * attribute header messages with H5O_msg_iterate, but then
- * the object header would be locked during the callback into
- * the application code, causing problems if they attempt to
- * do anything with the object the attribute is on - QAK)
- */
- idx = skip;
- while(H5O_msg_read(loc, H5O_ATTR_ID, (int)idx, &found_attr, dxpl_id) != NULL) {
- /* Call application's callback */
- idx++;
- if((ret_value = (op)(loc_id, found_attr.name, op_data)) != 0) {
- H5A_free(&found_attr);
- break;
- } /* end if */
- H5A_free(&found_attr);
- } /* end while */
-
- /* Clear error stack from running off end of attributes */
- if(ret_value == 0)
- H5E_clear_stack(NULL);
- } /* end if */
- else
- if(skip > 0)
+ /* 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)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "error building attribute table")
+
+ /* Release the object header */
+ if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_PROTECT, FAIL, "unable to release object header")
+ 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 */
- /* Update last attribute looked at */
- if(last_attr)
- *last_attr = idx;
+ /* Iterate over attributes in table */
+ if((ret_value = H5A_attr_iterate_table(&atable, skip, last_attr, loc_id, attr_op, op_data)) < 0)
+ HERROR(H5E_ATTR, H5E_CANTNEXT, "iteration operator failed");
} /* end else */
done:
+ /* Release resources */
+ if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_PROTECT, FAIL, "unable to release object header")
+ if(atable.attrs && H5A_attr_release_table(&atable) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute table")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_attr_iterate */
@@ -1079,12 +1136,12 @@ H5O_attr_remove(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete dense attribute storage")
} /* end if */
else {
- H5A_attr_table_t atable = {0, NULL, NULL}; /* Table of attributes */
+ H5A_attr_table_t atable = {0, NULL}; /* Table of attributes */
hbool_t can_convert = TRUE; /* Whether converting to attribute messages is possible */
size_t u; /* Local index */
/* Build the table of attributes for this object */
- if(H5A_dense_build_table(loc->file, dxpl_id, oh, H5_INDEX_NAME, H5_ITER_NATIVE, &atable) < 0)
+ 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)
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "error building attribute table")
/* Inspect attributes in table for ones that can't be converted back
@@ -1100,8 +1157,13 @@ H5O_attr_remove(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
/* If ok, insert attributes as object header messages */
if(can_convert) {
/* Insert attribute messages into object header */
+ /* (Set the "shared" message flag for all attributes added -
+ * attributes that are actually shared will be converted
+ * to shared messages and attributes that are not shared
+ * will have the flag turned off -QAK)
+ */
for(u = 0; u < oh->nattrs; u++)
- if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_ATTR, (unsigned)atable.flags[u], H5O_UPDATE_TIME, &(atable.attrs[u]), &oh_flags) < 0)
+ if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_ATTR, H5O_MSG_FLAG_SHARED, H5O_UPDATE_TIME, &(atable.attrs[u]), &oh_flags) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "can't create message")
/* Remove the dense storage */
diff --git a/src/H5Opkg.h b/src/H5Opkg.h
index 8b52c2e..2b367db 100644
--- a/src/H5Opkg.h
+++ b/src/H5Opkg.h
@@ -421,14 +421,17 @@ H5_DLL void * H5O_shared_read(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *share
/* Attribute operations */
H5_DLL herr_t H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr);
-H5_DLL H5A_t *H5O_attr_open(const H5O_loc_t *loc, const char *name,
+H5_DLL H5A_t *H5O_attr_open_by_name(const H5O_loc_t *loc, const char *name,
+ hid_t dxpl_id);
+H5_DLL H5A_t *H5O_attr_open_by_idx(const H5O_loc_t *loc, hsize_t n,
hid_t dxpl_id);
H5_DLL herr_t H5O_attr_write(const H5O_loc_t *loc, hid_t dxpl_id,
H5A_t *attr);
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,
- unsigned skip, unsigned *last_attr, H5A_operator_t op, void *op_data);
+ H5_iter_order_t order, unsigned skip, unsigned *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/src/H5SM.c b/src/H5SM.c
index 102bb8b..76914b8 100755
--- a/src/H5SM.c
+++ b/src/H5SM.c
@@ -1185,3 +1185,33 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5SM_get_info() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5SM_reconstitute
+ *
+ * Purpose: Reconstitute a shared object header message structure from
+ * a plain heap ID.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Monday, December 18, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5SM_reconstitute(H5O_shared_t *sh_mesg, const uint8_t *heap_id)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_reconstitute)
+
+ /* Sanity check args */
+ HDassert(sh_mesg);
+ HDassert(heap_id);
+
+ /* Set flag for shared message */
+ sh_mesg->flags = H5O_SHARED_IN_HEAP_FLAG;
+ HDmemcpy(&sh_mesg->u.heap_id, heap_id, H5SM_FHEAP_ID_LEN);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5SM_reconstitute() */
+
diff --git a/src/H5SMprivate.h b/src/H5SMprivate.h
index 2308167..fd421e1 100755
--- a/src/H5SMprivate.h
+++ b/src/H5SMprivate.h
@@ -50,6 +50,7 @@ H5_DLL herr_t H5SM_get_info(H5F_t *f, unsigned *index_flags, unsigned *minsizes,
unsigned *list_to_btree, unsigned *btree_to_list, hid_t dxpl_id);
H5_DLL htri_t H5SM_type_shared(H5F_t *f, unsigned type_id, hid_t dxpl_id);
H5_DLL haddr_t H5SM_get_fheap_addr(H5F_t *f, unsigned type_id, hid_t dxpl_id);
+H5_DLL herr_t H5SM_reconstitute(H5O_shared_t *sh_mesg, const uint8_t *heap_id);
#endif /*_H5SMprivate_H*/
diff --git a/src/Makefile.am b/src/Makefile.am
index 44c318f..630e7fb 100755
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -41,7 +41,8 @@ DISTCLEANFILES=H5pubconf.h
# library sources
libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
- H5A.c H5Abtree2.c H5Adense.c H5Adeprec.c H5AC.c H5B.c H5Bcache.c \
+ H5A.c H5Abtree2.c H5Adense.c H5Adeprec.c H5Aint.c \
+ H5AC.c H5B.c H5Bcache.c \
H5B2.c H5B2cache.c H5B2dbg.c H5B2int.c H5B2stat.c H5B2test.c \
H5C.c H5CS.c H5D.c H5Dcompact.c H5Dcontig.c \
H5Defl.c H5Dio.c H5Distore.c H5Dmpio.c H5Doh.c H5Dselect.c H5Dtest.c \
diff --git a/src/Makefile.in b/src/Makefile.in
index 9221d38..90d13cd 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -82,7 +82,7 @@ LTLIBRARIES = $(lib_LTLIBRARIES)
libhdf5_la_LIBADD =
am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \
H5timer.lo H5trace.lo H5A.lo H5Abtree2.lo H5Adense.lo \
- H5Adeprec.lo H5AC.lo H5B.lo H5Bcache.lo H5B2.lo H5B2cache.lo \
+ H5Adeprec.lo H5Aint.lo H5AC.lo H5B.lo H5Bcache.lo H5B2.lo H5B2cache.lo \
H5B2dbg.lo H5B2int.lo H5B2stat.lo H5B2test.lo H5C.lo H5CS.lo \
H5D.lo H5Dcompact.lo H5Dcontig.lo H5Defl.lo H5Dio.lo \
H5Distore.lo H5Dmpio.lo H5Doh.lo H5Dselect.lo H5Dtest.lo \
@@ -398,7 +398,7 @@ DISTCLEANFILES = H5pubconf.h
# library sources
libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
- H5A.c H5Abtree2.c H5Adense.c H5Adeprec.c H5AC.c H5B.c H5Bcache.c \
+ H5A.c H5Abtree2.c H5Adense.c H5Adeprec.c H5Aint.c H5AC.c H5B.c H5Bcache.c \
H5B2.c H5B2cache.c H5B2dbg.c H5B2int.c H5B2stat.c H5B2test.c \
H5C.c H5CS.c H5D.c H5Dcompact.c H5Dcontig.c \
H5Defl.c H5Dio.c H5Distore.c H5Dmpio.c H5Doh.c H5Dselect.c H5Dtest.c \
@@ -572,6 +572,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Abtree2.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Adense.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Adeprec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Aint.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5B.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5B2.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5B2cache.Plo@am__quote@
diff --git a/test/tattr.c b/test/tattr.c
index 3e7e73d..5860dae 100644
--- a/test/tattr.c
+++ b/test/tattr.c
@@ -1683,6 +1683,65 @@ test_attr_dtype_shared(hid_t fapl)
/****************************************************************
**
+** test_attr_dense_verify(): Test basic H5A (attribute) code.
+** Verify attributes on object
+**
+****************************************************************/
+static void
+test_attr_dense_verify(hid_t loc_id, unsigned max_attr)
+{
+ char attrname[NAME_BUF_SIZE]; /* Name of attribute */
+ hid_t attr; /* Attribute ID */
+ unsigned value; /* Attribute value */
+ unsigned u; /* Local index variable */
+ herr_t ret; /* Generic return value */
+
+ /* Re-open all the attributes by name and verify the data */
+ for(u = 0; u < max_attr; u++) {
+ /* Open attribute */
+ sprintf(attrname, "attr %02u", u);
+ attr = H5Aopen_name(loc_id, attrname);
+ CHECK(attr, FAIL, "H5Aopen");
+
+ /* Read data from the attribute */
+ ret = H5Aread(attr, H5T_NATIVE_UINT, &value);
+ CHECK(ret, FAIL, "H5Aread");
+ VERIFY(value, u, "H5Aread");
+
+ /* Close attribute */
+ ret = H5Aclose(attr);
+ CHECK(ret, FAIL, "H5Aclose");
+ } /* end for */
+
+ /* Re-open all the attributes by index and verify the data */
+ for(u = 0; u < max_attr; u++) {
+ size_t name_len; /* Length of attribute name */
+ char check_name[ATTR_NAME_LEN]; /* Buffer for checking attribute names */
+
+ /* Open attribute */
+ attr = H5Aopen_idx(loc_id, u);
+ CHECK(attr, FAIL, "H5Aopen_idx");
+
+ /* Verify Name */
+ sprintf(attrname, "attr %02u", u);
+ name_len = H5Aget_name(attr, (size_t)ATTR_NAME_LEN, check_name);
+ VERIFY(name_len, HDstrlen(attrname), "H5Aget_name");
+ if(HDstrcmp(check_name, attrname))
+ TestErrPrintf("attribute name different: attr_name = '%s', should be '%s'\n", check_name, attrname);
+
+ /* Read data from the attribute */
+ ret = H5Aread(attr, H5T_NATIVE_UINT, &value);
+ CHECK(ret, FAIL, "H5Aread");
+ VERIFY(value, u, "H5Aread");
+
+ /* Close attribute */
+ ret = H5Aclose(attr);
+ CHECK(ret, FAIL, "H5Aclose");
+ } /* end for */
+} /* test_attr_dense_verify() */
+
+/****************************************************************
+**
** test_attr_dense_create(): Test basic H5A (attribute) code.
** Tests "dense" attribute storage creation
**
@@ -1852,6 +1911,9 @@ HDfprintf(stderr, "max_compact = %u, min_dense = %u\n", max_compact, min_dense);
/* Close attribute */
ret = H5Aclose(attr);
CHECK(ret, FAIL, "H5Aclose");
+
+ /* Verify attributes written so far */
+ test_attr_dense_verify(dataset, u);
} /* end for */
/* Check on dataset's attribute storage status */
@@ -1880,24 +1942,8 @@ HDfprintf(stderr, "max_compact = %u, min_dense = %u\n", max_compact, min_dense);
ret = H5Sclose(sid);
CHECK(ret, FAIL, "H5Sclose");
- /* Re-open all the attributes and verify the data */
- for(u = 0; u <= max_compact; u++) {
- unsigned value;
-
- /* Open attribute */
- sprintf(attrname, "attr %02u", u);
- attr = H5Aopen_name(dataset, attrname);
- CHECK(attr, FAIL, "H5Aopen");
-
- /* Read data from the attribute */
- ret = H5Aread(attr, H5T_NATIVE_UINT, &value);
- CHECK(ret, FAIL, "H5Aread");
- VERIFY(value, u, "H5Aread");
-
- /* Close attribute */
- ret = H5Aclose(attr);
- CHECK(ret, FAIL, "H5Aclose");
- } /* end for */
+ /* Verify all the attributes written */
+ test_attr_dense_verify(dataset, (u + 1));
/* Close Dataset */
ret = H5Dclose(dataset);
@@ -1978,7 +2024,7 @@ HDfprintf(stderr, "max_compact = %u, min_dense = %u\n", max_compact, min_dense);
/* Check # of attributes */
attr_count = H5Aget_num_attrs(dataset);
CHECK(attr_count, FAIL, "H5Aget_num_attrs");
- VERIFY(attr_count, (u + 1), "H5Aget_num_attrs");
+ VERIFY(attr_count, (int)(u + 1), "H5Aget_num_attrs");
} /* end for */
/* Check on dataset's attribute storage status */
@@ -2012,6 +2058,9 @@ HDfprintf(stderr, "max_compact = %u, min_dense = %u\n", max_compact, min_dense);
sprintf(attrname, "attr %02u", u);
ret = H5Adelete(dataset, attrname);
CHECK(ret, FAIL, "H5Adelete");
+
+ /* Verify attributes still left */
+ test_attr_dense_verify(dataset, u);
} /* end for */
/* Check on dataset's attribute storage status */
@@ -2023,6 +2072,13 @@ HDfprintf(stderr, "max_compact = %u, min_dense = %u\n", max_compact, min_dense);
ret = H5Adelete(dataset, attrname);
CHECK(ret, FAIL, "H5Adelete");
+ /* Check on dataset's attribute storage status */
+ is_dense = H5O_is_attr_dense_test(dataset);
+ VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
+
+ /* Verify attributes still left */
+ test_attr_dense_verify(dataset, (u - 1));
+
/* Close Dataset */
ret = H5Dclose(dataset);
CHECK(ret, FAIL, "H5Dclose");
diff --git a/test/titerate.c b/test/titerate.c
index 539a9fa..aa78581 100644
--- a/test/titerate.c
+++ b/test/titerate.c
@@ -361,11 +361,11 @@ aiter_cb(hid_t UNUSED group, const char *name, void *op_data)
case RET_CHANGE:
count++;
- return(count > 10 ? 1: 0);
+ return(count > 10 ? 1 : 0);
case RET_CHANGE2:
count2++;
- return(count2 > 10 ? 1: 0);
+ return(count2 > 10 ? 1 : 0);
default:
printf("invalid iteration command");