summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2006-12-19 01:59:28 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2006-12-19 01:59:28 (GMT)
commit43ec5b7ef4df2d72bcde2da9366d55383b8f40e8 (patch)
tree705125a1b023c990db69abd82ae878eb90800447
parent5865018c85449e4b03bb3f5d5e7d7948e110fe17 (diff)
downloadhdf5-43ec5b7ef4df2d72bcde2da9366d55383b8f40e8.zip
hdf5-43ec5b7ef4df2d72bcde2da9366d55383b8f40e8.tar.gz
hdf5-43ec5b7ef4df2d72bcde2da9366d55383b8f40e8.tar.bz2
[svn-r13074] Description:
Add support for opening attributes in dense and/or shared storage by index. Move routines for building and operating on tables of attributes into separate source module. Fix bug where reverting from "dense" to "compact" storage would 'unshare' attributes. Minor code cleanups, etc. Tested on: Linux/32 2.6 (chicago) Linux/64 2.6 (chicago2)
-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");