summaryrefslogtreecommitdiffstats
path: root/src/H5Oattribute.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Oattribute.c')
-rw-r--r--src/H5Oattribute.c194
1 files changed, 128 insertions, 66 deletions
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 */