summaryrefslogtreecommitdiffstats
path: root/src/H5Oattribute.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2007-03-10 04:56:53 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2007-03-10 04:56:53 (GMT)
commita127510b7b3049d0e136b677b180c8e644bdc7ea (patch)
tree0a7144ca74266b0e6eed3d86febd2968c9af7d40 /src/H5Oattribute.c
parent1bca28acc3294e465d22e4dee8ecfc92fbc55ebe (diff)
downloadhdf5-a127510b7b3049d0e136b677b180c8e644bdc7ea.zip
hdf5-a127510b7b3049d0e136b677b180c8e644bdc7ea.tar.gz
hdf5-a127510b7b3049d0e136b677b180c8e644bdc7ea.tar.bz2
[svn-r13486] Description:
Move attribute tracking information out of object header prefix and make it into a message that is inserted only when attributes are present on the object. Tested on: FreeBSD/32 6.2 (duty)
Diffstat (limited to 'src/H5Oattribute.c')
-rw-r--r--src/H5Oattribute.c466
1 files changed, 291 insertions, 175 deletions
diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c
index 3e97862..f824ad9 100644
--- a/src/H5Oattribute.c
+++ b/src/H5Oattribute.c
@@ -55,6 +55,7 @@
typedef struct {
H5F_t *f; /* Pointer to file for insertion */
hid_t dxpl_id; /* DXPL during iteration */
+ H5O_ainfo_t *ainfo; /* Attribute info struct */
} H5O_iter_cvt_t;
/* User data for iteration when opening an attribute */
@@ -173,9 +174,13 @@ H5O_attr_to_dense_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
/* check args */
HDassert(oh);
HDassert(mesg);
+ HDassert(udata);
+ HDassert(udata->f);
+ HDassert(udata->ainfo);
+ HDassert(attr);
/* Insert attribute into dense storage */
- if(H5A_dense_insert(udata->f, udata->dxpl_id, oh, attr) < 0)
+ if(H5A_dense_insert(udata->f, udata->dxpl_id, udata->ainfo, attr) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, H5_ITER_ERROR, "unable to add to dense storage")
/* Convert message into a null message in the header */
@@ -207,6 +212,7 @@ herr_t
H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
{
H5O_t *oh = NULL; /* Pointer to actual object header */
+ H5O_ainfo_t ainfo; /* Attribute information for object */
unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */
herr_t ret_value = SUCCEED; /* Return value */
@@ -221,59 +227,107 @@ H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
- /* Check if switching to "dense" attribute storage is possible */
- if(oh->version > H5O_VERSION_1 && !H5F_addr_defined(oh->attr_fheap_addr)) {
- htri_t sharable; /* Whether the attribute will be shared */
- size_t raw_size = 0; /* Raw size of message */
-
- /* Check for attribute being sharable */
- if((sharable = H5SM_can_share(loc->file, dxpl_id, NULL, NULL, H5O_ATTR_ID, attr)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, FAIL, "can't determine attribute sharing status")
- else if(sharable == FALSE) {
- /* Compute the size needed to encode the attribute */
- raw_size = (H5O_MSG_ATTR->raw_size)(loc->file, FALSE, attr);
+ /* Check if this object already has attribute information */
+ if(oh->version > H5O_VERSION_1) {
+ hbool_t new_ainfo = FALSE; /* Flag to indicate that the attribute information is new */
+
+ if(NULL == H5O_msg_read_real(loc->file, dxpl_id, oh, H5O_AINFO_ID, &ainfo)) {
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+
+ /* Initialize attribute information */
+ ainfo.track_corder = (oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED) ? TRUE : FALSE;
+ ainfo.index_corder = (oh->flags & H5O_HDR_ATTR_CRT_ORDER_INDEXED) ? TRUE : FALSE;
+ ainfo.max_crt_idx = 0;
+ ainfo.corder_bt2_addr = HADDR_UNDEF;
+ ainfo.nattrs = 0;
+ ainfo.fheap_addr = HADDR_UNDEF;
+ ainfo.name_bt2_addr = HADDR_UNDEF;
+
+ /* Set flag to add attribute information to object header */
+ new_ainfo = TRUE;
} /* end if */
+ else {
+ /* Sanity check attribute info read in */
+ HDassert(ainfo.nattrs > 0);
+ HDassert(ainfo.track_corder == ((oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED) > 0));
+ HDassert(ainfo.index_corder == ((oh->flags & H5O_HDR_ATTR_CRT_ORDER_INDEXED) > 0));
+ } /* end else */
- /* Check for condititions for switching to "dense" attribute storage are met */
- if(oh->nattrs == oh->max_compact || (!sharable && raw_size >= H5O_MESG_MAX_SIZE)) {
- H5O_iter_cvt_t udata; /* User data for callback */
- H5O_mesg_operator_t op; /* Wrapper for operator */
-
- /* Create dense storage for attributes */
- if(H5A_dense_create(loc->file, dxpl_id, oh) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create dense storage for attributes")
-
- /* Set up user data for callback */
- udata.f = loc->file;
- udata.dxpl_id = dxpl_id;
+ /* Check if switching to "dense" attribute storage is possible */
+ if(!H5F_addr_defined(ainfo.fheap_addr)) {
+ htri_t sharable; /* Whether the attribute will be shared */
+ size_t raw_size = 0; /* Raw size of message */
+
+ /* Check for attribute being sharable */
+ if((sharable = H5SM_can_share(loc->file, dxpl_id, NULL, NULL, H5O_ATTR_ID, attr)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, FAIL, "can't determine attribute sharing status")
+ else if(sharable == FALSE) {
+ /* Compute the size needed to encode the attribute */
+ raw_size = (H5O_MSG_ATTR->raw_size)(loc->file, FALSE, attr);
+ } /* end if */
- /* Iterate over existing attributes, moving them to dense storage */
- op.op_type = H5O_MESG_OP_LIB;
- op.u.lib_op = H5O_attr_to_dense_cb;
- if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, &op, &udata, dxpl_id) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCONVERT, FAIL, "error converting attributes to dense storage")
+ /* Check for condititions for switching to "dense" attribute storage are met */
+ if(ainfo.nattrs == oh->max_compact || (!sharable && raw_size >= H5O_MESG_MAX_SIZE)) {
+ H5O_iter_cvt_t udata; /* User data for callback */
+ H5O_mesg_operator_t op; /* Wrapper for operator */
+
+ /* Create dense storage for attributes */
+ if(H5A_dense_create(loc->file, dxpl_id, &ainfo) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create dense storage for attributes")
+
+ /* Set up user data for callback */
+ udata.f = loc->file;
+ udata.dxpl_id = dxpl_id;
+ udata.ainfo = &ainfo;
+
+ /* Iterate over existing attributes, moving them to dense storage */
+ op.op_type = H5O_MESG_OP_LIB;
+ op.u.lib_op = H5O_attr_to_dense_cb;
+ if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, &op, &udata, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCONVERT, FAIL, "error converting attributes to dense storage")
+ } /* end if */
} /* end if */
- } /* end if */
- /* Increment attribute count on object */
- oh->nattrs++;
+ /* Increment attribute count on object */
+ ainfo.nattrs++;
- /* Later versions of the object header track the creation index on attributes */
- if(oh->version > H5O_VERSION_1 && (oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)) {
- /* Check for attribute creation order index on the object wrapping around */
- if(oh->max_attr_crt_idx == H5O_MAX_CRT_ORDER_IDX)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINC, FAIL, "attribute creation index can't be incremented")
+ /* Check whether we're tracking the creation index on attributes */
+ if(ainfo.track_corder) {
+ /* Check for attribute creation order index on the object wrapping around */
+ if(ainfo.max_crt_idx == H5O_MAX_CRT_ORDER_IDX)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINC, FAIL, "attribute creation index can't be incremented")
- /* Set the creation order index on the attribute & incr. creation order index */
- attr->crt_idx = oh->max_attr_crt_idx++;
+ /* Set the creation order index on the attribute & incr. creation order index */
+ attr->crt_idx = ainfo.max_crt_idx++;
+ } /* end if */
+ else
+ /* Set "bogus" creation index for attribute */
+ attr->crt_idx = H5O_MAX_CRT_ORDER_IDX;
+
+ /* Add the attribute information message, if one is needed */
+ if(new_ainfo) {
+ if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_AINFO, H5O_MSG_FLAG_DONTSHARE, 0, &ainfo) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to create new attribute info message")
+ } /* end if */
+ /* Otherwise, update existing message */
+ else {
+ if(H5O_msg_write_real(loc->file, dxpl_id, oh, H5O_MSG_AINFO, H5O_MSG_FLAG_DONTSHARE, 0, &ainfo) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update attribute info message")
+ } /* end else */
} /* end if */
- else
+ else {
+ /* Set "bogus" creation index for attribute */
attr->crt_idx = H5O_MAX_CRT_ORDER_IDX;
+ /* Set attribute info value to get attribute into object header */
+ ainfo.fheap_addr = HADDR_UNDEF;
+ } /* end else */
+
/* Check for storing attribute with dense storage */
- if(H5F_addr_defined(oh->attr_fheap_addr)) {
+ if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Insert attribute into dense storage */
- if(H5A_dense_insert(loc->file, dxpl_id, oh, attr) < 0)
+ if(H5A_dense_insert(loc->file, dxpl_id, &ainfo, attr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to add to dense storage")
} /* end if */
else {
@@ -399,6 +453,7 @@ H5A_t *
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 */
+ H5O_ainfo_t ainfo; /* Attribute information for object */
H5A_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_open_by_name)
@@ -411,10 +466,16 @@ H5O_attr_open_by_name(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, NULL, "unable to load object header")
+ /* Check for attribute info stored */
+ ainfo.fheap_addr = HADDR_UNDEF;
+ if(oh->version > H5O_VERSION_1 && NULL == H5O_msg_read_real(loc->file, dxpl_id, oh, H5O_AINFO_ID, &ainfo))
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+
/* Check for opening attribute with dense storage */
- if(H5F_addr_defined(oh->attr_fheap_addr)) {
+ if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Open attribute in dense storage */
- if(NULL == (ret_value = H5A_dense_open(loc->file, dxpl_id, oh, name)))
+ if(NULL == (ret_value = H5A_dense_open(loc->file, dxpl_id, &ainfo, name)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "can't open attribute")
} /* end if */
else {
@@ -671,6 +732,7 @@ herr_t
H5O_attr_write(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
{
H5O_t *oh = NULL; /* Pointer to actual object header */
+ H5O_ainfo_t ainfo; /* Attribute information for object */
unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
herr_t ret_value = SUCCEED; /* Return value */
@@ -684,10 +746,16 @@ H5O_attr_write(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
+ /* Check for attribute info stored */
+ ainfo.fheap_addr = HADDR_UNDEF;
+ if(oh->version > H5O_VERSION_1 && NULL == H5O_msg_read_real(loc->file, dxpl_id, oh, H5O_AINFO_ID, &ainfo))
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+
/* Check for attributes stored densely */
- if(H5F_addr_defined(oh->attr_fheap_addr)) {
+ if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Modify the attribute data in dense storage */
- if(H5A_dense_write(loc->file, dxpl_id, oh, attr) < 0)
+ if(H5A_dense_write(loc->file, dxpl_id, &ainfo, attr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "error updating attribute")
} /* end if */
else {
@@ -836,13 +904,6 @@ H5O_attr_rename_mod_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
attr = (H5A_t *)mesg->native;
mesg->native = NULL;
- /* If the later version of the object header format, decrement attribute */
- /* (must be decremented before call to H5O_release_mesg(),
- * so that the sanity checks pass - QAK)
- */
- if(oh->version > H5O_VERSION_1)
- oh->nattrs--;
-
/* Delete old attribute */
/* (doesn't decrement the link count on shared components becuase
* the "native" pointer has been reset)
@@ -850,13 +911,6 @@ H5O_attr_rename_mod_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
if(H5O_release_mesg(udata->f, udata->dxpl_id, oh, mesg, FALSE) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, H5_ITER_ERROR, "unable to release previous attribute")
- /* Increment attribute count */
- /* (must be incremented before call to H5O_msg_append_real(),
- * so that the sanity checks pass - QAK)
- */
- if(oh->version > H5O_VERSION_1)
- oh->nattrs++;
-
/* Append renamed attribute to object header */
/* (Don't let it become shared) */
if(H5O_msg_append_real(udata->f, udata->dxpl_id, oh, H5O_MSG_ATTR, (mesg->flags | H5O_MSG_FLAG_DONTSHARE), 0, attr) < 0)
@@ -902,6 +956,7 @@ H5O_attr_rename(const H5O_loc_t *loc, hid_t dxpl_id, const char *old_name,
const char *new_name)
{
H5O_t *oh = NULL; /* Pointer to actual object header */
+ H5O_ainfo_t ainfo; /* Attribute information for object */
unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
herr_t ret_value = SUCCEED; /* Return value */
@@ -916,10 +971,16 @@ H5O_attr_rename(const H5O_loc_t *loc, hid_t dxpl_id, const char *old_name,
if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
+ /* Check for attribute info stored */
+ ainfo.fheap_addr = HADDR_UNDEF;
+ if(oh->version > H5O_VERSION_1 && NULL == H5O_msg_read_real(loc->file, dxpl_id, oh, H5O_AINFO_ID, &ainfo))
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+
/* Check for attributes stored densely */
- if(H5F_addr_defined(oh->attr_fheap_addr)) {
+ if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Rename the attribute data in dense storage */
- if(H5A_dense_rename(loc->file, dxpl_id, oh, old_name, new_name) < 0)
+ if(H5A_dense_rename(loc->file, dxpl_id, &ainfo, old_name, new_name) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "error updating attribute")
} /* end if */
else {
@@ -987,6 +1048,7 @@ H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id,
hsize_t *last_attr, const H5A_attr_iter_op_t *attr_op, void *op_data)
{
H5O_t *oh = NULL; /* Pointer to actual object header */
+ H5O_ainfo_t ainfo; /* Attribute information for object */
H5A_attr_table_t atable = {0, NULL}; /* Table of attributes */
herr_t ret_value; /* Return value */
@@ -1002,30 +1064,26 @@ H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id,
if(NULL == (oh = (H5O_t *)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")
- /* 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 */
- haddr_t corder_bt2_addr; /* Address of v2 B-tree for creation order index on dense attribute storage */
+ /* Check for attribute info stored */
+ ainfo.fheap_addr = HADDR_UNDEF;
+ if(oh->version > H5O_VERSION_1 && NULL == H5O_msg_read_real(loc->file, dxpl_id, oh, H5O_AINFO_ID, &ainfo))
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+ /* Check for attributes stored densely */
+ if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Check for skipping too many attributes */
- if(skip > 0 && skip >= oh->nattrs)
+ if(skip > 0 && skip >= ainfo.nattrs)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified")
- /* Retrieve the information about dense attribute storage */
- attr_fheap_addr = oh->attr_fheap_addr;
- name_bt2_addr = oh->name_bt2_addr;
- corder_bt2_addr = oh->corder_bt2_addr;
-
/* Release the object header */
if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 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, corder_bt2_addr, idx_type, order, skip,
- last_attr, attr_op, op_data)) < 0)
+ if((ret_value = H5A_dense_iterate(loc->file, dxpl_id, loc_id, &ainfo,
+ idx_type, order, skip, last_attr, attr_op, op_data)) < 0)
HERROR(H5E_ATTR, H5E_BADITER, "error iterating over attributes");
} /* end if */
else {
@@ -1109,85 +1167,90 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_attr_remove_update(const H5O_loc_t *loc, H5O_t *oh, hid_t dxpl_id)
+H5O_attr_remove_update(const H5O_loc_t *loc, H5O_t *oh, H5O_ainfo_t *ainfo,
+ hid_t dxpl_id)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5A_attr_table_t atable = {0, NULL}; /* Table of attributes */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_remove_update)
/* Check arguments */
HDassert(loc);
HDassert(oh);
+ HDassert(ainfo);
- /* Reset the creation order min/max if there's no more attributes on the object */
- if(oh->nattrs == 0)
- oh->max_attr_crt_idx = 0;
+ /* Decrement the number of attributes on the object */
+ ainfo->nattrs--;
/* Check for shifting from dense storage back to compact storage */
- if(H5F_addr_defined(oh->attr_fheap_addr)) {
- /* Check if there's no more attributes */
- if(oh->nattrs == 0) {
- /* Delete the dense storage */
- if(H5A_dense_delete(loc->file, dxpl_id, oh) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete dense attribute storage")
- } /* end if */
- else if(oh->nattrs < oh->min_dense) {
- 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->attr_fheap_addr, oh->name_bt2_addr, H5_INDEX_NAME, H5_ITER_NATIVE, &atable) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table")
-
- /* Inspect attributes in table for ones that can't be converted back
- * into attribute message form (currently only attributes which
- * can't fit into an object header message)
- */
- for(u = 0; u < oh->nattrs; u++)
- if(H5O_msg_size_oh(loc->file, oh, H5O_ATTR_ID, &(atable.attrs[u]), (size_t)0) >= H5O_MESG_MAX_SIZE) {
- can_convert = FALSE;
- break;
- } /* end if */
+ if(H5F_addr_defined(ainfo->fheap_addr) && ainfo->nattrs < oh->min_dense) {
+ 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, ainfo, H5_INDEX_NAME, H5_ITER_NATIVE, &atable) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table")
- /* If ok, insert attributes as object header messages */
- if(can_convert) {
- /* Iterate over attributes, to put them into header */
- for(u = 0; u < oh->nattrs; u++) {
- htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */
-
- /* Check if attribute is shared */
- if((shared_mesg = H5O_msg_is_shared(H5O_ATTR_ID, &(atable.attrs[u]))) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "error determining if message is shared")
- else if(shared_mesg == 0) {
- /* Increment reference count on attribute components */
- /* (so that they aren't deleted when the dense attribute storage is deleted) */
- if(H5O_attr_link(loc->file, dxpl_id, &(atable.attrs[u])) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust attribute link count")
- } /* end if */
- else {
- /* Reset 'shared' status, so attributes will be shared again */
- atable.attrs[u].sh_loc.flags = 0;
- } /* end else */
-
- /* Insert attribute message into object header */
- /* (Will increment reference count on shared attributes) */
- if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_ATTR, 0, 0, &(atable.attrs[u])) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "can't create message")
- } /* end for */
-
- /* Remove the dense storage */
- if(H5A_dense_delete(loc->file, dxpl_id, oh) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete dense attribute storage")
+ /* Inspect attributes in table for ones that can't be converted back
+ * into attribute message form (currently only attributes which
+ * can't fit into an object header message)
+ */
+ for(u = 0; u < ainfo->nattrs; u++)
+ if(H5O_msg_size_oh(loc->file, oh, H5O_ATTR_ID, &(atable.attrs[u]), (size_t)0) >= H5O_MESG_MAX_SIZE) {
+ can_convert = FALSE;
+ break;
} /* end if */
- /* Free attribute table information */
- if(H5A_attr_release_table(&atable) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute table")
- } /* end else */
+ /* If ok, insert attributes as object header messages */
+ if(can_convert) {
+ /* Iterate over attributes, to put them into header */
+ for(u = 0; u < ainfo->nattrs; u++) {
+ htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */
+
+ /* Check if attribute is shared */
+ if((shared_mesg = H5O_msg_is_shared(H5O_ATTR_ID, &(atable.attrs[u]))) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "error determining if message is shared")
+ else if(shared_mesg == 0) {
+ /* Increment reference count on attribute components */
+ /* (so that they aren't deleted when the dense attribute storage is deleted) */
+ if(H5O_attr_link(loc->file, dxpl_id, &(atable.attrs[u])) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust attribute link count")
+ } /* end if */
+ else {
+ /* Reset 'shared' status, so attributes will be shared again */
+ atable.attrs[u].sh_loc.flags = 0;
+ } /* end else */
+
+ /* Insert attribute message into object header */
+ /* (Will increment reference count on shared attributes) */
+ if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_ATTR, 0, 0, &(atable.attrs[u])) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "can't create message")
+ } /* end for */
+
+ /* Remove the dense storage */
+ if(H5A_dense_delete(loc->file, dxpl_id, ainfo) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete dense attribute storage")
+ } /* end if */
} /* end if */
+ /* Check if we have deleted all the attributes and the attribute info
+ * message should be deleted itself.
+ */
+ if(ainfo->nattrs == 0) {
+ if(H5O_msg_remove_real(loc->file, oh, H5O_MSG_AINFO, H5O_ALL, NULL, NULL, TRUE, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute info")
+ } /* end if */
+ else {
+ if(H5O_msg_write_real(loc->file, dxpl_id, oh, H5O_MSG_AINFO, H5O_MSG_FLAG_DONTSHARE, 0, ainfo) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update attribute info message")
+ } /* end else */
+
done:
+ /* Release resources */
+ 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_remove_update() */
@@ -1222,13 +1285,6 @@ H5O_attr_remove_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
/* Check for correct attribute message to modify */
if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->name) == 0) {
- /* If the later version of the object header format, decrement attribute */
- /* (must be decremented before call to H5O_release_mesg(), in order for
- * sanity checks to pass - QAK)
- */
- if(oh->version > H5O_VERSION_1)
- oh->nattrs--;
-
/* Convert message into a null message (i.e. delete it) */
if(H5O_release_mesg(udata->f, udata->dxpl_id, oh, mesg, TRUE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, H5_ITER_ERROR, "unable to convert into null message")
@@ -1264,6 +1320,8 @@ herr_t
H5O_attr_remove(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
{
H5O_t *oh = NULL; /* Pointer to actual object header */
+ H5O_ainfo_t ainfo; /* Attribute information for object */
+ H5O_ainfo_t *ainfo_ptr = NULL; /* Pointer to attribute information for object */
unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1277,14 +1335,17 @@ H5O_attr_remove(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
+ /* Check for attribute info stored */
+ ainfo.fheap_addr = HADDR_UNDEF;
+ if(oh->version > H5O_VERSION_1 && NULL == (ainfo_ptr = H5O_msg_read_real(loc->file, dxpl_id, oh, H5O_AINFO_ID, &ainfo)))
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+
/* Check for attributes stored densely */
- if(H5F_addr_defined(oh->attr_fheap_addr)) {
+ if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Delete attribute from dense storage */
- if(H5A_dense_remove(loc->file, dxpl_id, oh, name) < 0)
+ if(H5A_dense_remove(loc->file, dxpl_id, &ainfo, name) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute in dense storage")
-
- /* Decrement # of attributes on object */
- oh->nattrs--;
} /* end if */
else {
H5O_iter_rm_t udata; /* User data for callback */
@@ -1307,9 +1368,10 @@ H5O_attr_remove(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't locate attribute")
} /* end else */
- /* Update the object header information after removing an attribute */
- if(H5O_attr_remove_update(loc, oh, dxpl_id) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update attribute info")
+ /* Update the attribute information after removing an attribute */
+ if(ainfo_ptr)
+ if(H5O_attr_remove_update(loc, oh, &ainfo, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update attribute info")
/* Update the modification time, if any */
if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE) < 0)
@@ -1344,6 +1406,8 @@ H5O_attr_remove_by_idx(const H5O_loc_t *loc, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, hid_t dxpl_id)
{
H5O_t *oh = NULL; /* Pointer to actual object header */
+ H5O_ainfo_t ainfo; /* Attribute information for object */
+ H5O_ainfo_t *ainfo_ptr = NULL; /* Pointer to attribute information for object */
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 */
@@ -1357,14 +1421,17 @@ H5O_attr_remove_by_idx(const H5O_loc_t *loc, H5_index_t idx_type,
if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
+ /* Check for attribute info stored */
+ ainfo.fheap_addr = HADDR_UNDEF;
+ if(oh->version > H5O_VERSION_1 && NULL == (ainfo_ptr = H5O_msg_read_real(loc->file, dxpl_id, oh, H5O_AINFO_ID, &ainfo)))
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+
/* Check for attributes stored densely */
- if(H5F_addr_defined(oh->attr_fheap_addr)) {
+ if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Delete attribute from dense storage */
- if(H5A_dense_remove_by_idx(loc->file, dxpl_id, oh, idx_type, order, n) < 0)
+ if(H5A_dense_remove_by_idx(loc->file, dxpl_id, &ainfo, idx_type, order, n) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute in dense storage")
-
- /* Decrement # of attributes on object */
- oh->nattrs--;
} /* end if */
else {
H5O_iter_rm_t udata; /* User data for callback */
@@ -1395,9 +1462,10 @@ H5O_attr_remove_by_idx(const H5O_loc_t *loc, H5_index_t idx_type,
HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't locate attribute")
} /* end else */
- /* Update the object header information after removing an attribute */
- if(H5O_attr_remove_update(loc, oh, dxpl_id) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update attribute info")
+ /* Update the attribute information after removing an attribute */
+ if(ainfo_ptr)
+ if(H5O_attr_remove_update(loc, oh, &ainfo, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update attribute info")
/* Update the modification time, if any */
if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE) < 0)
@@ -1417,6 +1485,56 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5O_attr_count_real
+ *
+ * Purpose: Determine the # of attributes on an object
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 9, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+hsize_t
+H5O_attr_count_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
+{
+ hsize_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_attr_count_real)
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(oh);
+
+ /* Check for attributes stored densely */
+ if(oh->version > H5O_VERSION_1) {
+ H5O_ainfo_t ainfo; /* Attribute information for object */
+
+ /* Attempt to get the attribute information from the object header */
+ if(H5O_msg_read_real(f, dxpl_id, oh, H5O_AINFO_ID, &ainfo))
+ ret_value = ainfo.nattrs;
+ else {
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+
+ ret_value = 0;
+ } /* end else */
+ } /* end if */
+ else {
+ unsigned u; /* Local index variable */
+
+ /* Loop over all messages, counting the attributes */
+ for(u = ret_value = 0; u < oh->nmesgs; u++)
+ if(oh->mesg[u].type == H5O_MSG_ATTR)
+ ret_value++;
+ } /* end else */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_attr_count_real */
+
+
+/*-------------------------------------------------------------------------
* Function: H5O_attr_count
*
* Purpose: Determine the # of attributes on an object
@@ -1443,17 +1561,8 @@ H5O_attr_count(const H5O_loc_t *loc, hid_t dxpl_id)
if(NULL == (oh = (H5O_t *)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")
- /* Check for attributes stored densely */
- if(oh->version > H5O_VERSION_1)
- ret_value = (int)oh->nattrs;
- else {
- unsigned u; /* Local index variable */
-
- /* Loop over all messages, counting the attributes */
- for(u = ret_value = 0; u < oh->nmesgs; u++)
- if(oh->mesg[u].type == H5O_MSG_ATTR)
- ret_value++;
- } /* end else */
+ /* Retrieve # of attributes on object */
+ ret_value = (int)H5O_attr_count_real(loc->file, dxpl_id, oh);
done:
if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
@@ -1519,6 +1628,7 @@ htri_t
H5O_attr_exists(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
{
H5O_t *oh = NULL; /* Pointer to actual object header */
+ H5O_ainfo_t ainfo; /* Attribute information for object */
htri_t ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_exists)
@@ -1531,10 +1641,16 @@ H5O_attr_exists(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
if(NULL == (oh = (H5O_t *)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")
+ /* Check for attribute info stored */
+ ainfo.fheap_addr = HADDR_UNDEF;
+ if(oh->version > H5O_VERSION_1 && NULL == H5O_msg_read_real(loc->file, dxpl_id, oh, H5O_AINFO_ID, &ainfo))
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+
/* Check for attributes stored densely */
- if(H5F_addr_defined(oh->attr_fheap_addr)) {
+ if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Check if attribute exists in dense storage */
- if((ret_value = H5A_dense_exists(loc->file, dxpl_id, oh, name)) < 0)
+ if((ret_value = H5A_dense_exists(loc->file, dxpl_id, &ainfo, name)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error checking for existence of attribute")
} /* end if */
else {