summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/H5A.c213
-rw-r--r--src/H5Abtree2.c377
-rw-r--r--src/H5Adense.c716
-rw-r--r--src/H5Apkg.h84
-rw-r--r--src/H5Aprivate.h32
-rw-r--r--src/H5B2.c5
-rw-r--r--src/H5B2private.h3
-rw-r--r--src/H5Gdense.c36
-rw-r--r--src/H5Gprivate.h1
-rw-r--r--src/H5HFman.c16
-rw-r--r--src/H5HFprivate.h4
-rw-r--r--src/H5O.c22
-rw-r--r--src/H5Oattr.c525
-rw-r--r--src/H5Ocopy.c27
-rw-r--r--src/H5Odbg.c2
-rw-r--r--src/H5Odtype.c4
-rw-r--r--src/H5Oefl.c4
-rw-r--r--src/H5Ofill.c8
-rw-r--r--src/H5Oginfo.c4
-rw-r--r--src/H5Olayout.c4
-rw-r--r--src/H5Olinfo.c6
-rw-r--r--src/H5Olink.c4
-rw-r--r--src/H5Omessage.c260
-rw-r--r--src/H5Omtime.c4
-rw-r--r--src/H5Oname.c4
-rw-r--r--src/H5Opkg.h38
-rw-r--r--src/H5Opline.c6
-rw-r--r--src/H5Oprivate.h22
-rw-r--r--src/H5Osdspace.c4
-rw-r--r--src/H5Oshared.c6
-rw-r--r--src/H5Ostab.c4
-rw-r--r--src/H5Otest.c122
-rwxr-xr-xsrc/H5SM.c17
-rw-r--r--src/H5Tcommit.c2
-rwxr-xr-xsrc/Makefile.am5
-rw-r--r--src/Makefile.in11
36 files changed, 2238 insertions, 364 deletions
diff --git a/src/H5A.c b/src/H5A.c
index 8eede77..52bce59 100644
--- a/src/H5A.c
+++ b/src/H5A.c
@@ -70,7 +70,6 @@ static herr_t H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid
static herr_t H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id);
static int H5A_get_index(H5O_loc_t *loc, const char *name, hid_t dxpl_id);
static hsize_t H5A_get_storage_size(const H5A_t *attr);
-static herr_t H5A_rename(H5O_loc_t *loc, const char *old_name, const char *new_name, hid_t dxpl_id);
static herr_t H5A_find_idx_by_name(const void *mesg, unsigned idx, void *op_data);
@@ -246,8 +245,8 @@ H5Acreate(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id,
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
/* Go do the real work for attaching the attribute to the dataset */
- if ((ret_value=H5A_create(&loc, name, type, space, plist_id, H5AC_dxpl_id)) < 0)
- HGOTO_ERROR (H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create attribute")
+ if((ret_value = H5A_create(&loc, name, type, space, plist_id, H5AC_dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create attribute")
done:
FUNC_LEAVE_API(ret_value)
@@ -361,11 +360,11 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type,
* SOHM table */
/* Data type */
if(H5SM_try_share(attr->oloc.file, dxpl_id, H5O_DTYPE_ID, attr->dt) <0)
- HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "trying to share datatype failed");
+ HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "trying to share datatype failed")
/* Data space */
if(H5SM_try_share(attr->oloc.file, dxpl_id, H5O_SDSPACE_ID, attr->ds) <0)
- HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "trying to share dataspace failed");
+ HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "trying to share dataspace failed")
/* Compute the size of pieces on disk. This is either the size of the
@@ -463,19 +462,19 @@ H5A_find_idx_by_name(const void *_mesg, unsigned idx, void *_op_data)
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_find_idx_by_name)
- assert(mesg);
- assert(op_data);
+ HDassert(mesg);
+ HDassert(op_data);
/*
* Compare found attribute name to queried name and set the idx in the
* callback info if names are the same.
*/
- if(HDstrcmp(mesg->name,op_data->name)==0) {
+ if(HDstrcmp(mesg->name, op_data->name) == 0) {
op_data->idx = idx;
- ret_value=1;
+ ret_value = H5_ITER_STOP;
} /* end if */
else
- ret_value=0;
+ ret_value = H5_ITER_CONT;
FUNC_LEAVE_NOAPI(ret_value)
} /* H5A_find_idx_by_name() */
@@ -563,7 +562,7 @@ H5Aopen_name(hid_t loc_id, const char *name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
/* Look up the attribute for the object */
- if((idx = H5A_get_index(loc.oloc, name, H5AC_dxpl_id)) < 0)
+ if((idx = H5A_get_index(loc.oloc, name, H5AC_ind_dxpl_id)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "attribute not found")
/* Go do the real work for opening the attribute */
@@ -725,7 +724,7 @@ H5Awrite(hid_t attr_id, hid_t type_id, const void *buf)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null attribute buffer")
/* Go write the actual data to the attribute */
- if((ret_value = H5A_write(attr,mem_type,buf, H5AC_dxpl_id)) < 0)
+ if((ret_value = H5A_write(attr, mem_type, buf, H5AC_dxpl_id)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "unable to write attribute")
done:
@@ -753,6 +752,7 @@ static herr_t
H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id)
{
uint8_t *tconv_buf = NULL; /* datatype conv buffer */
+ hbool_t tconv_owned = FALSE; /* Whether the datatype conv buffer is owned by attribute */
uint8_t *bkg_buf = NULL; /* temp conversion buffer */
hssize_t snelmts; /* elements in attribute */
size_t nelmts; /* elements in attribute */
@@ -761,7 +761,6 @@ H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id)
size_t src_type_size; /* size of source type */
size_t dst_type_size; /* size of destination type*/
size_t buf_size; /* desired buffer size */
- int idx; /* index of attribute in object header */
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT(H5A_write)
@@ -770,11 +769,12 @@ H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id)
HDassert(mem_type);
HDassert(buf);
- /* Create buffer for data to store on disk */
+ /* Get # of elements for attribute's dataspace */
if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->ds)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid")
H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t);
+ /* If there's actually data elements for the attribute, make a copy of the data passed in */
if(nelmts > 0) {
/* Get the memory and file datatype sizes */
src_type_size = H5T_get_size(mem_type);
@@ -809,27 +809,24 @@ H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id)
/* Set the pointer to the attribute data to the converted information */
attr->data = tconv_buf;
+ tconv_owned = TRUE;
} /* end if */
/* No type conversion necessary */
else {
HDassert(dst_type_size == src_type_size);
- /* Allocate the attribute buffer, if there isn't one */
- if(attr->data == NULL)
- if(NULL == (attr->data = H5FL_BLK_MALLOC(attr_buf, dst_type_size * nelmts)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ /* Allocate the attribute buffer, if there isn't one */
+ if(attr->data == NULL)
+ if(NULL == (attr->data = H5FL_BLK_MALLOC(attr_buf, dst_type_size * nelmts)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- /* Copy the attribute data into the user's buffer */
- HDmemcpy(attr->data, buf, (dst_type_size * nelmts));
+ /* Copy the attribute data into the user's buffer */
+ HDmemcpy(attr->data, buf, (dst_type_size * nelmts));
} /* end else */
- /* Look up the attribute for the object */
- if((idx = H5A_get_index(&(attr->oloc), attr->name, dxpl_id)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "attribute not found")
-
- /* Modify the attribute data */
- if(H5O_msg_write(&(attr->oloc), H5O_ATTR_ID, idx, 0, H5O_UPDATE_DATA_ONLY|H5O_UPDATE_TIME, attr, dxpl_id) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to update attribute header messages")
+ /* Modify the attribute in the object header */
+ if(H5O_attr_write(&(attr->oloc), dxpl_id, attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to modify attribute")
} /* end if */
/* Indicate the the attribute doesn't need fill-values */
@@ -841,6 +838,8 @@ done:
(void)H5I_dec_ref(src_id);
if(dst_id >= 0)
(void)H5I_dec_ref(dst_id);
+ if(tconv_buf && !tconv_owned)
+ tconv_buf = H5FL_BLK_FREE(attr_buf, tconv_buf);
if(bkg_buf)
bkg_buf = H5FL_BLK_FREE(attr_buf, bkg_buf);
@@ -1314,8 +1313,8 @@ H5Arename(hid_t loc_id, const char *old_name, const char *new_name)
if(H5G_loc(loc_id, & loc) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
- /* Call private function */
- if(H5A_rename(loc.oloc, old_name, new_name, H5AC_dxpl_id) < 0)
+ /* Call attribute rename routine */
+ if(H5O_attr_rename(loc.oloc, H5AC_dxpl_id, old_name, new_name) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't rename attribute")
done:
@@ -1323,75 +1322,6 @@ done:
} /* H5Arename() */
-/*-------------------------------------------------------------------------
- * Function: H5A_rename
- *
- * Purpose: Private function for H5Arename. Rename an attribute
- *
- * Return: Success: Non-negative
- * Failure: Negative
- *
- * Programmer: Raymond Lu
- * October 23, 2002
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5A_rename(H5O_loc_t *loc, const char *old_name, const char *new_name, hid_t dxpl_id)
-{
- int seq, idx = FAIL; /* Index of attribute being querried */
- H5A_t found_attr; /* Attribute with OLD_NAME */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5A_rename)
-
- /* Check arguments */
- HDassert(loc);
- HDassert(old_name);
- HDassert(new_name);
-
- /* Read in the existing attributes to check for duplicates */
- seq = 0;
- while(H5O_msg_read(loc, H5O_ATTR_ID, seq, &found_attr, dxpl_id) != NULL) {
- /*
- * Compare found attribute name.
- */
- if(HDstrcmp(found_attr.name, old_name) == 0) {
- idx = seq;
- break;
- }
- if(H5O_msg_reset(H5O_ATTR_ID, &found_attr) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "can't release attribute info")
- seq++;
- } /* end while */
- H5E_clear_stack(NULL);
- if(idx < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "attribute cannot be found")
-
- /* Copy the attribute name. */
- if(found_attr.name)
- HDfree(found_attr.name);
- found_attr.name = H5MM_xstrdup(new_name);
- if(!found_attr.name)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "String copy failed")
-
- /* Indicate entry is not opened and the attribute doesn't need fill-values. */
- found_attr.obj_opened = FALSE;
- found_attr.initialized = TRUE;
-
- /* Modify the attribute message */
- if(H5O_msg_write(loc, H5O_ATTR_ID, idx, 0, H5O_UPDATE_TIME, &found_attr, dxpl_id) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to update attribute header messages")
-
- /* Close the attribute */
- if(H5A_free(&found_attr) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "unable to close renamed attribute")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5A_rename() */
-
-
/*--------------------------------------------------------------------------
NAME
H5Aiterate
@@ -1431,9 +1361,8 @@ herr_t
H5Aiterate(hid_t loc_id, unsigned *attr_num, H5A_operator_t op, void *op_data)
{
H5G_loc_t loc; /* Object location */
- H5A_t found_attr;
- int idx, start_idx;
- herr_t ret_value = 0;
+ unsigned start_idx; /* Index of attribute to start iterating at */
+ herr_t ret_value; /* Return value */
FUNC_ENTER_API(H5Aiterate, FAIL)
H5TRACE4("e","i*Iuxx",loc_id,attr_num,op,op_data);
@@ -1444,35 +1373,10 @@ 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")
- /*
- * Look up the attribute for the object. Make certain the start point is
- * reasonable.
- */
- start_idx = idx = (attr_num ? (int)*attr_num : 0);
- if(idx < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified")
- if(idx < H5O_msg_count(loc.oloc, H5O_ATTR_ID, H5AC_dxpl_id)) {
- while(H5O_msg_read(loc.oloc, H5O_ATTR_ID, idx++, &found_attr, H5AC_dxpl_id) != NULL) {
- /*
- * Compare found attribute name to new attribute name reject
- * creation if names are the same.
- */
- if((ret_value = (op)(loc_id,found_attr.name,op_data)) != 0) {
- if(H5O_msg_reset(H5O_ATTR_ID, &found_attr) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "can't release attribute info")
- break;
- } /* end if */
- if(H5O_msg_reset(H5O_ATTR_ID, &found_attr) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "can't release attribute info")
- } /* end while */
- H5E_clear_stack(NULL);
- } /* end if */
- else
- if(start_idx>0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified")
-
- if(attr_num)
- *attr_num = (unsigned)idx;
+ /* 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)
+ HERROR(H5E_ATTR, H5E_BADITER, "error iterating over attributes");
done:
FUNC_LEAVE_API(ret_value)
@@ -1576,12 +1480,10 @@ done:
* Programmer: Robb Matzke
* Thursday, December 4, 1997
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
H5A_t *
-H5A_copy(H5A_t *_new_attr, const H5A_t *old_attr, unsigned update_flags)
+H5A_copy(H5A_t *_new_attr, const H5A_t *old_attr)
{
H5A_t *new_attr = NULL;
hbool_t allocated_attr = FALSE; /* Whether the attribute was allocated */
@@ -1590,38 +1492,37 @@ H5A_copy(H5A_t *_new_attr, const H5A_t *old_attr, unsigned update_flags)
FUNC_ENTER_NOAPI(H5A_copy, NULL)
/* check args */
- assert(old_attr);
+ HDassert(old_attr);
- /* get space */
+ /* Allocate attribute structure */
if(_new_attr == NULL) {
- /* Sanity check - We should not be only updating data if we don'y have anything */
- HDassert(!(update_flags&H5O_UPDATE_DATA_ONLY));
-
if(NULL == (new_attr = H5FL_MALLOC(H5A_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
allocated_attr = TRUE;
} /* end if */
else
- new_attr=_new_attr;
+ new_attr = _new_attr;
- if(!(update_flags&H5O_UPDATE_DATA_ONLY)) {
- /* Copy the top level of the attribute */
- *new_attr = *old_attr;
+ /* Copy the top level of the attribute */
+ *new_attr = *old_attr;
- /* Don't open the object header for a copy */
- new_attr->obj_opened = FALSE;
+ /* Don't open the object header for a copy */
+ new_attr->obj_opened = FALSE;
- /* Copy the guts of the attribute */
- new_attr->name = H5MM_xstrdup(old_attr->name);
- new_attr->dt = H5T_copy(old_attr->dt, H5T_COPY_ALL);
- new_attr->ds = H5S_copy(old_attr->ds, FALSE);
- } /* end if */
+ /* Copy the guts of the attribute */
+ new_attr->name = H5MM_xstrdup(old_attr->name);
+ new_attr->dt = H5T_copy(old_attr->dt, H5T_COPY_ALL);
+ new_attr->ds = H5S_copy(old_attr->ds, FALSE);
+ /* XXX: Copy the object location and group path? -QAK */
+
+ /* Copy the attribute data, if there is any */
if(old_attr->data) {
- if(!(update_flags&H5O_UPDATE_DATA_ONLY) || new_attr->data == NULL) {
- if(NULL == (new_attr->data = H5FL_BLK_MALLOC(attr_buf,old_attr->data_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- } /* end if */
- HDmemcpy(new_attr->data,old_attr->data,old_attr->data_size);
+ /* Allocate data buffer for new attribute */
+ if(NULL == (new_attr->data = H5FL_BLK_MALLOC(attr_buf, old_attr->data_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* Copy the attribute data */
+ HDmemcpy(new_attr->data, old_attr->data, old_attr->data_size);
} /* end if */
/* Set the return value */
@@ -1629,12 +1530,12 @@ H5A_copy(H5A_t *_new_attr, const H5A_t *old_attr, unsigned update_flags)
done:
if(ret_value == NULL) {
- if(new_attr!=NULL && allocated_attr)
+ if(new_attr != NULL && allocated_attr)
(void)H5A_close(new_attr);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5A_copy() */
/*-------------------------------------------------------------------------
diff --git a/src/H5Abtree2.c b/src/H5Abtree2.c
new file mode 100644
index 0000000..47cbaae
--- /dev/null
+++ b/src/H5Abtree2.c
@@ -0,0 +1,377 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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: H5Abtree2.c
+ * Dec 4 2006
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: v2 B-tree callbacks for indexing attributes on objects
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5A_PACKAGE /*suppress error about including H5Apkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Apkg.h" /* Attributes */
+#include "H5Eprivate.h" /* Error handling */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/*
+ * Data exchange structure for dense attribute storage. This structure is
+ * passed through the fractal heap layer to compare attributes.
+ */
+typedef struct H5A_fh_ud_cmp_t {
+ /* downward */
+ H5F_t *f; /* Pointer to file that fractal heap is in */
+ hid_t dxpl_id; /* DXPL for operation */
+ const char *name; /* Name of attribute to compare */
+ H5B2_found_t found_op; /* Callback when correct attribute is found */
+ void *found_op_data; /* Callback data when correct attribute is found */
+
+ /* upward */
+ int cmp; /* Comparison of two attribute names */
+} H5A_fh_ud_cmp_t;
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* v2 B-tree function callbacks */
+
+/* v2 B-tree driver callbacks for 'name' index */
+static herr_t H5A_dense_btree2_name_store(void *native, const void *udata);
+static herr_t H5A_dense_btree2_name_retrieve(void *udata, const void *native);
+static herr_t H5A_dense_btree2_name_compare(const void *rec1, const void *rec2);
+static herr_t H5A_dense_btree2_name_encode(const H5F_t *f, uint8_t *raw,
+ const void *native);
+static herr_t H5A_dense_btree2_name_decode(const H5F_t *f, const uint8_t *raw,
+ void *native);
+static herr_t H5A_dense_btree2_name_debug(FILE *stream, const H5F_t *f, hid_t dxpl_id,
+ int indent, int fwidth, const void *record, const void *_udata);
+
+/* Fractal heap function callbacks */
+static herr_t H5A_dense_fh_name_cmp(const void *obj, size_t obj_len, void *op_data);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+/* v2 B-tree class for indexing 'name' field of links */
+const H5B2_class_t H5A_BT2_NAME[1]={{ /* B-tree class information */
+ H5B2_ATTR_DENSE_NAME_ID, /* Type of B-tree */
+ sizeof(H5A_dense_bt2_name_rec_t), /* Size of native record */
+ H5A_dense_btree2_name_store, /* Record storage callback */
+ H5A_dense_btree2_name_retrieve, /* Record retrieval callback */
+ H5A_dense_btree2_name_compare, /* Record comparison callback */
+ H5A_dense_btree2_name_encode, /* Record encoding callback */
+ H5A_dense_btree2_name_decode, /* Record decoding callback */
+ H5A_dense_btree2_name_debug /* Record debugging callback */
+}};
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_fh_name_cmp
+ *
+ * Purpose: Compares the name of a attribute in a fractal heap to another
+ * name
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 4 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5A_dense_fh_name_cmp(const void *obj, size_t UNUSED obj_len, void *_udata)
+{
+ H5A_fh_ud_cmp_t *udata = (H5A_fh_ud_cmp_t *)_udata; /* User data for 'op' callback */
+ H5A_t *attr = NULL; /* Pointer to attribute created from heap object */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_dense_fh_name_cmp)
+
+ /* Decode link information */
+ if(NULL == (attr = H5O_msg_decode(udata->f, udata->dxpl_id, H5O_ATTR_ID, obj)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "can't decode attribute")
+
+ /* Compare the string values */
+ udata->cmp = HDstrcmp(udata->name, attr->name);
+
+ /* Check for correct attribute & callback to make */
+ if(udata->cmp == 0 && udata->found_op) {
+ if((udata->found_op)(attr, udata->found_op_data) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTOPERATE, FAIL, "attribute found callback failed")
+ } /* end if */
+
+done:
+ /* Release the space allocated for the attrbute */
+ if(attr)
+ H5O_msg_free(H5O_ATTR_ID, attr);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_dense_fh_name_cmp() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_btree2_name_store
+ *
+ * Purpose: Store user information into native record for v2 B-tree
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, December 4, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5A_dense_btree2_name_store(void *_nrecord, const void *_udata)
+{
+ const H5A_bt2_ud_ins_t *udata = (const H5A_bt2_ud_ins_t *)_udata;
+ H5A_dense_bt2_name_rec_t *nrecord = (H5A_dense_bt2_name_rec_t *)_nrecord;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_dense_btree2_name_store)
+
+ /* Copy user information info native record */
+ nrecord->hash = udata->common.name_hash;
+ nrecord->flags = udata->common.flags;
+ HDmemcpy(nrecord->id, udata->id, (size_t)H5A_DENSE_FHEAP_ID_LEN);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5A_dense_btree2_name_store() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_btree2_name_retrieve
+ *
+ * Purpose: Retrieve native information from record for v2 B-tree
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, December 4, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5A_dense_btree2_name_retrieve(void *udata, const void *nrecord)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_dense_btree2_name_retrieve)
+
+ *(H5A_dense_bt2_name_rec_t *)udata = *(const H5A_dense_bt2_name_rec_t *)nrecord;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5A_dense_btree2_name_retrieve() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_btree2_name_compare
+ *
+ * Purpose: Compare two native information records, according to some key
+ *
+ * Return: <0 if rec1 < rec2
+ * =0 if rec1 == rec2
+ * >0 if rec1 > rec2
+ *
+ * Programmer: Quincey Koziol
+ * Monday, December 4, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5A_dense_btree2_name_compare(const void *_bt2_udata, const void *_bt2_rec)
+{
+ const H5A_bt2_ud_common_t *bt2_udata = (const H5A_bt2_ud_common_t *)_bt2_udata;
+ const H5A_dense_bt2_name_rec_t *bt2_rec = (const H5A_dense_bt2_name_rec_t *)_bt2_rec;
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_dense_btree2_name_compare)
+
+ /* Sanity check */
+ HDassert(bt2_udata);
+ HDassert(bt2_rec);
+
+ /* Check hash value */
+ if(bt2_udata->name_hash < bt2_rec->hash)
+ HGOTO_DONE(-1)
+ else if(bt2_udata->name_hash > bt2_rec->hash)
+ HGOTO_DONE(1)
+ else {
+ H5A_fh_ud_cmp_t fh_udata; /* User data for fractal heap 'op' callback */
+ herr_t status; /* Status from fractal heap 'op' routine */
+
+ /* Sanity check */
+ HDassert(bt2_udata->name_hash == bt2_rec->hash);
+
+ /* Prepare user data for callback */
+ /* down */
+ fh_udata.f = bt2_udata->f;
+ fh_udata.dxpl_id = bt2_udata->dxpl_id;
+ fh_udata.name = bt2_udata->name;
+ fh_udata.found_op = bt2_udata->found_op;
+ fh_udata.found_op_data = bt2_udata->found_op_data;
+
+ /* up */
+ fh_udata.cmp = 0;
+
+ /* Check for attribute in shared storage */
+ if(bt2_rec->flags) {
+HDfprintf(stderr, "%s: Shared dense storage for attributes not supported yet!\n", "H5A_dense_btree2_name_compare");
+HDassert(0 && "Shared dense storage for attributes not supported yet!");
+ } /* end if */
+
+ /* Check if the user's link and the B-tree's link have the same name */
+ status = H5HF_op(bt2_udata->fheap, bt2_udata->dxpl_id, bt2_rec->id,
+ H5A_dense_fh_name_cmp, &fh_udata);
+ HDassert(status >= 0);
+
+ /* Callback will set comparison value */
+ HGOTO_DONE(fh_udata.cmp)
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5A_dense_btree2_name_compare() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_btree2_name_encode
+ *
+ * Purpose: Encode native information into raw form for storing on disk
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, December 4, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5A_dense_btree2_name_encode(const H5F_t UNUSED *f, uint8_t *raw, const void *_nrecord)
+{
+ const H5A_dense_bt2_name_rec_t *nrecord = (const H5A_dense_bt2_name_rec_t *)_nrecord;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_dense_btree2_name_encode)
+
+ /* Encode the record's fields */
+ UINT32ENCODE(raw, nrecord->hash)
+ HDmemcpy(raw, nrecord->id, (size_t)H5A_DENSE_FHEAP_ID_LEN);
+ *raw++ = nrecord->flags;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5A_dense_btree2_name_encode() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_btree2_name_decode
+ *
+ * Purpose: Decode raw disk form of record into native form
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, December 4, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5A_dense_btree2_name_decode(const H5F_t UNUSED *f, const uint8_t *raw, void *_nrecord)
+{
+ H5A_dense_bt2_name_rec_t *nrecord = (H5A_dense_bt2_name_rec_t *)_nrecord;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_dense_btree2_name_decode)
+
+ /* Decode the record's fields */
+ UINT32DECODE(raw, nrecord->hash)
+ HDmemcpy(nrecord->id, raw, (size_t)H5A_DENSE_FHEAP_ID_LEN);
+ nrecord->flags = *raw++;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5A_dense_btree2_name_decode() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_btree2_name_debug
+ *
+ * Purpose: Debug native form of record
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, December 4, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5A_dense_btree2_name_debug(FILE *stream, const H5F_t UNUSED *f, hid_t UNUSED dxpl_id,
+ int indent, int fwidth, const void *_nrecord, const void UNUSED *_udata)
+{
+ const H5A_dense_bt2_name_rec_t *nrecord = (const H5A_dense_bt2_name_rec_t *)_nrecord;
+ unsigned u; /* Local index variable */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_dense_btree2_name_debug)
+
+ HDfprintf(stream, "%*s%-*s {%lx, ", indent, "", fwidth, "Record:",
+ nrecord->hash);
+ for(u = 0; u < H5A_DENSE_FHEAP_ID_LEN; u++)
+ HDfprintf(stderr, "%02x%s", nrecord->id[u], (u < (H5A_DENSE_FHEAP_ID_LEN - 1) ? " " : ", "));
+ HDfprintf(stderr, "%02x}\n", nrecord->flags);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5A_dense_btree2_name_debug() */
+
diff --git a/src/H5Adense.c b/src/H5Adense.c
new file mode 100644
index 0000000..7cacf13
--- /dev/null
+++ b/src/H5Adense.c
@@ -0,0 +1,716 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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: H5Adense.c
+ * Dec 4 2006
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Routines for operating on "dense" attribute storage
+ * for an object.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* 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 "H5Opkg.h" /* Object headers */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+/* Fractal heap creation parameters for "dense" attribute storage */
+#define H5A_FHEAP_MAN_WIDTH 4
+#define H5A_FHEAP_MAN_START_BLOCK_SIZE 512
+#define H5A_FHEAP_MAN_MAX_DIRECT_SIZE (64 * 1024)
+#define H5A_FHEAP_MAN_MAX_INDEX 32
+#define H5A_FHEAP_MAN_START_ROOT_ROWS 1
+#define H5A_FHEAP_CHECKSUM_DBLOCKS TRUE
+#define H5A_FHEAP_MAX_MAN_SIZE (4 * 1024)
+
+/* v2 B-tree creation macros for 'name' field index */
+#define H5A_NAME_BT2_NODE_SIZE 512
+#define H5A_NAME_BT2_MERGE_PERC 40
+#define H5A_NAME_BT2_SPLIT_PERC 100
+
+/* v2 B-tree creation macros for 'corder' field index */
+#define H5A_CORDER_BT2_NODE_SIZE 512
+#define H5A_CORDER_BT2_MERGE_PERC 40
+#define H5A_CORDER_BT2_SPLIT_PERC 100
+
+/* Size of stack buffer for serialized attribute */
+#define H5A_ATTR_BUF_SIZE 128
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/*
+ * Data exchange structure for dense attribute storage. This structure is
+ * passed through the v2 B-tree layer when modifying attributes.
+ */
+typedef struct H5A_bt2_od_wrt_t {
+ /* downward */
+ H5HF_t *fheap; /* Fractal heap handle to operate on */
+ hid_t dxpl_id; /* DXPL for operation */
+ void *attr_buf; /* Pointer to encoded attribute to store */
+ size_t attr_size; /* Size of encode attribute */
+} H5A_bt2_od_wrt_t;
+
+
+/*
+ * Data exchange structure to pass through the v2 B-tree layer for the
+ * H5B2_iterate function when iterating over densely stored attributes.
+ */
+typedef struct {
+ /* downward (internal) */
+ H5F_t *f; /* Pointer to file that fractal heap is in */
+ hid_t dxpl_id; /* DXPL for operation */
+ H5HF_t *fheap; /* Fractal heap handle */
+
+ /* downward (from application) */
+ hid_t loc_id; /* Object ID for application callback */
+ unsigned skip; /* Number of attributes to skip */
+ unsigned count; /* The # of attributes visited */
+ H5A_operator_t op; /* Callback for each attribute */
+ void *op_data; /* Callback data for each attribute */
+
+ /* upward */
+ int op_ret; /* Return value from callback */
+} H5A_bt2_ud_it_t;
+
+/*
+ * Data exchange structure to pass through the fractal heap layer for the
+ * H5HF_op function when iterating over densely stored attributes.
+ */
+typedef struct {
+ /* downward (internal) */
+ H5F_t *f; /* Pointer to file that fractal heap is in */
+ hid_t dxpl_id; /* DXPL for operation */
+
+ /* upward */
+ H5A_t *attr; /* Copy of attribute */
+} H5A_fh_ud_it_t;
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Declare a free list to manage the serialized attribute information */
+H5FL_BLK_DEFINE(ser_attr);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_create
+ *
+ * Purpose: Creates dense attribute storage structures for an object
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 4 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5A_dense_create(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
+{
+ H5HF_create_t fheap_cparam; /* Fractal heap creation parameters */
+ H5HF_t *fheap; /* Fractal heap handle */
+ size_t fheap_id_len; /* Fractal heap ID length */
+ size_t bt2_rrec_size; /* v2 B-tree raw record size */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5A_dense_create, FAIL)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(oh);
+
+ /* Set fractal heap creation parameters */
+/* XXX: Give some control of these to applications? */
+ HDmemset(&fheap_cparam, 0, sizeof(fheap_cparam));
+ fheap_cparam.managed.width = H5A_FHEAP_MAN_WIDTH;
+ fheap_cparam.managed.start_block_size = H5A_FHEAP_MAN_START_BLOCK_SIZE;
+ fheap_cparam.managed.max_direct_size = H5A_FHEAP_MAN_MAX_DIRECT_SIZE;
+ fheap_cparam.managed.max_index = H5A_FHEAP_MAN_MAX_INDEX;
+ fheap_cparam.managed.start_root_rows = H5A_FHEAP_MAN_START_ROOT_ROWS;
+ fheap_cparam.checksum_dblocks = H5A_FHEAP_CHECKSUM_DBLOCKS;
+ fheap_cparam.max_man_size = H5A_FHEAP_MAX_MAN_SIZE;
+
+ /* Create fractal heap for storing attributes */
+ if(NULL == (fheap = H5HF_create(f, dxpl_id, &fheap_cparam)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create fractal heap")
+
+ /* Retrieve the heap's address in the file */
+ if(H5HF_get_heap_addr(fheap, &(oh->attr_fheap_addr)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGETSIZE, FAIL, "can't get fractal heap address")
+#ifdef QAK
+HDfprintf(stderr, "%s: oh->attr_fheap_addr = %a\n", FUNC, oh->attr_fheap_addr);
+#endif /* QAK */
+
+ /* Retrieve the heap's ID length in the file */
+ if(H5HF_get_id_len(fheap, &fheap_id_len) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGETSIZE, FAIL, "can't get fractal heap ID length")
+ HDassert(fheap_id_len == H5A_DENSE_FHEAP_ID_LEN);
+#ifdef QAK
+HDfprintf(stderr, "%s: fheap_id_len = %Zu\n", FUNC, fheap_id_len);
+#endif /* QAK */
+
+ /* Close the fractal heap */
+ if(H5HF_close(fheap, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
+
+ /* Create the name index v2 B-tree */
+ bt2_rrec_size = 4 + /* Name's hash value */
+ fheap_id_len; /* Fractal heap ID */
+ if(H5B2_create(f, dxpl_id, H5A_BT2_NAME,
+ (size_t)H5A_NAME_BT2_NODE_SIZE, bt2_rrec_size,
+ H5A_NAME_BT2_SPLIT_PERC, H5A_NAME_BT2_MERGE_PERC,
+ &(oh->name_bt2_addr)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create v2 B-tree for name index")
+#ifdef QAK
+HDfprintf(stderr, "%s: oh->name_bt2_addr = %a\n", FUNC, oh->name_bt2_addr);
+#endif /* QAK */
+
+/* XXX: fix me */
+#ifdef NOT_YET
+ /* Check if we should create a creation order index v2 B-tree */
+ if(linfo->index_corder) {
+ /* Create the creation order index v2 B-tree */
+ bt2_rrec_size = 8 + /* Creation order value */
+ fheap_id_len; /* Fractal heap ID */
+ if(H5B2_create(f, dxpl_id, H5A_BT2_CORDER,
+ (size_t)H5A_CORDER_BT2_NODE_SIZE, bt2_rrec_size,
+ H5A_CORDER_BT2_SPLIT_PERC, H5A_CORDER_BT2_MERGE_PERC,
+ &(linfo->corder_bt2_addr)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create v2 B-tree for name index")
+#ifdef QAK
+HDfprintf(stderr, "%s: linfo->corder_bt2_addr = %a\n", FUNC, linfo->corder_bt2_addr);
+#endif /* QAK */
+ } /* end if */
+#endif /* NOT_YET */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_dense_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_insert
+ *
+ * Purpose: Insert an attribute into dense storage structures for an object
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 4 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5A_dense_insert(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, unsigned mesg_flags,
+ const H5A_t *attr)
+{
+ H5A_bt2_ud_ins_t udata; /* User data for v2 B-tree insertion */
+ H5HF_t *fheap = NULL; /* Fractal heap handle */
+ size_t attr_size; /* Size of serialized attribute in the heap */
+ uint8_t attr_buf[H5A_ATTR_BUF_SIZE]; /* Buffer for serializing attribute */
+ void *attr_ptr = NULL; /* Pointer to serialized attribute */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5A_dense_insert, FAIL)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(oh);
+ HDassert(attr);
+
+ /* Check for insertin shared attribute */
+ if(mesg_flags & H5O_MSG_FLAG_SHARED) {
+/* XXX: fix me */
+HDfprintf(stderr, "%s: inserting shared attributes in dense storage not supported yet!\n", FUNC);
+HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "inserting shared attributes in dense storage not supported yet")
+ } /* end if */
+
+ /* Find out the size of buffer needed for serialized attribute */
+ if((attr_size = H5O_msg_raw_size(f, H5O_ATTR_ID, attr)) == 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGETSIZE, FAIL, "can't get attribute size")
+
+ /* Allocate space for serialized attribute, if necessary */
+ if(attr_size > sizeof(attr_buf)) {
+ if(NULL == (attr_ptr = H5FL_BLK_MALLOC(ser_attr, attr_size)))
+ HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "memory allocation failed")
+ } /* end if */
+ else
+ attr_ptr = attr_buf;
+
+ /* Create serialized form of attribute */
+ if(H5O_msg_encode(f, H5O_ATTR_ID, attr_ptr, attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode attribute")
+
+ /* Open the fractal heap */
+ if(NULL == (fheap = H5HF_open(f, dxpl_id, oh->attr_fheap_addr)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
+
+ /* Insert the serialized attribute into the fractal heap */
+ if(H5HF_insert(fheap, dxpl_id, attr_size, attr_ptr, udata.id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to insert attribute into fractal heap")
+
+ /* Create the callback information for v2 B-tree record insertion */
+ udata.common.f = f;
+ udata.common.dxpl_id = dxpl_id;
+ udata.common.fheap = fheap;
+ udata.common.name = attr->name;
+ udata.common.name_hash = H5_checksum_lookup3(attr->name, HDstrlen(attr->name), 0);
+ udata.common.flags = mesg_flags;
+ udata.common.corder = -1; /* XXX: None yet */
+ udata.common.found_op = NULL;
+ udata.common.found_op_data = NULL;
+ /* udata.id already set in H5HF_insert() call */
+
+ /* Insert attribute into 'name' tracking v2 B-tree */
+ if(H5B2_insert(f, dxpl_id, H5A_BT2_NAME, oh->name_bt2_addr, &udata) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to insert record into v2 B-tree")
+
+done:
+ /* Release resources */
+ if(fheap && H5HF_close(fheap, dxpl_id) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
+ if(attr_ptr && attr_ptr != attr_buf)
+ H5FL_BLK_FREE(ser_attr, attr_ptr);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_dense_insert() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_write_cb
+ *
+ * Purpose: v2 B-tree modify callback to update the data for an attribute
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, December 5, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5A_dense_write_cb(void *_record, void *_op_data, hbool_t *changed)
+{
+ H5A_dense_bt2_name_rec_t *record = (H5A_dense_bt2_name_rec_t *)_record; /* Record from B-tree */
+ H5A_bt2_od_wrt_t *op_data = (H5A_bt2_od_wrt_t *)_op_data; /* "op data" from v2 B-tree modify */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_dense_write_cb)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(record);
+ HDassert(op_data);
+ HDassert(changed);
+
+ /* Check for modifying shared attribute */
+ if(record->flags & H5O_MSG_FLAG_SHARED) {
+/* XXX: fix me */
+HDfprintf(stderr, "%s: modifying shared attributes in dense storage not supported yet!\n", FUNC);
+HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "modifying shared attributes in dense storage not supported yet")
+ } /* end if */
+
+/* XXX: Add "write" routine (or allow "op" routine to modify values) to
+ * fractal heap code
+ */
+/* Sanity check */
+#ifndef NDEBUG
+{
+ size_t obj_len; /* Length of existing encoded attribute */
+
+ if(H5HF_get_obj_len(op_data->fheap, op_data->dxpl_id, record->id, &obj_len) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGETSIZE, FAIL, "can't get object size")
+ HDassert(obj_len == op_data->attr_size);
+}
+#endif /* NDEBUG */
+ /* Remove existing attribute from heap */
+ if(H5HF_remove(op_data->fheap, op_data->dxpl_id, record->id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTREMOVE, FAIL, "unable to remove attribute from heap")
+
+ /* Insert new encoded attribute into heap */
+ if(H5HF_insert(op_data->fheap, op_data->dxpl_id, op_data->attr_size, op_data->attr_buf, record->id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to insert attribute in heap")
+
+ /* Indicate that the B-tree record has changed */
+/* (XXX:We won't need this once we can write to an existing fractal heap object) */
+ *changed = TRUE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_dense_write_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_write
+ *
+ * Purpose: Modify an attribute in dense storage structures for an object
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 4 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5A_dense_write(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const H5A_t *attr)
+{
+ H5A_bt2_ud_common_t udata; /* User data for v2 B-tree modify */
+ H5A_bt2_od_wrt_t op_data; /* "Op data" for v2 B-tree modify */
+ H5HF_t *fheap = NULL; /* Fractal heap handle */
+ size_t attr_size; /* Size of serialized attribute in the heap */
+ uint8_t attr_buf[H5A_ATTR_BUF_SIZE]; /* Buffer for serializing attribute */
+ void *attr_ptr = NULL; /* Pointer to serialized attribute */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5A_dense_write, FAIL)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(oh);
+ HDassert(attr);
+
+ /* Find out the size of buffer needed for serialized attribute */
+ if((attr_size = H5O_msg_raw_size(f, H5O_ATTR_ID, attr)) == 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGETSIZE, FAIL, "can't get attribute size")
+
+ /* Allocate space for serialized attribute, if necessary */
+ if(attr_size > sizeof(attr_buf)) {
+ if(NULL == (attr_ptr = H5FL_BLK_MALLOC(ser_attr, attr_size)))
+ HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "memory allocation failed")
+ } /* end if */
+ else
+ attr_ptr = attr_buf;
+
+ /* Create serialized form of attribute */
+ if(H5O_msg_encode(f, H5O_ATTR_ID, attr_ptr, attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode attribute")
+
+ /* Open the fractal heap */
+ if(NULL == (fheap = H5HF_open(f, dxpl_id, oh->attr_fheap_addr)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
+
+ /* Create the "udata" information for v2 B-tree record modify */
+ udata.f = f;
+ udata.dxpl_id = dxpl_id;
+ udata.fheap = fheap;
+ udata.name = attr->name;
+ udata.name_hash = H5_checksum_lookup3(attr->name, HDstrlen(attr->name), 0);
+ udata.flags = 0;
+ udata.corder = -1; /* XXX: None yet */
+ udata.found_op = NULL;
+ udata.found_op_data = NULL;
+
+ /* Create the "op_data" for the v2 B-tree record modify */
+ op_data.fheap = fheap;
+ op_data.dxpl_id = dxpl_id;
+ op_data.attr_buf = attr_ptr;
+ op_data.attr_size = attr_size;
+
+ /* Modify attribute through 'name' tracking v2 B-tree */
+ if(H5B2_modify(f, dxpl_id, H5A_BT2_NAME, oh->name_bt2_addr, &udata, H5A_dense_write_cb, &op_data) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to modify record in v2 B-tree")
+
+done:
+ /* Release resources */
+ if(fheap && H5HF_close(fheap, dxpl_id) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
+ if(attr_ptr && attr_ptr != attr_buf)
+ H5FL_BLK_FREE(ser_attr, attr_ptr);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_dense_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_iterate_fh_cb
+ *
+ * Purpose: Callback for fractal heap operator, to make user's callback
+ * when iterating over attributes
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 5 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5A_dense_iterate_fh_cb(const void *obj, size_t UNUSED obj_len, void *_udata)
+{
+ H5A_fh_ud_it_t *udata = (H5A_fh_ud_it_t *)_udata; /* User data for fractal heap 'op' callback */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_dense_iterate_fh_cb)
+
+ /* Decode attribute information & keep a copy */
+ /* (we make a copy instead of calling the user/library callback directly in
+ * this routine because this fractal heap 'op' callback routine is called
+ * with the direct block protected and if the callback routine invokes an
+ * HDF5 routine, it could attempt to re-protect that direct block for the
+ * heap, causing the HDF5 routine called to fail)
+ */
+ if(NULL == (udata->attr = H5O_msg_decode(udata->f, udata->dxpl_id, H5O_ATTR_ID, obj)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, FAIL, "can't decode attribute")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_dense_iterate_fh_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_iterate_bt2_cb
+ *
+ * Purpose: v2 B-tree callback for dense attribute storage iterator
+ *
+ * Return: H5_ITER_ERROR/H5_ITER_CONT/H5_ITER_STOP
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 5 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5A_dense_iterate_bt2_cb(const void *_record, void *_bt2_udata)
+{
+ const H5A_dense_bt2_name_rec_t *record = (const H5A_dense_bt2_name_rec_t *)_record; /* Record from B-tree */
+ H5A_bt2_ud_it_t *bt2_udata = (H5A_bt2_ud_it_t *)_bt2_udata; /* User data for callback */
+ herr_t ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_dense_iterate_bt2_cb)
+
+ /* Check for skipping attributes */
+ if(bt2_udata->skip > 0)
+ --bt2_udata->skip;
+ else {
+ H5A_fh_ud_it_t fh_udata; /* User data for fractal heap 'op' callback */
+
+ /* Check for iterating over shared attribute */
+ if(record->flags & H5O_MSG_FLAG_SHARED) {
+/* XXX: fix me */
+HDfprintf(stderr, "%s: iterating over shared attributes in dense storage not supported yet!\n", FUNC);
+HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, H5_ITER_ERROR, "iterating over shared attributes in dense storage not supported yet")
+ } /* end if */
+
+ /* Prepare user data for callback */
+ /* down */
+ fh_udata.f = bt2_udata->f;
+ fh_udata.dxpl_id = bt2_udata->dxpl_id;
+
+ /* Call fractal heap 'op' routine, to copy the attribute information */
+ if(H5HF_op(bt2_udata->fheap, bt2_udata->dxpl_id, record->id,
+ H5A_dense_iterate_fh_cb, &fh_udata) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPERATE, H5_ITER_ERROR, "heap op callback failed")
+
+ /* Make the callback */
+ ret_value = (bt2_udata->op)(bt2_udata->loc_id, fh_udata.attr->name, bt2_udata->op_data);
+
+ /* Release the space allocated for the attribute */
+ H5O_msg_free(H5O_ATTR_ID, fh_udata.attr);
+ } /* end else */
+
+ /* Increment the number of attributes passed through */
+ /* (whether we skipped them or not) */
+ bt2_udata->count++;
+
+ /* Check for callback failure and pass along return value */
+ if(ret_value < 0)
+ HERROR(H5E_ATTR, H5E_CANTNEXT, "iteration operator failed");
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_dense_iterate_bt2_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_iterate
+ *
+ * Purpose: Iterate over attributes in dense storage structures for an object
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 5 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+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, H5A_operator_t op,
+ void *op_data)
+{
+ H5A_bt2_ud_it_t udata; /* User data for iterator callback */
+ H5HF_t *fheap = NULL; /* Fractal heap handle */
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5A_dense_iterate, FAIL)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(H5F_addr_defined(attr_fheap_addr));
+ HDassert(H5F_addr_defined(name_bt2_addr));
+ HDassert(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")
+
+ /* 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")
+
+ /* Construct the user data for v2 B-tree iterator callback */
+ udata.f = f;
+ udata.dxpl_id = dxpl_id;
+ udata.fheap = fheap;
+ udata.loc_id = loc_id;
+ udata.skip = skip;
+ udata.count = 0;
+ udata.op = 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;
+
+done:
+ /* Release resources */
+ if(fheap && H5HF_close(fheap, dxpl_id) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_dense_iterate() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_delete
+ *
+ * Purpose: Delete all dense storage structures for attributes on an object
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 6 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5A_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5A_dense_delete, FAIL)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(oh);
+
+/* XXX: iterate through name index v2 B-tree and delete shared attributes */
+/* XXX: we need to delete attributes that use shared & committed components also */
+
+ /* Delete name index v2 B-tree */
+ if(H5B2_delete(f, dxpl_id, H5A_BT2_NAME, oh->name_bt2_addr, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete v2 B-tree for name index")
+ oh->name_bt2_addr = HADDR_UNDEF;
+
+ /* Delete fractal heap */
+ if(H5HF_delete(f, dxpl_id, oh->attr_fheap_addr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete fractal heap")
+ oh->attr_fheap_addr = HADDR_UNDEF;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_dense_delete() */
+
diff --git a/src/H5Apkg.h b/src/H5Apkg.h
index e01d788..a8a7dd7 100644
--- a/src/H5Apkg.h
+++ b/src/H5Apkg.h
@@ -38,13 +38,29 @@
#include "H5Aprivate.h"
/* Other private headers needed by this file */
+#include "H5B2private.h" /* v2 B-trees */
#include "H5FLprivate.h" /* Free Lists */
+#include "H5HFprivate.h" /* Fractal heaps */
#include "H5Oprivate.h" /* Object headers */
#include "H5Sprivate.h" /* Dataspace */
#include "H5Tprivate.h" /* Datatype functions */
+
+/**************************/
+/* Package Private Macros */
+/**************************/
+
+/* Standard length of fractal heap ID for attribute */
+#define H5A_DENSE_FHEAP_ID_LEN 7
+
+
+/****************************/
+/* Package Private Typedefs */
+/****************************/
+
+/* Define the main attribute structure */
struct H5A_t {
- hbool_t initialized;/* Indicate whether the attribute has been modified */
+ hbool_t initialized;/* Indicate whether the attribute has been modified */
hbool_t obj_opened; /* Object header entry opened? */
H5O_loc_t oloc; /* Object location for object attribute is on */
H5G_name_t path; /* Group hierarchy path */
@@ -56,19 +72,79 @@ struct H5A_t {
void *data; /* Attribute data (on a temporary basis) */
size_t data_size; /* Size of data on disk */
H5T_cset_t encoding; /* Character encoding of attribute */
- H5O_shared_t sh_loc; /*location of shared message */
+ H5O_shared_t sh_loc; /* Location of shared message */
};
+/* Typedefs for "dense" attribute storage */
+/* (fractal heap & v2 B-tree info) */
+
+/* Typedef for native 'name' field index records in the v2 B-tree */
+/* (Keep 'id' field first so generic record handling in callbacks works) */
+typedef struct H5A_dense_bt2_name_rec_t {
+ uint8_t id[H5A_DENSE_FHEAP_ID_LEN]; /* Heap ID for link */
+ uint8_t flags; /* Message flags for attribute */
+ uint32_t hash; /* Hash of 'name' field value */
+} H5A_dense_bt2_name_rec_t;
+
+/*
+ * Common data exchange structure for dense attribute storage. This structure
+ * is passed through the v2 B-tree layer to the methods for the objects
+ * to which the v2 B-tree points.
+ */
+typedef struct H5A_bt2_ud_common_t {
+ /* downward */
+ H5F_t *f; /* Pointer to file that fractal heap is in */
+ hid_t dxpl_id; /* DXPL for operation */
+ H5HF_t *fheap; /* Fractal heap handle */
+ const char *name; /* Name of attribute to compare */
+ uint32_t name_hash; /* Hash of name of attribute to compare */
+ uint8_t flags; /* Flags for attribute storage location */
+ int64_t corder; /* Creation order value of attribute to compare */
+ H5B2_found_t found_op; /* Callback when correct attribute is found */
+ void *found_op_data; /* Callback data when correct attribute is found */
+} H5A_bt2_ud_common_t;
+
+/*
+ * Data exchange structure for dense attribute storage. This structure is
+ * passed through the v2 B-tree layer when inserting attributes.
+ */
+typedef struct H5A_bt2_ud_ins_t {
+ /* downward */
+ H5A_bt2_ud_common_t common; /* Common info for B-tree user data (must be first) */
+ uint8_t id[H5A_DENSE_FHEAP_ID_LEN]; /* Heap ID of attribute to insert */
+} H5A_bt2_ud_ins_t;
+
+
+/*****************************/
+/* Package Private Variables */
+/*****************************/
+
/* Declare extern the free list for H5A_t's */
H5FL_EXTERN(H5A_t);
/* Declare extern a free list to manage blocks of type conversion data */
H5FL_BLK_EXTERN(attr_buf);
+/* The v2 B-tree class for indexing 'name' field on attributes */
+H5_DLLVAR const H5B2_class_t H5A_BT2_NAME[1];
+
+
+/******************************/
+/* Package Private Prototypes */
+/******************************/
+
/* Function prototypes for H5A package scope */
H5_DLL herr_t H5A_init(void);
-H5_DLL H5A_t *H5A_copy(H5A_t *new_attr, const H5A_t *old_attr, unsigned update_flags);
+H5_DLL H5A_t *H5A_copy(H5A_t *new_attr, const H5A_t *old_attr);
H5_DLL herr_t H5A_free(H5A_t *attr);
H5_DLL herr_t H5A_close(H5A_t *attr);
-#endif
+/* Attribute "dense" storage routines */
+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, H5A_operator_t op, void *op_data);
+
+#endif /* _H5Apkg_H */
+
diff --git a/src/H5Aprivate.h b/src/H5Aprivate.h
index 9b24490..75ccafd 100644
--- a/src/H5Aprivate.h
+++ b/src/H5Aprivate.h
@@ -24,11 +24,39 @@
/* Private headers needed by this file */
#include "H5Gprivate.h" /* Groups */
+
+/**************************/
+/* Library Private Macros */
+/**************************/
+
+
+/****************************/
+/* Library Private Typedefs */
+/****************************/
+
/* Forward references of package typedefs */
typedef struct H5A_t H5A_t;
-/* Library private functions in package */
+
+/*****************************/
+/* Library-private Variables */
+/*****************************/
+
+
+/***************************************/
+/* Library-private Function Prototypes */
+/***************************************/
+struct H5O_t; /*forward decl*/
+
+/* General attribute routines */
H5_DLL struct H5O_loc_t *H5A_oloc(H5A_t *attr);
H5_DLL H5G_name_t *H5A_nameof(H5A_t *attr);
-#endif
+/* Attribute "dense" storage routines */
+H5_DLL herr_t H5A_dense_create(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh);
+H5_DLL herr_t H5A_dense_insert(H5F_t *f, hid_t dxpl_id, const struct H5O_t *oh,
+ unsigned mesg_flags, const H5A_t *attr);
+H5_DLL herr_t H5A_dense_delete(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh);
+
+#endif /* _H5Aprivate_H */
+
diff --git a/src/H5B2.c b/src/H5B2.c
index dd95858..358e8ac 100644
--- a/src/H5B2.c
+++ b/src/H5B2.c
@@ -1008,8 +1008,9 @@ done:
* Function: H5B2_modify
*
* Purpose: Locate the specified information in a B-tree and modify it.
- * The UDATA can point to additional data passed
- * to the key comparison function.
+ * The UDATA points to additional data passed
+ * to the key comparison function for locating the record to
+ * modify.
*
* The 'OP' routine is called with the record found and the
* OP_DATA pointer, to allow caller to modify information about
diff --git a/src/H5B2private.h b/src/H5B2private.h
index aa4bb12..a0e9c3b 100644
--- a/src/H5B2private.h
+++ b/src/H5B2private.h
@@ -50,7 +50,8 @@ typedef enum H5B2_subid_t {
H5B2_FHEAP_HUGE_FILT_DIR_ID, /* B-tree is for fractal heap directly accessed, filtered 'huge' objects */
H5B2_GRP_DENSE_NAME_ID, /* B-tree is for indexing 'name' field for "dense" link storage in groups */
H5B2_GRP_DENSE_CORDER_ID, /* B-tree is for indexing 'creation order' field for "dense" link storage in groups */
- H5B2_SOHM_INDEX_ID, /* B-tree is an index for shared object header messages */
+ H5B2_SOHM_INDEX_ID, /* B-tree is an index for shared object header messages */
+ H5B2_ATTR_DENSE_NAME_ID, /* B-tree is for indexing 'name' field for "dense" attribute storage on objects */
H5B2_NUM_BTREE_ID /* Number of B-tree IDs (must be last) */
} H5B2_subid_t;
diff --git a/src/H5Gdense.c b/src/H5Gdense.c
index 899e833..cd0b242 100644
--- a/src/H5Gdense.c
+++ b/src/H5Gdense.c
@@ -445,9 +445,8 @@ HDfprintf(stderr, "%s: HDstrlen(lnk->name) = %Zu, link_size = %Zu\n", FUNC, HDst
done:
/* Release resources */
- if(fheap)
- if(H5HF_close(fheap, dxpl_id) < 0)
- HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
+ if(fheap && H5HF_close(fheap, dxpl_id) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
if(link_ptr && link_ptr != link_buf)
H5FL_BLK_FREE(ser_link, link_ptr);
@@ -545,9 +544,8 @@ H5G_dense_lookup(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
done:
/* Release resources */
- if(fheap)
- if(H5HF_close(fheap, dxpl_id) < 0)
- HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
+ if(fheap && H5HF_close(fheap, dxpl_id) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5G_dense_lookup() */
@@ -895,7 +893,7 @@ H5G_dense_iterate_bt2_cb(const void *_record, void *_bt2_udata)
{
const H5G_dense_bt2_name_rec_t *record = (const H5G_dense_bt2_name_rec_t *)_record;
H5G_bt2_ud_it_t *bt2_udata = (H5G_bt2_ud_it_t *)_bt2_udata; /* User data for callback */
- int ret_value = H5_ITER_CONT; /* Return value */
+ herr_t ret_value = H5_ITER_CONT; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5G_dense_iterate_bt2_cb)
@@ -913,7 +911,7 @@ H5G_dense_iterate_bt2_cb(const void *_record, void *_bt2_udata)
/* Call fractal heap 'op' routine, to copy the link information */
if(H5HF_op(bt2_udata->fheap, bt2_udata->dxpl_id, record->id,
H5G_dense_iterate_fh_cb, &fh_udata) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTOPERATE, H5_ITER_ERROR, "link found callback failed")
+ HGOTO_ERROR(H5E_SYM, H5E_CANTOPERATE, H5_ITER_ERROR, "heap op callback failed")
/* Check which type of callback to make */
switch(bt2_udata->lnk_op->op_type) {
@@ -976,7 +974,6 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
H5L_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk,
hid_t gid, H5G_link_iterate_t *lnk_op, void *op_data)
{
- H5G_bt2_ud_it_t udata; /* User data for iterator callback */
H5HF_t *fheap = NULL; /* Fractal heap handle */
H5G_link_table_t ltable = {0, NULL}; /* Table of links */
herr_t ret_value; /* Return value */
@@ -994,9 +991,25 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
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 */
+
+ /* Retrieve # of records in name index */
+ /* (# of records in all indices the same) */
+ if(H5B2_get_nrec(f, dxpl_id, H5G_BT2_NAME, linfo->name_bt2_addr, &nrec) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve # of records in index")
+
+ /* Check for bad starting index */
+ if(skip >= nrec)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified")
+ } /* end if */
+
/* Check on iteration order */
/* ("native" iteration order is unordered for this link storage mechanism) */
if(order == H5_ITER_NATIVE) {
+ H5G_bt2_ud_it_t udata; /* User data for iterator callback */
+
/* Construct the user data for v2 B-tree iterator callback */
udata.f = f;
udata.dxpl_id = dxpl_id;
@@ -1471,9 +1484,8 @@ H5G_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
done:
/* Release resources */
- if(fheap)
- if(H5HF_close(fheap, dxpl_id) < 0)
- HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
+ if(fheap && H5HF_close(fheap, dxpl_id) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5G_dense_remove() */
diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h
index aadcc9a..d5350f9 100644
--- a/src/H5Gprivate.h
+++ b/src/H5Gprivate.h
@@ -169,7 +169,6 @@ H5_DLL herr_t H5G_node_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream
/*
* These functions operate on group object locations.
*/
-/* forward reference for later use */
H5_DLL herr_t H5G_obj_ent_decode(H5F_t *f, const uint8_t **pp,
struct H5O_loc_t *oloc);
H5_DLL herr_t H5G_obj_ent_encode(H5F_t *f, uint8_t **pp,
diff --git a/src/H5HFman.c b/src/H5HFman.c
index 56f24ca..6270905 100644
--- a/src/H5HFman.c
+++ b/src/H5HFman.c
@@ -248,7 +248,7 @@ static herr_t
H5HF_man_op_real(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
H5HF_operator_t op, void *op_data)
{
- H5HF_direct_t *dblock; /* Pointer to direct block to query */
+ H5HF_direct_t *dblock = NULL; /* Pointer to direct block to query */
hsize_t obj_off; /* Object's offset in heap */
size_t obj_len; /* Object's length in heap */
size_t blk_off; /* Offset of object in block */
@@ -360,20 +360,14 @@ HDfprintf(stderr, "%s: dblock_addr = %a, dblock_size = %Zu\n", FUNC, dblock_addr
p = dblock->blk + blk_off;
/* Call the user's 'op' callback */
- if(op(p, obj_len, op_data) < 0) {
- /* Release direct block */
- if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block")
-
+ if(op(p, obj_len, op_data) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "application's callback failed")
- } /* end if */
+done:
/* Unlock direct block */
- if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block")
- dblock = NULL;
+ if(dblock && H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block")
-done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_man_op_real() */
diff --git a/src/H5HFprivate.h b/src/H5HFprivate.h
index c762eca..bc6363a 100644
--- a/src/H5HFprivate.h
+++ b/src/H5HFprivate.h
@@ -105,10 +105,12 @@ typedef herr_t (*H5HF_operator_t)(const void *obj/*in*/, size_t obj_len,
/***************************************/
/* Library-private Function Prototypes */
/***************************************/
+
+/* General routines for fractal heap operations */
H5_DLL H5HF_t *H5HF_create(H5F_t *f, hid_t dxpl_id, const H5HF_create_t *cparam);
H5_DLL H5HF_t *H5HF_open(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr);
H5_DLL herr_t H5HF_get_id_len(H5HF_t *fh, size_t *id_len_p/*out*/);
-H5_DLL herr_t H5HF_get_heap_addr(H5HF_t *fh, haddr_t *heap_addr);
+H5_DLL herr_t H5HF_get_heap_addr(H5HF_t *fh, haddr_t *heap_addr/*out*/);
H5_DLL herr_t H5HF_insert(H5HF_t *fh, hid_t dxpl_id, size_t size,
const void *obj, void *id/*out*/);
H5_DLL herr_t H5HF_get_obj_len(H5HF_t *fh, hid_t dxpl_id, const void *id,
diff --git a/src/H5O.c b/src/H5O.c
index d68efd2..7daed1f 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -34,6 +34,7 @@
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
+#include "H5Aprivate.h" /* Attributes */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* File access */
#include "H5FLprivate.h" /* Free lists */
@@ -63,7 +64,6 @@
/********************/
static hid_t H5O_open_by_loc(H5G_loc_t *obj_loc, hid_t dxpl_id);
-static H5O_loc_t * H5O_get_loc(hid_t id);
static herr_t H5O_new(H5F_t *f, hid_t dxpl_id, haddr_t header, size_t chunk_size,
hid_t ocpl_id, H5O_loc_t *loc/*out*/);
static herr_t H5O_delete_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh);
@@ -1400,6 +1400,12 @@ H5O_delete_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message")
} /* end for */
+ /* Check for dense attribute storage & delete it if necessary */
+ if(oh->version > H5O_VERSION_1 && H5F_addr_defined(oh->attr_fheap_addr)) {
+ if(H5A_dense_delete(f, dxpl_id, oh) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message")
+ } /* end if */
+
/* Free main (first) object header "chunk" */
if(H5MF_xfree(f, H5FD_MEM_OHDR, dxpl_id, oh->chunk[0].addr, (hsize_t)oh->chunk[0].size) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free object header")
@@ -1576,7 +1582,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-static H5O_loc_t *
+H5O_loc_t *
H5O_get_loc(hid_t object_id)
{
H5O_loc_t *ret_value; /* Return value */
@@ -1875,8 +1881,16 @@ H5O_get_info(H5O_loc_t *oloc, H5O_info_t *oinfo, hid_t dxpl_id)
if(curr_msg->flags & H5O_MSG_FLAG_SHARED) \
oinfo->hdr.msg_shared |= type_flag;
} /* end for */
- if(oh->version > H5O_VERSION_1)
- HDassert(oh->nattrs == oinfo->num_attrs);
+
+ /* Sanity checking, etc. for # of attributes */
+ if(oh->version > H5O_VERSION_1) {
+ if(H5F_addr_defined(oh->attr_fheap_addr)) {
+ HDassert(oinfo->num_attrs == 0);
+ oinfo->num_attrs = oh->nattrs;
+ } /* end if */
+ else
+ HDassert(oh->nattrs == oinfo->num_attrs);
+ } /* end if */
/* Iterate over all the chunks, adding any gaps to the free space */
oinfo->hdr.hdr_size = 0;
diff --git a/src/H5Oattr.c b/src/H5Oattr.c
index fa104a9..617614e 100644
--- a/src/H5Oattr.c
+++ b/src/H5Oattr.c
@@ -29,10 +29,47 @@
#include "H5Spkg.h" /* Dataspaces */
#include "H5SMprivate.h" /* Shared Object Header Messages */
+/* User data for iteration when updating an attribute */
+typedef struct {
+ /* down */
+ H5F_t *f; /* Pointer to file attribute is in */
+ hid_t dxpl_id; /* DXPL for operation */
+ H5A_t *attr; /* Attribute data to update object header with */
+
+ /* up */
+ hbool_t found; /* Whether the attribute was found */
+} H5O_iter_wrt_t;
+
+/* User data for iteration when renaming an attribute */
+typedef struct {
+ /* down */
+ H5F_t *f; /* Pointer to file attribute is in */
+ hid_t dxpl_id; /* DXPL for operation */
+ const char *old_name; /* Old name of attribute */
+ const char *new_name; /* New name of attribute */
+
+ /* up */
+ hbool_t found; /* Whether the attribute was found */
+} H5O_iter_ren_t;
+
+/* User data for iteration when iterating over attributes */
+typedef struct {
+ /* down */
+ H5F_t *f; /* Pointer to file attribute is in */
+ hid_t dxpl_id; /* DXPL for operation */
+ hid_t loc_id; /* ID of object being iterated over */
+ unsigned skip; /* # of attributes to skip over */
+ H5A_operator_t op; /* Callback routine for each attribute */
+ void *op_data; /* User data for callback */
+
+ /* up */
+ unsigned count; /* Count of attributes examined */
+} H5O_iter_itr_t;
+
/* PRIVATE PROTOTYPES */
static herr_t H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg);
static void *H5O_attr_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p);
-static void *H5O_attr_copy(const void *_mesg, void *_dest, unsigned update_flags);
+static void *H5O_attr_copy(const void *_mesg, void *_dest);
static size_t H5O_attr_size(const H5F_t *f, const void *_mesg);
static herr_t H5O_attr_reset(void *_mesg);
static herr_t H5O_attr_free(void *mesg);
@@ -470,18 +507,17 @@ done:
allocating the destination structure if necessary.
--------------------------------------------------------------------------*/
static void *
-H5O_attr_copy(const void *_src, void *_dst, unsigned update_flags)
+H5O_attr_copy(const void *_src, void *_dst)
{
- const H5A_t *src = (const H5A_t *) _src;
- void *ret_value; /* Return value */
+ void *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_copy)
/* check args */
- HDassert(src);
+ HDassert(_src);
/* copy */
- if(NULL == (ret_value = H5A_copy(_dst, src, update_flags)))
+ if(NULL == (ret_value = H5A_copy(_dst, _src)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "can't copy attribute")
done:
@@ -1229,3 +1265,480 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_attr_debug() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_attr_write_cb
+ *
+ * Purpose: Object header iterator callback routine to update an
+ * attribute stored compactly.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 4 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_attr_write_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
+ unsigned UNUSED sequence, unsigned *oh_flags_ptr, void *_udata/*in,out*/)
+{
+ H5O_iter_wrt_t *udata = (H5O_iter_wrt_t *)_udata; /* Operator user data */
+ herr_t ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_attr_write_cb)
+
+ /* check args */
+ HDassert(oh);
+ HDassert(mesg);
+ HDassert(!udata->found);
+
+ /* Check for shared message */
+ if(mesg->flags & H5O_MSG_FLAG_SHARED) {
+ H5A_t shared_attr; /* Copy of shared attribute */
+
+ /*
+ * 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, &shared_attr))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5_ITER_ERROR, "unable to read shared attribute")
+
+ /* Check for correct attribute message to modify */
+ if(HDstrcmp(shared_attr.name, udata->attr->name) == 0) {
+ htri_t shared_mesg; /* Whether the message should be shared */
+
+ /* Store new version of message as a SOHM */
+ /* (should always work, since we're not changing the size of the attribute) */
+ if((shared_mesg = H5SM_try_share(udata->f, udata->dxpl_id, H5O_ATTR_ID, udata->attr)) == 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, H5_ITER_ERROR, "attribute changed sharing status")
+ else if(shared_mesg < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, H5_ITER_ERROR, "can't share attribute")
+
+ /* Remove the old attribut from the SOHM index */
+ if(H5SM_try_delete(udata->f, udata->dxpl_id, H5O_ATTR_ID, mesg->native) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, H5_ITER_ERROR, "unable to delete shared attribute in shared storage")
+
+ /* Extract shared message info from current attribute */
+ if(H5O_attr_get_share(udata->attr, mesg->native) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, H5_ITER_ERROR, "can't get shared info")
+
+ /* Indicate that we found the correct attribute */
+ udata->found = TRUE;
+ } /* end if */
+
+ /* Release copy of shared attribute */
+ H5O_attr_reset(&shared_attr);
+ } /* end if */
+ else {
+ /* Check for correct attribute message to modify */
+ if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->attr->name) == 0) {
+ /* Allocate storage for the message's data, if necessary */
+ if(((H5A_t *)mesg->native)->data == NULL)
+ if(NULL == (((H5A_t *)mesg->native)->data = H5FL_BLK_MALLOC(attr_buf, udata->attr->data_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed")
+
+ /* Copy the data */
+ HDmemcpy(((H5A_t *)mesg->native)->data, udata->attr->data, udata->attr->data_size);
+
+ /* Indicate that we found the correct attribute */
+ udata->found = TRUE;
+ } /* end if */
+ } /* end else */
+
+ /* Set common info, if we found the correct attribute */
+ if(udata->found) {
+ /* Mark message as dirty */
+ mesg->dirty = TRUE;
+
+ /* Stop iterating */
+ ret_value = H5_ITER_STOP;
+
+ /* Indicate that the object header was modified */
+ *oh_flags_ptr |= H5AC__DIRTIED_FLAG;
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_attr_write_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_attr_write
+ *
+ * Purpose: Write a new value to an attribute.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Monday, December 4, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+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 */
+ unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_attr_write)
+
+ /* Check arguments */
+ HDassert(loc);
+ HDassert(attr);
+
+ /* Protect the object header to iterate over */
+ if(NULL == (oh = 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 attributes stored densely */
+ if(H5F_addr_defined(oh->attr_fheap_addr)) {
+ /* Modify the attribute data in dense storage */
+ if(H5A_dense_write(loc->file, dxpl_id, oh, attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "error updating attribute")
+ } /* end if */
+ else {
+ H5O_iter_wrt_t udata; /* User data for callback */
+ H5O_mesg_operator_t op; /* Wrapper for operator */
+
+ /* Set up user data for callback */
+ udata.f = loc->file;
+ udata.dxpl_id = dxpl_id;
+ udata.attr = attr;
+ udata.found = FALSE;
+
+ /* Iterate over attributes, to locate correct one to update */
+ op.lib_op = H5O_attr_write_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")
+
+ /* Check that we found the attribute */
+ if(!udata.found)
+ HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't locate open attribute?")
+ } /* end else */
+
+ /* Update the modification time, if any */
+ if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE, &oh_flags) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
+
+done:
+ 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")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_attr_write */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_attr_rename_dup_cb
+ *
+ * Purpose: Object header iterator callback routine to check for
+ * duplicate name during rename
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 5 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_attr_rename_dup_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)
+
+ /* check args */
+ HDassert(oh);
+ HDassert(mesg);
+ HDassert(!udata->found);
+
+ /* Check for shared message */
+ if(mesg->flags & H5O_MSG_FLAG_SHARED) {
+ H5A_t shared_attr; /* Copy of shared attribute */
+
+ /*
+ * 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, &shared_attr))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5_ITER_ERROR, "unable to read shared attribute")
+
+ /* Check for existing attribute with new name */
+ if(HDstrcmp(shared_attr.name, udata->new_name) == 0) {
+ /* Indicate that we found an existing attribute with the new name*/
+ udata->found = TRUE;
+
+ /* Stop iterating */
+ ret_value = H5_ITER_STOP;
+ } /* end if */
+
+ /* Release copy of shared attribute */
+ H5O_attr_reset(&shared_attr);
+ } /* end if */
+ else {
+ /* Check for existing attribute with new name */
+ if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->new_name) == 0) {
+ /* Indicate that we found an existing attribute with the new name*/
+ udata->found = TRUE;
+
+ /* Stop iterating */
+ ret_value = H5_ITER_STOP;
+ } /* end if */
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_attr_rename_dup_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_attr_rename_mod_cb
+ *
+ * Purpose: Object header iterator callback routine to change name of
+ * attribute during rename
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 5 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_attr_rename_mod_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
+ unsigned UNUSED sequence, unsigned *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_mod_cb)
+
+ /* check args */
+ HDassert(oh);
+ HDassert(mesg);
+ HDassert(!udata->found);
+
+ /* Check for shared message */
+ if(mesg->flags & H5O_MSG_FLAG_SHARED) {
+ H5A_t shared_attr; /* Copy of shared attribute */
+
+ /*
+ * 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, &shared_attr))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5_ITER_ERROR, "unable to read shared attribute")
+
+ /* Check for correct attribute message to modify */
+ if(HDstrcmp(shared_attr.name, udata->old_name) == 0) {
+/* XXX: fix me */
+HDfprintf(stderr, "%s: renaming a shared attribute not supported yet!\n", FUNC);
+HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, H5_ITER_ERROR, "renaming a shared attribute not supported yet")
+ } /* end if */
+
+ /* Release copy of shared attribute */
+ H5O_attr_reset(&shared_attr);
+ } /* end if */
+ else {
+ /* Find correct attribute message to rename */
+ if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->old_name) == 0) {
+ /* Change the name for the attribute */
+ H5MM_xfree(((H5A_t *)mesg->native)->name);
+ ((H5A_t *)mesg->native)->name = H5MM_xstrdup(udata->new_name);
+
+ /* Indicate that we found an existing attribute with the old name*/
+ udata->found = TRUE;
+
+ /* Mark message as dirty */
+ mesg->dirty = TRUE;
+
+ /* Stop iterating */
+ ret_value = H5_ITER_STOP;
+
+ /* Indicate that the object header was modified */
+ *oh_flags_ptr |= H5AC__DIRTIED_FLAG;
+ } /* end if */
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_attr_rename_mod_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_attr_rename
+ *
+ * Purpose: Rename an attribute.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, December 5, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+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 */
+ unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_attr_rename)
+
+ /* Check arguments */
+ HDassert(loc);
+ HDassert(old_name);
+ HDassert(new_name);
+
+ /* Protect the object header to iterate over */
+ if(NULL == (oh = 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 attributes stored densely */
+ if(H5F_addr_defined(oh->attr_fheap_addr)) {
+/* XXX: fix me */
+HDfprintf(stderr, "%s: renaming attributes in dense storage not supported yet!\n", FUNC);
+HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "renaming attributes in dense storage not supported yet")
+ } /* end if */
+ else {
+ H5O_iter_ren_t udata; /* User data for callback */
+ H5O_mesg_operator_t op; /* Wrapper for operator */
+
+ /* Set up user data for callback */
+ udata.f = loc->file;
+ udata.dxpl_id = dxpl_id;
+ udata.old_name = old_name;
+ udata.new_name = new_name;
+ udata.found = FALSE;
+
+ /* Iterate over attributes, to check if "new name" exists already */
+ op.lib_op = H5O_attr_rename_dup_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")
+
+ /* If the new name was found, indicate an error */
+ if(udata.found)
+ HGOTO_ERROR(H5E_ATTR, H5E_EXISTS, FAIL, "attribute with new name already exists")
+
+ /* Iterate over attributes again, to actually rename attribute with old name */
+ op.lib_op = H5O_attr_rename_mod_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")
+ } /* end else */
+
+ /* Update the modification time, if any */
+ if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE, &oh_flags) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
+
+done:
+ 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")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_attr_rename */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_attr_iterate
+ *
+ * Purpose: Iterate over attributes for an object.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, December 5, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+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)
+{
+ 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 */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_attr_iterate)
+
+ /* Check arguments */
+ HDassert(loc);
+ HDassert(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 */
+ if(oh->version > H5O_VERSION_1 && H5F_addr_defined(oh->attr_fheap_addr)) {
+ 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)
+ HDONE_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)) {
+ if((ret_value = H5A_dense_iterate(loc->file, dxpl_id, loc_id, attr_fheap_addr,
+ name_bt2_addr, skip, last_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)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified")
+
+ /* Update last attribute looked at */
+ if(last_attr)
+ *last_attr = idx;
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_attr_iterate */
+
diff --git a/src/H5Ocopy.c b/src/H5Ocopy.c
index 9048d25..a1c9c45 100644
--- a/src/H5Ocopy.c
+++ b/src/H5Ocopy.c
@@ -349,14 +349,21 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
/* Copy attribute information */
oh_dst->max_compact = oh_src->max_compact;
oh_dst->min_dense = oh_src->min_dense;
- oh_dst->nattrs = oh_src->nattrs;
- /* XXX: Bail out for now, if the source object has densely stored attributes */
- if(H5F_addr_defined(oh_src->attr_fheap_addr))
- HGOTO_ERROR(H5E_OHDR, H5E_UNSUPPORTED, FAIL, "densely stored attributes not supported yet")
- else {
- HDassert(!H5F_addr_defined(oh_src->name_bt2_addr));
+ if(cpy_info->copy_without_attr) {
+ oh_dst->nattrs = 0;
oh_dst->attr_fheap_addr = HADDR_UNDEF;
oh_dst->name_bt2_addr = HADDR_UNDEF;
+ } /* end if */
+ else {
+ oh_dst->nattrs = oh_src->nattrs;
+ /* XXX: Bail out for now, if the source object has densely stored attributes */
+ if(H5F_addr_defined(oh_src->attr_fheap_addr))
+ HGOTO_ERROR(H5E_OHDR, H5E_UNSUPPORTED, FAIL, "densely stored attributes not supported yet")
+ else {
+ HDassert(!H5F_addr_defined(oh_src->name_bt2_addr));
+ oh_dst->attr_fheap_addr = HADDR_UNDEF;
+ oh_dst->name_bt2_addr = HADDR_UNDEF;
+ } /* end else */
} /* end else */
@@ -438,10 +445,9 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
oh_dst->alloc_nmesgs = oh_dst->nmesgs = (oh_src->nmesgs - null_msgs);
/* Allocate memory for destination message array */
- if(oh_dst->alloc_nmesgs > 0) {
+ if(oh_dst->alloc_nmesgs > 0)
if(NULL == (oh_dst->mesg = H5FL_SEQ_CALLOC(H5O_mesg_t, oh_dst->alloc_nmesgs)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- }
/* "copy" pass over messages, to perform main message copying */
null_msgs = 0;
@@ -472,9 +478,8 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
/* If we're preserving deleted messages, set their types to 'NULL'
* in the destination.
*/
- if(cpy_info->preserve_null && deleted[mesgno]) {
+ if(cpy_info->preserve_null && deleted[mesgno])
mesg_dst->type = H5O_MSG_NULL;
- }
/* Check for shared message to operate on */
/* (Use destination message, in case the message has been removed (i.e
@@ -525,7 +530,7 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
for(mesgno = 0; mesgno < oh_dst->nmesgs; mesgno++) {
dst_oh_size += H5O_SIZEOF_MSGHDR_OH(oh_dst);
dst_oh_size += H5O_ALIGN_OH(oh_dst, oh_dst->mesg[mesgno].raw_size);
- }
+ } /* end for */
/* Allocate space for chunk in destination file */
if(HADDR_UNDEF == (oh_dst->chunk[0].addr = H5MF_alloc(oloc_dst->file, H5FD_MEM_OHDR, dxpl_id, (hsize_t)dst_oh_size)))
diff --git a/src/H5Odbg.c b/src/H5Odbg.c
index a016ec3..6f32d24 100644
--- a/src/H5Odbg.c
+++ b/src/H5Odbg.c
@@ -174,7 +174,7 @@ H5O_assert(const H5O_t *oh)
HDassert(!(tmp_msg->raw >= curr_msg->raw && tmp_msg->raw < (curr_msg->raw + curr_msg->raw_size)));
} /* end for */
} /* end for */
- if(oh->version > H5O_VERSION_1)
+ if(oh->version > H5O_VERSION_1 && !H5F_addr_defined(oh->attr_fheap_addr))
HDassert(oh->nattrs == num_attrs);
/* Sanity check that all the bytes are accounted for */
diff --git a/src/H5Odtype.c b/src/H5Odtype.c
index eff0d24..f6c1f3f 100644
--- a/src/H5Odtype.c
+++ b/src/H5Odtype.c
@@ -29,7 +29,7 @@
/* PRIVATE PROTOTYPES */
static herr_t H5O_dtype_encode(H5F_t *f, uint8_t *p, const void *mesg);
static void *H5O_dtype_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p);
-static void *H5O_dtype_copy(const void *_mesg, void *_dest, unsigned update_flags);
+static void *H5O_dtype_copy(const void *_mesg, void *_dest);
static size_t H5O_dtype_size(const H5F_t *f, const void *_mesg);
static herr_t H5O_dtype_reset(void *_mesg);
static herr_t H5O_dtype_free(void *_mesg);
@@ -1024,7 +1024,7 @@ done:
allocating the destination structure if necessary.
--------------------------------------------------------------------------*/
static void *
-H5O_dtype_copy(const void *_src, void *_dst, unsigned UNUSED update_flags)
+H5O_dtype_copy(const void *_src, void *_dst)
{
const H5T_t *src = (const H5T_t *) _src;
H5T_t *dst = NULL;
diff --git a/src/H5Oefl.c b/src/H5Oefl.c
index bf7647c..eb6e6cf 100644
--- a/src/H5Oefl.c
+++ b/src/H5Oefl.c
@@ -30,7 +30,7 @@
/* PRIVATE PROTOTYPES */
static void *H5O_efl_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p);
static herr_t H5O_efl_encode(H5F_t *f, uint8_t *p, const void *_mesg);
-static void *H5O_efl_copy(const void *_mesg, void *_dest, unsigned update_flags);
+static void *H5O_efl_copy(const void *_mesg, void *_dest);
static size_t H5O_efl_size(const H5F_t *f, const void *_mesg);
static herr_t H5O_efl_reset(void *_mesg);
static void *H5O_efl_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type,
@@ -259,7 +259,7 @@ H5O_efl_encode(H5F_t *f, uint8_t *p, const void *_mesg)
*-------------------------------------------------------------------------
*/
static void *
-H5O_efl_copy(const void *_mesg, void *_dest, unsigned UNUSED update_flags)
+H5O_efl_copy(const void *_mesg, void *_dest)
{
const H5O_efl_t *mesg = (const H5O_efl_t *) _mesg;
H5O_efl_t *dest = (H5O_efl_t *) _dest;
diff --git a/src/H5Ofill.c b/src/H5Ofill.c
index fedbfd2..213df3f 100644
--- a/src/H5Ofill.c
+++ b/src/H5Ofill.c
@@ -32,7 +32,7 @@
static void *H5O_fill_new_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p);
static herr_t H5O_fill_new_encode(H5F_t *f, uint8_t *p, const void *_mesg);
-static void *H5O_fill_new_copy(const void *_mesg, void *_dest, unsigned update_flags);
+static void *H5O_fill_new_copy(const void *_mesg, void *_dest);
static size_t H5O_fill_new_size(const H5F_t *f, const void *_mesg);
static herr_t H5O_fill_new_reset(void *_mesg);
static herr_t H5O_fill_new_free(void *_mesg);
@@ -41,7 +41,7 @@ static herr_t H5O_fill_new_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FIL
static void *H5O_fill_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p);
static herr_t H5O_fill_encode(H5F_t *f, uint8_t *p, const void *_mesg);
-static void *H5O_fill_copy(const void *_mesg, void *_dest, unsigned update_flags);
+static void *H5O_fill_copy(const void *_mesg, void *_dest);
static size_t H5O_fill_size(const H5F_t *f, const void *_mesg);
static herr_t H5O_fill_reset(void *_mesg);
static herr_t H5O_fill_free(void *_mesg);
@@ -341,7 +341,7 @@ H5O_fill_encode(H5F_t UNUSED *f, uint8_t *p, const void *_mesg)
*-------------------------------------------------------------------------
*/
static void *
-H5O_fill_new_copy(const void *_mesg, void *_dest, unsigned UNUSED update_flags)
+H5O_fill_new_copy(const void *_mesg, void *_dest)
{
const H5O_fill_new_t *mesg = (const H5O_fill_new_t *)_mesg;
H5O_fill_new_t *dest = (H5O_fill_new_t *)_dest;
@@ -417,7 +417,7 @@ done:
*-------------------------------------------------------------------------
*/
static void *
-H5O_fill_copy(const void *_mesg, void *_dest, unsigned UNUSED update_flags)
+H5O_fill_copy(const void *_mesg, void *_dest)
{
const H5O_fill_t *mesg = (const H5O_fill_t *)_mesg;
H5O_fill_t *dest = (H5O_fill_t *)_dest;
diff --git a/src/H5Oginfo.c b/src/H5Oginfo.c
index 95a19ab..f448bf4 100644
--- a/src/H5Oginfo.c
+++ b/src/H5Oginfo.c
@@ -36,7 +36,7 @@
/* PRIVATE PROTOTYPES */
static void *H5O_ginfo_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p);
static herr_t H5O_ginfo_encode(H5F_t *f, uint8_t *p, const void *_mesg);
-static void *H5O_ginfo_copy(const void *_mesg, void *_dest, unsigned update_flags);
+static void *H5O_ginfo_copy(const void *_mesg, void *_dest);
static size_t H5O_ginfo_size(const H5F_t *f, const void *_mesg);
static herr_t H5O_ginfo_free(void *_mesg);
static herr_t H5O_ginfo_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg,
@@ -204,7 +204,7 @@ H5O_ginfo_encode(H5F_t UNUSED *f, uint8_t *p, const void *_mesg)
*-------------------------------------------------------------------------
*/
static void *
-H5O_ginfo_copy(const void *_mesg, void *_dest, unsigned UNUSED update_flags)
+H5O_ginfo_copy(const void *_mesg, void *_dest)
{
const H5O_ginfo_t *ginfo = (const H5O_ginfo_t *)_mesg;
H5O_ginfo_t *dest = (H5O_ginfo_t *)_dest;
diff --git a/src/H5Olayout.c b/src/H5Olayout.c
index f8ec192..305ab17 100644
--- a/src/H5Olayout.c
+++ b/src/H5Olayout.c
@@ -34,7 +34,7 @@
/* PRIVATE PROTOTYPES */
static void *H5O_layout_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p);
static herr_t H5O_layout_encode(H5F_t *f, uint8_t *p, const void *_mesg);
-static void *H5O_layout_copy(const void *_mesg, void *_dest, unsigned update_flags);
+static void *H5O_layout_copy(const void *_mesg, void *_dest);
static size_t H5O_layout_size(const H5F_t *f, const void *_mesg);
static herr_t H5O_layout_reset(void *_mesg);
static herr_t H5O_layout_free(void *_mesg);
@@ -351,7 +351,7 @@ done:
*-------------------------------------------------------------------------
*/
static void *
-H5O_layout_copy(const void *_mesg, void *_dest, unsigned UNUSED update_flags)
+H5O_layout_copy(const void *_mesg, void *_dest)
{
const H5O_layout_t *mesg = (const H5O_layout_t *) _mesg;
H5O_layout_t *dest = (H5O_layout_t *) _dest;
diff --git a/src/H5Olinfo.c b/src/H5Olinfo.c
index 384a181..02da141 100644
--- a/src/H5Olinfo.c
+++ b/src/H5Olinfo.c
@@ -38,7 +38,7 @@
/* PRIVATE PROTOTYPES */
static void *H5O_linfo_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p);
static herr_t H5O_linfo_encode(H5F_t *f, uint8_t *p, const void *_mesg);
-static void *H5O_linfo_copy(const void *_mesg, void *_dest, unsigned update_flags);
+static void *H5O_linfo_copy(const void *_mesg, void *_dest);
static size_t H5O_linfo_size(const H5F_t *f, const void *_mesg);
static herr_t H5O_linfo_free(void *_mesg);
static herr_t H5O_linfo_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link);
@@ -239,7 +239,7 @@ H5O_linfo_encode(H5F_t *f, uint8_t *p, const void *_mesg)
*-------------------------------------------------------------------------
*/
static void *
-H5O_linfo_copy(const void *_mesg, void *_dest, unsigned UNUSED update_flags)
+H5O_linfo_copy(const void *_mesg, void *_dest)
{
const H5O_linfo_t *linfo = (const H5O_linfo_t *)_mesg;
H5O_linfo_t *dest = (H5O_linfo_t *) _dest;
@@ -391,7 +391,7 @@ H5O_linfo_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *mesg_t
HDassert(cpy_info);
/* Copy the source message */
- if(NULL == (linfo_dst = H5O_linfo_copy(linfo_src, NULL, FALSE)))
+ if(NULL == (linfo_dst = H5O_linfo_copy(linfo_src, NULL)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "memory allocation failed")
/* If we are performing a 'shallow hierarchy' copy, and the links in this
diff --git a/src/H5Olink.c b/src/H5Olink.c
index f7ee6e0..8de560f 100644
--- a/src/H5Olink.c
+++ b/src/H5Olink.c
@@ -39,7 +39,7 @@
/* PRIVATE PROTOTYPES */
static void *H5O_link_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p);
static herr_t H5O_link_encode(H5F_t *f, uint8_t *p, const void *_mesg);
-static void *H5O_link_copy(const void *_mesg, void *_dest, unsigned update_flags);
+static void *H5O_link_copy(const void *_mesg, void *_dest);
static size_t H5O_link_size(const H5F_t *f, const void *_mesg);
static herr_t H5O_link_reset(void *_mesg);
static herr_t H5O_link_free(void *_mesg);
@@ -317,7 +317,7 @@ H5O_link_encode(H5F_t *f, uint8_t *p, const void *_mesg)
*-------------------------------------------------------------------------
*/
static void *
-H5O_link_copy(const void *_mesg, void *_dest, unsigned UNUSED update_flags)
+H5O_link_copy(const void *_mesg, void *_dest)
{
const H5O_link_t *lnk = (const H5O_link_t *) _mesg;
H5O_link_t *dest = (H5O_link_t *) _dest;
diff --git a/src/H5Omessage.c b/src/H5Omessage.c
index 32ec4f8..b7bc47d 100644
--- a/src/H5Omessage.c
+++ b/src/H5Omessage.c
@@ -33,6 +33,7 @@
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
+#include "H5Aprivate.h" /* Attributes */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fprivate.h" /* File access */
#include "H5MMprivate.h" /* Memory management */
@@ -76,17 +77,13 @@ typedef struct {
H5O_operator_t op; /* Callback routine for removal operations */
void *op_data; /* Callback data for removal operations */
hbool_t adj_link; /* Whether to adjust links when removing messages */
-} H5O_iter_ud1_t;
+} H5O_iter_rm_t;
-/* Typedef for "internal library" iteration operations */
-typedef herr_t (*H5O_lib_operator_t)(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
- unsigned sequence, unsigned *oh_flags_ptr/*out*/, void *operator_data/*in,out*/);
-
-/* Some syntactic sugar to make the compiler happy with two different kinds of iterator callbacks */
-typedef union {
- H5O_operator_t app_op; /* Application callback for each message */
- H5O_lib_operator_t lib_op; /* Library internal callback for each message */
-} H5O_mesg_operator_t;
+/* User data for iteration when converting attributes to dense storage */
+typedef struct {
+ H5F_t *f; /* Pointer to file for insertion */
+ hid_t dxpl_id; /* DXPL during iteration */
+} H5O_iter_to_dense_t;
/********************/
@@ -100,7 +97,7 @@ typedef union {
static herr_t H5O_msg_write_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type,
unsigned overwrite, unsigned mesg_flags, unsigned update_flags,
- const void *mesg, unsigned *oh_flags_ptr, hid_t dxpl_id);
+ const void *mesg, hid_t dxpl_id, unsigned *oh_flags_ptr);
static herr_t H5O_msg_reset_real(const H5O_msg_class_t *type, void *native);
static void *H5O_msg_copy_real(const H5O_msg_class_t *type, const void *mesg,
void *dst);
@@ -108,8 +105,6 @@ static herr_t H5O_msg_remove_real(const H5O_loc_t *loc, const H5O_msg_class_t *t
int sequence, H5O_operator_t op, void *op_data, hbool_t adj_link, hid_t dxpl_id);
static herr_t H5O_msg_remove_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
unsigned sequence, unsigned *oh_flags_ptr, void *_udata/*in,out*/);
-static herr_t H5O_msg_iterate_real(const H5O_loc_t *loc, const H5O_msg_class_t *type,
- H5AC_protect_t prot, hbool_t internal, H5O_mesg_operator_t op, void *op_data, hid_t dxpl_id);
static unsigned H5O_new_mesg(H5F_t *f, H5O_t *oh, unsigned *flags,
const H5O_msg_class_t *orig_type, const void *orig_mesg, H5O_shared_t *sh_mesg,
const H5O_msg_class_t **new_type, const void **new_mesg, hid_t dxpl_id,
@@ -188,6 +183,49 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5O_msg_attr_to_dense_cb
+ *
+ * Purpose: Object header iterator callback routine to convert compact
+ * attributes to dense attributes
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 4 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_msg_attr_to_dense_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
+ unsigned UNUSED sequence, unsigned *oh_flags_ptr, void *_udata/*in,out*/)
+{
+ H5O_iter_to_dense_t *udata = (H5O_iter_to_dense_t *)_udata; /* Operator user data */
+ herr_t ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_msg_attr_to_dense_cb)
+
+ /* check args */
+ HDassert(oh);
+ HDassert(mesg);
+
+ /* Insert attribute into dense storage */
+ if(H5A_dense_insert(udata->f, udata->dxpl_id, oh, mesg->flags, mesg->native) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, H5_ITER_ERROR, "unable to add to dense storage")
+
+ /* Convert message into a null message */
+ if(H5O_release_mesg(udata->f, udata->dxpl_id, oh, mesg, TRUE, FALSE) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, H5_ITER_ERROR, "unable to convert into null message")
+
+ /* Indicate that the object header was modified */
+ *oh_flags_ptr |= H5AC__DIRTIED_FLAG;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_msg_attr_to_dense_cb() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5O_msg_append
*
* Purpose: Simplified version of H5O_msg_create, used when creating a new
@@ -213,8 +251,9 @@ H5O_msg_append(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id,
const H5O_msg_class_t *new_type; /* Actual H5O class type for the ID */
const void *new_mesg; /* Actual message to write */
const H5O_msg_class_t *type; /* Original H5O class type for the ID */
- H5O_shared_t sh_mesg; /* Shared object header info */
- unsigned idx; /* Index of message to modify */
+ H5O_shared_t sh_mesg; /* Shared object header info */
+ unsigned idx; /* Index of message to modify */
+ hbool_t new_format_attr; /* Whether this message is an attribute in a new-format header */
htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */
herr_t ret_value = SUCCEED; /* Return value */
@@ -237,23 +276,64 @@ H5O_msg_append(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id,
else if(shared_mesg < 0)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "error determining if message should be shared")
- /* If the message added is an attribute, increment count */
- if(H5O_ATTR_ID == type_id && oh->version > H5O_VERSION_1) {
+ /* Set the flag for an attribute in a new format header */
+ if(H5O_ATTR_ID == type_id && oh->version > H5O_VERSION_1)
+ new_format_attr = TRUE;
+ else
+ new_format_attr = FALSE;
+
+ /* If the message added is an attribute, check for dense storage */
+ if(new_format_attr) {
#ifdef QAK
HDfprintf(stderr, "%s: adding attribute to new-style object header\n", FUNC);
+HDfprintf(stderr, "%s: oh->nattrs = %Hu\n", FUNC, oh->nattrs);
+HDfprintf(stderr, "%s: oh->max_compact = %u\n", FUNC, oh->max_compact);
+HDfprintf(stderr, "%s: oh->min_dense = %u\n", FUNC, oh->min_dense);
+#endif /* QAK */
+ /* Check for switching to "dense" attribute storage */
+ if(oh->nattrs == oh->max_compact && !H5F_addr_defined(oh->attr_fheap_addr)) {
+ H5O_iter_to_dense_t udata; /* User data for callback */
+ H5O_mesg_operator_t op; /* Wrapper for operator */
+#ifdef QAK
+HDfprintf(stderr, "%s: converting attributes to dense storage\n", FUNC);
#endif /* QAK */
+
+ /* Create dense storage for attributes */
+ if(H5A_dense_create(f, 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 = f;
+ udata.dxpl_id = dxpl_id;
+
+ /* Iterate over existing attributes, moving them to dense storage */
+ op.lib_op = H5O_msg_attr_to_dense_cb;
+ if(H5O_msg_iterate_real(f, oh, H5O_MSG_ATTR, TRUE, op, &udata, dxpl_id, oh_flags_ptr) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCONVERT, FAIL, "error converting attributes to dense storage")
+ } /* end if */
} /* end if */
- /* Create a new message */
- if((idx = H5O_new_mesg(f, oh, &mesg_flags, type, mesg, &sh_mesg, &new_type, &new_mesg, dxpl_id, oh_flags_ptr)) == UFAIL)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create new message")
+ /* Check for storing attribute with dense storage */
+ if(new_format_attr && H5F_addr_defined(oh->attr_fheap_addr)) {
+ /* Insert attribute into dense storage */
+#ifdef QAK
+HDfprintf(stderr, "%s: inserting attribute to dense storage\n", FUNC);
+#endif /* QAK */
+ if(H5A_dense_insert(f, dxpl_id, oh, mesg_flags, mesg) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "unable to add to dense storage")
+ } /* end if */
+ else {
+ /* Create a new message */
+ if((idx = H5O_new_mesg(f, oh, &mesg_flags, type, mesg, &sh_mesg, &new_type, &new_mesg, dxpl_id, oh_flags_ptr)) == UFAIL)
+ HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "unable to create new message")
- /* Write the information to the message */
- if(H5O_write_mesg(f, dxpl_id, oh, idx, new_type, new_mesg, mesg_flags, update_flags, oh_flags_ptr) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to write message")
+ /* Write the information to the message */
+ if(H5O_write_mesg(f, dxpl_id, oh, idx, new_type, new_mesg, mesg_flags, update_flags, oh_flags_ptr) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to write message")
+ } /* end else */
/* If the message added is an attribute, increment count */
- if(H5O_ATTR_ID == type_id && oh->version > H5O_VERSION_1)
+ if(new_format_attr)
oh->nattrs++;
#ifdef H5O_DEBUG
H5O_assert(oh);
@@ -307,6 +387,7 @@ H5O_msg_write(H5O_loc_t *loc, unsigned type_id, unsigned overwrite,
HDassert(loc);
HDassert(loc->file);
HDassert(H5F_addr_defined(loc->addr));
+ HDassert(H5O_ATTR_ID != type_id); /* Attributes are modified in another routine */
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
HDassert(type);
@@ -329,8 +410,8 @@ H5O_msg_write(H5O_loc_t *loc, unsigned type_id, unsigned overwrite,
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
/* Call the "real" modify routine */
- if(H5O_msg_write_real(loc->file, oh, type, overwrite, mesg_flags, update_flags, mesg, &oh_flags, dxpl_id) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header message")
+ if(H5O_msg_write_real(loc->file, oh, type, overwrite, mesg_flags, update_flags, mesg, dxpl_id, &oh_flags) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header message")
done:
if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
@@ -368,12 +449,12 @@ done:
static herr_t
H5O_msg_write_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type,
unsigned overwrite, unsigned mesg_flags, unsigned update_flags,
- const void *mesg, unsigned *oh_flags_ptr, hid_t dxpl_id)
+ const void *mesg, hid_t dxpl_id, unsigned *oh_flags_ptr)
{
int sequence; /* Sequence # of message type to modify */
unsigned idx; /* Index of message to modify */
H5O_mesg_t *idx_msg; /* Pointer to message to modify */
- H5O_shared_t sh_mesg;
+ H5O_shared_t sh_mesg; /* Shared message to store */
const H5O_msg_class_t *write_type = type; /* Type of message to be written */
const void *write_mesg = mesg; /* Actual message being written */
herr_t ret_value = SUCCEED; /* Return value */
@@ -409,12 +490,11 @@ H5O_msg_write_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type,
* First, make sure it's not a committed message; these can't ever
* be modified.
*/
- if(((H5O_shared_t *)oh->mesg[idx].native)->flags & H5O_COMMITTED_FLAG)
- HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to modify committed message")
+ HDassert(!(((H5O_shared_t *)oh->mesg[idx].native)->flags & H5O_COMMITTED_FLAG));
/* Remove the old message from the SOHM index */
if(H5SM_try_delete(f, dxpl_id, oh->mesg[idx].type->id, oh->mesg[idx].native) < 0)
- HGOTO_ERROR (H5E_OHDR, H5E_CANTFREE, FAIL, "unable to delete message from SOHM table")
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to delete message from SOHM table")
/* Now this message is no longer shared and we can safely overwrite it.
* We need to make sure that the message we're writing is shared,
@@ -429,7 +509,7 @@ H5O_msg_write_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type,
/* Extract shared message info from current message */
if(H5O_msg_get_share(type->id, mesg, &sh_mesg) < 0)
- HGOTO_ERROR (H5E_OHDR, H5E_BADMESG, FAIL, "can't get shared message")
+ HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't get shared message")
/* Instead of writing the original message, write a shared message */
write_type = H5O_MSG_SHARED;
@@ -472,7 +552,8 @@ done:
*-------------------------------------------------------------------------
*/
void *
-H5O_msg_read(const H5O_loc_t *loc, unsigned type_id, int sequence, void *mesg, hid_t dxpl_id)
+H5O_msg_read(const H5O_loc_t *loc, unsigned type_id, int sequence, void *mesg,
+ hid_t dxpl_id)
{
H5O_t *oh = NULL; /* Object header to use */
void *ret_value; /* Return value */
@@ -575,7 +656,7 @@ H5O_msg_read_real(H5F_t *f, H5O_t *oh, unsigned type_id, int sequence,
* the raw message) so we must copy the native message before
* returning.
*/
- if(NULL == (ret_value = (type->copy)(oh->mesg[idx].native, mesg, 0)))
+ if(NULL == (ret_value = (type->copy)(oh->mesg[idx].native, mesg)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to copy message to user space")
} /* end else */
@@ -823,7 +904,7 @@ H5O_msg_copy_real(const H5O_msg_class_t *type, const void *mesg, void *dst)
HDassert(type->copy);
if(mesg)
- if(NULL == (ret_value = (type->copy)(mesg, dst, 0)))
+ if(NULL == (ret_value = (type->copy)(mesg, dst)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to copy object header message")
done:
@@ -847,7 +928,7 @@ done:
*-------------------------------------------------------------------------
*/
int
-H5O_msg_count(H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id)
+H5O_msg_count(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id)
{
H5O_t *oh = NULL; /* Object header to operate on */
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
@@ -1088,7 +1169,7 @@ static herr_t
H5O_msg_remove_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, unsigned sequence,
unsigned *oh_flags_ptr, void *_udata/*in,out*/)
{
- H5O_iter_ud1_t *udata = (H5O_iter_ud1_t *)_udata; /* Operator user data */
+ H5O_iter_rm_t *udata = (H5O_iter_rm_t *)_udata; /* Operator user data */
htri_t try_remove = FALSE; /* Whether to try removing a message */
herr_t ret_value = H5_ITER_CONT; /* Return value */
@@ -1106,7 +1187,7 @@ H5O_msg_remove_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, unsigned sequence,
else {
/* If there's no callback routine, does the sequence # match? */
if((int)sequence == udata->sequence || H5O_ALL == udata->sequence)
- try_remove = H5_ITER_STOP;
+ try_remove = TRUE;
} /* end else */
/* Try removing the message, if indicated */
@@ -1164,9 +1245,11 @@ static herr_t
H5O_msg_remove_real(const H5O_loc_t *loc, const H5O_msg_class_t *type, int sequence,
H5O_operator_t app_op, void *op_data, hbool_t adj_link, hid_t dxpl_id)
{
- H5O_iter_ud1_t udata; /* User data for iterator */
+ H5O_t *oh = NULL; /* Pointer to actual object header */
+ unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Start iteration with no flags set on object header */
+ H5O_iter_rm_t udata; /* User data for iterator */
H5O_mesg_operator_t op; /* Wrapper for operator */
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_msg_remove_real)
@@ -1188,16 +1271,23 @@ H5O_msg_remove_real(const H5O_loc_t *loc, const H5O_msg_class_t *type, int seque
udata.op_data = op_data;
udata.adj_link = adj_link;
+ /* Protect the object header to iterate over */
+ if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
+
/* Iterate over the messages, deleting appropriate one(s) */
op.lib_op = H5O_msg_remove_cb;
- if(H5O_msg_iterate_real(loc, type, H5AC_WRITE, TRUE, op, &udata, dxpl_id) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "error iterating over messages")
+ if(H5O_msg_iterate_real(loc->file, oh, type, TRUE, op, &udata, dxpl_id, &oh_flags) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "error iterating over messages")
/* Fail if we tried to remove any constant messages */
if(udata.nfailed)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to remove constant message(s)")
done:
+ if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_msg_remove_real() */
@@ -1217,7 +1307,7 @@ done:
*
* Description:
* This function interates over the object headers of an object
- * specified with 'ent' of type 'type_id'. For each object header of the
+ * specified with 'loc' of type 'type_id'. For each object header of the
* object, the 'op_data' and some additional information (specified below) are
* passed to the 'op' function.
* The operation receives a pointer to the object header message for the
@@ -1237,6 +1327,8 @@ herr_t
H5O_msg_iterate(const H5O_loc_t *loc, unsigned type_id, H5O_operator_t app_op,
void *op_data, hid_t dxpl_id)
{
+ H5O_t *oh = NULL; /* Pointer to actual object header */
+ unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Start iteration with no flags set on object header */
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
H5O_mesg_operator_t op; /* Wrapper for operator */
herr_t ret_value; /* Return value */
@@ -1251,12 +1343,19 @@ H5O_msg_iterate(const H5O_loc_t *loc, unsigned type_id, H5O_operator_t app_op,
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
HDassert(type);
+ /* Protect the object header to iterate over */
+ if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
+
/* Call the "real" iterate routine */
op.app_op = app_op;
- if((ret_value = H5O_msg_iterate_real(loc, type, H5AC_READ, FALSE, op, op_data, dxpl_id)) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "unable to iterate over object header messages")
+ if((ret_value = H5O_msg_iterate_real(loc->file, oh, type, FALSE, op, op_data, dxpl_id, &oh_flags)) < 0)
+ HERROR(H5E_OHDR, H5E_BADITER, "unable to iterate over object header messages");
done:
+ if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_msg_iterate() */
@@ -1292,53 +1391,44 @@ done:
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5O_msg_iterate_real(const H5O_loc_t *loc, const H5O_msg_class_t *type, H5AC_protect_t prot,
- hbool_t internal, H5O_mesg_operator_t op, void *op_data, hid_t dxpl_id)
+herr_t
+H5O_msg_iterate_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type,
+ hbool_t internal, H5O_mesg_operator_t op, void *op_data, hid_t dxpl_id,
+ unsigned *oh_flags_ptr)
{
- H5O_t *oh = NULL; /* Pointer to actual object header */
- unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Start iteration with no flags set on object header */
unsigned idx; /* Absolute index of current message in all messages */
unsigned sequence; /* Relative index of current message for messages of type */
H5O_mesg_t *idx_msg; /* Pointer to current message */
void *native_mesg; /* Native, readable message */
hbool_t native_mesg_alloc = FALSE; /* True if native_mesg needs to be freed */
-
herr_t ret_value = H5_ITER_CONT; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_msg_iterate_real)
/* check args */
- HDassert(loc);
- HDassert(loc->file);
- HDassert(H5F_addr_defined(loc->addr));
+ HDassert(f);
+ HDassert(oh);
HDassert(type);
HDassert(op.app_op);
-
- /* Protect the object header to iterate over */
- if (NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, prot)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
+ HDassert(oh_flags_ptr);
/* Iterate over messages */
for(sequence = 0, idx = 0, idx_msg = &oh->mesg[0]; idx < oh->nmesgs && !ret_value; idx++, idx_msg++) {
if(type->id == idx_msg->type->id) {
-
- /*
- * Decode the message if necessary.
- */
- H5O_LOAD_NATIVE(loc->file, dxpl_id, idx_msg, FAIL)
+ /* Decode the message if necessary. */
+ H5O_LOAD_NATIVE(f, dxpl_id, idx_msg, FAIL)
/* Check for making an "internal" (i.e. within the H5O package) callback */
if(internal) {
/* Call the "internal" iterator callback */
- if((ret_value = (op.lib_op)(oh, idx_msg, sequence, &oh_flags, op_data)) != 0)
+ if((ret_value = (op.lib_op)(oh, idx_msg, sequence, oh_flags_ptr, op_data)) != 0)
break;
} /* end if */
else {
/* If the message is shared, get the real message it points to */
/* JAMES: test */
if(idx_msg->flags & H5O_MSG_FLAG_SHARED) {
- if(NULL == (native_mesg = H5O_shared_read(loc->file, dxpl_id,
+ if(NULL == (native_mesg = H5O_shared_read(f, dxpl_id,
idx_msg->native, idx_msg->type, NULL)))
HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "unable to read shared message")
native_mesg_alloc = TRUE;
@@ -1371,27 +1461,18 @@ done:
if(native_mesg_alloc)
H5O_msg_free(idx_msg->type->id, native_mesg);
- /* Object header cleanup */
- if(oh) {
- /* Check if object header was modified */
- if(oh_flags & H5AC__DIRTIED_FLAG) {
- /* Shouldn't be able to modify object header if we don't have write access */
- HDassert(prot == H5AC_WRITE);
-
- /* Try to condense object header info */
- /* (Since this routine is invoked when a message is removed from
- * an object header, the header will be condensed after each
- * message removal)
- */
- if(H5O_condense_header(loc->file, oh, dxpl_id) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTPACK, FAIL, "can't pack object header")
-
- if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE, &oh_flags) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
- } /* end if */
+ /* Check if object message was modified */
+ if(*oh_flags_ptr & H5AC__DIRTIED_FLAG) {
+ /* Try to condense object header info */
+ /* (Since this routine is used to remove messages from an
+ * object header, the header will be condensed after each
+ * message removal)
+ */
+ if(H5O_condense_header(f, oh, dxpl_id) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTPACK, FAIL, "can't pack object header")
- if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
+ if(H5O_touch_oh(f, dxpl_id, oh, FALSE, oh_flags_ptr) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -1893,18 +1974,17 @@ H5O_write_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx,
idx_msg = &oh->mesg[idx];
/* Reset existing native information */
- if(!(update_flags & H5O_UPDATE_DATA_ONLY))
- H5O_msg_reset_real(type, idx_msg->native);
+ H5O_msg_reset_real(type, idx_msg->native);
/* Copy the native value for the message */
- if(NULL == (idx_msg->native = (type->copy)(mesg, idx_msg->native, update_flags)))
+ if(NULL == (idx_msg->native = (type->copy)(mesg, idx_msg->native)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy message to object header")
/* Update the message flags and mark the message as modified */
idx_msg->flags = mesg_flags;
idx_msg->dirty = TRUE;
- /* Update the modification time message if any */
+ /* Update the modification time, if requested */
if(update_flags & H5O_UPDATE_TIME)
if(H5O_touch_oh(f, dxpl_id, oh, FALSE, oh_flags_ptr) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
@@ -1966,7 +2046,7 @@ H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_mesg_t *mesg, hbool_t adj_link)
{
/* The native message here is actually a shared message. */
if(H5SM_try_delete(f, dxpl_id, mesg->type->id, mesg->native) < 0)
- HGOTO_ERROR (H5E_OHDR, H5E_CANTFREE, FAIL, "unable to delete message from SOHM table")
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to delete message from SOHM table")
}
if((type->del)(f, dxpl_id, mesg->native, adj_link) < 0)
diff --git a/src/H5Omtime.c b/src/H5Omtime.c
index f9c1b68..7b9c4fd 100644
--- a/src/H5Omtime.c
+++ b/src/H5Omtime.c
@@ -38,7 +38,7 @@ static size_t H5O_mtime_new_size(const H5F_t *f, const void *_mesg);
static void *H5O_mtime_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p);
static herr_t H5O_mtime_encode(H5F_t *f, uint8_t *p, const void *_mesg);
-static void *H5O_mtime_copy(const void *_mesg, void *_dest, unsigned update_flags);
+static void *H5O_mtime_copy(const void *_mesg, void *_dest);
static size_t H5O_mtime_size(const H5F_t *f, const void *_mesg);
static herr_t H5O_mtime_reset(void *_mesg);
static herr_t H5O_mtime_free(void *_mesg);
@@ -386,7 +386,7 @@ H5O_mtime_encode(H5F_t UNUSED *f, uint8_t *p, const void *_mesg)
*-------------------------------------------------------------------------
*/
static void *
-H5O_mtime_copy(const void *_mesg, void *_dest, unsigned UNUSED update_flags)
+H5O_mtime_copy(const void *_mesg, void *_dest)
{
const time_t *mesg = (const time_t *) _mesg;
time_t *dest = (time_t *) _dest;
diff --git a/src/H5Oname.c b/src/H5Oname.c
index 146ef8a..fc1aa21 100644
--- a/src/H5Oname.c
+++ b/src/H5Oname.c
@@ -36,7 +36,7 @@
/* PRIVATE PROTOTYPES */
static void *H5O_name_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p);
static herr_t H5O_name_encode(H5F_t *f, uint8_t *p, const void *_mesg);
-static void *H5O_name_copy(const void *_mesg, void *_dest, unsigned update_flags);
+static void *H5O_name_copy(const void *_mesg, void *_dest);
static size_t H5O_name_size(const H5F_t *f, const void *_mesg);
static herr_t H5O_name_reset(void *_mesg);
static herr_t H5O_name_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream,
@@ -167,7 +167,7 @@ H5O_name_encode(H5F_t UNUSED *f, uint8_t *p, const void *_mesg)
*-------------------------------------------------------------------------
*/
static void *
-H5O_name_copy(const void *_mesg, void *_dest, unsigned UNUSED update_flags)
+H5O_name_copy(const void *_mesg, void *_dest)
{
const H5O_name_t *mesg = (const H5O_name_t *) _mesg;
H5O_name_t *dest = (H5O_name_t *) _dest;
diff --git a/src/H5Opkg.h b/src/H5Opkg.h
index 55c31f3..f3a2df0 100644
--- a/src/H5Opkg.h
+++ b/src/H5Opkg.h
@@ -151,13 +151,14 @@
#define H5O_SIZEOF_CHKSUM_OH(O) \
H5O_SIZEOF_CHKSUM_VERS((O)->version)
+
struct H5O_msg_class_t {
unsigned id; /*message type ID on disk */
const char *name; /*for debugging */
size_t native_size; /*size of native message */
void *(*decode)(H5F_t*, hid_t, const uint8_t*);
herr_t (*encode)(H5F_t*, uint8_t*, const void*);
- void *(*copy)(const void*, void*, unsigned); /*copy native value */
+ void *(*copy)(const void *, void *); /*copy native value */
size_t (*raw_size)(const H5F_t*, const void*);/*sizeof encoded message */
herr_t (*reset)(void *); /*free nested data structs */
herr_t (*free)(void *); /*free main data struct */
@@ -253,6 +254,18 @@ typedef struct H5O_addr_map_t {
hsize_t inc_ref_count; /* Number of deferred increments to reference count */
} H5O_addr_map_t;
+
+/* Typedef for "internal library" iteration operations */
+typedef herr_t (*H5O_lib_operator_t)(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
+ unsigned sequence, unsigned *oh_flags_ptr/*out*/, void *operator_data/*in,out*/);
+
+/* Some syntactic sugar to make the compiler happy with two different kinds of iterator callbacks */
+typedef union {
+ H5O_operator_t app_op; /* Application callback for each message */
+ H5O_lib_operator_t lib_op; /* Library internal callback for each message */
+} H5O_mesg_operator_t;
+
+
/* H5O inherits cache-like properties from H5AC */
H5_DLLVAR const H5AC_class_t H5AC_OHDR[1];
@@ -387,6 +400,9 @@ H5_DLL htri_t H5O_msg_exists_oh(struct H5O_t *oh, unsigned type_id, int sequence
H5_DLL void * H5O_msg_copy_file(const H5O_msg_class_t *copy_type,
const H5O_msg_class_t *mesg_type, H5F_t *file_src, void *mesg_src,
H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata);
+H5_DLL herr_t H5O_msg_iterate_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type,
+ hbool_t internal, H5O_mesg_operator_t op, void *op_data, hid_t dxpl_id,
+ unsigned *oh_flags_ptr);
/* Object header allocation routines */
H5_DLL unsigned H5O_alloc(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
@@ -395,18 +411,26 @@ H5_DLL herr_t H5O_condense_header(H5F_t *f, H5O_t *oh, hid_t dxpl_id);
H5_DLL herr_t H5O_release_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
H5O_mesg_t *mesg, hbool_t delete_mesg, hbool_t adj_link);
-/* Object header debugging routines */
-#ifdef H5O_DEBUG
-H5_DLL herr_t H5O_assert(const H5O_t *oh);
-#endif /* H5O_DEBUG */
-H5_DLL herr_t H5O_debug_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, haddr_t addr, FILE *stream, int indent, int fwidth);
-
/* Shared object operators */
H5_DLL void * H5O_shared_read(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *shared,
const H5O_msg_class_t *type, void *mesg);
+/* These functions operate on object locations */
+H5_DLL H5O_loc_t *H5O_get_loc(hid_t id);
+
/* Useful metadata cache callbacks */
H5_DLL herr_t H5O_dest(H5F_t *f, H5O_t *oh);
+/* Testing functions */
+#ifdef H5O_TESTING
+H5_DLL htri_t H5O_is_attr_dense_test(hid_t oid);
+#endif /* H5O_TESTING */
+
+/* Object header debugging routines */
+#ifdef H5O_DEBUG
+H5_DLL herr_t H5O_assert(const H5O_t *oh);
+#endif /* H5O_DEBUG */
+H5_DLL herr_t H5O_debug_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, haddr_t addr, FILE *stream, int indent, int fwidth);
+
#endif /* _H5Opkg_H */
diff --git a/src/H5Opline.c b/src/H5Opline.c
index 0c7f754..5756aab 100644
--- a/src/H5Opline.c
+++ b/src/H5Opline.c
@@ -31,7 +31,7 @@
/* PRIVATE PROTOTYPES */
static herr_t H5O_pline_encode(H5F_t *f, uint8_t *p, const void *mesg);
static void *H5O_pline_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p);
-static void *H5O_pline_copy(const void *_mesg, void *_dest, unsigned update_flags);
+static void *H5O_pline_copy(const void *_mesg, void *_dest);
static size_t H5O_pline_size(const H5F_t *f, const void *_mesg);
static herr_t H5O_pline_reset(void *_mesg);
static herr_t H5O_pline_free(void *_mesg);
@@ -334,7 +334,7 @@ H5O_pline_encode(H5F_t UNUSED *f, uint8_t *p/*out*/, const void *mesg)
*-------------------------------------------------------------------------
*/
static void *
-H5O_pline_copy(const void *_src, void *_dst/*out*/, unsigned UNUSED update_flags)
+H5O_pline_copy(const void *_src, void *_dst/*out*/)
{
const H5O_pline_t *src = (const H5O_pline_t *)_src; /* Source pipeline message */
H5O_pline_t *dst = (H5O_pline_t *)_dst; /* Destination pipeline message */
@@ -586,7 +586,7 @@ H5O_pline_pre_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *ty
* the object copying process.
*/
if(udata)
- if(NULL == (udata->src_pline = H5O_pline_copy(pline_src, NULL, 0)))
+ if(NULL == (udata->src_pline = H5O_pline_copy(pline_src, NULL)))
HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, FAIL, "unable to copy")
done:
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 2248962..568a6ee 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -31,6 +31,7 @@
#include "H5Opublic.h" /* Object header functions */
/* Public headers needed by this file */
+#include "H5Apublic.h" /* Attributes */
#include "H5Dpublic.h" /* Dataset functions */
#include "H5Lpublic.h" /* Link functions */
#include "H5Spublic.h" /* Dataspace functions */
@@ -69,13 +70,11 @@ typedef uint64_t H5SM_fheap_id_t;
/* Flags needed when encoding messages */
#define H5O_MSG_FLAG_CONSTANT 0x01u
#define H5O_MSG_FLAG_SHARED 0x02u
-#define H5O_MSG_FLAG_SOHM 0x04u
-#define H5O_MSG_FLAG_DONTSOHM 0x08u
-#define H5O_MSG_FLAG_BITS (H5O_MSG_FLAG_CONSTANT|H5O_MSG_FLAG_SHARED|H5O_MSG_FLAG_SOHM|H5O_MSG_FLAG_DONTSOHM)
+#define H5O_MSG_FLAG_DONTSHARE 0x04u
+#define H5O_MSG_FLAG_BITS (H5O_MSG_FLAG_CONSTANT|H5O_MSG_FLAG_SHARED|H5O_MSG_FLAG_DONTSHARE)
/* Flags for updating messages */
#define H5O_UPDATE_TIME 0x01u
-#define H5O_UPDATE_DATA_ONLY 0x02u
/* Hash value constants */
/* JAMES: undefined hash value may not be great */
@@ -376,6 +375,7 @@ typedef herr_t (*H5O_operator_t)(const void *mesg/*in*/, unsigned idx,
struct H5P_genplist_t;
struct H5SL_t;
struct H5O_t;
+struct H5A_t;
/* Object header routines */
H5_DLL herr_t H5O_init(void);
@@ -413,7 +413,7 @@ H5_DLL void *H5O_msg_read(const H5O_loc_t *loc, unsigned type_id, int sequence,
H5_DLL herr_t H5O_msg_reset(unsigned type_id, void *native);
H5_DLL void *H5O_msg_free(unsigned type_id, void *mesg);
H5_DLL void *H5O_msg_copy(unsigned type_id, const void *mesg, void *dst);
-H5_DLL int H5O_msg_count(H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id);
+H5_DLL int H5O_msg_count(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id);
H5_DLL htri_t H5O_msg_exists(H5O_loc_t *loc, unsigned type_id, int sequence,
hid_t dxpl_id);
H5_DLL herr_t H5O_msg_remove(H5O_loc_t *loc, unsigned type_id, int sequence,
@@ -445,9 +445,7 @@ H5_DLL herr_t H5O_debug_id(unsigned type_id, H5F_t *f, hid_t dxpl_id, const void
H5_DLL herr_t H5O_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent,
int fwidth);
-/*
- * These functions operate on object locations
- */
+/* These functions operate on object locations */
H5_DLL herr_t H5O_loc_reset(H5O_loc_t *loc);
H5_DLL herr_t H5O_loc_copy(H5O_loc_t *dst, const H5O_loc_t *src, H5_copy_depth_t depth);
H5_DLL herr_t H5O_loc_hold_file(H5O_loc_t *loc);
@@ -465,5 +463,13 @@ H5_DLL herr_t H5O_fill_convert(void *_fill, H5T_t *type, hid_t dxpl_id);
/* Link operators */
H5_DLL herr_t H5O_link_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link);
+/* Attribute operations */
+H5_DLL herr_t H5O_attr_write(const H5O_loc_t *loc, hid_t dxpl_id,
+ struct 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);
+
#endif /* _H5Oprivate_H */
diff --git a/src/H5Osdspace.c b/src/H5Osdspace.c
index 7287f50..d691ca5 100644
--- a/src/H5Osdspace.c
+++ b/src/H5Osdspace.c
@@ -27,7 +27,7 @@
/* PRIVATE PROTOTYPES */
static void *H5O_sdspace_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p);
static herr_t H5O_sdspace_encode(H5F_t *f, uint8_t *p, const void *_mesg);
-static void *H5O_sdspace_copy(const void *_mesg, void *_dest, unsigned update_flags);
+static void *H5O_sdspace_copy(const void *_mesg, void *_dest);
static size_t H5O_sdspace_size(const H5F_t *f, const void *_mesg);
static herr_t H5O_sdspace_reset(void *_mesg);
static herr_t H5O_sdspace_free (void *_mesg);
@@ -317,7 +317,7 @@ H5O_sdspace_encode(H5F_t *f, uint8_t *p, const void *_mesg)
--------------------------------------------------------------------------*/
static void *
-H5O_sdspace_copy(const void *mesg, void *dest, unsigned UNUSED update_flags)
+H5O_sdspace_copy(const void *mesg, void *dest)
{
const H5S_extent_t *src = (const H5S_extent_t *) mesg;
H5S_extent_t *dst = (H5S_extent_t *) dest;
diff --git a/src/H5Oshared.c b/src/H5Oshared.c
index 18d67b7..f5fda9b 100644
--- a/src/H5Oshared.c
+++ b/src/H5Oshared.c
@@ -40,7 +40,7 @@
static void *H5O_shared_decode(H5F_t*, hid_t dxpl_id, const uint8_t*);
static herr_t H5O_shared_encode(H5F_t*, uint8_t*, const void*);
-static void *H5O_shared_copy(const void *_mesg, void *_dest, unsigned update_flags);
+static void *H5O_shared_copy(const void *_mesg, void *_dest);
static size_t H5O_shared_size(const H5F_t*, const void *_mesg);
static herr_t H5O_shared_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg,
hbool_t adj_link);
@@ -155,7 +155,7 @@ H5O_shared_read(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *shared,
HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "can't decode shared message.")
/* Copy this message to the user's buffer */
- if(NULL == (ret_value = (type->copy)(native_mesg, mesg, 0)))
+ if(NULL == (ret_value = (type->copy)(native_mesg, mesg)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to copy message to user space")
} /* end if */
else {
@@ -420,7 +420,7 @@ H5O_shared_encode (H5F_t *f, uint8_t *buf/*out*/, const void *_mesg)
*-------------------------------------------------------------------------
*/
static void *
-H5O_shared_copy(const void *_mesg, void *_dest, unsigned UNUSED update_flags)
+H5O_shared_copy(const void *_mesg, void *_dest)
{
const H5O_shared_t *mesg = (const H5O_shared_t *) _mesg;
H5O_shared_t *dest = (H5O_shared_t *) _dest;
diff --git a/src/H5Ostab.c b/src/H5Ostab.c
index 701667a..a9fe38d 100644
--- a/src/H5Ostab.c
+++ b/src/H5Ostab.c
@@ -39,7 +39,7 @@
/* PRIVATE PROTOTYPES */
static void *H5O_stab_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p);
static herr_t H5O_stab_encode(H5F_t *f, uint8_t *p, const void *_mesg);
-static void *H5O_stab_copy(const void *_mesg, void *_dest, unsigned update_flags);
+static void *H5O_stab_copy(const void *_mesg, void *_dest);
static size_t H5O_stab_size(const H5F_t *f, const void *_mesg);
static herr_t H5O_stab_free(void *_mesg);
static herr_t H5O_stab_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link);
@@ -179,7 +179,7 @@ H5O_stab_encode(H5F_t *f, uint8_t *p, const void *_mesg)
*-------------------------------------------------------------------------
*/
static void *
-H5O_stab_copy(const void *_mesg, void *_dest, unsigned UNUSED update_flags)
+H5O_stab_copy(const void *_mesg, void *_dest)
{
const H5O_stab_t *stab = (const H5O_stab_t *) _mesg;
H5O_stab_t *dest = (H5O_stab_t *) _dest;
diff --git a/src/H5Otest.c b/src/H5Otest.c
new file mode 100644
index 0000000..aeab284
--- /dev/null
+++ b/src/H5Otest.c
@@ -0,0 +1,122 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/* Programmer: Quincey Koziol <koziol@hdfgroup.org>
+ * Monday, December 4, 2006
+ *
+ * Purpose: Attribute testing functions.
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5O_PACKAGE /*suppress error about including H5Opkg */
+#define H5O_TESTING /*suppress warning about H5O testing funcs*/
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Opkg.h" /* Object headers */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5O_is_attr_dense_test
+ PURPOSE
+ Determine whether attributes for an object are stored "densely"
+ USAGE
+ htri_t H5O_is_dense_test(oid)
+ hid_t oid; IN: object to check
+ RETURNS
+ Non-negative TRUE/FALSE on success, negative on failure
+ DESCRIPTION
+ Checks to see if the object is storing attributes in the "dense" or
+ "compact" form.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ DO NOT USE THIS FUNCTION FOR ANYTHING EXCEPT TESTING
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+htri_t
+H5O_is_attr_dense_test(hid_t oid)
+{
+ H5O_t *oh = NULL; /* Object header */
+ H5O_loc_t *oloc; /* Pointer to object's location */
+ htri_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_is_attr_dense_test, FAIL)
+
+ /* Get object location for object */
+ if(NULL == (oloc = H5O_get_loc(oid)))
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found")
+
+ /* Get the object header */
+ if(NULL == (oh = H5AC_protect(oloc->file, H5AC_ind_dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
+
+ /* Check if dense storage is being used */
+ if(H5F_addr_defined(oh->attr_fheap_addr))
+ ret_value = TRUE;
+ else
+ ret_value = FALSE;
+
+done:
+ if(oh && H5AC_unprotect(oloc->file, H5AC_ind_dxpl_id, H5AC_OHDR, oloc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5O_is_attr_dense_test() */
+
+
diff --git a/src/H5SM.c b/src/H5SM.c
index 409c94b..c3c8d85 100755
--- a/src/H5SM.c
+++ b/src/H5SM.c
@@ -237,10 +237,9 @@ H5SM_get_index(const H5SM_master_table_t *table, unsigned type_id)
{
ssize_t x;
unsigned type_flag;
- hbool_t found = FALSE;
ssize_t ret_value = FAIL;
- FUNC_ENTER_NOAPI(H5SM_get_index, FAIL)
+ FUNC_ENTER_NOAPI_NOINIT(H5SM_get_index)
/* Translate the H5O type_id into an H5SM type flag */
switch(type_id)
@@ -267,12 +266,12 @@ H5SM_get_index(const H5SM_master_table_t *table, unsigned type_id)
/* Search the indexes until we find one that matches this flag or we've
* searched them all.
*/
- for(x=0; x<table->num_indexes && !found; ++x)
+ for(x = 0; x < table->num_indexes; ++x)
{
if(table->indexes[x].mesg_types & type_flag)
{
- found = TRUE;
ret_value = x;
+ break;
}
}
@@ -551,11 +550,11 @@ H5SM_try_share(H5F_t *f, hid_t dxpl_id, unsigned type_id, void *mesg)
/* Find the right index for this message type. If there is no such index
* then this type of message isn't shareable
*/
- H5E_BEGIN_TRY {
- index_num = H5SM_get_index(table, type_id);
- } H5E_END_TRY
- if(index_num < 0)
+ if((index_num = H5SM_get_index(table, type_id)) < 0)
+ {
+ H5E_clear_stack(NULL); /*ignore error*/
HGOTO_DONE(FALSE);
+ } /* end if */
/* If the message isn't big enough, don't bother sharing it */
if(0 == (mesg_size = H5O_msg_mesg_size(f, type_id, mesg, 0)))
@@ -579,7 +578,7 @@ H5SM_try_share(H5F_t *f, hid_t dxpl_id, unsigned type_id, void *mesg)
done:
/* Release the master SOHM table */
- if (table && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_TABLE, f->shared->sohm_addr, table, cache_flags) < 0)
+ if(table && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_TABLE, f->shared->sohm_addr, table, cache_flags) < 0)
HDONE_ERROR(H5E_CACHE, H5E_CANTRELEASE, FAIL, "unable to close SOHM master table")
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Tcommit.c b/src/H5Tcommit.c
index 2c1cf5b..58d274c 100644
--- a/src/H5Tcommit.c
+++ b/src/H5Tcommit.c
@@ -281,7 +281,7 @@ H5T_commit(H5F_t *file, H5T_t *type, hid_t dxpl_id, hid_t tcpl_id, hid_t UNUSED
*/
if(H5O_create(file, dxpl_id, dtype_size, tcpl_id, &temp_oloc) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to create datatype object header")
- if(H5O_msg_create(&temp_oloc, H5O_DTYPE_ID, H5O_MSG_FLAG_CONSTANT | H5O_MSG_FLAG_DONTSOHM, H5O_UPDATE_TIME, type, dxpl_id) < 0)
+ if(H5O_msg_create(&temp_oloc, H5O_DTYPE_ID, H5O_MSG_FLAG_CONSTANT | H5O_MSG_FLAG_DONTSHARE, H5O_UPDATE_TIME, type, dxpl_id) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to update type header message")
/* Copy the new object header's location into the datatype, taking ownership of it */
diff --git a/src/Makefile.am b/src/Makefile.am
index 099efbe..c6fe5fd 100755
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -41,7 +41,7 @@ DISTCLEANFILES=H5pubconf.h
# library sources
libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
- H5A.c H5Adeprec.c H5AC.c H5B.c H5Bcache.c \
+ H5A.c H5Abtree2.c H5Adense.c H5Adeprec.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 \
@@ -62,7 +62,8 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5Ocont.c H5Ocopy.c H5Odbg.c H5Odtype.c H5Oefl.c H5Ofill.c H5Oginfo.c \
H5Olayout.c \
H5Olinfo.c H5Olink.c H5Omessage.c H5Omtime.c \
- H5Oname.c H5Onull.c H5Opline.c H5Osdspace.c H5Oshared.c H5Ostab.c \
+ H5Oname.c H5Onull.c H5Opline.c H5Osdspace.c H5Oshared.c H5Ostab.c \
+ H5Otest.c \
H5P.c H5Pacpl.c H5Pdcpl.c H5Pdxpl.c H5Pfapl.c H5Pfcpl.c H5Pfmpl.c \
H5Pgcpl.c \
H5Plapl.c H5Plcpl.c H5Pocpl.c H5Pocpypl.c H5Pstrcpl.c H5Ptest.c \
diff --git a/src/Makefile.in b/src/Makefile.in
index 5dd5fda..92085be 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -81,7 +81,7 @@ libLTLIBRARIES_INSTALL = $(INSTALL)
LTLIBRARIES = $(lib_LTLIBRARIES)
libhdf5_la_LIBADD =
am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \
- H5timer.lo H5trace.lo H5A.lo H5Adeprec.lo H5AC.lo H5B.lo H5Bcache.lo \
+ H5timer.lo H5trace.lo H5A.lo H5Abtree2.lo H5Adense.lo H5Adeprec.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 \
@@ -102,7 +102,7 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \
H5Oattr.lo H5Obogus.lo H5Ocache.lo H5Ocont.lo H5Ocopy.lo \
H5Odbg.lo H5Odtype.lo H5Oefl.lo H5Ofill.lo H5Oginfo.lo \
H5Olayout.lo H5Olinfo.lo H5Olink.lo H5Omessage.lo H5Omtime.lo H5Oname.lo \
- H5Onull.lo H5Opline.lo H5Osdspace.lo H5Oshared.lo H5Ostab.lo \
+ H5Onull.lo H5Opline.lo H5Osdspace.lo H5Oshared.lo H5Ostab.lo H5Otest.lo \
H5P.lo H5Pacpl.lo H5Pdcpl.lo H5Pdxpl.lo H5Pfapl.lo H5Pfcpl.lo \
H5Pfmpl.lo H5Pgcpl.lo H5Plapl.lo H5Plcpl.lo H5Pocpl.lo H5Pocpypl.lo \
H5Pstrcpl.lo H5Ptest.lo H5R.lo H5RC.lo H5RS.lo H5S.lo \
@@ -397,7 +397,7 @@ DISTCLEANFILES = H5pubconf.h
# library sources
libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
- H5A.c H5Adeprec.c H5AC.c H5B.c H5Bcache.c \
+ H5A.c H5Abtree2.c H5Adense.c H5Adeprec.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 \
@@ -418,7 +418,7 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5Ocont.c H5Ocopy.c H5Odbg.c H5Odtype.c H5Oefl.c H5Ofill.c H5Oginfo.c \
H5Olayout.c \
H5Olinfo.c H5Olink.c H5Omessage.c H5Omtime.c \
- H5Oname.c H5Onull.c H5Opline.c H5Osdspace.c H5Oshared.c H5Ostab.c \
+ H5Oname.c H5Onull.c H5Opline.c H5Osdspace.c H5Oshared.c H5Ostab.c H5Otest.c \
H5P.c H5Pacpl.c H5Pdcpl.c H5Pdxpl.c H5Pfapl.c H5Pfcpl.c H5Pfmpl.c \
H5Pgcpl.c \
H5Plapl.c H5Plcpl.c H5Pocpl.c H5Pocpypl.c H5Pstrcpl.c H5Ptest.c H5R.c H5RC.c \
@@ -565,6 +565,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5A.Plo@am__quote@
+@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)/H5AC.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5B.Plo@am__quote@
@@ -678,6 +680,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Osdspace.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Oshared.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ostab.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Otest.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5P.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Pacpl.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Pdcpl.Plo@am__quote@