diff options
Diffstat (limited to 'src/H5Oattribute.c')
-rw-r--r-- | src/H5Oattribute.c | 466 |
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 { |