summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--release_docs/RELEASE.txt6
-rw-r--r--src/H5A.c304
-rw-r--r--src/H5Abtree2.c4
-rw-r--r--src/H5Adense.c32
-rw-r--r--src/H5Aint.c112
-rw-r--r--src/H5Apkg.h24
-rw-r--r--src/H5Atest.c2
-rw-r--r--src/H5Oattr.c295
-rw-r--r--src/H5Oattribute.c217
-rw-r--r--src/H5Tcompound.c2
-rw-r--r--test/dtypes.c3
-rwxr-xr-xtest/objcopy.c2
-rw-r--r--test/tattr.c779
-rw-r--r--test/testhdf5.c2
-rw-r--r--test/tsohm.c49
15 files changed, 1443 insertions, 390 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt
index fd1b34c..afa5431 100644
--- a/release_docs/RELEASE.txt
+++ b/release_docs/RELEASE.txt
@@ -99,7 +99,11 @@ Bug Fixes since HDF5-1.8.1
Library
-------
- - None
+ - when an attribute was opened twice and data was written with one of the handles,
+ the file didn't have the data. It happened because each handle had its own
+ object structure, and the empty one overwrote the data with fill value. This is
+ fixed by making some attribute information like the data be shared in the
+ attribute structure. SLU - 2008/07/07
Parallel Library
----------------
diff --git a/src/H5A.c b/src/H5A.c
index dc00135..15179b0 100644
--- a/src/H5A.c
+++ b/src/H5A.c
@@ -85,9 +85,12 @@ static herr_t H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_
/* Local Variables */
/*******************/
-/* Declare the free lists for H5A_t's */
+/* Declare the free lists of H5A_t */
H5FL_DEFINE(H5A_t);
+/* Declare the free lists for H5A_shared_t's */
+H5FL_DEFINE(H5A_shared_t);
+
/* Declare a free list to manage blocks of type conversion data */
H5FL_BLK_DEFINE(attr_buf);
@@ -392,9 +395,12 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type,
if((attr = H5FL_CALLOC(H5A_t)) == NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for attribute info")
+ if(NULL == (attr->shared = H5FL_CALLOC(H5A_shared_t)))
+ HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate shared attr structure")
+
/* If the creation property list is H5P_DEFAULT, use the default character encoding */
if(acpl_id == H5P_DEFAULT)
- attr->encoding = H5F_DEFAULT_CSET;
+ attr->shared->encoding = H5F_DEFAULT_CSET;
else {
H5P_genplist_t *ac_plist; /* ACPL Property list */
@@ -402,59 +408,59 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type,
if(NULL == (ac_plist = (H5P_genplist_t *)H5I_object(acpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
- if(H5P_get(ac_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->encoding)) < 0)
+ if(H5P_get(ac_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->shared->encoding)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get character encoding flag")
} /* end else */
/* Copy the attribute name */
- attr->name = H5MM_xstrdup(name);
+ attr->shared->name = H5MM_xstrdup(name);
/* Copy the attribute's datatype */
- attr->dt = H5T_copy(type, H5T_COPY_ALL);
+ attr->shared->dt = H5T_copy(type, H5T_COPY_ALL);
/* Mark any datatypes as being on disk now */
- if(H5T_set_loc(attr->dt, loc->oloc->file, H5T_LOC_DISK) < 0)
+ if(H5T_set_loc(attr->shared->dt, loc->oloc->file, H5T_LOC_DISK) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location")
/* Set the latest format for datatype, if requested */
if(H5F_USE_LATEST_FORMAT(loc->oloc->file))
- if(H5T_set_latest_version(attr->dt) < 0)
+ if(H5T_set_latest_version(attr->shared->dt) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set latest version of datatype")
/* Copy the dataspace for the attribute */
- attr->ds = H5S_copy(space, FALSE, TRUE);
+ attr->shared->ds = H5S_copy(space, FALSE, TRUE);
/* Set the latest format for dataspace, if requested */
if(H5F_USE_LATEST_FORMAT(loc->oloc->file))
- if(H5S_set_latest_version(attr->ds) < 0)
+ if(H5S_set_latest_version(attr->shared->ds) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set latest version of dataspace")
/* Mark it initially set to initialized */
- attr->initialized = TRUE; /*for now, set to false later*/
+ attr->shared->initialized = TRUE; /*for now, set to false later*/
/* Copy the object header information */
- if(H5O_loc_copy(&(attr->oloc), loc->oloc, H5_COPY_DEEP) < 0)
+ if(H5O_loc_copy(&(attr->shared->oloc), loc->oloc, H5_COPY_DEEP) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry")
/* Deep copy of the group hierarchy path */
if(H5G_name_copy(&(attr->path), loc->path, H5_COPY_DEEP) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy path")
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy path")
/* Check if any of the pieces should be (or are already) shared in the
* SOHM table
*/
- if(H5SM_try_share(attr->oloc.file, dxpl_id, NULL, H5O_DTYPE_ID, attr->dt, NULL) < 0)
+ if(H5SM_try_share(attr->shared->oloc.file, dxpl_id, NULL, H5O_DTYPE_ID, attr->shared->dt, NULL) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "trying to share datatype failed")
- if(H5SM_try_share(attr->oloc.file, dxpl_id, NULL, H5O_SDSPACE_ID, attr->ds, NULL) < 0)
+ if(H5SM_try_share(attr->shared->oloc.file, dxpl_id, NULL, H5O_SDSPACE_ID, attr->shared->ds, NULL) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "trying to share dataspace failed")
/* Check whether datatype is committed & increment ref count
* (to maintain ref. count incr/decr similarity with "shared message"
* type of datatype sharing)
*/
- if(H5T_committed(attr->dt)) {
+ if(H5T_committed(attr->shared->dt)) {
/* Increment the reference count on the shared datatype */
- if(H5T_link(attr->dt, 1, dxpl_id) < 0)
+ if(H5T_link(attr->shared->dt, 1, dxpl_id) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared datatype link count")
} /* end if */
@@ -462,29 +468,29 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type,
* datatype and dataspace messages themselves, or the size of the "shared"
* messages if either or both of them are shared.
*/
- attr->dt_size = H5O_msg_raw_size(attr->oloc.file, H5O_DTYPE_ID, FALSE, attr->dt);
- attr->ds_size = H5O_msg_raw_size(attr->oloc.file, H5O_SDSPACE_ID, FALSE, attr->ds);
+ attr->shared->dt_size = H5O_msg_raw_size(attr->shared->oloc.file, H5O_DTYPE_ID, FALSE, attr->shared->dt);
+ attr->shared->ds_size = H5O_msg_raw_size(attr->shared->oloc.file, H5O_SDSPACE_ID, FALSE, attr->shared->ds);
/* Get # of elements for attribute's dataspace */
- if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->ds)) < 0)
+ if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid")
H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t);
- HDassert(attr->dt_size > 0);
- HDassert(attr->ds_size > 0);
- attr->data_size = nelmts * H5T_get_size(attr->dt);
+ HDassert(attr->shared->dt_size > 0);
+ HDassert(attr->shared->ds_size > 0);
+ attr->shared->data_size = nelmts * H5T_get_size(attr->shared->dt);
/* Hold the symbol table entry (and file) open */
- if(H5O_open(&(attr->oloc)) < 0)
+ if(H5O_open(&(attr->shared->oloc)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open")
attr->obj_opened = TRUE;
/* Set the version to encode the attribute with */
- if(H5A_set_version(attr->oloc.file, attr) < 0)
+ if(H5A_set_version(attr->shared->oloc.file, attr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "unable to update attribute version")
/* Insert the attribute into the object header */
- if(H5O_attr_create(&(attr->oloc), dxpl_id, attr) < 0)
+ if(H5O_attr_create(&(attr->shared->oloc), dxpl_id, attr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to create attribute in object header")
/* Register the new attribute and get an ID for it */
@@ -492,12 +498,11 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type,
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID")
/* Now it's safe to say it's uninitialized */
- attr->initialized = FALSE;
+ attr->shared->initialized = FALSE;
done:
/* Cleanup on failure */
- if(ret_value < 0)
- if(attr && H5A_close(attr) < 0)
+ if(ret_value < 0 && attr && H5A_close(attr) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "can't close attribute")
FUNC_LEAVE_NOAPI(ret_value)
@@ -544,7 +549,7 @@ H5Aopen(hid_t loc_id, const char *attr_name, hid_t UNUSED aapl_id)
/* Read in attribute from object header */
if(NULL == (attr = H5O_attr_open_by_name(loc.oloc, attr_name, H5AC_ind_dxpl_id)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to load attribute info from object header")
- attr->initialized = TRUE;
+ attr->shared->initialized = TRUE;
/* Finish initializing attribute */
if(H5A_open_common(&loc, attr) < 0)
@@ -731,7 +736,7 @@ H5A_open_common(const H5G_loc_t *loc, H5A_t *attr)
#if defined(H5_USING_MEMCHECKER) || !defined(NDEBUG)
/* Clear object location */
- if(H5O_loc_reset(&(attr->oloc)) < 0)
+ if(H5O_loc_reset(&(attr->shared->oloc)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to reset location")
#endif /* H5_USING_MEMCHECKER */
@@ -740,15 +745,15 @@ H5A_open_common(const H5G_loc_t *loc, H5A_t *attr)
HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path")
/* Deep copy of the symbol table entry */
- if(H5O_loc_copy(&(attr->oloc), loc->oloc, H5_COPY_DEEP) < 0)
+ if(H5O_loc_copy(&(attr->shared->oloc), loc->oloc, H5_COPY_DEEP) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry")
/* Deep copy of the group hier. path */
if(H5G_name_copy(&(attr->path), loc->path, H5_COPY_DEEP) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry")
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy entry")
/* Hold the symbol table entry (and file) open */
- if(H5O_open(&(attr->oloc)) < 0)
+ if(H5O_open(&(attr->shared->oloc)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open")
attr->obj_opened = TRUE;
@@ -799,7 +804,7 @@ H5A_open_by_idx(const H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type,
/* Read in attribute from object header */
if(NULL == (attr = H5O_attr_open_by_idx(obj_loc.oloc, idx_type, order, n, dxpl_id)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to load attribute info from object header")
- attr->initialized = TRUE;
+ attr->shared->initialized = TRUE;
/* Finish initializing attribute */
if(H5A_open_common(&obj_loc, attr) < 0)
@@ -865,7 +870,7 @@ H5A_open_by_name(const H5G_loc_t *loc, const char *obj_name, const char *attr_na
/* Read in attribute from object header */
if(NULL == (attr = H5O_attr_open_by_name(obj_loc.oloc, attr_name, dxpl_id)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to load attribute info from object header")
- attr->initialized = TRUE;
+ attr->shared->initialized = TRUE;
/* Finish initializing attribute */
if(H5A_open_common(loc, attr) < 0)
@@ -969,7 +974,7 @@ H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id)
HDassert(buf);
/* Get # of elements for attribute's dataspace */
- if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->ds)) < 0)
+ if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid")
H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t);
@@ -977,17 +982,17 @@ H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id)
if(nelmts > 0) {
/* Get the memory and file datatype sizes */
src_type_size = H5T_get_size(mem_type);
- dst_type_size = H5T_get_size(attr->dt);
+ dst_type_size = H5T_get_size(attr->shared->dt);
/* Convert memory buffer into disk buffer */
/* Set up type conversion function */
- if(NULL == (tpath = H5T_path_find(mem_type, attr->dt, NULL, NULL, dxpl_id, FALSE)))
+ if(NULL == (tpath = H5T_path_find(mem_type, attr->shared->dt, NULL, NULL, dxpl_id, FALSE)))
HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dst datatypes")
/* Check for type conversion required */
if(!H5T_path_noop(tpath)) {
if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL))) < 0 ||
- (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->dt, H5T_COPY_ALL))) < 0)
+ (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->shared->dt, H5T_COPY_ALL))) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, FAIL, "unable to register types for conversion")
/* Get the maximum buffer size needed and allocate it */
@@ -1003,11 +1008,11 @@ H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id)
HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "datatype conversion failed")
/* Free the previous attribute data buffer, if there is one */
- if(attr->data)
- attr->data = H5FL_BLK_FREE(attr_buf, attr->data);
+ if(attr->shared->data)
+ attr->shared->data = H5FL_BLK_FREE(attr_buf, attr->shared->data);
/* Set the pointer to the attribute data to the converted information */
- attr->data = tconv_buf;
+ attr->shared->data = tconv_buf;
tconv_owned = TRUE;
} /* end if */
/* No type conversion necessary */
@@ -1015,21 +1020,21 @@ H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id)
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)))
+ if(attr->shared->data == NULL)
+ if(NULL == (attr->shared->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));
+ HDmemcpy(attr->shared->data, buf, (dst_type_size * nelmts));
} /* end else */
/* Modify the attribute in the object header */
- if(H5O_attr_write(&(attr->oloc), dxpl_id, attr) < 0)
+ if(H5O_attr_write(&(attr->shared->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 */
- attr->initialized = TRUE;
+ attr->shared->initialized = TRUE;
done:
/* Release resources */
@@ -1126,27 +1131,27 @@ H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id)
HDassert(buf);
/* Create buffer for data to store on disk */
- if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->ds)) < 0)
+ if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid")
H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t);
if(nelmts > 0) {
/* Get the memory and file datatype sizes */
- src_type_size = H5T_get_size(attr->dt);
+ src_type_size = H5T_get_size(attr->shared->dt);
dst_type_size = H5T_get_size(mem_type);
/* Check if the attribute has any data yet, if not, fill with zeroes */
- if(attr->obj_opened && !attr->initialized)
+ if(attr->obj_opened && !attr->shared->initialized)
HDmemset(buf, 0, (dst_type_size * nelmts));
else { /* Attribute exists and has a value */
/* Convert memory buffer into disk buffer */
/* Set up type conversion function */
- if(NULL == (tpath = H5T_path_find(attr->dt, mem_type, NULL, NULL, dxpl_id, FALSE)))
+ if(NULL == (tpath = H5T_path_find(attr->shared->dt, mem_type, NULL, NULL, dxpl_id, FALSE)))
HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dst datatypes")
/* Check for type conversion required */
if(!H5T_path_noop(tpath)) {
- if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->dt, H5T_COPY_ALL))) < 0 ||
+ if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->shared->dt, H5T_COPY_ALL))) < 0 ||
(dst_id = H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL))) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, FAIL, "unable to register types for conversion")
@@ -1156,7 +1161,7 @@ H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Copy the attribute data into the buffer for conversion */
- HDmemcpy(tconv_buf, attr->data, (src_type_size * nelmts));
+ HDmemcpy(tconv_buf, attr->shared->data, (src_type_size * nelmts));
/* Perform datatype conversion. */
if(H5T_convert(tpath, src_id, dst_id, nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, dxpl_id) < 0)
@@ -1170,7 +1175,7 @@ H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id)
HDassert(dst_type_size == src_type_size);
/* Copy the attribute data into the user's buffer */
- HDmemcpy(buf, attr->data, (dst_type_size * nelmts));
+ HDmemcpy(buf, attr->shared->data, (dst_type_size * nelmts));
} /* end else */
} /* end else */
} /* end if */
@@ -1221,7 +1226,7 @@ H5Aget_space(hid_t attr_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute")
/* Copy the attribute's dataspace */
- if(NULL == (ds = H5S_copy(attr->ds, FALSE, TRUE)))
+ if(NULL == (ds = H5S_copy(attr->shared->ds, FALSE, TRUE)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to copy dataspace")
/* Atomize */
@@ -1271,7 +1276,7 @@ H5Aget_type(hid_t attr_id)
* reopen the type before returning it to the user. Make the type
* read-only.
*/
- if(NULL == (dt = H5T_copy(attr->dt, H5T_COPY_REOPEN)))
+ if(NULL == (dt = H5T_copy(attr->shared->dt, H5T_COPY_REOPEN)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to copy datatype")
/* Mark any datatypes as being in memory now */
@@ -1340,7 +1345,7 @@ H5Aget_create_plist(hid_t attr_id)
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get property list")
/* Set the character encoding on the new property list */
- if(H5P_set(new_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->encoding)) < 0)
+ if(H5P_set(new_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->shared->encoding)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set character encoding")
ret_value = new_plist_id;
@@ -1374,21 +1379,53 @@ done:
ssize_t
H5Aget_name(hid_t attr_id, size_t buf_size, char *buf)
{
- H5A_t *attr; /* Attribute object for ID */
- size_t copy_len, nbytes;
+ H5A_t *my_attr; /* Attribute object for ID */
ssize_t ret_value;
FUNC_ENTER_API(H5Aget_name, FAIL)
H5TRACE3("Zs", "iz*s", attr_id, buf_size, buf);
/* check arguments */
- if(NULL == (attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR)))
+ if(NULL == (my_attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute")
if(!buf && buf_size)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid buffer")
+ /* Call private function in turn */
+ if(0 > (ret_value = H5A_get_name(my_attr, buf_size, buf)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get attribute name")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5Aget_name() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5A_get_name
+ PURPOSE
+ Private function for H5Aget_name. Gets a copy of the name for an
+ attribute
+ RETURNS
+ This function returns the length of the attribute's name (which may be
+ longer than 'buf_size') on success or negative for failure.
+ DESCRIPTION
+ This function retrieves the name of an attribute for an attribute ID.
+ Up to 'buf_size' characters are stored in 'buf' followed by a '\0' string
+ terminator. If the name of the attribute is longer than 'buf_size'-1,
+ the string terminator is stored in the last position of the buffer to
+ properly terminate the string.
+--------------------------------------------------------------------------*/
+ssize_t
+H5A_get_name(H5A_t *attr, size_t buf_size, char *buf)
+{
+ size_t copy_len, nbytes;
+ ssize_t ret_value;
+
+ FUNC_ENTER_NOAPI(H5A_get_name, FAIL)
+
/* get the real attribute length */
- nbytes = HDstrlen(attr->name);
+ nbytes = HDstrlen(attr->shared->name);
HDassert((ssize_t)nbytes >= 0); /*overflow, pretty unlikely --rpm*/
/* compute the string length which will fit into the user's buffer */
@@ -1396,7 +1433,7 @@ H5Aget_name(hid_t attr_id, size_t buf_size, char *buf)
/* Copy all/some of the name */
if(buf && copy_len > 0) {
- HDmemcpy(buf, attr->name, copy_len);
+ HDmemcpy(buf, attr->shared->name, copy_len);
/* Terminate the string */
buf[copy_len]='\0';
@@ -1406,8 +1443,8 @@ H5Aget_name(hid_t attr_id, size_t buf_size, char *buf)
ret_value = (ssize_t)nbytes;
done:
- FUNC_LEAVE_API(ret_value)
-} /* H5Aget_name() */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5A_get_name() */
/*-------------------------------------------------------------------------
@@ -1462,11 +1499,11 @@ H5Aget_name_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "can't open attribute")
/* Get the length of the name */
- ret_value = (ssize_t)HDstrlen(attr->name);
+ ret_value = (ssize_t)HDstrlen(attr->shared->name);
/* Copy the name into the user's buffer, if given */
if(name) {
- HDstrncpy(name, attr->name, MIN((size_t)(ret_value + 1), size));
+ HDstrncpy(name, attr->shared->name, MIN((size_t)(ret_value + 1), size));
if((size_t)ret_value >= size)
name[size - 1]='\0';
} /* end if */
@@ -1511,7 +1548,7 @@ H5Aget_storage_size(hid_t attr_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not an attribute")
/* Set return value */
- ret_value = attr->data_size;
+ ret_value = attr->shared->data_size;
done:
FUNC_LEAVE_API(ret_value)
@@ -1698,15 +1735,15 @@ H5A_get_info(const H5A_t *attr, H5A_info_t *ainfo)
HDassert(ainfo);
/* Set info for attribute */
- ainfo->cset = attr->encoding;
- ainfo->data_size = attr->data_size;
- if(attr->crt_idx == H5O_MAX_CRT_ORDER_IDX) {
+ ainfo->cset = attr->shared->encoding;
+ ainfo->data_size = attr->shared->data_size;
+ if(attr->shared->crt_idx == H5O_MAX_CRT_ORDER_IDX) {
ainfo->corder_valid = FALSE;
ainfo->corder = 0;
} /* end if */
else {
ainfo->corder_valid = TRUE;
- ainfo->corder = attr->crt_idx;
+ ainfo->corder = attr->shared->crt_idx;
} /* end else */
done:
@@ -2259,6 +2296,10 @@ done:
* Programmer: Robb Matzke
* Thursday, December 4, 1997
*
+ * Modification:Raymond Lu
+ * 4 June 2008
+ * Changed some attribute information to be shared.
+ *
*-------------------------------------------------------------------------
*/
H5A_t *
@@ -2275,7 +2316,7 @@ H5A_copy(H5A_t *_new_attr, const H5A_t *old_attr)
/* Allocate attribute structure */
if(_new_attr == NULL) {
- if(NULL == (new_attr = H5FL_MALLOC(H5A_t)))
+ if(NULL == (new_attr = H5FL_CALLOC(H5A_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
allocated_attr = TRUE;
} /* end if */
@@ -2283,44 +2324,20 @@ H5A_copy(H5A_t *_new_attr, const H5A_t *old_attr)
new_attr = _new_attr;
/* Copy the top level of the attribute */
- *new_attr = *old_attr;
+ new_attr->sh_loc = old_attr->sh_loc;
- /* Don't open the object header for a copy */
- new_attr->obj_opened = FALSE;
-
- /* Copy the guts of the attribute */
- if(NULL == (new_attr->name = H5MM_xstrdup(old_attr->name)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy attribute name")
- if(NULL == (new_attr->dt = H5T_copy(old_attr->dt, H5T_COPY_ALL)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy attribute datatype")
- if(NULL == (new_attr->ds = H5S_copy(old_attr->ds, FALSE, TRUE)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy attribute dataspace")
-
-#if defined(H5_USING_MEMCHECKER) || !defined(NDEBUG)
- /* Clear object location */
- if(H5O_loc_reset(&(new_attr->oloc)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to reset location")
-
- /* Clear path name */
- if(H5G_name_reset(&(new_attr->path)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to reset path")
-#endif /* H5_USING_MEMCHECKER */
-
- /* Copy the object location and group path */
- if(H5O_loc_copy(&(new_attr->oloc), &(old_attr->oloc), H5_COPY_DEEP) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "can't copy object location")
+ /* Deep copy of the group hierarchy path */
if(H5G_name_copy(&(new_attr->path), &(old_attr->path), H5_COPY_DEEP) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "can't copy path")
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy path")
- /* Copy the attribute data, if there is any */
- if(old_attr->data) {
- /* 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")
+ /* Share some attribute information */
+ new_attr->shared = old_attr->shared;
- /* Copy the attribute data */
- HDmemcpy(new_attr->data, old_attr->data, old_attr->data_size);
- } /* end if */
+ /* Increment reference count for shared object */
+ new_attr->shared->nrefs++;
+
+ /* Don't open the object header for a copy */
+ new_attr->obj_opened = FALSE;
/* Set the return value */
ret_value = new_attr;
@@ -2359,18 +2376,22 @@ H5A_free(H5A_t *attr)
HDassert(attr);
/* Free dynamicly allocated items */
- if(attr->name)
- H5MM_xfree(attr->name);
- if(attr->dt)
- if(H5T_close(attr->dt) < 0)
+ if(attr->shared->name) {
+ H5MM_xfree(attr->shared->name);
+ attr->shared->name = NULL;
+ }
+ if(attr->shared->dt) {
+ if(H5T_close(attr->shared->dt) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release datatype info")
- if(attr->ds)
- if(H5S_close(attr->ds) < 0)
+ attr->shared->dt = NULL;
+ }
+ if(attr->shared->ds) {
+ if(H5S_close(attr->shared->ds) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release dataspace info")
- if(attr->data)
- attr->data = H5FL_BLK_FREE(attr_buf, attr->data);
- if(H5G_name_free(&(attr->path)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path")
+ attr->shared->ds = NULL;
+ }
+ if(attr->shared->data)
+ attr->shared->data = H5FL_BLK_FREE(attr_buf, attr->shared->data);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -2388,41 +2409,46 @@ done:
* Monday, December 8, 1997
*
* Modifications:
- *
+ * Raymond Lu
+ * 4 June 2008
+ * Changed some attribute object information to be shared.
*-------------------------------------------------------------------------
*/
herr_t
H5A_close(H5A_t *attr)
{
+ H5O_t *oh = NULL; /* Pointer to attr's object header */
+ unsigned free_failed = FALSE;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5A_close, FAIL)
HDassert(attr);
-
- /* Check if the attribute has any data yet, if not, fill with zeroes */
- if(attr->obj_opened && !attr->initialized && attr->data_size) {
- uint8_t *tmp_buf = H5FL_BLK_CALLOC(attr_buf, attr->data_size);
- if(NULL == tmp_buf)
- HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "memory allocation failed for attribute fill-value")
-
- /* Go write the fill data to the attribute */
- if(H5A_write(attr, attr->dt, tmp_buf, H5AC_dxpl_id) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "unable to write attribute")
-
- /* Free temporary buffer */
- H5FL_BLK_FREE(attr_buf, tmp_buf);
- } /* end if */
-
- /* Free dynamicly allocated items */
- if(H5A_free(attr) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release attribute info")
+ HDassert(attr->shared>0);
/* Close the object's symbol-table entry */
- if(attr->obj_opened)
- if(H5O_close(&(attr->oloc)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release object header info")
+ if(attr->obj_opened && (H5O_close(&(attr->shared->oloc)) < 0))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release object header info")
+
+ /* Reference count can be 0. It only happens when H5A_create fails. */
+ if(1 >= attr->shared->nrefs) {
+ /* Free dynamicly allocated items */
+ if(H5A_free(attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release attribute info")
+
+ /* Destroy shared attribute struct */
+ attr->shared = H5FL_FREE(H5A_shared_t, attr->shared);
+ } else if(attr->shared->nrefs > 1) {
+ /* There are other references to the shared part of the attribute.
+ * Only decrement the reference count. */
+ --attr->shared->nrefs;
+ }
+
+ /* Free group hierarchy path */
+ if(H5G_name_free(&(attr->path)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path")
+ attr->shared = NULL;
H5FL_FREE(H5A_t, attr);
done:
@@ -2455,7 +2481,7 @@ H5A_oloc(H5A_t *attr)
HDassert(attr);
/* Set return value */
- ret_value = &(attr->oloc);
+ ret_value = &(attr->shared->oloc);
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Abtree2.c b/src/H5Abtree2.c
index b685af7..07550da 100644
--- a/src/H5Abtree2.c
+++ b/src/H5Abtree2.c
@@ -172,7 +172,7 @@ H5A_dense_fh_name_cmp(const void *obj, size_t UNUSED obj_len, void *_udata)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "can't decode attribute")
/* Compare the string values */
- udata->cmp = HDstrcmp(udata->name, attr->name);
+ udata->cmp = HDstrcmp(udata->name, attr->shared->name);
/* Check for correct attribute & callback to make */
if(udata->cmp == 0 && udata->found_op) {
@@ -181,7 +181,7 @@ H5A_dense_fh_name_cmp(const void *obj, size_t UNUSED obj_len, void *_udata)
H5SM_reconstitute(&(attr->sh_loc), udata->f, H5O_ATTR_ID, udata->record->id);
/* Set the creation order index for the attribute */
- attr->crt_idx = udata->record->corder;
+ attr->shared->crt_idx = udata->record->corder;
/* Make callback */
if((udata->found_op)(attr, &took_ownership, udata->found_op_data) < 0)
diff --git a/src/H5Adense.c b/src/H5Adense.c
index 45537be..79cd6fe 100644
--- a/src/H5Adense.c
+++ b/src/H5Adense.c
@@ -502,10 +502,10 @@ H5A_dense_insert(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, H5A_t *attr)
udata.common.dxpl_id = dxpl_id;
udata.common.fheap = fheap;
udata.common.shared_fheap = shared_fheap;
- udata.common.name = attr->name;
- udata.common.name_hash = H5_checksum_lookup3(attr->name, HDstrlen(attr->name), 0);
+ udata.common.name = attr->shared->name;
+ udata.common.name_hash = H5_checksum_lookup3(attr->shared->name, HDstrlen(attr->shared->name), 0);
H5_ASSIGN_OVERFLOW(udata.common.flags, mesg_flags, unsigned, uint8_t);
- udata.common.corder = attr->crt_idx;
+ udata.common.corder = attr->shared->crt_idx;
udata.common.found_op = NULL;
udata.common.found_op_data = NULL;
/* udata.id already set */
@@ -624,7 +624,7 @@ H5A_dense_write_bt2_cb(void *_record, void *_op_data, hbool_t *changed)
udata.name = NULL;
udata.name_hash = 0;
udata.flags = 0;
- udata.corder = op_data->attr->crt_idx;
+ udata.corder = op_data->attr->shared->crt_idx;
udata.found_op = NULL;
udata.found_op_data = NULL;
@@ -744,8 +744,8 @@ H5A_dense_write(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, H5A_t *attr)
udata.dxpl_id = dxpl_id;
udata.fheap = fheap;
udata.shared_fheap = shared_fheap;
- udata.name = attr->name;
- udata.name_hash = H5_checksum_lookup3(attr->name, HDstrlen(attr->name), 0);
+ udata.name = attr->shared->name;
+ udata.name_hash = H5_checksum_lookup3(attr->shared->name, HDstrlen(attr->shared->name), 0);
udata.flags = 0;
udata.corder = 0;
udata.found_op = NULL;
@@ -807,7 +807,7 @@ H5A_dense_copy_fh_cb(const void *obj, size_t UNUSED obj_len, void *_udata)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, FAIL, "can't decode attribute")
/* Set the creation order index for the attribute */
- udata->attr->crt_idx = udata->record->corder;
+ udata->attr->shared->crt_idx = udata->record->corder;
/* Check whether we should "reconstitute" the shared message info */
if(udata->record->flags & H5O_MSG_FLAG_SHARED)
@@ -904,8 +904,8 @@ H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *
} /* end if */
/* Change name of attribute */
- H5MM_xfree(attr_copy->name);
- attr_copy->name = H5MM_xstrdup(new_name);
+ H5MM_xfree(attr_copy->shared->name);
+ attr_copy->shared->name = H5MM_xstrdup(new_name);
/* Recompute the version to encode the attribute with */
if(H5A_set_version(f, attr_copy) < 0)
@@ -1020,14 +1020,14 @@ H5A_dense_iterate_bt2_cb(const void *_record, void *_bt2_udata)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, H5_ITER_ERROR, "unable to get attribute info")
/* Make the application callback */
- ret_value = (bt2_udata->attr_op->u.app_op2)(bt2_udata->loc_id, fh_udata.attr->name, &ainfo, bt2_udata->op_data);
+ ret_value = (bt2_udata->attr_op->u.app_op2)(bt2_udata->loc_id, fh_udata.attr->shared->name, &ainfo, bt2_udata->op_data);
break;
}
#ifndef H5_NO_DEPRECATED_SYMBOLS
case H5A_ATTR_OP_APP:
/* Make the application callback */
- ret_value = (bt2_udata->attr_op->u.app_op)(bt2_udata->loc_id, fh_udata.attr->name, bt2_udata->op_data);
+ ret_value = (bt2_udata->attr_op->u.app_op)(bt2_udata->loc_id, fh_udata.attr->shared->name, bt2_udata->op_data);
break;
#endif /* H5_NO_DEPRECATED_SYMBOLS */
@@ -1220,7 +1220,7 @@ H5A_dense_remove_bt2_cb(const void *_record, void *_udata)
/* Check for removing the link from the creation order index */
if(H5F_addr_defined(udata->corder_bt2_addr)) {
/* Set up the user data for the v2 B-tree 'record remove' callback */
- udata->common.corder = attr->crt_idx;
+ udata->common.corder = attr->shared->crt_idx;
/* Remove the record from the creation order index v2 B-tree */
if(H5B2_remove(udata->common.f, udata->common.dxpl_id, H5A_BT2_CORDER, udata->corder_bt2_addr, udata, NULL, NULL) < 0)
@@ -1400,7 +1400,7 @@ H5A_dense_remove_by_idx_bt2_cb(const void *_record, void *_bt2_udata)
other_bt2_class = H5A_BT2_CORDER;
/* Set up the user data for the v2 B-tree 'record remove' callback */
- other_bt2_udata.corder = fh_udata.attr->crt_idx;
+ other_bt2_udata.corder = fh_udata.attr->shared->crt_idx;
} /* end if */
else {
HDassert(bt2_udata->idx_type == H5_INDEX_CRT_ORDER);
@@ -1413,8 +1413,8 @@ H5A_dense_remove_by_idx_bt2_cb(const void *_record, void *_bt2_udata)
other_bt2_udata.dxpl_id = bt2_udata->dxpl_id;
other_bt2_udata.fheap = bt2_udata->fheap;
other_bt2_udata.shared_fheap = bt2_udata->shared_fheap;
- other_bt2_udata.name = fh_udata.attr->name;
- other_bt2_udata.name_hash = H5_checksum_lookup3(fh_udata.attr->name, HDstrlen(fh_udata.attr->name), 0);
+ other_bt2_udata.name = fh_udata.attr->shared->name;
+ other_bt2_udata.name_hash = H5_checksum_lookup3(fh_udata.attr->shared->name, HDstrlen(fh_udata.attr->shared->name), 0);
other_bt2_udata.found_op = NULL;
other_bt2_udata.found_op_data = NULL;
} /* end else */
@@ -1570,7 +1570,7 @@ H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified")
/* Delete appropriate attribute from dense storage */
- if(H5A_dense_remove(f, dxpl_id, ainfo, atable.attrs[n].name) < 0)
+ if(H5A_dense_remove(f, dxpl_id, ainfo, ((atable.attrs[n])->shared)->name) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute in dense storage")
} /* end else */
diff --git a/src/H5Aint.c b/src/H5Aint.c
index 71b6689..1ff4c43 100644
--- a/src/H5Aint.c
+++ b/src/H5Aint.c
@@ -100,6 +100,8 @@ static herr_t H5A_attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type,
/* Local Variables */
/*******************/
+typedef H5A_t* H5A_t_ptr;
+H5FL_SEQ_DEFINE(H5A_t_ptr);
/*-------------------------------------------------------------------------
@@ -114,6 +116,10 @@ static herr_t H5A_attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type,
* koziol@hdfgroup.org
* Dec 18 2006
*
+ * Modification:Raymond Lu
+ * 24 June 2008
+ * Changed the table of attribute objects to be the table of
+ * pointers to attribute objects for the ease of operation.
*-------------------------------------------------------------------------
*/
static herr_t
@@ -128,11 +134,20 @@ H5A_compact_build_table_cb(H5O_t UNUSED *oh, H5O_mesg_t *mesg/*in,out*/,
/* check args */
HDassert(mesg);
- /* Check for re-allocating table */
+ /* Re-allocate the table if necessary */
if(udata->curr_attr == udata->atable->nattrs) {
+ size_t i;
size_t n = MAX(1, 2 * udata->atable->nattrs);
- H5A_t *table = (H5A_t *)H5MM_realloc(udata->atable->attrs,
- n * sizeof(H5A_t));
+ H5A_t **table = (H5A_t **)H5FL_SEQ_CALLOC(H5A_t_ptr, n);
+
+ /* Use attribute functions for operation */
+ for(i=0; i<udata->atable->nattrs; i++) {
+ table[i] = (H5A_t *)H5FL_CALLOC(H5A_t);
+ HDmemcpy(&(table[i]), &(udata->atable->attrs[i]), sizeof(H5A_t*));
+ }
+
+ if(udata->atable->nattrs)
+ udata->atable->attrs = (H5A_t **)H5FL_SEQ_FREE(H5A_t_ptr, udata->atable->attrs);
if(!table)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "unable to extend attribute table")
@@ -141,12 +156,14 @@ H5A_compact_build_table_cb(H5O_t UNUSED *oh, H5O_mesg_t *mesg/*in,out*/,
} /* end if */
/* Copy attribute into table */
- if(NULL == H5A_copy(&udata->atable->attrs[udata->curr_attr], (const H5A_t *)mesg->native))
+ udata->atable->attrs[udata->curr_attr] = (H5A_t *)H5FL_CALLOC(H5A_t);
+
+ if(NULL == H5A_copy(udata->atable->attrs[udata->curr_attr], (const H5A_t *)mesg->native))
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute")
/* Assign [somewhat arbitrary] creation order value, if requested */
if(udata->bogus_crt_idx)
- udata->atable->attrs[udata->curr_attr].crt_idx = sequence;
+ ((udata->atable->attrs[udata->curr_attr])->shared)->crt_idx = sequence;
/* Increment current attribute */
udata->curr_attr++;
@@ -246,8 +263,8 @@ H5A_dense_build_table_cb(const H5A_t *attr, void *_udata)
HDassert(udata);
HDassert(udata->curr_attr < udata->atable->nattrs);
- /* Copy attribute information */
- if(NULL == H5A_copy(&udata->atable->attrs[udata->curr_attr], attr))
+ /* Copy attribute information. Share the attribute object in copying. */
+ if(NULL == H5A_copy(udata->atable->attrs[udata->curr_attr], attr))
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute")
/* Increment number of attributes stored */
@@ -305,11 +322,17 @@ H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
if(atable->nattrs > 0) {
H5A_dense_bt_ud_t udata; /* User data for iteration callback */
H5A_attr_iter_op_t attr_op; /* Attribute operator */
+ unsigned i;
/* Allocate the table to store the attributes */
- if((atable->attrs = (H5A_t *)H5MM_malloc(sizeof(H5A_t) * atable->nattrs)) == NULL)
+ if((atable->attrs = (H5A_t **)H5FL_SEQ_MALLOC(H5A_t_ptr, atable->nattrs)) == NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ /* Allocate pointers for each entry in the table */
+ for(i=0; i<atable->nattrs; i++)
+ if((atable->attrs[i] = (H5A_t *)H5FL_CALLOC(H5A_t)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
/* Set up user data for iteration */
udata.atable = atable;
udata.curr_attr = 0;
@@ -358,7 +381,8 @@ H5A_attr_cmp_name_inc(const void *attr1, const void *attr2)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_attr_cmp_name_inc)
- FUNC_LEAVE_NOAPI(HDstrcmp(((const H5A_t *)attr1)->name, ((const H5A_t *)attr2)->name))
+ FUNC_LEAVE_NOAPI(HDstrcmp((*(const H5A_t **)attr1)->shared->name,
+ (*(const H5A_t **)attr2)->shared->name))
} /* end H5A_attr_cmp_name_inc() */
@@ -385,7 +409,8 @@ H5A_attr_cmp_name_dec(const void *attr1, const void *attr2)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_attr_cmp_name_dec)
- FUNC_LEAVE_NOAPI(HDstrcmp(((const H5A_t *)attr2)->name, ((const H5A_t *)attr1)->name))
+ FUNC_LEAVE_NOAPI(HDstrcmp((*(const H5A_t **)attr2)->shared->name,
+ (*(const H5A_t **)attr1)->shared->name))
} /* end H5A_attr_cmp_name_dec() */
@@ -413,9 +438,9 @@ H5A_attr_cmp_corder_inc(const void *attr1, const void *attr2)
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_attr_cmp_corder_inc)
- if(((const H5A_t *)attr1)->crt_idx < ((const H5A_t *)attr2)->crt_idx)
+ if((*(const H5A_t **)attr1)->shared->crt_idx < (*(const H5A_t **)attr2)->shared->crt_idx)
ret_value = -1;
- else if(((const H5A_t *)attr1)->crt_idx > ((const H5A_t *)attr2)->crt_idx)
+ else if((*(const H5A_t **)attr1)->shared->crt_idx > (*(const H5A_t **)attr2)->shared->crt_idx)
ret_value = 1;
else
ret_value = 0;
@@ -448,9 +473,9 @@ H5A_attr_cmp_corder_dec(const void *attr1, const void *attr2)
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_attr_cmp_corder_dec)
- if(((const H5A_t *)attr1)->crt_idx < ((const H5A_t *)attr2)->crt_idx)
+ if((*(const H5A_t **)attr1)->shared->crt_idx < (*(const H5A_t **)attr2)->shared->crt_idx)
ret_value = 1;
- else if(((const H5A_t *)attr1)->crt_idx > ((const H5A_t *)attr2)->crt_idx)
+ else if((*(const H5A_t **)attr1)->shared->crt_idx > (*(const H5A_t **)attr2)->shared->crt_idx)
ret_value = -1;
else
ret_value = 0;
@@ -484,18 +509,18 @@ H5A_attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type,
/* Pick appropriate comparison routine */
if(idx_type == H5_INDEX_NAME) {
if(order == H5_ITER_INC)
- HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t), H5A_attr_cmp_name_inc);
+ HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t*), H5A_attr_cmp_name_inc);
else if(order == H5_ITER_DEC)
- HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t), H5A_attr_cmp_name_dec);
+ HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t*), H5A_attr_cmp_name_dec);
else
HDassert(order == H5_ITER_NATIVE);
} /* end if */
else {
HDassert(idx_type == H5_INDEX_CRT_ORDER);
if(order == H5_ITER_INC)
- HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t), H5A_attr_cmp_corder_inc);
+ HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t*), H5A_attr_cmp_corder_inc);
else if(order == H5_ITER_DEC)
- HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t), H5A_attr_cmp_corder_dec);
+ HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t*), H5A_attr_cmp_corder_dec);
else
HDassert(order == H5_ITER_NATIVE);
} /* end else */
@@ -546,24 +571,24 @@ H5A_attr_iterate_table(const H5A_attr_table_t *atable, hsize_t skip,
H5A_info_t ainfo; /* Info for attribute */
/* Get the attribute information */
- if(H5A_get_info(&atable->attrs[u], &ainfo) < 0)
+ if(H5A_get_info(atable->attrs[u], &ainfo) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, H5_ITER_ERROR, "unable to get attribute info")
/* Make the application callback */
- ret_value = (attr_op->u.app_op2)(loc_id, atable->attrs[u].name, &ainfo, op_data);
+ ret_value = (attr_op->u.app_op2)(loc_id, ((atable->attrs[u])->shared)->name, &ainfo, op_data);
break;
}
#ifndef H5_NO_DEPRECATED_SYMBOLS
case H5A_ATTR_OP_APP:
/* Make the application callback */
- ret_value = (attr_op->u.app_op)(loc_id, atable->attrs[u].name, op_data);
+ ret_value = (attr_op->u.app_op)(loc_id, ((atable->attrs[u])->shared)->name, op_data);
break;
#endif /* H5_NO_DEPRECATED_SYMBOLS */
case H5A_ATTR_OP_LIB:
/* Call the library's callback */
- ret_value = (attr_op->u.lib_op)(&(atable->attrs[u]), op_data);
+ ret_value = (attr_op->u.lib_op)((atable->attrs[u]), op_data);
break;
default:
@@ -588,22 +613,25 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5A_attr_release_table
+ * Function: H5A_attr_release_table
*
- * Purpose: Release table containing a list of attributes for an object
+ * Purpose: Release table containing a list of attributes for an object
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Quincey Koziol
- * Dec 11, 2006
+ * Programmer: Quincey Koziol
+ * Dec 11, 2006
*
+ * Modification: Raymond Lu
+ * 4 June 2008
+ * Changed from H5A_free to H5A_close to release attributes.
*-------------------------------------------------------------------------
*/
herr_t
H5A_attr_release_table(H5A_attr_table_t *atable)
{
- size_t u; /* Local index variable */
+ size_t u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5A_attr_release_table)
@@ -611,19 +639,19 @@ H5A_attr_release_table(H5A_attr_table_t *atable)
/* Sanity check */
HDassert(atable);
- /* Release attribute info, if any */
+ /* Release attribute info, if any. */
if(atable->nattrs > 0) {
/* Free attribute message information */
- for(u = 0; u < atable->nattrs; u++)
- if(H5A_free(&(atable->attrs[u])) < 0)
+ for(u = 0; u < atable->nattrs; u++) {
+ if(H5A_close((atable->attrs[u])) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute")
-
- /* Free table of attributes */
- H5MM_xfree(atable->attrs);
+ }
} /* end if */
else
HDassert(atable->attrs == NULL);
+ atable->attrs = (H5A_t **)H5FL_SEQ_FREE(H5A_t_ptr, atable->attrs);
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A_attr_release_table() */
@@ -711,25 +739,25 @@ H5A_set_version(const H5F_t *f, H5A_t *attr)
use_latest_format = H5F_USE_LATEST_FORMAT(f);
/* Check whether datatype and dataspace are shared */
- if(H5O_msg_is_shared(H5O_DTYPE_ID, attr->dt) > 0)
+ if(H5O_msg_is_shared(H5O_DTYPE_ID, attr->shared->dt) > 0)
type_shared = TRUE;
else
type_shared = FALSE;
- if(H5O_msg_is_shared(H5O_SDSPACE_ID, attr->ds) > 0)
+ if(H5O_msg_is_shared(H5O_SDSPACE_ID, attr->shared->ds) > 0)
space_shared = TRUE;
else
space_shared = FALSE;
/* Check which version to encode attribute with */
if(use_latest_format)
- attr->version = H5O_ATTR_VERSION_LATEST; /* Write out latest version of format */
- else if(attr->encoding != H5T_CSET_ASCII)
- attr->version = H5O_ATTR_VERSION_3; /* Write version which includes the character encoding */
+ attr->shared->version = H5O_ATTR_VERSION_LATEST; /* Write out latest version of format */
+ else if(attr->shared->encoding != H5T_CSET_ASCII)
+ attr->shared->version = H5O_ATTR_VERSION_3; /* Write version which includes the character encoding */
else if(type_shared || space_shared)
- attr->version = H5O_ATTR_VERSION_2; /* Write out version with flag for indicating shared datatype or dataspace */
+ attr->shared->version = H5O_ATTR_VERSION_2; /* Write out version with flag for indicating shared datatype or dataspace */
else
- attr->version = H5O_ATTR_VERSION_1; /* Write out basic version */
+ attr->shared->version = H5O_ATTR_VERSION_1; /* Write out basic version */
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5A_set_version() */
diff --git a/src/H5Apkg.h b/src/H5Apkg.h
index 049877e..a1b5e62 100644
--- a/src/H5Apkg.h
+++ b/src/H5Apkg.h
@@ -72,16 +72,11 @@
/****************************/
/* Package Private Typedefs */
/****************************/
-
-/* Define the main attribute structure */
-struct H5A_t {
- H5O_shared_t sh_loc; /* Shared message info (must be first) */
-
+/* Define the shared attribute structure */
+typedef struct H5A_shared_t {
unsigned version; /* Version to encode attribute with */
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 */
char *name; /* Attribute's name */
H5T_cset_t encoding; /* Character encoding of attribute name */
@@ -95,6 +90,15 @@ struct H5A_t {
void *data; /* Attribute data (on a temporary basis) */
size_t data_size; /* Size of data on disk */
H5O_msg_crt_idx_t crt_idx; /* Attribute's creation index in the object header */
+ unsigned nrefs; /* Ref count for times this object is refered */
+} H5A_shared_t;
+
+/* Define the main attribute structure */
+struct H5A_t {
+ H5O_shared_t sh_loc; /* Shared message info (must be first) */
+ hbool_t obj_opened; /* Object header entry opened? */
+ H5G_name_t path; /* Group hierarchy path */
+ H5A_shared_t *shared; /* Shared attribute information */
};
/* Typedefs for "dense" attribute storage */
@@ -152,7 +156,7 @@ typedef struct H5A_bt2_ud_ins_t {
/* Data structure to hold table of attributes for an object */
typedef struct {
size_t nattrs; /* # of attributes in table */
- H5A_t *attrs; /* Pointer to array of attributes */
+ H5A_t **attrs; /* Pointer to array of attribute pointers */
} H5A_attr_table_t;
/* Attribute iteration operator for internal library callbacks */
@@ -184,6 +188,9 @@ struct H5A_attr_iter_op_t {
/* Declare extern the free list for H5A_t's */
H5FL_EXTERN(H5A_t);
+/* Declare the external free lists for H5A_shared_t's */
+H5FL_EXTERN(H5A_shared_t);
+
/* Declare extern a free list to manage blocks of type conversion data */
H5FL_BLK_EXTERN(attr_buf);
@@ -206,6 +213,7 @@ H5_DLL H5A_t * H5A_open_by_name(const H5G_loc_t *loc, const char *obj_name,
const char *attr_name, hid_t lapl_id, hid_t dxpl_id);
H5_DLL H5A_t *H5A_open_by_idx(const H5G_loc_t *loc, const char *obj_name,
H5_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t lapl_id, hid_t dxpl_id);
+H5_DLL ssize_t H5A_get_name(H5A_t *attr, size_t buf_size, char *buf);
H5_DLL H5A_t *H5A_copy(H5A_t *new_attr, const H5A_t *old_attr);
H5_DLL herr_t H5A_get_info(const H5A_t *attr, H5A_info_t *ainfo);
H5_DLL herr_t H5A_free(H5A_t *attr);
diff --git a/src/H5Atest.c b/src/H5Atest.c
index df88472..de03a25 100644
--- a/src/H5Atest.c
+++ b/src/H5Atest.c
@@ -139,7 +139,7 @@ H5A_get_shared_rc_test(hid_t attr_id, hsize_t *ref_count)
HDassert(H5O_msg_is_shared(H5O_ATTR_ID, attr));
/* Retrieve ref count for shared or shareable attribute */
- if(H5SM_get_refcount(attr->oloc.file, H5AC_ind_dxpl_id, H5O_ATTR_ID,
+ if(H5SM_get_refcount(attr->shared->oloc.file, H5AC_ind_dxpl_id, H5O_ATTR_ID,
&attr->sh_loc, ref_count) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve shared message ref count")
diff --git a/src/H5Oattr.c b/src/H5Oattr.c
index adca14c..bf4c521 100644
--- a/src/H5Oattr.c
+++ b/src/H5Oattr.c
@@ -77,7 +77,7 @@ const H5O_msg_class_t H5O_MSG_ATTR[1] = {{
H5O_attr_shared_encode, /* encode message */
H5O_attr_copy, /* copy the native value */
H5O_attr_shared_size, /* size of raw message */
- H5O_attr_reset, /* reset method */
+ H5O_attr_reset, /* reset method */
H5O_attr_free, /* free method */
H5O_attr_shared_delete, /* file delete method */
H5O_attr_shared_link, /* link method */
@@ -141,13 +141,16 @@ H5O_attr_decode(H5F_t *f, hid_t dxpl_id, unsigned UNUSED mesg_flags,
if(NULL == (attr = H5FL_CALLOC(H5A_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ if(NULL == (attr->shared = H5FL_CALLOC(H5A_shared_t)))
+ HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate shared attr structure")
+
/* Version number */
- attr->version = *p++;
- if(attr->version < H5O_ATTR_VERSION_1 || attr->version > H5O_ATTR_VERSION_LATEST)
+ attr->shared->version = *p++;
+ if(attr->shared->version < H5O_ATTR_VERSION_1 || attr->shared->version > H5O_ATTR_VERSION_LATEST)
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, NULL, "bad version number for attribute message")
/* Get the flags byte if we have a later version of the attribute */
- if(attr->version >= H5O_ATTR_VERSION_2) {
+ if(attr->shared->version >= H5O_ATTR_VERSION_2) {
flags = *p++;
/* Check for unknown flag */
@@ -162,36 +165,36 @@ H5O_attr_decode(H5F_t *f, hid_t dxpl_id, unsigned UNUSED mesg_flags,
* the file are exact but the parts are aligned on 8-byte boundaries.
*/
UINT16DECODE(p, name_len); /*including null*/
- UINT16DECODE(p, attr->dt_size);
- UINT16DECODE(p, attr->ds_size);
+ UINT16DECODE(p, attr->shared->dt_size);
+ UINT16DECODE(p, attr->shared->ds_size);
/*
* Decode the character encoding for the name for versions 3 or later,
* as well as some reserved bytes.
*/
- if(attr->version >= H5O_ATTR_VERSION_3)
- attr->encoding = *p++;
+ if(attr->shared->version >= H5O_ATTR_VERSION_3)
+ attr->shared->encoding = *p++;
/* Decode and store the name */
- if(NULL == (attr->name = H5MM_strdup((const char *)p)))
+ if(NULL == (attr->shared->name = H5MM_strdup((const char *)p)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- if(attr->version < H5O_ATTR_VERSION_2)
+ if(attr->shared->version < H5O_ATTR_VERSION_2)
p += H5O_ALIGN_OLD(name_len); /* advance the memory pointer */
else
p += name_len; /* advance the memory pointer */
/* Decode the attribute's datatype */
- if((attr->dt = (H5T_t *)(H5O_MSG_DTYPE->decode)(f, dxpl_id, ((flags & H5O_ATTR_FLAG_TYPE_SHARED) ? H5O_MSG_FLAG_SHARED : 0), p)) == NULL)
+ if((attr->shared->dt = (H5T_t *)(H5O_MSG_DTYPE->decode)(f, dxpl_id, ((flags & H5O_ATTR_FLAG_TYPE_SHARED) ? H5O_MSG_FLAG_SHARED : 0), p)) == NULL)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute datatype")
- if(attr->version < H5O_ATTR_VERSION_2)
- p += H5O_ALIGN_OLD(attr->dt_size);
+ if(attr->shared->version < H5O_ATTR_VERSION_2)
+ p += H5O_ALIGN_OLD(attr->shared->dt_size);
else
- p += attr->dt_size;
+ p += attr->shared->dt_size;
/* decode the attribute dataspace. It can be shared in versions >= 3
* What's actually shared, though, is only the extent.
*/
- if(NULL == (attr->ds = H5FL_CALLOC(H5S_t)))
+ if(NULL == (attr->shared->ds = H5FL_CALLOC(H5S_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Decode attribute's dataspace extent */
@@ -199,32 +202,36 @@ H5O_attr_decode(H5F_t *f, hid_t dxpl_id, unsigned UNUSED mesg_flags,
HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute dataspace")
/* Copy the extent information to the dataspace */
- HDmemcpy(&(attr->ds->extent), extent, sizeof(H5S_extent_t));
+ HDmemcpy(&(attr->shared->ds->extent), extent, sizeof(H5S_extent_t));
/* Release temporary extent information */
H5FL_FREE(H5S_extent_t, extent);
/* Default to entire dataspace being selected */
- if(H5S_select_all(attr->ds, FALSE) < 0)
+ if(H5S_select_all(attr->shared->ds, FALSE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection")
- if(attr->version < H5O_ATTR_VERSION_2)
- p += H5O_ALIGN_OLD(attr->ds_size);
+ if(attr->shared->version < H5O_ATTR_VERSION_2)
+ p += H5O_ALIGN_OLD(attr->shared->ds_size);
else
- p += attr->ds_size;
+ p += attr->shared->ds_size;
/* Compute the size of the data */
- H5_ASSIGN_OVERFLOW(attr->data_size, H5S_GET_EXTENT_NPOINTS(attr->ds) * H5T_get_size(attr->dt), hsize_t, size_t);
+ H5_ASSIGN_OVERFLOW(attr->shared->data_size, H5S_GET_EXTENT_NPOINTS(attr->shared->ds) * H5T_get_size(attr->shared->dt), hsize_t, size_t);
/* Go get the data */
- if(attr->data_size) {
- if(NULL == (attr->data = H5FL_BLK_MALLOC(attr_buf, attr->data_size)))
+ if(attr->shared->data_size) {
+ if(NULL == (attr->shared->data = H5FL_BLK_MALLOC(attr_buf, attr->shared->data_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- HDmemcpy(attr->data, p, attr->data_size);
+ HDmemcpy(attr->shared->data, p, attr->shared->data_size);
} /* end if */
/* Indicate that the fill values aren't to be written out */
- attr->initialized = 1;
+ attr->shared->initialized = 1;
+
+ /* Increment the reference count for this object header message in cache(compact
+ storage) or for the object from dense storage. */
+ attr->shared->nrefs++;
/* Set return value */
ret_value = attr;
@@ -268,17 +275,17 @@ H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg)
HDassert(attr);
/* Check whether datatype and dataspace are shared */
- if((is_type_shared = H5O_msg_is_shared(H5O_DTYPE_ID, attr->dt)) < 0)
+ if((is_type_shared = H5O_msg_is_shared(H5O_DTYPE_ID, attr->shared->dt)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't determine if datatype is shared")
- if((is_space_shared = H5O_msg_is_shared(H5O_SDSPACE_ID, attr->ds)) < 0)
+ if((is_space_shared = H5O_msg_is_shared(H5O_SDSPACE_ID, attr->shared->ds)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't determine if dataspace is shared")
/* Encode Version */
- *p++ = attr->version;
+ *p++ = attr->shared->version;
/* Set attribute flags if version >1 */
- if(attr->version >= H5O_ATTR_VERSION_2) {
+ if(attr->shared->version >= H5O_ATTR_VERSION_2) {
flags = (is_type_shared ? H5O_ATTR_FLAG_TYPE_SHARED : 0 );
flags |= (is_space_shared ? H5O_ATTR_FLAG_SPACE_SHARED : 0);
*p++ = flags; /* Set flags for attribute */
@@ -291,18 +298,18 @@ H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg)
* encoded lengths are exact but we pad each part except the data to be a
* multiple of eight bytes (in the first version).
*/
- name_len = HDstrlen(attr->name) + 1;
+ name_len = HDstrlen(attr->shared->name) + 1;
UINT16ENCODE(p, name_len);
- UINT16ENCODE(p, attr->dt_size);
- UINT16ENCODE(p, attr->ds_size);
+ UINT16ENCODE(p, attr->shared->dt_size);
+ UINT16ENCODE(p, attr->shared->ds_size);
/* The character encoding for the attribute's name, in later versions */
- if(attr->version >= H5O_ATTR_VERSION_3)
- *p++ = attr->encoding;
+ if(attr->shared->version >= H5O_ATTR_VERSION_3)
+ *p++ = attr->shared->encoding;
/* Write the name including null terminator */
- HDmemcpy(p, attr->name, name_len);
- if(attr->version < H5O_ATTR_VERSION_2) {
+ HDmemcpy(p, attr->shared->name, name_len);
+ if(attr->shared->version < H5O_ATTR_VERSION_2) {
/* Pad to the correct number of bytes */
HDmemset(p + name_len, 0, H5O_ALIGN_OLD(name_len) - name_len);
p += H5O_ALIGN_OLD(name_len);
@@ -311,32 +318,32 @@ H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg)
p += name_len;
/* encode the attribute datatype */
- if((H5O_MSG_DTYPE->encode)(f, FALSE, p, attr->dt) < 0)
+ if((H5O_MSG_DTYPE->encode)(f, FALSE, p, attr->shared->dt) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode attribute datatype")
- if(attr->version < H5O_ATTR_VERSION_2) {
- HDmemset(p + attr->dt_size, 0, H5O_ALIGN_OLD(attr->dt_size) - attr->dt_size);
- p += H5O_ALIGN_OLD(attr->dt_size);
+ if(attr->shared->version < H5O_ATTR_VERSION_2) {
+ HDmemset(p + attr->shared->dt_size, 0, H5O_ALIGN_OLD(attr->shared->dt_size) - attr->shared->dt_size);
+ p += H5O_ALIGN_OLD(attr->shared->dt_size);
} /* end if */
else
- p += attr->dt_size;
+ p += attr->shared->dt_size;
/* encode the attribute dataspace */
- if((H5O_MSG_SDSPACE->encode)(f, FALSE, p, &(attr->ds->extent)) < 0)
+ if((H5O_MSG_SDSPACE->encode)(f, FALSE, p, &(attr->shared->ds->extent)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode attribute dataspace")
- if(attr->version < H5O_ATTR_VERSION_2) {
- HDmemset(p + attr->ds_size, 0, H5O_ALIGN_OLD(attr->ds_size) - attr->ds_size);
- p += H5O_ALIGN_OLD(attr->ds_size);
+ if(attr->shared->version < H5O_ATTR_VERSION_2) {
+ HDmemset(p + attr->shared->ds_size, 0, H5O_ALIGN_OLD(attr->shared->ds_size) - attr->shared->ds_size);
+ p += H5O_ALIGN_OLD(attr->shared->ds_size);
} /* end if */
else
- p += attr->ds_size;
+ p += attr->shared->ds_size;
- /* Store attribute data */
- if(attr->data)
- HDmemcpy(p, attr->data, attr->data_size);
+ /* Store attribute data. If there's no data, store 0 as fill value. */
+ if(attr->shared->data)
+ HDmemcpy(p, attr->shared->data, attr->shared->data_size);
else
- HDmemset(p, 0, attr->data_size);
+ HDmemset(p, 0, attr->shared->data_size);
done:
FUNC_LEAVE_NOAPI(ret_value);
@@ -412,25 +419,25 @@ H5O_attr_size(const H5F_t UNUSED *f, const void *_mesg)
2; /*space size */
/* Length of attribute name */
- name_len = HDstrlen(attr->name) + 1;
+ name_len = HDstrlen(attr->shared->name) + 1;
/* Version-specific size information */
- if(attr->version == H5O_ATTR_VERSION_1)
+ if(attr->shared->version == H5O_ATTR_VERSION_1)
ret_value += H5O_ALIGN_OLD(name_len) + /*attribute name */
- H5O_ALIGN_OLD(attr->dt_size) + /*datatype */
- H5O_ALIGN_OLD(attr->ds_size) + /*dataspace */
- attr->data_size; /*the data itself */
- else if(attr->version == H5O_ATTR_VERSION_2)
+ H5O_ALIGN_OLD(attr->shared->dt_size) + /*datatype */
+ H5O_ALIGN_OLD(attr->shared->ds_size) + /*dataspace */
+ attr->shared->data_size; /*the data itself */
+ else if(attr->shared->version == H5O_ATTR_VERSION_2)
ret_value += name_len + /*attribute name */
- attr->dt_size + /*datatype */
- attr->ds_size + /*dataspace */
- attr->data_size; /*the data itself */
- else if(attr->version == H5O_ATTR_VERSION_3)
+ attr->shared->dt_size + /*datatype */
+ attr->shared->ds_size + /*dataspace */
+ attr->shared->data_size; /*the data itself */
+ else if(attr->shared->version == H5O_ATTR_VERSION_3)
ret_value += 1 + /*character encoding */
name_len + /*attribute name */
- attr->dt_size + /*datatype */
- attr->ds_size + /*dataspace */
- attr->data_size; /*the data itself */
+ attr->shared->dt_size + /*datatype */
+ attr->shared->ds_size + /*dataspace */
+ attr->shared->data_size; /*the data itself */
else
HDassert(0 && "Bad attribute version");
@@ -449,6 +456,13 @@ H5O_attr_size(const H5F_t UNUSED *f, const void *_mesg)
* Programmer: Robb Matzke
* Tuesday, December 9, 1997
*
+ * Modification:Raymond Lu
+ * 25 June 2008
+ * Made this function empty. The freeing action is actually
+ * done in H5O_attr_free (see H5O_msg_free_real). But this
+ * empty reset function needs to be here. Otherwise, the
+ * caller function H5O_msg_reset_real will zero-set the whole
+ * message.
*-------------------------------------------------------------------------
*/
herr_t
@@ -458,9 +472,6 @@ H5O_attr_reset(void *_mesg)
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_attr_reset)
- if(attr)
- H5A_free(attr);
-
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_attr_reset() */
@@ -475,18 +486,27 @@ H5O_attr_reset(void *_mesg)
* Programmer: Quincey Koziol
* Thursday, November 18, 2004
*
+ * Modification:Raymond Lu
+ * 4 June 2008
+ * Let this function call H5A_close in turn.
+ *
*-------------------------------------------------------------------------
*/
static herr_t
H5O_attr_free(void *mesg)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_attr_free)
+ H5A_t *attr = (H5A_t *)mesg;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_attr_free)
HDassert(mesg);
- H5FL_FREE(H5A_t, mesg);
+ if(H5A_close(attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCLOSEOBJ, FAIL, "unable to close attribute object")
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_attr_free() */
@@ -515,11 +535,11 @@ H5O_attr_delete(H5F_t *f, hid_t dxpl_id, H5O_t *oh, void *_mesg)
HDassert(attr);
/* Decrement reference count on datatype in file */
- if((H5O_MSG_DTYPE->del)(f, dxpl_id, oh, attr->dt) < 0)
+ if((H5O_MSG_DTYPE->del)(f, dxpl_id, oh, attr->shared->dt) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust datatype link count")
/* Decrement reference count on dataspace in file */
- if((H5O_MSG_SDSPACE->del)(f, dxpl_id, oh, attr->ds) < 0)
+ if((H5O_MSG_SDSPACE->del)(f, dxpl_id, oh, attr->shared->ds) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust dataspace link count")
done:
@@ -558,9 +578,9 @@ H5O_attr_link(H5F_t *f, hid_t dxpl_id, H5O_t *oh, void *_mesg)
* message is deleted.
*/
/* Increment reference count on datatype & dataspace in file */
- if((H5O_MSG_DTYPE->link)(f, dxpl_id, oh, attr->dt) < 0)
+ if((H5O_MSG_DTYPE->link)(f, dxpl_id, oh, attr->shared->dt) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust datatype link count")
- if((H5O_MSG_SDSPACE->link)(f, dxpl_id, oh, attr->ds) < 0)
+ if((H5O_MSG_SDSPACE->link)(f, dxpl_id, oh, attr->shared->ds) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust dataspace link count")
done:
@@ -650,33 +670,39 @@ H5O_attr_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *mesg_ty
/* Copy the top level of the attribute */
*attr_dst = *attr_src;
+ if(NULL == (attr_dst->shared = H5FL_CALLOC(H5A_shared_t)))
+ HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate shared attr structure")
+
/* Don't have an opened group location for copy */
- H5O_loc_reset(&(attr_dst->oloc));
+ H5O_loc_reset(&(attr_dst->shared->oloc));
H5G_name_reset(&(attr_dst->path));
attr_dst->obj_opened = FALSE;
-
+
+ /* Reference count for the header message in the cache */
+ attr_dst->shared->nrefs = 1;
+
/* Copy attribute's name */
- attr_dst->name = H5MM_strdup(attr_src->name);
- HDassert(attr_dst->name);
+ attr_dst->shared->name = H5MM_strdup(attr_src->shared->name);
+ HDassert(attr_dst->shared->name);
/* Copy attribute's datatype */
/* (Start destination datatype as transient, even if source is named) */
- attr_dst->dt = H5T_copy(attr_src->dt, H5T_COPY_ALL);
- HDassert(attr_dst->dt);
+ attr_dst->shared->dt = H5T_copy(attr_src->shared->dt, H5T_COPY_ALL);
+ HDassert(attr_dst->shared->dt);
/* Set the location of the destination datatype */
- if(H5T_set_loc(attr_dst->dt, file_dst, H5T_LOC_DISK) < 0)
+ if(H5T_set_loc(attr_dst->shared->dt, file_dst, H5T_LOC_DISK) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "cannot mark datatype on disk")
/* Check for named datatype being copied */
- if(H5T_committed(attr_src->dt)) {
+ if(H5T_committed(attr_src->shared->dt)) {
H5O_loc_t *src_oloc; /* Pointer to source datatype's object location */
H5O_loc_t *dst_oloc; /* Pointer to dest. datatype's object location */
/* Get group entries for source & destination */
- src_oloc = H5T_oloc(attr_src->dt);
+ src_oloc = H5T_oloc(attr_src->shared->dt);
HDassert(src_oloc);
- dst_oloc = H5T_oloc(attr_dst->dt);
+ dst_oloc = H5T_oloc(attr_dst->shared->dt);
HDassert(dst_oloc);
/* Reset object location for new object */
@@ -688,59 +714,59 @@ H5O_attr_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *mesg_ty
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy object")
/* Update shared message info from named datatype info */
- H5T_update_shared(attr_dst->dt);
+ H5T_update_shared(attr_dst->shared->dt);
} /* end if */
else {
/* If the datatype is not named, it may have been shared in the
* source file's heap. Un-share it for now. We'll try to shared
* it in the destination file below.
*/
- if(H5O_msg_reset_share(H5O_DTYPE_ID, attr_dst->dt) < 0)
+ if(H5O_msg_reset_share(H5O_DTYPE_ID, attr_dst->shared->dt) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to reset datatype sharing")
} /* end else */
/* Copy the dataspace for the attribute */
- attr_dst->ds = H5S_copy(attr_src->ds, FALSE, FALSE);
- HDassert(attr_dst->ds);
+ attr_dst->shared->ds = H5S_copy(attr_src->shared->ds, FALSE, FALSE);
+ HDassert(attr_dst->shared->ds);
/* Reset the dataspace's sharing in the source file before trying to share
* it in the destination.
*/
- if(H5O_msg_reset_share(H5O_SDSPACE_ID, attr_dst->ds) < 0)
+ if(H5O_msg_reset_share(H5O_SDSPACE_ID, attr_dst->shared->ds) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to reset dataspace sharing")
/* Try to share both the datatype and dataset. This does nothing if the
* datatype is committed or sharing is disabled.
*/
- if(H5SM_try_share(file_dst, dxpl_id, NULL, H5O_DTYPE_ID, attr_dst->dt, NULL) < 0)
+ if(H5SM_try_share(file_dst, dxpl_id, NULL, H5O_DTYPE_ID, attr_dst->shared->dt, NULL) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, NULL, "can't share attribute datatype")
- if(H5SM_try_share(file_dst, dxpl_id, NULL, H5O_SDSPACE_ID, attr_dst->ds, NULL) < 0)
+ if(H5SM_try_share(file_dst, dxpl_id, NULL, H5O_SDSPACE_ID, attr_dst->shared->ds, NULL) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, NULL, "can't share attribute dataspace")
/* Compute the sizes of the datatype and dataspace. This is their raw
* size unless they're shared.
*/
- attr_dst->dt_size = H5O_msg_raw_size(file_dst, H5O_DTYPE_ID, FALSE, attr_dst->dt);
- HDassert(attr_dst->dt_size > 0);
- attr_dst->ds_size = H5O_msg_raw_size(file_dst, H5O_SDSPACE_ID, FALSE, attr_dst->ds);
- HDassert(attr_dst->ds_size > 0);
+ attr_dst->shared->dt_size = H5O_msg_raw_size(file_dst, H5O_DTYPE_ID, FALSE, attr_dst->shared->dt);
+ HDassert(attr_dst->shared->dt_size > 0);
+ attr_dst->shared->ds_size = H5O_msg_raw_size(file_dst, H5O_SDSPACE_ID, FALSE, attr_dst->shared->ds);
+ HDassert(attr_dst->shared->ds_size > 0);
/* Check whether to recompute the size of the attribute */
/* (happens when the datatype or dataspace changes sharing status) */
- if(attr_dst->dt_size != attr_src->dt_size || attr_dst->ds_size != attr_src->ds_size)
+ if(attr_dst->shared->dt_size != attr_src->shared->dt_size || attr_dst->shared->ds_size != attr_src->shared->ds_size)
*recompute_size = TRUE;
/* Compute the size of the data */
- H5_ASSIGN_OVERFLOW(attr_dst->data_size, H5S_GET_EXTENT_NPOINTS(attr_dst->ds) * H5T_get_size(attr_dst->dt), hsize_t, size_t);
+ H5_ASSIGN_OVERFLOW(attr_dst->shared->data_size, H5S_GET_EXTENT_NPOINTS(attr_dst->shared->ds) * H5T_get_size(attr_dst->shared->dt), hsize_t, size_t);
/* Copy (& convert) the data, if necessary */
- if(attr_src->data) {
- if(NULL == (attr_dst->data = H5FL_BLK_MALLOC(attr_buf, attr_dst->data_size)))
+ if(attr_src->shared->data) {
+ if(NULL == (attr_dst->shared->data = H5FL_BLK_MALLOC(attr_buf, attr_dst->shared->data_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Check if we need to convert data */
- if(H5T_detect_class(attr_src->dt, H5T_VLEN) > 0) {
+ if(H5T_detect_class(attr_src->shared->dt, H5T_VLEN) > 0) {
H5T_path_t *tpath_src_mem, *tpath_mem_dst; /* Datatype conversion paths */
H5T_t *dt_mem; /* Memory datatype */
size_t src_dt_size; /* Source datatype size */
@@ -752,37 +778,37 @@ H5O_attr_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *mesg_ty
size_t buf_size; /* Size of copy buffer */
/* Create datatype ID for src datatype */
- if((tid_src = H5I_register(H5I_DATATYPE, attr_src->dt)) < 0)
+ if((tid_src = H5I_register(H5I_DATATYPE, attr_src->shared->dt)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register source file datatype")
/* create a memory copy of the variable-length datatype */
- if(NULL == (dt_mem = H5T_copy(attr_src->dt, H5T_COPY_TRANSIENT)))
+ if(NULL == (dt_mem = H5T_copy(attr_src->shared->dt, H5T_COPY_TRANSIENT)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy")
if((tid_mem = H5I_register(H5I_DATATYPE, dt_mem)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register memory datatype")
/* create variable-length datatype at the destinaton file */
- if((tid_dst = H5I_register(H5I_DATATYPE, attr_dst->dt)) < 0)
+ if((tid_dst = H5I_register(H5I_DATATYPE, attr_dst->shared->dt)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register destination file datatype")
/* Set up the conversion functions */
- if(NULL == (tpath_src_mem = H5T_path_find(attr_src->dt, dt_mem, NULL, NULL, dxpl_id, FALSE)))
+ if(NULL == (tpath_src_mem = H5T_path_find(attr_src->shared->dt, dt_mem, NULL, NULL, dxpl_id, FALSE)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to convert between src and mem datatypes")
- if(NULL == (tpath_mem_dst = H5T_path_find(dt_mem, attr_dst->dt, NULL, NULL, dxpl_id, FALSE)))
+ if(NULL == (tpath_mem_dst = H5T_path_find(dt_mem, attr_dst->shared->dt, NULL, NULL, dxpl_id, FALSE)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to convert between mem and dst datatypes")
/* Determine largest datatype size */
- if(0 == (src_dt_size = H5T_get_size(attr_src->dt)))
+ if(0 == (src_dt_size = H5T_get_size(attr_src->shared->dt)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to determine datatype size")
if(0 == (tmp_dt_size = H5T_get_size(dt_mem)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to determine datatype size")
max_dt_size = MAX(src_dt_size, tmp_dt_size);
- if(0 == (tmp_dt_size = H5T_get_size(attr_dst->dt)))
+ if(0 == (tmp_dt_size = H5T_get_size(attr_dst->shared->dt)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to determine datatype size")
max_dt_size = MAX(max_dt_size, tmp_dt_size);
/* Set number of whole elements that fit in buffer */
- if(0 == (nelmts = attr_src->data_size / src_dt_size))
+ if(0 == (nelmts = attr_src->shared->data_size / src_dt_size))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "element size too large")
/* Set up number of bytes to copy, and initial buffer size */
@@ -809,7 +835,7 @@ H5O_attr_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *mesg_ty
if(NULL == (buf = H5FL_BLK_MALLOC(attr_buf, buf_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation NULLed for raw data chunk")
- HDmemcpy(buf, attr_src->data, attr_src->data_size);
+ HDmemcpy(buf, attr_src->shared->data, attr_src->shared->data_size);
/* Convert from source file to memory */
if(H5T_convert(tpath_src_mem, tid_src, tid_mem, nelmts, (size_t)0, (size_t)0, buf, NULL, dxpl_id) < 0)
@@ -821,23 +847,23 @@ H5O_attr_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *mesg_ty
if(H5T_convert(tpath_mem_dst, tid_mem, tid_dst, nelmts, (size_t)0, (size_t)0, buf, NULL, dxpl_id) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "datatype conversion NULLed")
- HDmemcpy(attr_dst->data, buf, attr_dst->data_size);
+ HDmemcpy(attr_dst->shared->data, buf, attr_dst->shared->data_size);
if(H5D_vlen_reclaim(tid_mem, buf_space, H5P_DATASET_XFER_DEFAULT, reclaim_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADITER, NULL, "unable to reclaim variable-length data")
} /* end if */
else {
- HDassert(attr_dst->data_size == attr_src->data_size);
- HDmemcpy(attr_dst->data, attr_src->data, attr_src->data_size);
+ HDassert(attr_dst->shared->data_size == attr_src->shared->data_size);
+ HDmemcpy(attr_dst->shared->data, attr_src->shared->data, attr_src->shared->data_size);
} /* end else */
- } /* end if(attr_src->data) */
+ } /* end if(attr_src->shared->data) */
/* Recompute the version to encode the destination attribute */
if(H5A_set_version(file_dst, attr_dst) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "unable to update attribute version")
/* Indicate that the fill values aren't to be written out */
- attr_dst->initialized = TRUE;
+ attr_dst->shared->initialized = TRUE;
/* Set return value */
ret_value = attr_dst;
@@ -864,9 +890,8 @@ done:
reclaim_buf = H5FL_BLK_FREE(attr_buf, reclaim_buf);
/* Release destination attribute information on failure */
- if(!ret_value)
- if(attr_dst)
- (void)H5A_free(attr_dst);
+ if(!ret_value && attr_dst && H5A_close(attr_dst) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_attr_copy_file() */
@@ -911,8 +936,8 @@ H5O_attr_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src,
/* Only need to fix reference attribute with real data being copied to
* another file.
*/
- if((NULL != attr_src->data) &&
- (H5T_get_class(attr_src->dt, FALSE) == H5T_REFERENCE) &&
+ if((NULL != attr_src->shared->data) &&
+ (H5T_get_class(attr_src->shared->dt, FALSE) == H5T_REFERENCE) &&
(file_src != file_dst)) {
/* copy object pointed by reference. The current implementation does not
@@ -924,16 +949,16 @@ H5O_attr_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src,
size_t ref_count;
/* Determine # of reference elements to copy */
- ref_count = attr_dst->data_size / H5T_get_size(attr_dst->dt);
+ ref_count = attr_dst->shared->data_size / H5T_get_size(attr_dst->shared->dt);
/* Copy objects referenced in source buffer to destination file and set destination elements */
- if(H5O_copy_expand_ref(file_src, attr_src->data, dxpl_id,
- file_dst, attr_dst->data, ref_count, H5T_get_ref_type(attr_src->dt), cpy_info) < 0)
+ if(H5O_copy_expand_ref(file_src, attr_src->shared->data, dxpl_id,
+ file_dst, attr_dst->shared->data, ref_count, H5T_get_ref_type(attr_src->shared->dt), cpy_info) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy reference attribute")
} /* end if */
else
/* Reset value to zero */
- HDmemset(attr_dst->data, 0, attr_dst->data_size);
+ HDmemset(attr_dst->shared->data, 0, attr_dst->shared->data_size);
} /* end if */
done:
@@ -965,7 +990,7 @@ H5O_attr_get_crt_index(const void *_mesg, H5O_msg_crt_idx_t *crt_idx /*out*/)
HDassert(crt_idx);
/* Get the attribute's creation index */
- *crt_idx = attr->crt_idx;
+ *crt_idx = attr->shared->crt_idx;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_attr_get_crt_index() */
@@ -994,7 +1019,7 @@ H5O_attr_set_crt_index(void *_mesg, H5O_msg_crt_idx_t crt_idx)
HDassert(attr);
/* Set the creation index */
- attr->crt_idx = crt_idx;
+ attr->shared->crt_idx = crt_idx;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_attr_set_crt_index() */
@@ -1037,8 +1062,8 @@ H5O_attr_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int in
fprintf(stream, "%*s%-*s \"%s\"\n", indent, "", fwidth,
"Name:",
- mesg->name);
- switch(mesg->encoding) {
+ mesg->shared->name);
+ switch(mesg->shared->encoding) {
case H5T_CSET_ASCII:
s = "ASCII";
break;
@@ -1046,7 +1071,7 @@ H5O_attr_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int in
s = "UTF-8";
break;
default:
- sprintf(buf, "H5T_CSET_RESERVED_%d", (int)(mesg->encoding));
+ sprintf(buf, "H5T_CSET_RESERVED_%d", (int)(mesg->shared->encoding));
s = buf;
break;
} /* end switch */
@@ -1055,32 +1080,32 @@ H5O_attr_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int in
s);
HDfprintf(stream, "%*s%-*s %t\n", indent, "", fwidth,
"Initialized:",
- mesg->initialized);
+ mesg->shared->initialized);
HDfprintf(stream, "%*s%-*s %t\n", indent, "", fwidth,
"Object opened:",
mesg->obj_opened);
HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
"Object:",
- mesg->oloc.addr);
+ mesg->shared->oloc.addr);
/* Check for attribute creation order index on the attribute */
- if(mesg->crt_idx != H5O_MAX_CRT_ORDER_IDX)
+ if(mesg->shared->crt_idx != H5O_MAX_CRT_ORDER_IDX)
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"Creation Index:",
- (unsigned)mesg->crt_idx);
+ (unsigned)mesg->shared->crt_idx);
fprintf(stream, "%*sDatatype...\n", indent, "");
fprintf(stream, "%*s%-*s %lu\n", indent+3, "", MAX(0,fwidth-3),
"Encoded Size:",
- (unsigned long)(mesg->dt_size));
- if((H5O_MSG_DTYPE->debug)(f, dxpl_id, mesg->dt, stream, indent + 3, MAX(0, fwidth - 3)) < 0)
+ (unsigned long)(mesg->shared->dt_size));
+ if((H5O_MSG_DTYPE->debug)(f, dxpl_id, mesg->shared->dt, stream, indent + 3, MAX(0, fwidth - 3)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to display datatype message info")
fprintf(stream, "%*sDataspace...\n", indent, "");
fprintf(stream, "%*s%-*s %lu\n", indent+3, "", MAX(0, fwidth - 3),
"Encoded Size:",
- (unsigned long)(mesg->ds_size));
- if(H5S_debug(f, dxpl_id, mesg->ds, stream, indent+3, MAX(0, fwidth - 3)) < 0)
+ (unsigned long)(mesg->shared->ds_size));
+ if(H5S_debug(f, dxpl_id, mesg->shared->ds, stream, indent+3, MAX(0, fwidth - 3)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to display dataspace message info")
done:
diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c
index 5c9f875..249437b 100644
--- a/src/H5Oattribute.c
+++ b/src/H5Oattribute.c
@@ -136,7 +136,8 @@ typedef struct {
static herr_t H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc,
hid_t dxpl_id, H5_index_t idx_type, H5_iter_order_t order, hsize_t skip,
hsize_t *last_attr, const H5A_attr_iter_op_t *attr_op, void *op_data);
-
+static htri_t H5O_attr_find_opened_attr(const H5O_loc_t *loc, H5A_t **attr,
+ const char* name_to_open);
/*********************/
/* Package Variables */
@@ -306,11 +307,11 @@ H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINC, FAIL, "attribute creation index can't be incremented")
/* Set the creation order index on the attribute & incr. creation order index */
- attr->crt_idx = ainfo.max_crt_idx++;
+ attr->shared->crt_idx = ainfo.max_crt_idx++;
} /* end if */
else
/* Set "bogus" creation index for attribute */
- attr->crt_idx = H5O_MAX_CRT_ORDER_IDX;
+ attr->shared->crt_idx = H5O_MAX_CRT_ORDER_IDX;
/* Add the attribute information message, if one is needed */
if(new_ainfo) {
@@ -325,7 +326,7 @@ H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
} /* end if */
else {
/* Set "bogus" creation index for attribute */
- attr->crt_idx = H5O_MAX_CRT_ORDER_IDX;
+ attr->shared->crt_idx = H5O_MAX_CRT_ORDER_IDX;
/* Set attribute info value to get attribute into object header */
ainfo.fheap_addr = HADDR_UNDEF;
@@ -343,6 +344,12 @@ H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to create new attribute in header")
} /* end else */
+ /* Increment reference count for shared attribute object for the
+ * object handle created by the caller function H5A_create. The count
+ * for the cached object header has been incremented in the step above
+ * (in H5O_msg_append_real). The dense storage doesn't need a count. */
+ attr->shared->nrefs += 1;
+
/* Was new attribute shared? */
if((shared_mesg = H5O_msg_is_shared(H5O_ATTR_ID, attr)) > 0) {
hsize_t attr_rc; /* Attribute's ref count in shared message storage */
@@ -426,14 +433,14 @@ H5O_attr_open_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, unsigned sequence,
HDassert(!udata->attr);
/* Check for correct attribute message to modify */
- if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->name) == 0) {
+ if(HDstrcmp(((H5A_t *)mesg->native)->shared->name, udata->name) == 0) {
/* Make a copy of the attribute to return */
if(NULL == (udata->attr = H5A_copy(NULL, (H5A_t *)mesg->native)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "unable to copy attribute")
/* Assign [somewhat arbitrary] creation order value, for older versions of the format */
if(oh->version == H5O_VERSION_1)
- udata->attr->crt_idx = sequence;
+ udata->attr->shared->crt_idx = sequence;
/* Stop iterating */
ret_value = H5_ITER_STOP;
@@ -454,6 +461,11 @@ done:
* Programmer: Quincey Koziol
* Monday, December 11, 2006
*
+ * Modification:Raymond Lu
+ * 23 June 2008
+ * If the attribute is in dense storage and has already been
+ * opened, make a copy of already opened object to share some
+ * object information.
*-------------------------------------------------------------------------
*/
H5A_t *
@@ -481,8 +493,17 @@ H5O_attr_open_by_name(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
/* Check for opening attribute with dense storage */
if(H5F_addr_defined(ainfo.fheap_addr)) {
- /* Open attribute in dense storage */
- if(NULL == (ret_value = H5A_dense_open(loc->file, dxpl_id, &ainfo, name)))
+ H5A_t *exist_attr = NULL;
+ htri_t found_open_attr = FALSE;
+
+ /* If found the attribute is already opened, make a copy of it to share the
+ object information. If not, open attribute in dense storage */
+ if((found_open_attr = H5O_attr_find_opened_attr(loc, &exist_attr, name)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "failed in finding opened attribute")
+ else if(found_open_attr == TRUE) {
+ if(NULL == (ret_value = H5A_copy(NULL, exist_attr)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "can't copy existing attribute")
+ } else if(NULL == (ret_value = H5A_dense_open(loc->file, dxpl_id, &ainfo, name)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "can't open attribute")
} /* end if */
else {
@@ -542,7 +563,7 @@ H5O_attr_open_by_idx_cb(const H5A_t *attr, void *_ret_attr)
HDassert(attr);
HDassert(ret_attr);
- /* Copy attribute information */
+ /* Copy attribute information. Shared some attribute information. */
if(NULL == (*ret_attr = H5A_copy(NULL, attr)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute")
@@ -562,6 +583,11 @@ done:
* Programmer: Quincey Koziol
* Monday, December 18, 2006
*
+ * Modification:Raymond Lu
+ * 23 June 2008
+ * After opening the attribute, check whether it's in dense
+ * storage and has already been opened. If it has, close the
+ * opened object and make a copy of already opened object.
*-------------------------------------------------------------------------
*/
H5A_t *
@@ -569,7 +595,11 @@ H5O_attr_open_by_idx(const H5O_loc_t *loc, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, hid_t dxpl_id)
{
H5A_attr_iter_op_t attr_op; /* Attribute operator */
+ H5A_t *exist_attr = NULL;
+ htri_t found_open_attr = FALSE;
H5A_t *ret_value = NULL; /* Return value */
+ H5O_t *oh = NULL; /* Object header */
+ H5O_ainfo_t ainfo; /* Attribute information for object */
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_open_by_idx)
@@ -584,12 +614,103 @@ H5O_attr_open_by_idx(const H5O_loc_t *loc, H5_index_t idx_type,
if(H5O_attr_iterate_real((hid_t)-1, loc, dxpl_id, idx_type, order, n, NULL, &attr_op, &ret_value) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_BADITER, NULL, "can't locate attribute")
+
+ /* Protect the object header to iterate over */
+ if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, NULL, "unable to load object header")
+
+ /* Check for attribute info stored */
+ ainfo.fheap_addr = HADDR_UNDEF;
+ if(oh->version > H5O_VERSION_1 && NULL == H5A_get_ainfo(loc->file, dxpl_id, oh, &ainfo))
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+
+ /* If the opened attribute is in dense storage, find out whether it has already been
+ * opened. If it has, close the object and make a copy of the already opened object
+ * to share the object info. */
+ if(H5F_addr_defined(ainfo.fheap_addr) && ret_value) {
+ if((found_open_attr = H5O_attr_find_opened_attr(loc, &exist_attr,
+ ret_value->shared->name)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "failed in finding opened attribute")
+
+ /* If found that the attribute is already opened, make a copy of it
+ and close the object just opened. */
+ if(found_open_attr && exist_attr) {
+ if(H5A_close(ret_value) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCLOSEOBJ, NULL, "can't close attribute")
+
+ if(NULL == (ret_value = H5A_copy(NULL, exist_attr)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "can't copy existing attribute")
+ }
+ }
+
done:
+ if(oh && H5AC_unprotect(loc->file, H5AC_ind_dxpl_id, H5AC_OHDR, loc->addr, oh,
+ H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_PROTECT, NULL, "unable to release object header")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_attr_open_by_idx() */
/*-------------------------------------------------------------------------
+ * Function: H5O_attr_find_opened_attr
+ *
+ * Purpose: Find out whether an attribute has been opened by giving
+ * the name. Return the pointer to the object if found.
+ *
+ * Return: TRUE: found the already opened object
+ * FALSE: didn't find the opened object
+ * FAIL: function failed.
+ *
+ * Programmer: Raymond Lu
+ * 23 June 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static
+htri_t H5O_attr_find_opened_attr(const H5O_loc_t *loc, H5A_t **attr, const char* name_to_open)
+{
+ htri_t ret_value = FALSE;
+ int num_open_attr = 0;
+ ssize_t name_len = 0;
+ hid_t *attr_id_list = NULL;
+ int i;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_attr_find_opened_attr)
+
+ /* Count all opened attributes */
+ if((num_open_attr = H5F_get_obj_count(loc->file, H5F_OBJ_ATTR)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "can't get number of opened attributes")
+
+ /* Find out whether the attribute has been opened */
+ if(num_open_attr) {
+ attr_id_list = (hid_t*)H5MM_malloc(num_open_attr*sizeof(hid_t));
+
+ /* Retrieve the IDs of all opened attributes */
+ if(H5F_get_obj_ids(loc->file, H5F_OBJ_ATTR, num_open_attr, attr_id_list) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't IDs of opened attributes")
+
+ for(i=0; i<num_open_attr; i++) {
+ if(NULL == (*attr = (H5A_t *)H5I_object_verify(attr_id_list[i], H5I_ATTR)))
+ HGOTO_ERROR(H5E_ATTR, H5E_BADTYPE, FAIL, "not an attribute")
+
+ /* Verify whether it's the right object */
+ if(!strcmp(name_to_open, (*attr)->shared->name) && loc->addr ==
+ (*attr)->shared->oloc.addr) {
+ ret_value = TRUE;
+ break;
+ }
+ }
+ H5MM_free(attr_id_list);
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_attr_find_opened_attr */
+
+
+/*-------------------------------------------------------------------------
* Function: H5O_attr_update_shared
*
* Purpose: Update a shared attribute.
@@ -677,6 +798,10 @@ done:
* koziol@hdfgroup.org
* Dec 4 2006
*
+ * Modification:Raymond Lu
+ * 4 June 2008
+ * Took out the data copying part because the attribute data
+ * is shared between attribute handle and object header.
*-------------------------------------------------------------------------
*/
static herr_t
@@ -694,18 +819,7 @@ H5O_attr_write_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
HDassert(!udata->found);
/* 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 into the header message */
- /* (Needs to occur before updating the shared message, or the hash
- * value on the old & new messages will be the same)
- */
- HDmemcpy(((H5A_t *)mesg->native)->data, udata->attr->data, udata->attr->data_size);
-
+ if(HDstrcmp(((H5A_t *)mesg->native)->shared->name, udata->attr->shared->name) == 0) {
/* Update the shared attribute in the SOHM storage */
if(mesg->flags & H5O_MSG_FLAG_SHARED)
if(H5O_attr_update_shared(udata->f, udata->dxpl_id, oh, udata->attr, (H5O_shared_t *)mesg->native) < 0)
@@ -836,7 +950,7 @@ H5O_attr_rename_chk_cb(H5O_t UNUSED *oh, H5O_mesg_t *mesg/*in,out*/,
HDassert(!udata->found);
/* Check for existing attribute with new name */
- if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->new_name) == 0) {
+ if(HDstrcmp(((H5A_t *)mesg->native)->shared->name, udata->new_name) == 0) {
/* Indicate that we found an existing attribute with the new name*/
udata->found = TRUE;
@@ -882,12 +996,12 @@ H5O_attr_rename_mod_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
HDassert(!udata->found);
/* Find correct attribute message to rename */
- if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->old_name) == 0) {
- unsigned old_version = ((H5A_t *)mesg->native)->version; /* Old version of the attribute */
+ if(HDstrcmp(((H5A_t *)mesg->native)->shared->name, udata->old_name) == 0) {
+ unsigned old_version = ((H5A_t *)mesg->native)->shared->version; /* Old version of the attribute */
/* Change the name for the attribute */
- H5MM_xfree(((H5A_t *)mesg->native)->name);
- ((H5A_t *)mesg->native)->name = H5MM_xstrdup(udata->new_name);
+ H5MM_xfree(((H5A_t *)mesg->native)->shared->name);
+ ((H5A_t *)mesg->native)->shared->name = H5MM_xstrdup(udata->new_name);
/* Recompute the version to encode the attribute with */
if(H5A_set_version(udata->f, ((H5A_t *)mesg->native)) < 0)
@@ -908,7 +1022,7 @@ H5O_attr_rename_mod_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
/* Check for attribute message changing size */
if(HDstrlen(udata->new_name) != HDstrlen(udata->old_name) ||
- old_version != ((H5A_t *)mesg->native)->version) {
+ old_version != ((H5A_t *)mesg->native)->shared->version) {
H5A_t *attr; /* Attribute to re-add */
/* Take ownership of the message's native info (the attribute)
@@ -939,8 +1053,8 @@ H5O_attr_rename_mod_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
/* Sanity check */
HDassert(H5O_msg_is_shared(H5O_ATTR_ID, attr) == FALSE);
- /* Release the local copy of the attribute */
- H5O_msg_free_real(H5O_MSG_ATTR, attr);
+ /* Close the local copy of the attribute */
+ H5A_close(attr);
} /* end if */
} /* end else */
@@ -1184,6 +1298,13 @@ done:
* Programmer: Quincey Koziol
* Wednesday, February 14, 2007
*
+ * Modification:Raymond Lu
+ * 24 June 2008
+ * When converting storage from dense to compact, if found
+ * the attribute is already opened, use the opened message
+ * to insert. If not, still use the message in the attribute
+ * table. This will guarantee that the attribute message is
+ * shared.
*-------------------------------------------------------------------------
*/
static herr_t
@@ -1217,35 +1338,51 @@ H5O_attr_remove_update(const H5O_loc_t *loc, H5O_t *oh, H5O_ainfo_t *ainfo,
* can't fit into an object header message)
*/
for(u = 0; u < ainfo->nattrs; u++)
- if(H5O_msg_size_oh(loc->file, oh, H5O_ATTR_ID, &(atable.attrs[u]), (size_t)0) >= H5O_MESG_MAX_SIZE) {
+ if(H5O_msg_size_oh(loc->file, oh, H5O_ATTR_ID, (atable.attrs[u]), (size_t)0) >= H5O_MESG_MAX_SIZE) {
can_convert = FALSE;
break;
} /* end if */
/* If ok, insert attributes as object header messages */
if(can_convert) {
+ H5A_t *exist_attr = NULL;
+ htri_t found_open_attr = FALSE;
+
/* Iterate over attributes, to put them into header */
for(u = 0; u < ainfo->nattrs; u++) {
htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */
/* Check if attribute is shared */
- if((shared_mesg = H5O_msg_is_shared(H5O_ATTR_ID, &(atable.attrs[u]))) < 0)
+ if((shared_mesg = H5O_msg_is_shared(H5O_ATTR_ID, (atable.attrs[u]))) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "error determining if message is shared")
else if(shared_mesg == 0) {
/* Increment reference count on attribute components */
/* (so that they aren't deleted when the dense attribute storage is deleted) */
- if(H5O_attr_link(loc->file, dxpl_id, oh, &(atable.attrs[u])) < 0)
+ if(H5O_attr_link(loc->file, dxpl_id, oh, (atable.attrs[u])) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust attribute link count")
} /* end if */
else {
/* Reset 'shared' status, so attribute will be shared again */
- atable.attrs[u].sh_loc.type = H5O_SHARE_TYPE_UNSHARED;
+ (atable.attrs[u])->sh_loc.type = H5O_SHARE_TYPE_UNSHARED;
} /* end else */
- /* Insert attribute message into object header */
- /* (Will increment reference count on shared attributes) */
- if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_ATTR, 0, 0, &(atable.attrs[u])) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "can't create message")
+ /* Insert attribute message into object header (Will increment
+ reference count on shared attributes) */
+ /* Find out whether the attribute has been opened */
+ if((found_open_attr = H5O_attr_find_opened_attr(loc, &exist_attr,
+ (atable.attrs[u])->shared->name)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "failed in finding opened attribute")
+
+ /* If found the attribute is already opened, use the opened message to insert.
+ If not, still use the message in the attribute table. */
+ if(found_open_attr && exist_attr) {
+ if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_ATTR, 0, 0, exist_attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "can't create message")
+
+ } else {
+ if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_ATTR, 0, 0, (atable.attrs[u])) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "can't create message")
+ }
} /* end for */
/* Remove the dense storage */
@@ -1304,7 +1441,7 @@ H5O_attr_remove_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
HDassert(!udata->found);
/* Check for correct attribute message to modify */
- if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->name) == 0) {
+ if(HDstrcmp(((H5A_t *)mesg->native)->shared->name, udata->name) == 0) {
/* Convert message into a null message (i.e. delete it) */
if(H5O_release_mesg(udata->f, udata->dxpl_id, oh, mesg, TRUE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, H5_ITER_ERROR, "unable to convert into null message")
@@ -1468,7 +1605,7 @@ H5O_attr_remove_by_idx(const H5O_loc_t *loc, H5_index_t idx_type,
/* Set up user data for callback, to remove the attribute by name */
udata.f = loc->file;
udata.dxpl_id = dxpl_id;
- udata.name = atable.attrs[n].name;
+ udata.name = ((atable.attrs[n])->shared)->name;
udata.found = FALSE;
/* Iterate over attributes, to locate correct one to delete */
@@ -1582,7 +1719,7 @@ H5O_attr_exists_cb(H5O_t UNUSED *oh, H5O_mesg_t *mesg/*in,out*/,
HDassert(!udata->found);
/* Check for correct attribute message */
- if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->name) == 0) {
+ if(HDstrcmp(((H5A_t *)mesg->native)->shared->name, udata->name) == 0) {
/* Indicate that this message is the attribute sought */
udata->found = TRUE;
diff --git a/src/H5Tcompound.c b/src/H5Tcompound.c
index 94439cc..dc7ae23 100644
--- a/src/H5Tcompound.c
+++ b/src/H5Tcompound.c
@@ -560,7 +560,7 @@ H5T_pack(const H5T_t *dt)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to pack part of a compound datatype")
/* Update the member size */
- dt->shared->u.compnd.memb[i].size = dt->shared->u.compnd.memb[i].type->shared->size;
+ dt->shared->u.compnd.memb[i].size = (dt->shared->u.compnd.memb[i].type)->shared->size;
}
/* Remove padding between members */
diff --git a/test/dtypes.c b/test/dtypes.c
index cf4c2ea..c469be1 100644
--- a/test/dtypes.c
+++ b/test/dtypes.c
@@ -1525,7 +1525,7 @@ test_compound_8(void)
if(tsize != (sizeof(char) + sizeof(char) + sizeof(int))) {
H5_FAILED(); AT();
- printf("The size of the packed compound datatype is incorrect\n");
+ printf("The size of the packed compound datatype is incorrect: tsize=%d\n", tsize);
goto error;
} /* end if */
@@ -5042,6 +5042,7 @@ main(void)
nerrors += test_detect();
nerrors += test_compound_1();
nerrors += test_query();
+
nerrors += test_transient(fapl);
nerrors += test_named(fapl);
nerrors += test_encode();
diff --git a/test/objcopy.c b/test/objcopy.c
index 5fdbdba..e82c2f6 100755
--- a/test/objcopy.c
+++ b/test/objcopy.c
@@ -7226,6 +7226,7 @@ main(void)
nerrors += test_copy_dataset_simple_empty(fcpl_src, fcpl_dst, my_fapl);
nerrors += test_copy_dataset_compound(fcpl_src, fcpl_dst, my_fapl);
nerrors += test_copy_dataset_chunked(fcpl_src, fcpl_dst, my_fapl);
+
nerrors += test_copy_dataset_chunked_empty(fcpl_src, fcpl_dst, my_fapl);
nerrors += test_copy_dataset_chunked_sparse(fcpl_src, fcpl_dst, my_fapl);
nerrors += test_copy_dataset_compressed(fcpl_src, fcpl_dst, my_fapl);
@@ -7236,6 +7237,7 @@ main(void)
nerrors += test_copy_dataset_named_dtype_hier_outside(fcpl_src, fcpl_dst, my_fapl);
nerrors += test_copy_dataset_multi_ohdr_chunks(fcpl_src, fcpl_dst, my_fapl);
nerrors += test_copy_dataset_attr_named_dtype(fcpl_src, fcpl_dst, my_fapl);
+
nerrors += test_copy_dataset_contig_vl(fcpl_src, fcpl_dst, my_fapl);
nerrors += test_copy_dataset_chunked_vl(fcpl_src, fcpl_dst, my_fapl);
nerrors += test_copy_dataset_compact_vl(fcpl_src, fcpl_dst, my_fapl);
diff --git a/test/tattr.c b/test/tattr.c
index 12350c3..2edca05 100644
--- a/test/tattr.c
+++ b/test/tattr.c
@@ -191,7 +191,6 @@ test_attr_basic_write(hid_t fapl)
sid2 = H5Screate_simple(ATTR1_RANK, dims2, NULL);
CHECK(sid2, FAIL, "H5Screate_simple");
-
/* Try to create an attribute on the file (should create an attribute on root group) */
attr = H5Acreate2(fid1, ATTR1_NAME, H5T_NATIVE_INT, sid2, H5P_DEFAULT, H5P_DEFAULT);
CHECK(attr, FAIL, "H5Acreate2");
@@ -216,7 +215,6 @@ test_attr_basic_write(hid_t fapl)
ret = H5Gclose(group);
CHECK(ret, FAIL, "H5Gclose");
-
/* Create an attribute for the dataset */
attr = H5Acreate2(dataset, ATTR1_NAME, H5T_NATIVE_INT, sid2, H5P_DEFAULT, H5P_DEFAULT);
CHECK(attr, FAIL, "H5Acreate2");
@@ -1779,6 +1777,255 @@ test_attr_dtype_shared(hid_t fapl)
/****************************************************************
**
+** test_attr_duplicate_ids(): Test operations with more than
+** one ID handles.
+**
+****************************************************************/
+static int
+test_attr_duplicate_ids(hid_t fapl)
+{
+ hid_t fid1; /* HDF5 File IDs */
+ hid_t dataset; /* Dataset ID */
+ hid_t gid1, gid2; /* Group ID */
+ hid_t sid1,sid2; /* Dataspace ID */
+ hid_t attr, attr2; /* Attribute ID */
+ hsize_t attr_size; /* storage size for attribute */
+ ssize_t attr_name_size; /* size of attribute name */
+ char *attr_name=NULL; /* name of attribute */
+ hsize_t dims1[] = {SPACE1_DIM1, SPACE1_DIM2, SPACE1_DIM3};
+ hsize_t dims2[] = {ATTR1_DIM1};
+ hsize_t dims3[] = {ATTR2_DIM1,ATTR2_DIM2};
+ int read_data1[ATTR1_DIM1]={0}; /* Buffer for reading 1st attribute */
+ int rewrite_data[ATTR1_DIM1]={1234, -423, 9907256}; /* Test data for rewrite */
+ int i;
+ herr_t ret; /* Generic return value */
+
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing operations with two ID handles\n"));
+
+ /*-----------------------------------------------------------------------------------
+ * Create an attribute in a new file and fill it with fill value.
+ */
+ /* Create file */
+ fid1 = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
+ CHECK(fid1, FAIL, "H5Fcreate");
+
+ /* Create dataspace for dataset */
+ sid1 = H5Screate_simple(SPACE1_RANK, dims1, NULL);
+ CHECK(sid1, FAIL, "H5Screate_simple");
+
+ /* Create a dataset */
+ dataset = H5Dcreate2(fid1, DSET1_NAME, H5T_NATIVE_UCHAR, sid1, H5P_DEFAULT,
+ H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(dataset, FAIL, "H5Dcreate2");
+
+ /* Create dataspace for attribute */
+ sid2 = H5Screate_simple(ATTR1_RANK, dims2, NULL);
+ CHECK(sid2, FAIL, "H5Screate_simple");
+
+ /* Try to create an attribute on the dataset */
+ attr = H5Acreate2(dataset, ATTR1_NAME, H5T_NATIVE_INT, sid2, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(attr, FAIL, "H5Acreate2");
+
+ /* Open the attribute just created and get a second ID */
+ attr2 = H5Aopen(dataset, ATTR1_NAME, H5P_DEFAULT);
+ CHECK(attr2, FAIL, "H5Aopen");
+
+ /* Close attribute */
+ ret = H5Aclose(attr2);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ /* Close attribute */
+ ret = H5Aclose(attr);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ /* Close Dataset */
+ ret = H5Dclose(dataset);
+ CHECK(ret, FAIL, "H5Dclose");
+
+ /* Close file */
+ ret = H5Fclose(fid1);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*-----------------------------------------------------------------------------------
+ * Reopen the file and verify the fill value for attribute. Also write
+ * some real data.
+ */
+
+ /* Open file */
+ fid1 = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
+ CHECK(fid1, FAIL, "H5Fopen");
+
+ /* Open the dataset */
+ dataset = H5Dopen2(fid1, DSET1_NAME, H5P_DEFAULT);
+ CHECK(dataset, FAIL, "H5Dopen2");
+
+ /* Open first attribute for the dataset */
+ attr = H5Aopen(dataset, ATTR1_NAME, H5P_DEFAULT);
+ CHECK(attr, FAIL, "H5Aopen");
+
+ /* Read attribute with fill value */
+ ret = H5Aread(attr, H5T_NATIVE_INT, read_data1);
+ CHECK(ret, FAIL, "H5Aread");
+
+ /* Verify values read in */
+ for(i = 0; i < ATTR1_DIM1; i++)
+ if(0 != read_data1[i])
+ TestErrPrintf("%d: attribute data different: read_data1[%d]=%d\n", __LINE__, i, read_data1[i]);
+
+ /* Open attribute for the second time */
+ attr2 = H5Aopen(dataset, ATTR1_NAME, H5P_DEFAULT);
+ CHECK(attr, FAIL, "H5Aopen");
+
+ /* Write attribute information */
+ ret = H5Awrite(attr2, H5T_NATIVE_INT, attr_data1);
+ CHECK(ret, FAIL, "H5Awrite");
+
+ /* Close attribute */
+ ret = H5Aclose(attr2);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ /* Close attribute */
+ ret = H5Aclose(attr);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ /* Close Dataset */
+ ret = H5Dclose(dataset);
+ CHECK(ret, FAIL, "H5Dclose");
+
+ /* Close file */
+ ret = H5Fclose(fid1);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*-----------------------------------------------------------------------------------
+ * Reopen the file and verify the data. Also rewrite the data and verify it.
+ */
+
+ /* Open file */
+ fid1 = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
+ CHECK(fid1, FAIL, "H5Fopen");
+
+ /* Open the dataset */
+ dataset = H5Dopen2(fid1, DSET1_NAME, H5P_DEFAULT);
+ CHECK(dataset, FAIL, "H5Dopen2");
+
+ /* Open first attribute for the dataset */
+ attr = H5Aopen(dataset, ATTR1_NAME, H5P_DEFAULT);
+ CHECK(attr, FAIL, "H5Aopen");
+
+ /* Read attribute information */
+ ret = H5Aread(attr, H5T_NATIVE_INT, read_data1);
+ CHECK(ret, FAIL, "H5Aread");
+
+ /* Verify values read in */
+ for(i = 0; i < ATTR1_DIM1; i++)
+ if(attr_data1[i] != read_data1[i])
+ TestErrPrintf("%d: attribute data different: attr_data1[%d]=%d, read_data1[%d]=%d\n", __LINE__, i, attr_data1[i], i, read_data1[i]);
+
+ /* Open attribute for the second time */
+ attr2 = H5Aopen(dataset, ATTR1_NAME, H5P_DEFAULT);
+ CHECK(attr, FAIL, "H5Aopen");
+
+ /* Write attribute information */
+ ret = H5Awrite(attr2, H5T_NATIVE_INT, rewrite_data);
+ CHECK(ret, FAIL, "H5Awrite");
+
+ /* Read attribute information */
+ ret = H5Aread(attr, H5T_NATIVE_INT, read_data1);
+ CHECK(ret, FAIL, "H5Aread");
+
+ /* Verify values read in */
+ for(i = 0; i < ATTR1_DIM1; i++)
+ if(read_data1[i] != rewrite_data[i])
+ TestErrPrintf("%d: attribute data different: read_data1[%d]=%d, rewrite_data[%d]=%d\n", __LINE__, i, read_data1[i], i, rewrite_data[i]);
+
+ /* Close attribute */
+ ret = H5Aclose(attr);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ ret = H5Aclose(attr2);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ /* Close Dataset */
+ ret = H5Dclose(dataset);
+ CHECK(ret, FAIL, "H5Dclose");
+
+ /* Close file */
+ ret = H5Fclose(fid1);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*-----------------------------------------------------------------------------------
+ * Verify that the attribute being pointed to by different paths shares
+ * the same data.
+ */
+ /* Open file */
+ fid1 = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
+ CHECK(fid1, FAIL, "H5Fopen");
+
+ /* Create a group */
+ gid1 = H5Gcreate2(fid1, GROUP1_NAME, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(gid1, FAIL, "H5Gcreate2");
+
+ /* Create hard link to the first group */
+ ret = H5Lcreate_hard(gid1, GROUP1_NAME, H5L_SAME_LOC, GROUP2_NAME, H5P_DEFAULT,
+ H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Lcreate_hard");
+
+ /* Try to create an attribute on the group */
+ attr = H5Acreate2(gid1, ATTR2_NAME, H5T_NATIVE_INT, sid2, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(attr, FAIL, "H5Acreate2");
+
+ /* Open the hard link just created */
+ gid2 = H5Gopen2(fid1, GROUP2_NAME, H5P_DEFAULT);
+ CHECK(gid2, FAIL, "H5Gopen2");
+
+ /* Open the attribute of the group for the second time */
+ attr2 = H5Aopen(gid2, ATTR2_NAME, H5P_DEFAULT);
+ CHECK(attr2, FAIL, "H5Aopen");
+
+ /* Write attribute information with the first attribute handle */
+ ret = H5Awrite(attr, H5T_NATIVE_INT, attr_data1);
+ CHECK(ret, FAIL, "H5Awrite");
+
+ /* Read attribute information with the second attribute handle */
+ ret = H5Aread(attr2, H5T_NATIVE_INT, read_data1);
+ CHECK(ret, FAIL, "H5Aread");
+
+ /* Verify values read in */
+ for(i = 0; i < ATTR1_DIM1; i++)
+ if(attr_data1[i] != read_data1[i])
+ TestErrPrintf("%d: attribute data different: attr_data1[%d]=%d, read_data1[%d]=%d\n", __LINE__, i, attr_data1[i], i, read_data1[i]);
+
+ /* Close attribute */
+ ret = H5Aclose(attr);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ ret = H5Aclose(attr2);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ /* Close group */
+ ret = H5Gclose(gid1);
+ CHECK(ret, FAIL, "H5Gclose");
+
+ ret = H5Gclose(gid2);
+ CHECK(ret, FAIL, "H5Gclose");
+
+ /* Close Attribute dataspace */
+ ret = H5Sclose(sid2);
+ CHECK(ret, FAIL, "H5Sclose");
+
+ /* Close Dataset dataspace */
+ ret = H5Sclose(sid1);
+ CHECK(ret, FAIL, "H5Sclose");
+
+ /* Close file */
+ ret = H5Fclose(fid1);
+ CHECK(ret, FAIL, "H5Fclose");
+} /* test_attr_duplicate_ids() */
+
+
+/****************************************************************
+**
** test_attr_dense_verify(): Test basic H5A (attribute) code.
** Verify attributes on object
**
@@ -2751,6 +2998,529 @@ test_attr_dense_limits(hid_t fcpl, hid_t fapl)
/****************************************************************
**
+** test_attr_dense_dup_ids(): Test operations with multiple ID
+** handles with "dense" attribute storage creation
+**
+****************************************************************/
+static void
+test_attr_dense_dup_ids(hid_t fcpl, hid_t fapl)
+{
+ hid_t fid; /* HDF5 File ID */
+ hid_t dataset; /* Dataset ID */
+ hid_t gid1, gid2; /* Group ID */
+ hid_t sid, sid2; /* Dataspace ID */
+ hid_t attr, attr2, add_attr; /* Attribute ID */
+ hid_t dcpl; /* Dataset creation property list ID */
+ char attrname[NAME_BUF_SIZE]; /* Name of attribute */
+ hsize_t dims[] = {ATTR1_DIM1};
+ int read_data1[ATTR1_DIM1]={0}; /* Buffer for reading attribute */
+ int rewrite_data[ATTR1_DIM1]={1234, -423, 9907256}; /* Test data for rewrite */
+ unsigned scalar_data = 1317; /* scalar data for attribute */
+ unsigned read_scalar; /* variable for reading attribute*/
+ unsigned max_compact; /* Maximum # of attributes to store compactly */
+ unsigned min_dense; /* Minimum # of attributes to store "densely" */
+ htri_t is_dense; /* Are attributes stored densely? */
+ unsigned u, i; /* Local index variable */
+ herr_t ret; /* Generic return value */
+
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing operations with two IDs for Dense Storage\n"));
+
+ /*-----------------------------------------------------------------------------------
+ * Create an attribute in dense storage and fill it with fill value.
+ */
+ /* Create file */
+ fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl);
+ CHECK(fid, FAIL, "H5Fcreate");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Re-open file */
+ fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Create dataspace for dataset */
+ sid = H5Screate(H5S_SCALAR);
+ CHECK(sid, FAIL, "H5Screate");
+
+ /* Query the group creation properties */
+ dcpl = H5Pcreate(H5P_DATASET_CREATE);
+ CHECK(dcpl, FAIL, "H5Pcreate");
+
+ /* Create a dataset */
+ dataset = H5Dcreate2(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT);
+ CHECK(dataset, FAIL, "H5Dcreate2");
+
+ /* Retrieve limits for compact/dense attribute storage */
+ ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense);
+ CHECK(ret, FAIL, "H5Pget_attr_phase_change");
+
+ /* Close property list */
+ ret = H5Pclose(dcpl);
+ CHECK(ret, FAIL, "H5Pclose");
+
+ /* Check on dataset's attribute storage status */
+ is_dense = H5O_is_attr_dense_test(dataset);
+ VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
+
+ /* Add attributes, until just before converting to dense storage */
+ for(u = 0; u < max_compact; u++) {
+ /* Create attribute */
+ sprintf(attrname, "attr %02u", u);
+ attr = H5Acreate2(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(attr, FAIL, "H5Acreate2");
+
+ /* Write data into the attribute */
+ ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
+ CHECK(ret, FAIL, "H5Awrite");
+
+ /* Close attribute */
+ ret = H5Aclose(attr);
+ CHECK(ret, FAIL, "H5Aclose");
+ } /* end for */
+
+ /* Check on dataset's attribute storage status */
+ is_dense = H5O_is_attr_dense_test(dataset);
+ VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
+
+ /* Add one more attribute, to push into "dense" storage */
+ /* Create dataspace for attribute */
+ sid2 = H5Screate_simple(ATTR1_RANK, dims, NULL);
+ CHECK(sid2, FAIL, "H5Screate_simple");
+
+ /* Create attribute */
+ sprintf(attrname, "attr %02u", u);
+ attr = H5Acreate2(dataset, attrname, H5T_NATIVE_INT, sid2, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(attr, FAIL, "H5Acreate2");
+
+ /* Check on dataset's attribute storage status */
+ is_dense = H5O_is_attr_dense_test(dataset);
+ VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");
+
+ /* Open the attribute just created and get a second ID */
+ attr2 = H5Aopen(dataset, attrname, H5P_DEFAULT);
+ CHECK(attr2, FAIL, "H5Aopen");
+
+ /* Close attribute */
+ ret = H5Aclose(attr);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ ret = H5Aclose(attr2);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ /* Close Dataset */
+ ret = H5Dclose(dataset);
+ CHECK(ret, FAIL, "H5Dclose");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*-----------------------------------------------------------------------------------
+ * Reopen the file and verify the fill value for attribute. Also write
+ * some real data.
+ */
+ /* Open file */
+ fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Open the dataset */
+ dataset = H5Dopen2(fid, DSET1_NAME, H5P_DEFAULT);
+ CHECK(dataset, FAIL, "H5Dopen2");
+
+ /* Check on dataset's attribute storage status */
+ is_dense = H5O_is_attr_dense_test(dataset);
+ VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");
+
+ /* Open first attribute for the dataset */
+ attr = H5Aopen(dataset, attrname, H5P_DEFAULT);
+ CHECK(attr, FAIL, "H5Aopen");
+
+ /* Read attribute with fill value */
+ ret = H5Aread(attr, H5T_NATIVE_INT, read_data1);
+ CHECK(ret, FAIL, "H5Aread");
+
+ /* Verify values read in */
+ for(i = 0; i < ATTR1_DIM1; i++)
+ if(0 != read_data1[i])
+ TestErrPrintf("%d: attribute data different: read_data1[%d]=%d\n", __LINE__,
+ i, read_data1[i]);
+
+ /* Open attribute for the second time */
+ attr2 = H5Aopen(dataset, attrname, H5P_DEFAULT);
+ CHECK(attr, FAIL, "H5Aopen");
+
+ /* Write attribute information */
+ ret = H5Awrite(attr2, H5T_NATIVE_INT, attr_data1);
+ CHECK(ret, FAIL, "H5Awrite");
+
+ /* Close attribute */
+ ret = H5Aclose(attr2);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ /* Close attribute */
+ ret = H5Aclose(attr);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ /* Close Dataset */
+ ret = H5Dclose(dataset);
+ CHECK(ret, FAIL, "H5Dclose");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*-----------------------------------------------------------------------------------
+ * Reopen the file and verify the data. Also rewrite the data and verify it.
+ */
+ /* Open file */
+ fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Open the dataset */
+ dataset = H5Dopen2(fid, DSET1_NAME, H5P_DEFAULT);
+ CHECK(dataset, FAIL, "H5Dopen2");
+
+ /* Check on dataset's attribute storage status */
+ is_dense = H5O_is_attr_dense_test(dataset);
+ VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");
+
+ /* Open first attribute for the dataset */
+ attr = H5Aopen(dataset, attrname, H5P_DEFAULT);
+ CHECK(attr, FAIL, "H5Aopen");
+
+ /* Read attribute information */
+ ret = H5Aread(attr, H5T_NATIVE_INT, read_data1);
+ CHECK(ret, FAIL, "H5Aread");
+
+ /* Verify values read in */
+ for(i = 0; i < ATTR1_DIM1; i++)
+ if(attr_data1[i] != read_data1[i])
+ TestErrPrintf("%d: attribute data different: attr_data1[%d]=%d, read_data1[%d]=%d\n", __LINE__, i, attr_data1[i], i, read_data1[i]);
+
+ /* Open attribute for the second time */
+ attr2 = H5Aopen(dataset, attrname, H5P_DEFAULT);
+ CHECK(attr, FAIL, "H5Aopen");
+
+ /* Write attribute information with the second ID */
+ ret = H5Awrite(attr2, H5T_NATIVE_INT, rewrite_data);
+ CHECK(ret, FAIL, "H5Awrite");
+
+ /* Read attribute information with the first ID */
+ ret = H5Aread(attr, H5T_NATIVE_INT, read_data1);
+ CHECK(ret, FAIL, "H5Aread");
+
+ /* Verify values read in */
+ for(i = 0; i < ATTR1_DIM1; i++)
+ if(read_data1[i] != rewrite_data[i])
+ TestErrPrintf("%d: attribute data different: read_data1[%d]=%d, rewrite_data[%d]=%d\n", __LINE__, i, read_data1[i], i, rewrite_data[i]);
+
+ /* Close attribute */
+ ret = H5Aclose(attr);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ ret = H5Aclose(attr2);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ /* Close Dataset */
+ ret = H5Dclose(dataset);
+ CHECK(ret, FAIL, "H5Dclose");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*-----------------------------------------------------------------------------------
+ * Open the attribute by index. Verify the data is shared when the attribute
+ * is opened twice.
+ */
+ /* Open file */
+ fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Open the dataset */
+ dataset = H5Dopen2(fid, DSET1_NAME, H5P_DEFAULT);
+ CHECK(dataset, FAIL, "H5Dopen2");
+
+ /* Check on dataset's attribute storage status */
+ is_dense = H5O_is_attr_dense_test(dataset);
+ VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");
+
+ /* Open first attribute for the dataset */
+ attr = H5Aopen_by_idx(dataset, ".", H5_INDEX_NAME, H5_ITER_INC, 4,
+ H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(attr, FAIL, "H5Aopen");
+
+ /* Open attribute for the second time */
+ attr2 = H5Aopen_by_idx(dataset, ".", H5_INDEX_NAME, H5_ITER_INC, 4,
+ H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(attr, FAIL, "H5Aopen");
+
+ /* Write attribute information with the second ID */
+ ret = H5Awrite(attr2, H5T_NATIVE_UINT, &scalar_data);
+ CHECK(ret, FAIL, "H5Awrite");
+
+ /* Read attribute information with the first ID */
+ ret = H5Aread(attr, H5T_NATIVE_INT, &read_scalar);
+ CHECK(ret, FAIL, "H5Aread");
+
+ /* Verify values read in */
+ if(read_scalar != scalar_data)
+ TestErrPrintf("%d: attribute data different: read_scalar=%d, scalar_data=%d\n",
+ __LINE__, read_scalar, scalar_data);
+
+ /* Close attribute */
+ ret = H5Aclose(attr);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ ret = H5Aclose(attr2);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ /* Close Dataset */
+ ret = H5Dclose(dataset);
+ CHECK(ret, FAIL, "H5Dclose");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*-----------------------------------------------------------------------------------
+ * Open one attribute. As it remains open, delete some attributes. The
+ * attribute storage should switch from dense to compact. Then open the
+ * same attribute for the second time and verify that the attribute data
+ * is shared.
+ */
+ /* Open file */
+ fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Open the dataset */
+ dataset = H5Dopen2(fid, DSET1_NAME, H5P_DEFAULT);
+ CHECK(dataset, FAIL, "H5Dopen2");
+
+ /* Check on dataset's attribute storage status */
+ is_dense = H5O_is_attr_dense_test(dataset);
+ VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");
+
+ /* Open attribute of the dataset for the first time */
+ attr = H5Aopen_by_idx(dataset, ".", H5_INDEX_NAME, H5_ITER_INC, 2,
+ H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(attr, FAIL, "H5Aopen");
+
+ /* Delete a few attributes until the storage switches to compact */
+ for(u = max_compact; u >= min_dense - 1; u--) {
+ ret = H5Adelete_by_idx(dataset, ".", H5_INDEX_NAME, H5_ITER_INC, u,
+ H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Adelete_by_idx");
+ }
+
+ /* Check on dataset's attribute storage status */
+ is_dense = H5O_is_attr_dense_test(dataset);
+ VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
+
+ /* Open attribute for the second time */
+ attr2 = H5Aopen_by_idx(dataset, ".", H5_INDEX_NAME, H5_ITER_INC, 2,
+ H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(attr, FAIL, "H5Aopen");
+
+ /* Write attribute information with the second ID */
+ ret = H5Awrite(attr2, H5T_NATIVE_UINT, &scalar_data);
+ CHECK(ret, FAIL, "H5Awrite");
+
+ /* Read attribute information with the first ID */
+ ret = H5Aread(attr, H5T_NATIVE_INT, &read_scalar);
+ CHECK(ret, FAIL, "H5Aread");
+
+ /* Verify values read in */
+ if(read_scalar != scalar_data)
+ TestErrPrintf("%d: attribute data different: read_scalar=%d, scalar_data=%d\n",
+ __LINE__, read_scalar, scalar_data);
+
+ /* Close attribute */
+ ret = H5Aclose(attr);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ ret = H5Aclose(attr2);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ /* Close Dataset */
+ ret = H5Dclose(dataset);
+ CHECK(ret, FAIL, "H5Dclose");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*-----------------------------------------------------------------------------------
+ * Open one attribute. As it remains open, create some attributes. The
+ * attribute storage should switch from compact to dense. Then open the
+ * same attribute for the second time and verify that the attribute data
+ * is shared.
+ */
+ /* Open file */
+ fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Open the dataset */
+ dataset = H5Dopen2(fid, DSET1_NAME, H5P_DEFAULT);
+ CHECK(dataset, FAIL, "H5Dopen2");
+
+ /* Check on dataset's attribute storage status */
+ is_dense = H5O_is_attr_dense_test(dataset);
+ VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
+
+ /* Open attribute of the dataset for the first time */
+ attr = H5Aopen_by_idx(dataset, ".", H5_INDEX_NAME, H5_ITER_INC, 3,
+ H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(attr, FAIL, "H5Aopen");
+
+ /* Delete a few attributes until the storage switches to compact */
+ for(u = min_dense-1; u <= max_compact; u++) {
+ /* Create attribute */
+ sprintf(attrname, "attr %02u", u);
+ add_attr = H5Acreate2(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(add_attr, FAIL, "H5Acreate2");
+
+ /* Write data into the attribute */
+ ret = H5Awrite(add_attr, H5T_NATIVE_UINT, &u);
+ CHECK(ret, FAIL, "H5Awrite");
+
+ /* Close attribute */
+ ret = H5Aclose(add_attr);
+ CHECK(ret, FAIL, "H5Aclose");
+ }
+
+ /* Check on dataset's attribute storage status */
+ is_dense = H5O_is_attr_dense_test(dataset);
+ VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");
+
+ /* Open attribute for the second time */
+ attr2 = H5Aopen_by_idx(dataset, ".", H5_INDEX_NAME, H5_ITER_INC, 3,
+ H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(attr, FAIL, "H5Aopen");
+
+ /* Write attribute information with the second ID */
+ ret = H5Awrite(attr2, H5T_NATIVE_UINT, &scalar_data);
+ CHECK(ret, FAIL, "H5Awrite");
+
+ /* Read attribute information with the first ID */
+ ret = H5Aread(attr, H5T_NATIVE_INT, &read_scalar);
+ CHECK(ret, FAIL, "H5Aread");
+
+ /* Verify values read in */
+ if(read_scalar != scalar_data)
+ TestErrPrintf("%d: attribute data different: read_scalar=%d, scalar_data=%d\n",
+ __LINE__, read_scalar, scalar_data);
+
+ /* Close attribute */
+ ret = H5Aclose(attr);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ ret = H5Aclose(attr2);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ /* Close Dataset */
+ ret = H5Dclose(dataset);
+ CHECK(ret, FAIL, "H5Dclose");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /*-----------------------------------------------------------------------------------
+ * Verify that the attribute being pointed to by different paths shares
+ * the same data.
+ */
+ /* Open file */
+ fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Create a group */
+ gid1 = H5Gcreate2(fid, GROUP1_NAME, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(gid1, FAIL, "H5Gcreate2");
+
+ /* Create hard link to the first group */
+ ret = H5Lcreate_hard(gid1, GROUP1_NAME, H5L_SAME_LOC, GROUP2_NAME, H5P_DEFAULT,
+ H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Lcreate_hard");
+
+ /* Add attributes, until just before converting to dense storage */
+ for(u = 0; u < max_compact; u++) {
+ /* Create attribute */
+ sprintf(attrname, "attr %02u", u);
+ attr = H5Acreate2(gid1, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(attr, FAIL, "H5Acreate2");
+
+ /* Write data into the attribute */
+ ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
+ CHECK(ret, FAIL, "H5Awrite");
+
+ /* Close attribute */
+ ret = H5Aclose(attr);
+ CHECK(ret, FAIL, "H5Aclose");
+ } /* end for */
+
+ /* Try to create another attribute to make dense storage */
+ attr = H5Acreate2(gid1, ATTR2_NAME, H5T_NATIVE_INT, sid2, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(attr, FAIL, "H5Acreate2");
+
+ /* Check on group's attribute storage status */
+ is_dense = H5O_is_attr_dense_test(gid1);
+ VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");
+
+ /* Open the hard link just created */
+ gid2 = H5Gopen2(fid, GROUP2_NAME, H5P_DEFAULT);
+ CHECK(gid2, FAIL, "H5Gopen2");
+
+ /* Open the attribute of the group for the second time */
+ attr2 = H5Aopen(gid2, ATTR2_NAME, H5P_DEFAULT);
+ CHECK(attr2, FAIL, "H5Aopen");
+
+ /* Write attribute information with the first attribute handle */
+ ret = H5Awrite(attr, H5T_NATIVE_INT, attr_data1);
+ CHECK(ret, FAIL, "H5Awrite");
+
+ /* Read attribute information with the second attribute handle */
+ ret = H5Aread(attr2, H5T_NATIVE_INT, read_data1);
+ CHECK(ret, FAIL, "H5Aread");
+
+ /* Verify values read in */
+ for(i = 0; i < ATTR1_DIM1; i++)
+ if(attr_data1[i] != read_data1[i])
+ TestErrPrintf("%d: attribute data different: attr_data1[%d]=%d, read_data1[%d]=%d\n", __LINE__, i, attr_data1[i], i, read_data1[i]);
+
+ /* Close attribute */
+ ret = H5Aclose(attr);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ ret = H5Aclose(attr2);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ /* Close group */
+ ret = H5Gclose(gid1);
+ CHECK(ret, FAIL, "H5Gclose");
+
+ ret = H5Gclose(gid2);
+ CHECK(ret, FAIL, "H5Gclose");
+
+ /* Close Attribute dataspace */
+ ret = H5Sclose(sid);
+ CHECK(ret, FAIL, "H5Sclose");
+
+ /* Close Dataset dataspace */
+ ret = H5Sclose(sid2);
+ CHECK(ret, FAIL, "H5Sclose");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+} /* test_attr_dense_dup_ids() */
+
+
+/****************************************************************
+**
** test_attr_big(): Test basic H5A (attribute) code.
** Tests storing "big" attribute in dense storage immediately, if available
**
@@ -8925,6 +9695,9 @@ test_attr(void)
/* This next test uses its own file information */
test_attr_dtype_shared(my_fapl); /* Test using shared dataypes in attributes */
+ /* This next test uses its own file information */
+ test_attr_duplicate_ids(my_fapl);
+
/* Tests on "new format" attribute storage */
if(new_format == TRUE) {
/* Loop over using shared attributes */
@@ -8948,6 +9721,8 @@ test_attr(void)
test_attr_dense_rename(my_fcpl, my_fapl); /* Test renaming attributes in dense storage */
test_attr_dense_unlink(my_fcpl, my_fapl); /* Test unlinking object with attributes in dense storage */
test_attr_dense_limits(my_fcpl, my_fapl); /* Test dense attribute storage limits */
+ test_attr_dense_dup_ids(my_fcpl, my_fapl); /* Test duplicated IDs for dense attribute storage */
+
test_attr_big(my_fcpl, my_fapl); /* Test storing big attribute */
test_attr_null_space(my_fcpl, my_fapl); /* Test storing attribute with NULL dataspace */
test_attr_deprec(fcpl, my_fapl); /* Test deprecated API routines */
diff --git a/test/testhdf5.c b/test/testhdf5.c
index 4afbfe8..95ec90c 100644
--- a/test/testhdf5.c
+++ b/test/testhdf5.c
@@ -87,4 +87,4 @@ main(int argc, char *argv[])
TestCleanup();
return (GetTestNumErrs());
-} /* end main() */
+} /* end main() */
diff --git a/test/tsohm.c b/test/tsohm.c
index 0fc94f2..e213d25 100644
--- a/test/tsohm.c
+++ b/test/tsohm.c
@@ -974,13 +974,16 @@ static void sohm_attr_helper(hid_t fcpl_id)
hid_t type_id;
hid_t space_id;
hid_t group_id;
- hid_t attr_id;
+ hid_t attr_id, attr_id2;
hsize_t dims = 2;
int wdata[2] = {7, 42};
int rdata[2];
herr_t ret;
size_t x;
+ /*----------------------------------------------------------------------------
+ * Test attribute with transient datatype
+ */
/* Create a file using the fcpl */
file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
CHECK_I(file_id, "H5Fcreate");
@@ -1021,6 +1024,9 @@ static void sohm_attr_helper(hid_t fcpl_id)
ret = H5Aclose(attr_id);
CHECK_I(ret, "H5Aclose");
+ /*----------------------------------------------------------------------------
+ * Test attribute with committed datatype
+ */
/* Repeat with a committed datatype */
type_id = H5Tcopy(H5T_NATIVE_INT);
CHECK_I(type_id, "H5Tcopy");
@@ -1056,6 +1062,47 @@ static void sohm_attr_helper(hid_t fcpl_id)
/* Cleanup */
ret = H5Aclose(attr_id);
CHECK_I(ret, "H5Aclose");
+
+ /*----------------------------------------------------------------------------
+ * Test attribute operation with two ID handles
+ */
+ /* Create and verify an attribute */
+ group_id = H5Gcreate2(file_id, "yet_another_group", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK_I(group_id, "H5Gcreate2");
+
+ attr_id = H5Acreate2(group_id, "attribute", H5T_NATIVE_INT, space_id, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK_I(attr_id, "H5Acreate2");
+
+ /* Open the attribute to get another handle */
+ attr_id2 = H5Aopen(group_id, "attribute", H5P_DEFAULT);
+ CHECK_I(attr_id2, "H5Aopen");
+
+ ret = H5Awrite(attr_id, H5T_NATIVE_INT, wdata);
+ CHECK_I(ret, "H5Awrite");
+
+ /* Close the group */
+ ret = H5Gclose(group_id);
+ CHECK_I(ret, "H5Gclose");
+
+ /* Flush the file to force data to be written */
+ ret = H5Fflush(file_id, H5F_SCOPE_GLOBAL);
+ CHECK_I(ret, "H5Fflush");
+
+ /* Verify the data with another ID handle */
+ memset(rdata, 0, sizeof(rdata));
+ ret = H5Aread(attr_id2, H5T_NATIVE_INT, rdata);
+ CHECK_I(ret, "H5Aread");
+
+ for(x=0; x<(size_t)dims; ++x) {
+ VERIFY(rdata[x], wdata[x], "H5Aread");
+ }
+
+ /* Cleanup */
+ ret = H5Aclose(attr_id);
+ CHECK_I(ret, "H5Aclose");
+ ret = H5Aclose(attr_id2);
+ CHECK_I(ret, "H5Aclose");
+
ret = H5Sclose(space_id);
CHECK_I(ret, "H5Sclose");
ret = H5Fclose(file_id);