summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/H5Adense.c138
-rw-r--r--src/H5Aint.c17
-rw-r--r--src/H5Apkg.h28
-rw-r--r--src/H5Aprivate.h4
-rw-r--r--src/H5O.c33
-rw-r--r--src/H5Oainfo.c154
-rw-r--r--src/H5Oattr.c53
-rw-r--r--src/H5Oattribute.c466
-rw-r--r--src/H5Ocache.c26
-rw-r--r--src/H5Ocopy.c21
-rw-r--r--src/H5Odbg.c93
-rw-r--r--src/H5Omessage.c64
-rw-r--r--src/H5Opkg.h23
-rw-r--r--src/H5Oprivate.h4
-rw-r--r--src/H5Otest.c75
15 files changed, 687 insertions, 512 deletions
diff --git a/src/H5Adense.c b/src/H5Adense.c
index a1f9587..5a4f256 100644
--- a/src/H5Adense.c
+++ b/src/H5Adense.c
@@ -185,7 +185,7 @@ H5FL_BLK_DEFINE(ser_attr);
*-------------------------------------------------------------------------
*/
herr_t
-H5A_dense_create(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
+H5A_dense_create(H5F_t *f, hid_t dxpl_id, H5O_ainfo_t *ainfo)
{
H5HF_create_t fheap_cparam; /* Fractal heap creation parameters */
H5HF_t *fheap; /* Fractal heap handle */
@@ -198,7 +198,7 @@ H5A_dense_create(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
* Check arguments.
*/
HDassert(f);
- HDassert(oh);
+ HDassert(ainfo);
/* Set fractal heap creation parameters */
/* XXX: Give some control of these to applications? */
@@ -216,10 +216,10 @@ H5A_dense_create(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create fractal heap")
/* Retrieve the heap's address in the file */
- if(H5HF_get_heap_addr(fheap, &(oh->attr_fheap_addr)) < 0)
+ if(H5HF_get_heap_addr(fheap, &ainfo->fheap_addr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGETSIZE, FAIL, "can't get fractal heap address")
#ifdef QAK
-HDfprintf(stderr, "%s: oh->attr_fheap_addr = %a\n", FUNC, oh->attr_fheap_addr);
+HDfprintf(stderr, "%s: ainfo->fheap_addr = %a\n", FUNC, ainfo->fheap_addr);
#endif /* QAK */
#ifndef NDEBUG
@@ -248,14 +248,14 @@ HDfprintf(stderr, "%s: fheap_id_len = %Zu\n", FUNC, fheap_id_len);
if(H5B2_create(f, dxpl_id, H5A_BT2_NAME,
(size_t)H5A_NAME_BT2_NODE_SIZE, bt2_rrec_size,
H5A_NAME_BT2_SPLIT_PERC, H5A_NAME_BT2_MERGE_PERC,
- &(oh->name_bt2_addr)) < 0)
+ &ainfo->name_bt2_addr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create v2 B-tree for name index")
#ifdef QAK
-HDfprintf(stderr, "%s: oh->name_bt2_addr = %a\n", FUNC, oh->name_bt2_addr);
+HDfprintf(stderr, "%s: ainfo->name_bt2_addr = %a\n", FUNC, ainfo->name_bt2_addr);
#endif /* QAK */
/* Check if we should create a creation order index v2 B-tree */
- if(oh->flags & H5P_CRT_ORDER_INDEXED) {
+ if(ainfo->index_corder) {
/* Create the creation order index v2 B-tree */
bt2_rrec_size = 4 + /* Creation order index */
1 + /* Message flags */
@@ -263,10 +263,10 @@ HDfprintf(stderr, "%s: oh->name_bt2_addr = %a\n", FUNC, oh->name_bt2_addr);
if(H5B2_create(f, dxpl_id, H5A_BT2_CORDER,
(size_t)H5A_CORDER_BT2_NODE_SIZE, bt2_rrec_size,
H5A_CORDER_BT2_SPLIT_PERC, H5A_CORDER_BT2_MERGE_PERC,
- &(oh->corder_bt2_addr)) < 0)
+ &ainfo->corder_bt2_addr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create v2 B-tree for name index")
#ifdef QAK
-HDfprintf(stderr, "%s: oh->corder_bt2_addr = %a\n", FUNC, oh->corder_bt2_addr);
+HDfprintf(stderr, "%s: ainfo->corder_bt2_addr = %a\n", FUNC, ainfo->corder_bt2_addr);
#endif /* QAK */
} /* end if */
@@ -323,7 +323,7 @@ H5A_dense_fnd_cb(const H5A_t *attr, hbool_t *took_ownership, void *_user_attr)
*-------------------------------------------------------------------------
*/
H5A_t *
-H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *name)
+H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *name)
{
H5A_bt2_ud_common_t udata; /* User data for v2 B-tree modify */
H5HF_t *fheap = NULL; /* Fractal heap handle */
@@ -337,11 +337,11 @@ H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *name)
* Check arguments.
*/
HDassert(f);
- HDassert(oh);
+ HDassert(ainfo);
HDassert(name);
/* Open the fractal heap */
- if(NULL == (fheap = H5HF_open(f, dxpl_id, oh->attr_fheap_addr)))
+ if(NULL == (fheap = H5HF_open(f, dxpl_id, ainfo->fheap_addr)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to open fractal heap")
/* Check if attributes are shared in this file */
@@ -377,7 +377,7 @@ H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *name)
udata.found_op_data = &ret_value;
/* Find & copy the attribute in the 'name' index */
- if(H5B2_find(f, dxpl_id, H5A_BT2_NAME, oh->name_bt2_addr, &udata, NULL, NULL) < 0)
+ if(H5B2_find(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, NULL, NULL) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "can't locate attribute in name index")
done:
@@ -405,7 +405,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5A_dense_insert(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, H5A_t *attr)
+H5A_dense_insert(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, H5A_t *attr)
{
H5A_bt2_ud_ins_t udata; /* User data for v2 B-tree insertion */
H5HF_t *fheap = NULL; /* Fractal heap handle for attributes */
@@ -422,7 +422,7 @@ H5A_dense_insert(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, H5A_t *attr)
* Check arguments.
*/
HDassert(f);
- HDassert(oh);
+ HDassert(ainfo);
HDassert(attr);
/* Check if attributes are shared in this file */
@@ -462,7 +462,7 @@ H5A_dense_insert(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, H5A_t *attr)
} /* end if */
/* Open the fractal heap */
- if(NULL == (fheap = H5HF_open(f, dxpl_id, oh->attr_fheap_addr)))
+ if(NULL == (fheap = H5HF_open(f, dxpl_id, ainfo->fheap_addr)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
/* Check for inserting shared attribute */
@@ -512,14 +512,14 @@ H5A_dense_insert(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, H5A_t *attr)
/* udata.id already set */
/* Insert attribute into 'name' tracking v2 B-tree */
- if(H5B2_insert(f, dxpl_id, H5A_BT2_NAME, oh->name_bt2_addr, &udata) < 0)
+ if(H5B2_insert(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to insert record into v2 B-tree")
/* Check if we should create a creation order index v2 B-tree record */
- if(oh->flags & H5P_CRT_ORDER_INDEXED) {
+ if(ainfo->index_corder) {
/* Insert the record into the creation order index v2 B-tree */
- HDassert(H5F_addr_defined(oh->corder_bt2_addr));
- if(H5B2_insert(f, dxpl_id, H5A_BT2_CORDER, oh->corder_bt2_addr, &udata) < 0)
+ HDassert(H5F_addr_defined(ainfo->corder_bt2_addr));
+ if(H5B2_insert(f, dxpl_id, H5A_BT2_CORDER, ainfo->corder_bt2_addr, &udata) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert record into v2 B-tree")
} /* end if */
@@ -695,7 +695,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5A_dense_write(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, H5A_t *attr)
+H5A_dense_write(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, H5A_t *attr)
{
H5A_bt2_ud_common_t udata; /* User data for v2 B-tree modify */
H5A_bt2_od_wrt_t op_data; /* "Op data" for v2 B-tree modify */
@@ -710,7 +710,9 @@ H5A_dense_write(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, H5A_t *attr)
* Check arguments.
*/
HDassert(f);
- HDassert(oh);
+ HDassert(ainfo);
+ HDassert(H5F_addr_defined(ainfo->fheap_addr));
+ HDassert(H5F_addr_defined(ainfo->name_bt2_addr));
HDassert(attr);
/* Check if attributes are shared in this file */
@@ -734,7 +736,7 @@ H5A_dense_write(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, H5A_t *attr)
} /* end if */
/* Open the fractal heap */
- if(NULL == (fheap = H5HF_open(f, dxpl_id, oh->attr_fheap_addr)))
+ if(NULL == (fheap = H5HF_open(f, dxpl_id, ainfo->fheap_addr)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
/* Create the "udata" information for v2 B-tree record modify */
@@ -755,10 +757,10 @@ H5A_dense_write(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, H5A_t *attr)
op_data.fheap = fheap;
op_data.shared_fheap = shared_fheap;
op_data.attr = attr;
- op_data.corder_bt2_addr = oh->corder_bt2_addr;
+ op_data.corder_bt2_addr = ainfo->corder_bt2_addr;
/* Modify attribute through 'name' tracking v2 B-tree */
- if(H5B2_modify(f, dxpl_id, H5A_BT2_NAME, oh->name_bt2_addr, &udata, H5A_dense_write_bt2_cb, &op_data) < 0)
+ if(H5B2_modify(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, H5A_dense_write_bt2_cb, &op_data) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to modify record in v2 B-tree")
done:
@@ -830,7 +832,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *old_name,
+H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *old_name,
const char *new_name)
{
H5A_bt2_ud_common_t udata; /* User data for v2 B-tree modify */
@@ -847,7 +849,7 @@ H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *old_name,
* Check arguments.
*/
HDassert(f);
- HDassert(oh);
+ HDassert(ainfo);
HDassert(old_name);
HDassert(new_name);
@@ -872,7 +874,7 @@ H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *old_name,
} /* end if */
/* Open the fractal heap */
- if(NULL == (fheap = H5HF_open(f, dxpl_id, oh->attr_fheap_addr)))
+ if(NULL == (fheap = H5HF_open(f, dxpl_id, ainfo->fheap_addr)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
/* Create the "udata" information for v2 B-tree record modify */
@@ -888,7 +890,7 @@ H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *old_name,
udata.found_op_data = &attr_copy;
/* Get copy of attribute through 'name' tracking v2 B-tree */
- if(H5B2_find(f, dxpl_id, H5A_BT2_NAME, oh->name_bt2_addr, &udata, NULL, NULL) < 0)
+ if(H5B2_find(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, NULL, NULL) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to find record in v2 B-tree")
HDassert(attr_copy);
@@ -907,7 +909,7 @@ H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *old_name,
/* Insert renamed attribute back into dense storage */
/* (Possibly making it shared) */
- if(H5A_dense_insert(f, dxpl_id, oh, attr_copy) < 0)
+ if(H5A_dense_insert(f, dxpl_id, ainfo, attr_copy) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to add to dense storage")
/* Was this attribute shared? */
@@ -941,7 +943,7 @@ H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *old_name,
HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "error determining if message should be shared")
/* Delete old attribute from dense storage */
- if(H5A_dense_remove(f, dxpl_id, oh, old_name) < 0)
+ if(H5A_dense_remove(f, dxpl_id, ainfo, old_name) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute in dense storage")
done:
@@ -1059,9 +1061,8 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id, haddr_t attr_fheap_addr,
- haddr_t name_bt2_addr, haddr_t corder_bt2_addr, H5_index_t idx_type,
- H5_iter_order_t order, hsize_t skip, hsize_t *last_attr,
+H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id, const H5O_ainfo_t *ainfo,
+ 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)
{
H5HF_t *fheap = NULL; /* Fractal heap handle */
@@ -1077,8 +1078,9 @@ H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id, haddr_t attr_fheap_addr
* Check arguments.
*/
HDassert(f);
- HDassert(H5F_addr_defined(attr_fheap_addr));
- HDassert(H5F_addr_defined(name_bt2_addr));
+ HDassert(ainfo);
+ HDassert(H5F_addr_defined(ainfo->fheap_addr));
+ HDassert(H5F_addr_defined(ainfo->name_bt2_addr));
HDassert(attr_op);
/* Determine the address of the index to use */
@@ -1088,8 +1090,8 @@ H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id, haddr_t attr_fheap_addr
* table and sorting it.
*/
if(order == H5_ITER_NATIVE) {
- HDassert(H5F_addr_defined(name_bt2_addr));
- bt2_addr = name_bt2_addr;
+ HDassert(H5F_addr_defined(ainfo->name_bt2_addr));
+ bt2_addr = ainfo->name_bt2_addr;
bt2_class = H5A_BT2_NAME;
} /* end if */
else
@@ -1102,7 +1104,7 @@ H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id, haddr_t attr_fheap_addr
* there's no index on it. If there's no v2 B-tree that indexes
* the links, a table will be built.
*/
- bt2_addr = corder_bt2_addr;
+ bt2_addr = ainfo->corder_bt2_addr;
bt2_class = H5A_BT2_CORDER;
} /* end else */
@@ -1112,7 +1114,7 @@ H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id, haddr_t attr_fheap_addr
htri_t attr_sharable; /* Flag indicating attributes are sharable */
/* Open the fractal heap */
- if(NULL == (fheap = H5HF_open(f, dxpl_id, attr_fheap_addr)))
+ if(NULL == (fheap = H5HF_open(f, dxpl_id, ainfo->fheap_addr)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
/* Check if attributes are shared in this file */
@@ -1158,7 +1160,7 @@ H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id, haddr_t attr_fheap_addr
else {
/* Build the table of attributes for this object */
/* (build table using the name index, but sort according to idx_type) */
- if(H5A_dense_build_table(f, dxpl_id, attr_fheap_addr, name_bt2_addr, idx_type, order, &atable) < 0)
+ if(H5A_dense_build_table(f, dxpl_id, ainfo, idx_type, order, &atable) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "error building table of attributes")
/* Iterate over attributes in table */
@@ -1248,7 +1250,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5A_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *name)
+H5A_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *name)
{
H5A_bt2_ud_rm_t udata; /* User data for v2 B-tree record removal */
H5HF_t *fheap = NULL; /* Fractal heap handle */
@@ -1263,11 +1265,11 @@ H5A_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *name)
* Check arguments.
*/
HDassert(f);
- HDassert(oh);
+ HDassert(ainfo);
HDassert(name && *name);
/* Open the fractal heap */
- if(NULL == (fheap = H5HF_open(f, dxpl_id, oh->attr_fheap_addr)))
+ if(NULL == (fheap = H5HF_open(f, dxpl_id, ainfo->fheap_addr)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
/* Check if attributes are shared in this file */
@@ -1299,10 +1301,10 @@ H5A_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *name)
udata.common.name_hash = H5_checksum_lookup3(name, HDstrlen(name), 0);
udata.common.found_op = H5A_dense_fnd_cb; /* v2 B-tree comparison callback */
udata.common.found_op_data = &attr_copy;
- udata.corder_bt2_addr = oh->corder_bt2_addr;
+ udata.corder_bt2_addr = ainfo->corder_bt2_addr;
/* Remove the record from the name index v2 B-tree */
- if(H5B2_remove(f, dxpl_id, H5A_BT2_NAME, oh->name_bt2_addr, &udata, H5A_dense_remove_bt2_cb, &udata) < 0)
+ if(H5B2_remove(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, H5A_dense_remove_bt2_cb, &udata) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTREMOVE, FAIL, "unable to remove attribute from name index v2 B-tree")
done:
@@ -1437,7 +1439,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
+H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
H5_index_t idx_type, H5_iter_order_t order, hsize_t n)
{
H5HF_t *fheap = NULL; /* Fractal heap handle */
@@ -1453,7 +1455,7 @@ H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
* Check arguments.
*/
HDassert(f);
- HDassert(oh);
+ HDassert(ainfo);
/* Determine the address of the index to use */
if(idx_type == H5_INDEX_NAME) {
@@ -1462,7 +1464,7 @@ H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
* table and sorting it.
*/
if(order == H5_ITER_NATIVE) {
- bt2_addr = oh->name_bt2_addr;
+ bt2_addr = ainfo->name_bt2_addr;
bt2_class = H5A_BT2_NAME;
HDassert(H5F_addr_defined(bt2_addr));
} /* end if */
@@ -1476,7 +1478,7 @@ H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
* there's no index on it. If there's no v2 B-tree that indexes
* the links, a table will be built.
*/
- bt2_addr = oh->corder_bt2_addr;
+ bt2_addr = ainfo->corder_bt2_addr;
bt2_class = H5A_BT2_CORDER;
} /* end else */
@@ -1486,7 +1488,7 @@ H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
htri_t attr_sharable; /* Flag indicating attributes are sharable */
/* Open the fractal heap */
- if(NULL == (fheap = H5HF_open(f, dxpl_id, oh->attr_fheap_addr)))
+ if(NULL == (fheap = H5HF_open(f, dxpl_id, ainfo->fheap_addr)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
/* Check if attributes are shared in this file */
@@ -1515,7 +1517,7 @@ H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
udata.fheap = fheap;
udata.shared_fheap = shared_fheap;
udata.idx_type = idx_type;
- udata.other_bt2_addr = idx_type == H5_INDEX_NAME ? oh->corder_bt2_addr : oh->name_bt2_addr;
+ udata.other_bt2_addr = idx_type == H5_INDEX_NAME ? ainfo->corder_bt2_addr : ainfo->name_bt2_addr;
/* Remove the record from the name index v2 B-tree */
if(H5B2_remove_by_idx(f, dxpl_id, bt2_class, bt2_addr, order, n, H5A_dense_remove_by_idx_bt2_cb, &udata) < 0)
@@ -1524,7 +1526,7 @@ H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
else {
/* Build the table of attributes for this object */
/* (build table using the name index, but sort according to idx_type) */
- if(H5A_dense_build_table(f, dxpl_id, oh->attr_fheap_addr, oh->name_bt2_addr, idx_type, order, &atable) < 0)
+ if(H5A_dense_build_table(f, dxpl_id, ainfo, idx_type, order, &atable) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "error building table of attributes")
/* Check for skipping too many attributes */
@@ -1532,7 +1534,7 @@ H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified")
/* Delete appropriate attribute from dense storage */
- if(H5A_dense_remove(f, dxpl_id, oh, atable.attrs[n].name) < 0)
+ if(H5A_dense_remove(f, dxpl_id, ainfo, atable.attrs[n].name) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute in dense storage")
} /* end else */
@@ -1564,7 +1566,7 @@ done:
*-------------------------------------------------------------------------
*/
htri_t
-H5A_dense_exists(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *name)
+H5A_dense_exists(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *name)
{
H5A_bt2_ud_common_t udata; /* User data for v2 B-tree modify */
H5HF_t *fheap = NULL; /* Fractal heap handle */
@@ -1578,11 +1580,11 @@ H5A_dense_exists(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *name)
* Check arguments.
*/
HDassert(f);
- HDassert(oh);
+ HDassert(ainfo);
HDassert(name);
/* Open the fractal heap */
- if(NULL == (fheap = H5HF_open(f, dxpl_id, oh->attr_fheap_addr)))
+ if(NULL == (fheap = H5HF_open(f, dxpl_id, ainfo->fheap_addr)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
/* Check if attributes are shared in this file */
@@ -1618,7 +1620,7 @@ H5A_dense_exists(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *name)
udata.found_op_data = NULL;
/* Find the attribute in the 'name' index */
- if(H5B2_find(f, dxpl_id, H5A_BT2_NAME, oh->name_bt2_addr, &udata, NULL, NULL) < 0) {
+ if(H5B2_find(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, NULL, NULL) < 0) {
/* Assume that the failure was just not finding the attribute & clear stack */
H5E_clear_stack(NULL);
@@ -1715,7 +1717,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5A_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
+H5A_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_ainfo_t *ainfo)
{
H5A_bt2_ud_common_t udata; /* v2 B-tree user data for deleting attributes */
H5HF_t *fheap = NULL; /* Fractal heap handle */
@@ -1727,10 +1729,10 @@ H5A_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
* Check arguments.
*/
HDassert(f);
- HDassert(oh);
+ HDassert(ainfo);
/* Open the fractal heap */
- if(NULL == (fheap = H5HF_open(f, dxpl_id, oh->attr_fheap_addr)))
+ if(NULL == (fheap = H5HF_open(f, dxpl_id, ainfo->fheap_addr)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
/* Create the "udata" information for v2 B-tree 'delete' */
@@ -1746,9 +1748,9 @@ H5A_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
udata.found_op_data = NULL;
/* Delete name index v2 B-tree */
- if(H5B2_delete(f, dxpl_id, H5A_BT2_NAME, oh->name_bt2_addr, H5A_dense_delete_bt2_cb, &udata) < 0)
+ if(H5B2_delete(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, H5A_dense_delete_bt2_cb, &udata) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete v2 B-tree for name index")
- oh->name_bt2_addr = HADDR_UNDEF;
+ ainfo->name_bt2_addr = HADDR_UNDEF;
/* Release resources */
if(H5HF_close(fheap, dxpl_id) < 0)
@@ -1756,17 +1758,17 @@ H5A_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
fheap = NULL;
/* Check if we should delete the creation order index v2 B-tree */
- if(H5F_addr_defined(oh->corder_bt2_addr)) {
+ if(H5F_addr_defined(ainfo->corder_bt2_addr)) {
/* Delete the creation order index, without adjusting the ref. count on the attributes */
- if(H5B2_delete(f, dxpl_id, H5A_BT2_CORDER, oh->corder_bt2_addr, NULL, NULL) < 0)
+ if(H5B2_delete(f, dxpl_id, H5A_BT2_CORDER, ainfo->corder_bt2_addr, NULL, NULL) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete v2 B-tree for creation order index")
- oh->corder_bt2_addr = HADDR_UNDEF;
+ ainfo->corder_bt2_addr = HADDR_UNDEF;
} /* end if */
/* Delete fractal heap */
- if(H5HF_delete(f, dxpl_id, oh->attr_fheap_addr) < 0)
+ if(H5HF_delete(f, dxpl_id, ainfo->fheap_addr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete fractal heap")
- oh->attr_fheap_addr = HADDR_UNDEF;
+ ainfo->fheap_addr = HADDR_UNDEF;
done:
/* Release resources */
diff --git a/src/H5Aint.c b/src/H5Aint.c
index 953dda2..18b49f8 100644
--- a/src/H5Aint.c
+++ b/src/H5Aint.c
@@ -274,9 +274,8 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, haddr_t attr_fheap_addr,
- haddr_t name_bt2_addr, H5_index_t idx_type, H5_iter_order_t order,
- H5A_attr_table_t *atable)
+H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
+ H5_index_t idx_type, H5_iter_order_t order, H5A_attr_table_t *atable)
{
hsize_t nrec; /* # of records in v2 B-tree */
herr_t ret_value = SUCCEED; /* Return value */
@@ -285,13 +284,14 @@ H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, haddr_t attr_fheap_addr,
/* Sanity check */
HDassert(f);
- HDassert(H5F_addr_defined(attr_fheap_addr));
- HDassert(H5F_addr_defined(name_bt2_addr));
+ HDassert(ainfo);
+ HDassert(H5F_addr_defined(ainfo->fheap_addr));
+ HDassert(H5F_addr_defined(ainfo->name_bt2_addr));
HDassert(atable);
/* Retrieve # of records in "name" B-tree */
/* (should be same # of records in all indices) */
- if(H5B2_get_nrec(f, dxpl_id, H5A_BT2_NAME, name_bt2_addr, &nrec) < 0)
+ if(H5B2_get_nrec(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &nrec) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve # of records in index")
/* Set size of table */
@@ -316,9 +316,8 @@ H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, haddr_t attr_fheap_addr,
attr_op.u.lib_op = H5A_dense_build_table_cb;
/* Iterate over the links in the group, building a table of the link messages */
- if(H5A_dense_iterate(f, dxpl_id, (hid_t)0, attr_fheap_addr, name_bt2_addr,
- HADDR_UNDEF, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, NULL,
- &attr_op, &udata) < 0)
+ if(H5A_dense_iterate(f, dxpl_id, (hid_t)0, ainfo, H5_INDEX_NAME,
+ H5_ITER_NATIVE, (hsize_t)0, NULL, &attr_op, &udata) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table")
/* Sort attribute table in correct iteration order */
diff --git a/src/H5Apkg.h b/src/H5Apkg.h
index f5d843b..c3fe261 100644
--- a/src/H5Apkg.h
+++ b/src/H5Apkg.h
@@ -186,32 +186,34 @@ H5_DLL herr_t H5A_free(H5A_t *attr);
H5_DLL herr_t H5A_close(H5A_t *attr);
/* Attribute "dense" storage routines */
-H5_DLL herr_t H5A_dense_create(H5F_t *f, hid_t dxpl_id, H5O_t *oh);
-H5_DLL H5A_t *H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
+H5_DLL herr_t H5A_dense_create(H5F_t *f, hid_t dxpl_id, H5O_ainfo_t *ainfo);
+H5_DLL H5A_t *H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
const char *name);
-H5_DLL herr_t H5A_dense_insert(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
+H5_DLL herr_t H5A_dense_insert(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
H5A_t *attr);
-H5_DLL herr_t H5A_dense_write(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
+H5_DLL herr_t H5A_dense_write(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
H5A_t *attr);
-H5_DLL herr_t H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
+H5_DLL herr_t H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
const char *old_name, const char *new_name);
H5_DLL herr_t H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id,
- haddr_t attr_fheap_addr, haddr_t name_bt2_addr, haddr_t corder_bt2_addr,
- 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);
-H5_DLL herr_t H5A_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
+ const H5O_ainfo_t *ainfo, 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);
+H5_DLL herr_t H5A_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
const char *name);
-H5_DLL herr_t H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
+H5_DLL herr_t H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
H5_index_t idx_type, H5_iter_order_t order, hsize_t n);
-H5_DLL htri_t H5A_dense_exists(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
+H5_DLL htri_t H5A_dense_exists(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
const char *name);
+H5_DLL herr_t H5A_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_ainfo_t *ainfo);
+
/* Attribute table operations */
H5_DLL herr_t H5A_compact_build_table(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
H5_index_t idx_type, H5_iter_order_t order, H5A_attr_table_t *atable);
H5_DLL herr_t H5A_dense_build_table(H5F_t *f, hid_t dxpl_id,
- haddr_t attr_fheap_addr, haddr_t name_bt2_addr, H5_index_t idx_type,
- H5_iter_order_t order, H5A_attr_table_t *atable);
+ const H5O_ainfo_t *ainfo, H5_index_t idx_type, H5_iter_order_t order,
+ H5A_attr_table_t *atable);
H5_DLL herr_t H5A_attr_iterate_table(const H5A_attr_table_t *atable,
hsize_t skip, hsize_t *last_attr, hid_t loc_id,
const H5A_attr_iter_op_t *attr_op, void *op_data);
diff --git a/src/H5Aprivate.h b/src/H5Aprivate.h
index 75a2884..d46e46b 100644
--- a/src/H5Aprivate.h
+++ b/src/H5Aprivate.h
@@ -48,14 +48,10 @@ typedef struct H5A_attr_iter_op_t H5A_attr_iter_op_t;
/***************************************/
/* Library-private Function Prototypes */
/***************************************/
-struct H5O_t; /*forward decl*/
/* General attribute routines */
H5_DLL struct H5O_loc_t *H5A_oloc(H5A_t *attr);
H5_DLL H5G_name_t *H5A_nameof(H5A_t *attr);
-/* Attribute "dense" storage routines */
-H5_DLL herr_t H5A_dense_delete(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh);
-
#endif /* _H5Aprivate_H */
diff --git a/src/H5O.c b/src/H5O.c
index 0741621..cd961cd 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -38,7 +38,6 @@
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
-#include "H5Aprivate.h" /* Attributes */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* File access */
#include "H5FLprivate.h" /* Free lists */
@@ -693,11 +692,6 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id,
if(H5P_get(oc_plist, H5O_CRT_ATTR_MIN_DENSE_NAME, &oh->min_dense) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get min. # of dense attributes")
- /* Set starting values for dense attribute storage info */
- oh->attr_fheap_addr = HADDR_UNDEF;
- oh->name_bt2_addr = HADDR_UNDEF;
- oh->corder_bt2_addr = HADDR_UNDEF;
-
/* Check for non-default attribute storage phase change values */
if(oh->max_compact != H5O_CRT_ATTR_MAX_COMPACT_DEF || oh->min_dense != H5O_CRT_ATTR_MIN_DENSE_DEF)
oh->flags |= H5O_HDR_ATTR_STORE_PHASE_CHANGE;
@@ -708,11 +702,6 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id,
/* Reset unused time fields */
oh->atime = oh->mtime = oh->ctime = oh->btime = 0;
-
- /* Reset unused attribute fields */
- oh->attr_fheap_addr = HADDR_UNDEF;
- oh->name_bt2_addr = HADDR_UNDEF;
- oh->corder_bt2_addr = HADDR_UNDEF;
} /* end else */
/* Compute total size of initial object header */
@@ -1467,12 +1456,6 @@ H5O_delete_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message")
} /* end for */
- /* Check for dense attribute storage & delete it if necessary */
- if(oh->version > H5O_VERSION_1 && H5F_addr_defined(oh->attr_fheap_addr)) {
- if(H5A_dense_delete(f, dxpl_id, oh) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete dense attribute storage")
- } /* end if */
-
/* Free main (first) object header "chunk" */
if(H5MF_xfree(f, H5FD_MEM_OHDR, dxpl_id, oh->chunk[0].addr, (hsize_t)oh->chunk[0].size) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free object header")
@@ -1920,7 +1903,6 @@ H5O_get_info(H5O_loc_t *oloc, H5O_info_t *oinfo, hid_t dxpl_id)
oinfo->hdr.flags = oh->flags;
/* Iterate over all the messages, accumulating message size & type information */
- oinfo->num_attrs = 0;
oinfo->hdr.space.meta = H5O_SIZEOF_HDR(oh) + (H5O_SIZEOF_CHKHDR_OH(oh) * (oh->nchunks - 1));
oinfo->hdr.space.mesg = 0;
oinfo->hdr.space.free = 0;
@@ -1929,10 +1911,6 @@ H5O_get_info(H5O_loc_t *oloc, H5O_info_t *oinfo, hid_t dxpl_id)
for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) {
uint64_t type_flag; /* Flag for message type */
- /* Check for attribute message */
- if(H5O_ATTR_ID == curr_msg->type->id)
- oinfo->num_attrs++;
-
/* Accumulate space usage information, based on the type of message */
if(H5O_NULL_ID == curr_msg->type->id)
oinfo->hdr.space.free += H5O_SIZEOF_MSGHDR_OH(oh) + curr_msg->raw_size;
@@ -1952,15 +1930,8 @@ H5O_get_info(H5O_loc_t *oloc, H5O_info_t *oinfo, hid_t dxpl_id)
oinfo->hdr.mesg.shared |= type_flag;
} /* end for */
- /* Sanity checking, etc. for # of attributes */
- if(oh->version > H5O_VERSION_1) {
- if(H5F_addr_defined(oh->attr_fheap_addr)) {
- HDassert(oinfo->num_attrs == 0);
- oinfo->num_attrs = oh->nattrs;
- } /* end if */
- else
- HDassert(oh->nattrs == oinfo->num_attrs);
- } /* end if */
+ /* Retrieve # of attributes */
+ oinfo->num_attrs = H5O_attr_count_real(oloc->file, dxpl_id, oh);
/* Iterate over all the chunks, adding any gaps to the free space */
oinfo->hdr.space.total = 0;
diff --git a/src/H5Oainfo.c b/src/H5Oainfo.c
index 514d451..7c3183a 100644
--- a/src/H5Oainfo.c
+++ b/src/H5Oainfo.c
@@ -24,9 +24,11 @@
*-------------------------------------------------------------------------
*/
+#define H5A_PACKAGE /*suppress error about including H5Apkg */
#define H5O_PACKAGE /*suppress error about including H5Opkg */
#include "H5private.h" /* Generic Functions */
+#include "H5Apkg.h" /* Attributes */
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free lists */
#include "H5Opkg.h" /* Object headers */
@@ -39,6 +41,10 @@ static void *H5O_ainfo_copy(const void *_mesg, void *_dest);
static size_t H5O_ainfo_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
static herr_t H5O_ainfo_free(void *_mesg);
static herr_t H5O_ainfo_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg);
+static herr_t H5O_ainfo_pre_copy_file(H5F_t *file_src, const void *mesg_src,
+ hbool_t *deleted, const H5O_copy_t *cpy_info, void *udata);
+static void *H5O_ainfo_copy_file(H5F_t *file_src, void *mesg_src,
+ H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata);
static herr_t H5O_ainfo_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg,
FILE * stream, int indent, int fwidth);
@@ -58,8 +64,8 @@ const H5O_msg_class_t H5O_MSG_AINFO[1] = {{
NULL, /* link method */
NULL, /*set share method */
NULL, /*can share method */
- NULL, /* pre copy native value to file */
- NULL, /* copy native value to file */
+ H5O_ainfo_pre_copy_file, /* pre copy native value to file */
+ H5O_ainfo_copy_file, /* copy native value to file */
NULL, /* post copy native value to file */
NULL, /* get creation index */
NULL, /* set creation index */
@@ -69,10 +75,11 @@ const H5O_msg_class_t H5O_MSG_AINFO[1] = {{
/* Current version of attribute info information */
#define H5O_AINFO_VERSION 0
-/* Flags for attribute info index flag encoding */
+/* Flags for attribute info flag encoding */
#define H5O_AINFO_INDEX_NAME 0x01
-#define H5O_AINFO_INDEX_CORDER 0x02
-#define H5O_AINFO_ALL_FLAGS (H5O_AINFO_INDEX_NAME | H5O_AINFO_INDEX_CORDER)
+#define H5O_AINFO_TRACK_CORDER 0x02
+#define H5O_AINFO_INDEX_CORDER 0x04
+#define H5O_AINFO_ALL_FLAGS (H5O_AINFO_INDEX_NAME | H5O_AINFO_TRACK_CORDER | H5O_AINFO_INDEX_CORDER)
/* Declare a free list to manage the H5O_ainfo_t struct */
H5FL_DEFINE_STATIC(H5O_ainfo_t);
@@ -97,7 +104,7 @@ H5O_ainfo_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
const uint8_t *p)
{
H5O_ainfo_t *ainfo = NULL; /* Attribute info */
- unsigned char index_flags; /* Flags for encoding link index info */
+ unsigned char flags; /* Flags for encoding attribute info */
void *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_ainfo_decode)
@@ -114,18 +121,22 @@ H5O_ainfo_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
if(NULL == (ainfo = H5FL_MALLOC(H5O_ainfo_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- /* Get the index flags for the object */
- index_flags = *p++;
- HDassert(index_flags & H5O_AINFO_INDEX_NAME);
- if(index_flags & ~H5O_AINFO_ALL_FLAGS)
+ /* Get the flags for the message */
+ flags = *p++;
+ HDassert(flags & H5O_AINFO_INDEX_NAME);
+ if(flags & ~H5O_AINFO_ALL_FLAGS)
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad flag value for message")
- ainfo->index_corder = (index_flags & H5O_AINFO_INDEX_CORDER) ? TRUE : FALSE;
+ ainfo->track_corder = (flags & H5O_AINFO_TRACK_CORDER) ? TRUE : FALSE;
+ ainfo->index_corder = (flags & H5O_AINFO_INDEX_CORDER) ? TRUE : FALSE;
/* Number of attributes on the object */
H5F_DECODE_LENGTH(f, p, ainfo->nattrs)
/* Max. creation order value for the object */
- UINT16DECODE(p, ainfo->max_crt_idx);
+ if(ainfo->track_corder)
+ UINT16DECODE(p, ainfo->max_crt_idx)
+ else
+ ainfo->max_crt_idx = H5O_MAX_CRT_ORDER_IDX;
/* Address of fractal heap to store "dense" attributes */
H5F_addr_decode(f, &p, &(ainfo->fheap_addr));
@@ -143,9 +154,8 @@ H5O_ainfo_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
ret_value = ainfo;
done:
- if(ret_value == NULL)
- if(ainfo != NULL)
- H5FL_FREE(H5O_ainfo_t, ainfo);
+ if(ret_value == NULL && ainfo != NULL)
+ H5FL_FREE(H5O_ainfo_t, ainfo);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_ainfo_decode() */
@@ -168,7 +178,7 @@ static herr_t
H5O_ainfo_encode(H5F_t *f, hbool_t UNUSED disable_shared, uint8_t *p, const void *_mesg)
{
const H5O_ainfo_t *ainfo = (const H5O_ainfo_t *)_mesg;
- unsigned char index_flags; /* Flags for encoding attribute index info */
+ unsigned char flags; /* Flags for encoding attribute info */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_ainfo_encode)
@@ -181,15 +191,17 @@ H5O_ainfo_encode(H5F_t *f, hbool_t UNUSED disable_shared, uint8_t *p, const void
*p++ = H5O_AINFO_VERSION;
/* The flags for the attribute indices */
- index_flags = H5O_AINFO_INDEX_NAME; /* Names are always indexed */
- index_flags |= ainfo->index_corder ? H5O_AINFO_INDEX_CORDER : 0;
- *p++ = index_flags;
+ flags = H5O_AINFO_INDEX_NAME; /* Names are always indexed */
+ flags |= ainfo->track_corder ? H5O_AINFO_TRACK_CORDER : 0;
+ flags |= ainfo->index_corder ? H5O_AINFO_INDEX_CORDER : 0;
+ *p++ = flags;
/* Number of attributes on the object */
H5F_ENCODE_LENGTH(f, p, ainfo->nattrs)
/* Max. creation order value for the object */
- UINT16ENCODE(p, ainfo->max_crt_idx);
+ if(ainfo->track_corder)
+ UINT16ENCODE(p, ainfo->max_crt_idx);
/* Address of fractal heap to store "dense" attributes */
H5F_addr_encode(f, &p, ainfo->fheap_addr);
@@ -275,7 +287,7 @@ H5O_ainfo_size(const H5F_t *f, hbool_t UNUSED disable_shared, const void *_mesg)
ret_value = 1 /* Version */
+ 1 /* Index flags */
+ H5F_SIZEOF_SIZE(f) /* Number of attributes */
- + 2 /* Curr. max. creation order value */
+ + (ainfo->track_corder ? 2 : 0) /* Curr. max. creation order value */
+ H5F_SIZEOF_ADDR(f) /* Address of fractal heap to store "dense" attributes */
+ H5F_SIZEOF_ADDR(f) /* Address of v2 B-tree for indexing names of attributes */
+ (ainfo->index_corder ? H5F_SIZEOF_ADDR(f) : 0); /* Address of v2 B-tree for indexing creation order values of attributes */
@@ -334,11 +346,9 @@ H5O_ainfo_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg)
HDassert(ainfo);
/* If the object is using "dense" attribute storage, delete it */
-#ifdef NOT_YET
if(H5F_addr_defined(ainfo->fheap_addr))
- if(H5G_dense_delete(f, dxpl_id, (H5O_linfo_t *)linfo, TRUE) < 0) /* Casting away const OK - QAK */
- HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free dense link storage")
-#endif /* NOT_YET */
+ if(H5A_dense_delete(f, dxpl_id, (H5O_ainfo_t *)ainfo) < 0) /* Casting away const OK - QAK */
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free dense attribute storage")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -346,6 +356,94 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5O_ainfo_pre_copy_file
+ *
+ * Purpose: Perform any necessary actions before copying message between
+ * files.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Friday, March 9, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_ainfo_pre_copy_file(H5F_t UNUSED *file_src, const void UNUSED *native_src,
+ hbool_t *deleted, const H5O_copy_t *cpy_info, void UNUSED *udata)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_ainfo_pre_copy_file)
+
+ /* check args */
+ HDassert(deleted);
+ HDassert(cpy_info);
+
+ /* If we are not copying attributes into the destination file, indicate
+ * that this message should be deleted.
+ */
+ if(cpy_info->copy_without_attr)
+ *deleted = TRUE;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O_ainfo_pre_copy_file() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_ainfo_copy_file
+ *
+ * Purpose: Copies a message from _MESG to _DEST in file
+ *
+ * Return: Success: Ptr to _DEST
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * March 9, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5O_ainfo_copy_file(H5F_t UNUSED *file_src, void *mesg_src,
+ H5F_t UNUSED *file_dst, hid_t UNUSED dxpl_id, H5O_copy_t UNUSED *cpy_info,
+ void UNUSED *udata)
+{
+ H5O_ainfo_t *ainfo_src = (H5O_ainfo_t *)mesg_src;
+ H5O_ainfo_t *ainfo_dst = NULL;
+ void *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_ainfo_copy_file)
+
+ /* check args */
+ HDassert(file_src);
+ HDassert(ainfo_src);
+ HDassert(file_dst);
+ HDassert(cpy_info);
+ HDassert(!cpy_info->copy_without_attr);
+
+/* XXX: Bail out for now, if the source object has densely stored attributes */
+ if(H5F_addr_defined(ainfo_src->fheap_addr))
+ HGOTO_ERROR(H5E_OHDR, H5E_UNSUPPORTED, NULL, "densely stored attributes not supported yet")
+
+ /* Allocate space for the destination message */
+ if(NULL == (ainfo_dst = H5FL_MALLOC(H5O_ainfo_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* Copy the top level of the information */
+ *ainfo_dst = *ainfo_src;
+
+ /* Set return value */
+ ret_value = ainfo_dst;
+
+done:
+ /* Release destination attribute information on failure */
+ if(ret_value == NULL && ainfo_dst != NULL)
+ H5FL_FREE(H5O_ainfo_t, ainfo_dst);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5O_ainfo_copy_file() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5O_ainfo_debug
*
* Purpose: Prints debugging info for a message.
@@ -373,10 +471,12 @@ H5O_ainfo_debug(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_mesg, FILE *
HDassert(indent >= 0);
HDassert(fwidth >= 0);
- HDfprintf(stream, "%*s%-*s %t\n", indent, "", fwidth,
- "Index creation order of links:", ainfo->index_corder);
HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
"Number of attributes:", ainfo->nattrs);
+ HDfprintf(stream, "%*s%-*s %t\n", indent, "", fwidth,
+ "Track creation order of attributes:", ainfo->track_corder);
+ HDfprintf(stream, "%*s%-*s %t\n", indent, "", fwidth,
+ "Index creation order of attributes:", ainfo->index_corder);
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"Max. creation index value:", (unsigned)ainfo->max_crt_idx);
HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
diff --git a/src/H5Oattr.c b/src/H5Oattr.c
index 0db28fa..20af30c 100644
--- a/src/H5Oattr.c
+++ b/src/H5Oattr.c
@@ -711,7 +711,7 @@ H5O_attr_pre_copy_file(H5F_t UNUSED *file_src, const void UNUSED *native_src,
*-------------------------------------------------------------------------
*/
static void *
-H5O_attr_copy_file(H5F_t *file_src, const H5O_msg_class_t UNUSED *mesg_type,
+H5O_attr_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *mesg_type,
void *native_src, H5F_t *file_dst, hid_t dxpl_id,
H5O_copy_t *cpy_info, void UNUSED *udata)
{
@@ -970,10 +970,10 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_attr_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc,
- void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info)
+H5O_attr_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src,
+ H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info)
{
- H5A_t *attr_src = (H5A_t *)mesg_src;
+ const H5A_t *attr_src = (const H5A_t *)mesg_src;
H5A_t *attr_dst = (H5A_t *)mesg_dst;
H5F_t *file_src = src_oloc->file;
H5F_t *file_dst = dst_oloc->file;
@@ -988,30 +988,33 @@ H5O_attr_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, H5O_loc
HDassert(attr_dst);
HDassert(file_dst);
- /* only need to fix reference attribute */
- if ( (NULL == attr_src->data) ||
- (H5T_get_class(attr_src->dt, FALSE) != H5T_REFERENCE) ||
- (file_src == file_dst) )
- HGOTO_DONE(SUCCEED)
-
- /* copy object pointed by reference. The current implementation does not deal with
- nested reference such as reference in a compound structure */
-
- /* Check for expanding references */
- if(cpy_info->expand_ref) {
- size_t ref_count;
+ /* 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) &&
+ (file_src != file_dst)) {
- /* Determine # of reference elements to copy */
- ref_count = attr_dst->data_size / H5T_get_size(attr_dst->dt);
+ /* copy object pointed by reference. The current implementation does not
+ * deal with nested reference such as reference in a compound structure
+ */
- /* 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)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy reference attribute")
+ /* Check for expanding references */
+ if(cpy_info->expand_ref) {
+ size_t ref_count;
+
+ /* Determine # of reference elements to copy */
+ ref_count = attr_dst->data_size / H5T_get_size(attr_dst->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)
+ 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);
} /* end if */
- else
- /* Reset value to zero */
- HDmemset(attr_dst->data, 0, attr_dst->data_size);
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c
index 3e97862..f824ad9 100644
--- a/src/H5Oattribute.c
+++ b/src/H5Oattribute.c
@@ -55,6 +55,7 @@
typedef struct {
H5F_t *f; /* Pointer to file for insertion */
hid_t dxpl_id; /* DXPL during iteration */
+ H5O_ainfo_t *ainfo; /* Attribute info struct */
} H5O_iter_cvt_t;
/* User data for iteration when opening an attribute */
@@ -173,9 +174,13 @@ H5O_attr_to_dense_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
/* check args */
HDassert(oh);
HDassert(mesg);
+ HDassert(udata);
+ HDassert(udata->f);
+ HDassert(udata->ainfo);
+ HDassert(attr);
/* Insert attribute into dense storage */
- if(H5A_dense_insert(udata->f, udata->dxpl_id, oh, attr) < 0)
+ if(H5A_dense_insert(udata->f, udata->dxpl_id, udata->ainfo, attr) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, H5_ITER_ERROR, "unable to add to dense storage")
/* Convert message into a null message in the header */
@@ -207,6 +212,7 @@ herr_t
H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
{
H5O_t *oh = NULL; /* Pointer to actual object header */
+ H5O_ainfo_t ainfo; /* Attribute information for object */
unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */
herr_t ret_value = SUCCEED; /* Return value */
@@ -221,59 +227,107 @@ H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
- /* Check if switching to "dense" attribute storage is possible */
- if(oh->version > H5O_VERSION_1 && !H5F_addr_defined(oh->attr_fheap_addr)) {
- htri_t sharable; /* Whether the attribute will be shared */
- size_t raw_size = 0; /* Raw size of message */
-
- /* Check for attribute being sharable */
- if((sharable = H5SM_can_share(loc->file, dxpl_id, NULL, NULL, H5O_ATTR_ID, attr)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, FAIL, "can't determine attribute sharing status")
- else if(sharable == FALSE) {
- /* Compute the size needed to encode the attribute */
- raw_size = (H5O_MSG_ATTR->raw_size)(loc->file, FALSE, attr);
+ /* Check if this object already has attribute information */
+ if(oh->version > H5O_VERSION_1) {
+ hbool_t new_ainfo = FALSE; /* Flag to indicate that the attribute information is new */
+
+ if(NULL == H5O_msg_read_real(loc->file, dxpl_id, oh, H5O_AINFO_ID, &ainfo)) {
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+
+ /* Initialize attribute information */
+ ainfo.track_corder = (oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED) ? TRUE : FALSE;
+ ainfo.index_corder = (oh->flags & H5O_HDR_ATTR_CRT_ORDER_INDEXED) ? TRUE : FALSE;
+ ainfo.max_crt_idx = 0;
+ ainfo.corder_bt2_addr = HADDR_UNDEF;
+ ainfo.nattrs = 0;
+ ainfo.fheap_addr = HADDR_UNDEF;
+ ainfo.name_bt2_addr = HADDR_UNDEF;
+
+ /* Set flag to add attribute information to object header */
+ new_ainfo = TRUE;
} /* end if */
+ else {
+ /* Sanity check attribute info read in */
+ HDassert(ainfo.nattrs > 0);
+ HDassert(ainfo.track_corder == ((oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED) > 0));
+ HDassert(ainfo.index_corder == ((oh->flags & H5O_HDR_ATTR_CRT_ORDER_INDEXED) > 0));
+ } /* end else */
- /* Check for condititions for switching to "dense" attribute storage are met */
- if(oh->nattrs == oh->max_compact || (!sharable && raw_size >= H5O_MESG_MAX_SIZE)) {
- H5O_iter_cvt_t udata; /* User data for callback */
- H5O_mesg_operator_t op; /* Wrapper for operator */
-
- /* Create dense storage for attributes */
- if(H5A_dense_create(loc->file, dxpl_id, oh) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create dense storage for attributes")
-
- /* Set up user data for callback */
- udata.f = loc->file;
- udata.dxpl_id = dxpl_id;
+ /* Check if switching to "dense" attribute storage is possible */
+ if(!H5F_addr_defined(ainfo.fheap_addr)) {
+ htri_t sharable; /* Whether the attribute will be shared */
+ size_t raw_size = 0; /* Raw size of message */
+
+ /* Check for attribute being sharable */
+ if((sharable = H5SM_can_share(loc->file, dxpl_id, NULL, NULL, H5O_ATTR_ID, attr)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, FAIL, "can't determine attribute sharing status")
+ else if(sharable == FALSE) {
+ /* Compute the size needed to encode the attribute */
+ raw_size = (H5O_MSG_ATTR->raw_size)(loc->file, FALSE, attr);
+ } /* end if */
- /* Iterate over existing attributes, moving them to dense storage */
- op.op_type = H5O_MESG_OP_LIB;
- op.u.lib_op = H5O_attr_to_dense_cb;
- if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, &op, &udata, dxpl_id) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCONVERT, FAIL, "error converting attributes to dense storage")
+ /* Check for condititions for switching to "dense" attribute storage are met */
+ if(ainfo.nattrs == oh->max_compact || (!sharable && raw_size >= H5O_MESG_MAX_SIZE)) {
+ H5O_iter_cvt_t udata; /* User data for callback */
+ H5O_mesg_operator_t op; /* Wrapper for operator */
+
+ /* Create dense storage for attributes */
+ if(H5A_dense_create(loc->file, dxpl_id, &ainfo) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create dense storage for attributes")
+
+ /* Set up user data for callback */
+ udata.f = loc->file;
+ udata.dxpl_id = dxpl_id;
+ udata.ainfo = &ainfo;
+
+ /* Iterate over existing attributes, moving them to dense storage */
+ op.op_type = H5O_MESG_OP_LIB;
+ op.u.lib_op = H5O_attr_to_dense_cb;
+ if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, &op, &udata, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCONVERT, FAIL, "error converting attributes to dense storage")
+ } /* end if */
} /* end if */
- } /* end if */
- /* Increment attribute count on object */
- oh->nattrs++;
+ /* Increment attribute count on object */
+ ainfo.nattrs++;
- /* Later versions of the object header track the creation index on attributes */
- if(oh->version > H5O_VERSION_1 && (oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)) {
- /* Check for attribute creation order index on the object wrapping around */
- if(oh->max_attr_crt_idx == H5O_MAX_CRT_ORDER_IDX)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINC, FAIL, "attribute creation index can't be incremented")
+ /* Check whether we're tracking the creation index on attributes */
+ if(ainfo.track_corder) {
+ /* Check for attribute creation order index on the object wrapping around */
+ if(ainfo.max_crt_idx == H5O_MAX_CRT_ORDER_IDX)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINC, FAIL, "attribute creation index can't be incremented")
- /* Set the creation order index on the attribute & incr. creation order index */
- attr->crt_idx = oh->max_attr_crt_idx++;
+ /* Set the creation order index on the attribute & incr. creation order index */
+ attr->crt_idx = ainfo.max_crt_idx++;
+ } /* end if */
+ else
+ /* Set "bogus" creation index for attribute */
+ attr->crt_idx = H5O_MAX_CRT_ORDER_IDX;
+
+ /* Add the attribute information message, if one is needed */
+ if(new_ainfo) {
+ if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_AINFO, H5O_MSG_FLAG_DONTSHARE, 0, &ainfo) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to create new attribute info message")
+ } /* end if */
+ /* Otherwise, update existing message */
+ else {
+ if(H5O_msg_write_real(loc->file, dxpl_id, oh, H5O_MSG_AINFO, H5O_MSG_FLAG_DONTSHARE, 0, &ainfo) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update attribute info message")
+ } /* end else */
} /* end if */
- else
+ else {
+ /* Set "bogus" creation index for attribute */
attr->crt_idx = H5O_MAX_CRT_ORDER_IDX;
+ /* Set attribute info value to get attribute into object header */
+ ainfo.fheap_addr = HADDR_UNDEF;
+ } /* end else */
+
/* Check for storing attribute with dense storage */
- if(H5F_addr_defined(oh->attr_fheap_addr)) {
+ if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Insert attribute into dense storage */
- if(H5A_dense_insert(loc->file, dxpl_id, oh, attr) < 0)
+ if(H5A_dense_insert(loc->file, dxpl_id, &ainfo, attr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to add to dense storage")
} /* end if */
else {
@@ -399,6 +453,7 @@ H5A_t *
H5O_attr_open_by_name(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
{
H5O_t *oh = NULL; /* Pointer to actual object header */
+ H5O_ainfo_t ainfo; /* Attribute information for object */
H5A_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_open_by_name)
@@ -411,10 +466,16 @@ H5O_attr_open_by_name(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, NULL, "unable to load object header")
+ /* Check for attribute info stored */
+ ainfo.fheap_addr = HADDR_UNDEF;
+ if(oh->version > H5O_VERSION_1 && NULL == H5O_msg_read_real(loc->file, dxpl_id, oh, H5O_AINFO_ID, &ainfo))
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+
/* Check for opening attribute with dense storage */
- if(H5F_addr_defined(oh->attr_fheap_addr)) {
+ if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Open attribute in dense storage */
- if(NULL == (ret_value = H5A_dense_open(loc->file, dxpl_id, oh, name)))
+ if(NULL == (ret_value = H5A_dense_open(loc->file, dxpl_id, &ainfo, name)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "can't open attribute")
} /* end if */
else {
@@ -671,6 +732,7 @@ herr_t
H5O_attr_write(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
{
H5O_t *oh = NULL; /* Pointer to actual object header */
+ H5O_ainfo_t ainfo; /* Attribute information for object */
unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
herr_t ret_value = SUCCEED; /* Return value */
@@ -684,10 +746,16 @@ H5O_attr_write(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
+ /* Check for attribute info stored */
+ ainfo.fheap_addr = HADDR_UNDEF;
+ if(oh->version > H5O_VERSION_1 && NULL == H5O_msg_read_real(loc->file, dxpl_id, oh, H5O_AINFO_ID, &ainfo))
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+
/* Check for attributes stored densely */
- if(H5F_addr_defined(oh->attr_fheap_addr)) {
+ if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Modify the attribute data in dense storage */
- if(H5A_dense_write(loc->file, dxpl_id, oh, attr) < 0)
+ if(H5A_dense_write(loc->file, dxpl_id, &ainfo, attr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "error updating attribute")
} /* end if */
else {
@@ -836,13 +904,6 @@ H5O_attr_rename_mod_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
attr = (H5A_t *)mesg->native;
mesg->native = NULL;
- /* If the later version of the object header format, decrement attribute */
- /* (must be decremented before call to H5O_release_mesg(),
- * so that the sanity checks pass - QAK)
- */
- if(oh->version > H5O_VERSION_1)
- oh->nattrs--;
-
/* Delete old attribute */
/* (doesn't decrement the link count on shared components becuase
* the "native" pointer has been reset)
@@ -850,13 +911,6 @@ H5O_attr_rename_mod_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
if(H5O_release_mesg(udata->f, udata->dxpl_id, oh, mesg, FALSE) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, H5_ITER_ERROR, "unable to release previous attribute")
- /* Increment attribute count */
- /* (must be incremented before call to H5O_msg_append_real(),
- * so that the sanity checks pass - QAK)
- */
- if(oh->version > H5O_VERSION_1)
- oh->nattrs++;
-
/* Append renamed attribute to object header */
/* (Don't let it become shared) */
if(H5O_msg_append_real(udata->f, udata->dxpl_id, oh, H5O_MSG_ATTR, (mesg->flags | H5O_MSG_FLAG_DONTSHARE), 0, attr) < 0)
@@ -902,6 +956,7 @@ H5O_attr_rename(const H5O_loc_t *loc, hid_t dxpl_id, const char *old_name,
const char *new_name)
{
H5O_t *oh = NULL; /* Pointer to actual object header */
+ H5O_ainfo_t ainfo; /* Attribute information for object */
unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
herr_t ret_value = SUCCEED; /* Return value */
@@ -916,10 +971,16 @@ H5O_attr_rename(const H5O_loc_t *loc, hid_t dxpl_id, const char *old_name,
if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
+ /* Check for attribute info stored */
+ ainfo.fheap_addr = HADDR_UNDEF;
+ if(oh->version > H5O_VERSION_1 && NULL == H5O_msg_read_real(loc->file, dxpl_id, oh, H5O_AINFO_ID, &ainfo))
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+
/* Check for attributes stored densely */
- if(H5F_addr_defined(oh->attr_fheap_addr)) {
+ if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Rename the attribute data in dense storage */
- if(H5A_dense_rename(loc->file, dxpl_id, oh, old_name, new_name) < 0)
+ if(H5A_dense_rename(loc->file, dxpl_id, &ainfo, old_name, new_name) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "error updating attribute")
} /* end if */
else {
@@ -987,6 +1048,7 @@ H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id,
hsize_t *last_attr, const H5A_attr_iter_op_t *attr_op, void *op_data)
{
H5O_t *oh = NULL; /* Pointer to actual object header */
+ H5O_ainfo_t ainfo; /* Attribute information for object */
H5A_attr_table_t atable = {0, NULL}; /* Table of attributes */
herr_t ret_value; /* Return value */
@@ -1002,30 +1064,26 @@ H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id,
if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
- /* Check for attributes stored densely */
- if(oh->version > H5O_VERSION_1 && H5F_addr_defined(oh->attr_fheap_addr)) {
- haddr_t attr_fheap_addr; /* Address of fractal heap for dense attribute storage */
- haddr_t name_bt2_addr; /* Address of v2 B-tree for name index on dense attribute storage */
- haddr_t corder_bt2_addr; /* Address of v2 B-tree for creation order index on dense attribute storage */
+ /* Check for attribute info stored */
+ ainfo.fheap_addr = HADDR_UNDEF;
+ if(oh->version > H5O_VERSION_1 && NULL == H5O_msg_read_real(loc->file, dxpl_id, oh, H5O_AINFO_ID, &ainfo))
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+ /* Check for attributes stored densely */
+ if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Check for skipping too many attributes */
- if(skip > 0 && skip >= oh->nattrs)
+ if(skip > 0 && skip >= ainfo.nattrs)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified")
- /* Retrieve the information about dense attribute storage */
- attr_fheap_addr = oh->attr_fheap_addr;
- name_bt2_addr = oh->name_bt2_addr;
- corder_bt2_addr = oh->corder_bt2_addr;
-
/* Release the object header */
if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_PROTECT, FAIL, "unable to release object header")
oh = NULL;
/* Iterate over attributes in dense storage */
- if((ret_value = H5A_dense_iterate(loc->file, dxpl_id, loc_id, attr_fheap_addr,
- name_bt2_addr, corder_bt2_addr, idx_type, order, skip,
- last_attr, attr_op, op_data)) < 0)
+ if((ret_value = H5A_dense_iterate(loc->file, dxpl_id, loc_id, &ainfo,
+ idx_type, order, skip, last_attr, attr_op, op_data)) < 0)
HERROR(H5E_ATTR, H5E_BADITER, "error iterating over attributes");
} /* end if */
else {
@@ -1109,85 +1167,90 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_attr_remove_update(const H5O_loc_t *loc, H5O_t *oh, hid_t dxpl_id)
+H5O_attr_remove_update(const H5O_loc_t *loc, H5O_t *oh, H5O_ainfo_t *ainfo,
+ hid_t dxpl_id)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5A_attr_table_t atable = {0, NULL}; /* Table of attributes */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_remove_update)
/* Check arguments */
HDassert(loc);
HDassert(oh);
+ HDassert(ainfo);
- /* Reset the creation order min/max if there's no more attributes on the object */
- if(oh->nattrs == 0)
- oh->max_attr_crt_idx = 0;
+ /* Decrement the number of attributes on the object */
+ ainfo->nattrs--;
/* Check for shifting from dense storage back to compact storage */
- if(H5F_addr_defined(oh->attr_fheap_addr)) {
- /* Check if there's no more attributes */
- if(oh->nattrs == 0) {
- /* Delete the dense storage */
- if(H5A_dense_delete(loc->file, dxpl_id, oh) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete dense attribute storage")
- } /* end if */
- else if(oh->nattrs < oh->min_dense) {
- H5A_attr_table_t atable = {0, NULL}; /* Table of attributes */
- hbool_t can_convert = TRUE; /* Whether converting to attribute messages is possible */
- size_t u; /* Local index */
-
- /* Build the table of attributes for this object */
- if(H5A_dense_build_table(loc->file, dxpl_id, oh->attr_fheap_addr, oh->name_bt2_addr, H5_INDEX_NAME, H5_ITER_NATIVE, &atable) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table")
-
- /* Inspect attributes in table for ones that can't be converted back
- * into attribute message form (currently only attributes which
- * can't fit into an object header message)
- */
- for(u = 0; u < oh->nattrs; u++)
- if(H5O_msg_size_oh(loc->file, oh, H5O_ATTR_ID, &(atable.attrs[u]), (size_t)0) >= H5O_MESG_MAX_SIZE) {
- can_convert = FALSE;
- break;
- } /* end if */
+ if(H5F_addr_defined(ainfo->fheap_addr) && ainfo->nattrs < oh->min_dense) {
+ hbool_t can_convert = TRUE; /* Whether converting to attribute messages is possible */
+ size_t u; /* Local index */
+
+ /* Build the table of attributes for this object */
+ if(H5A_dense_build_table(loc->file, dxpl_id, ainfo, H5_INDEX_NAME, H5_ITER_NATIVE, &atable) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table")
- /* If ok, insert attributes as object header messages */
- if(can_convert) {
- /* Iterate over attributes, to put them into header */
- for(u = 0; u < oh->nattrs; u++) {
- htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */
-
- /* Check if attribute is shared */
- if((shared_mesg = H5O_msg_is_shared(H5O_ATTR_ID, &(atable.attrs[u]))) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "error determining if message is shared")
- else if(shared_mesg == 0) {
- /* Increment reference count on attribute components */
- /* (so that they aren't deleted when the dense attribute storage is deleted) */
- if(H5O_attr_link(loc->file, dxpl_id, &(atable.attrs[u])) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust attribute link count")
- } /* end if */
- else {
- /* Reset 'shared' status, so attributes will be shared again */
- atable.attrs[u].sh_loc.flags = 0;
- } /* end else */
-
- /* Insert attribute message into object header */
- /* (Will increment reference count on shared attributes) */
- if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_ATTR, 0, 0, &(atable.attrs[u])) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "can't create message")
- } /* end for */
-
- /* Remove the dense storage */
- if(H5A_dense_delete(loc->file, dxpl_id, oh) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete dense attribute storage")
+ /* Inspect attributes in table for ones that can't be converted back
+ * into attribute message form (currently only attributes which
+ * can't fit into an object header message)
+ */
+ for(u = 0; u < ainfo->nattrs; u++)
+ if(H5O_msg_size_oh(loc->file, oh, H5O_ATTR_ID, &(atable.attrs[u]), (size_t)0) >= H5O_MESG_MAX_SIZE) {
+ can_convert = FALSE;
+ break;
} /* end if */
- /* Free attribute table information */
- if(H5A_attr_release_table(&atable) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute table")
- } /* end else */
+ /* If ok, insert attributes as object header messages */
+ if(can_convert) {
+ /* Iterate over attributes, to put them into header */
+ for(u = 0; u < ainfo->nattrs; u++) {
+ htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */
+
+ /* Check if attribute is shared */
+ if((shared_mesg = H5O_msg_is_shared(H5O_ATTR_ID, &(atable.attrs[u]))) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "error determining if message is shared")
+ else if(shared_mesg == 0) {
+ /* Increment reference count on attribute components */
+ /* (so that they aren't deleted when the dense attribute storage is deleted) */
+ if(H5O_attr_link(loc->file, dxpl_id, &(atable.attrs[u])) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust attribute link count")
+ } /* end if */
+ else {
+ /* Reset 'shared' status, so attributes will be shared again */
+ atable.attrs[u].sh_loc.flags = 0;
+ } /* end else */
+
+ /* Insert attribute message into object header */
+ /* (Will increment reference count on shared attributes) */
+ if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_ATTR, 0, 0, &(atable.attrs[u])) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "can't create message")
+ } /* end for */
+
+ /* Remove the dense storage */
+ if(H5A_dense_delete(loc->file, dxpl_id, ainfo) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete dense attribute storage")
+ } /* end if */
} /* end if */
+ /* Check if we have deleted all the attributes and the attribute info
+ * message should be deleted itself.
+ */
+ if(ainfo->nattrs == 0) {
+ if(H5O_msg_remove_real(loc->file, oh, H5O_MSG_AINFO, H5O_ALL, NULL, NULL, TRUE, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute info")
+ } /* end if */
+ else {
+ if(H5O_msg_write_real(loc->file, dxpl_id, oh, H5O_MSG_AINFO, H5O_MSG_FLAG_DONTSHARE, 0, ainfo) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update attribute info message")
+ } /* end else */
+
done:
+ /* Release resources */
+ if(atable.attrs && H5A_attr_release_table(&atable) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute table")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_attr_remove_update() */
@@ -1222,13 +1285,6 @@ H5O_attr_remove_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
/* Check for correct attribute message to modify */
if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->name) == 0) {
- /* If the later version of the object header format, decrement attribute */
- /* (must be decremented before call to H5O_release_mesg(), in order for
- * sanity checks to pass - QAK)
- */
- if(oh->version > H5O_VERSION_1)
- oh->nattrs--;
-
/* Convert message into a null message (i.e. delete it) */
if(H5O_release_mesg(udata->f, udata->dxpl_id, oh, mesg, TRUE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, H5_ITER_ERROR, "unable to convert into null message")
@@ -1264,6 +1320,8 @@ herr_t
H5O_attr_remove(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
{
H5O_t *oh = NULL; /* Pointer to actual object header */
+ H5O_ainfo_t ainfo; /* Attribute information for object */
+ H5O_ainfo_t *ainfo_ptr = NULL; /* Pointer to attribute information for object */
unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1277,14 +1335,17 @@ H5O_attr_remove(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
+ /* Check for attribute info stored */
+ ainfo.fheap_addr = HADDR_UNDEF;
+ if(oh->version > H5O_VERSION_1 && NULL == (ainfo_ptr = H5O_msg_read_real(loc->file, dxpl_id, oh, H5O_AINFO_ID, &ainfo)))
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+
/* Check for attributes stored densely */
- if(H5F_addr_defined(oh->attr_fheap_addr)) {
+ if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Delete attribute from dense storage */
- if(H5A_dense_remove(loc->file, dxpl_id, oh, name) < 0)
+ if(H5A_dense_remove(loc->file, dxpl_id, &ainfo, name) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute in dense storage")
-
- /* Decrement # of attributes on object */
- oh->nattrs--;
} /* end if */
else {
H5O_iter_rm_t udata; /* User data for callback */
@@ -1307,9 +1368,10 @@ H5O_attr_remove(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't locate attribute")
} /* end else */
- /* Update the object header information after removing an attribute */
- if(H5O_attr_remove_update(loc, oh, dxpl_id) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update attribute info")
+ /* Update the attribute information after removing an attribute */
+ if(ainfo_ptr)
+ if(H5O_attr_remove_update(loc, oh, &ainfo, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update attribute info")
/* Update the modification time, if any */
if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE) < 0)
@@ -1344,6 +1406,8 @@ H5O_attr_remove_by_idx(const H5O_loc_t *loc, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, hid_t dxpl_id)
{
H5O_t *oh = NULL; /* Pointer to actual object header */
+ H5O_ainfo_t ainfo; /* Attribute information for object */
+ H5O_ainfo_t *ainfo_ptr = NULL; /* Pointer to attribute information for object */
unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
H5A_attr_table_t atable = {0, NULL}; /* Table of attributes */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1357,14 +1421,17 @@ H5O_attr_remove_by_idx(const H5O_loc_t *loc, H5_index_t idx_type,
if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
+ /* Check for attribute info stored */
+ ainfo.fheap_addr = HADDR_UNDEF;
+ if(oh->version > H5O_VERSION_1 && NULL == (ainfo_ptr = H5O_msg_read_real(loc->file, dxpl_id, oh, H5O_AINFO_ID, &ainfo)))
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+
/* Check for attributes stored densely */
- if(H5F_addr_defined(oh->attr_fheap_addr)) {
+ if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Delete attribute from dense storage */
- if(H5A_dense_remove_by_idx(loc->file, dxpl_id, oh, idx_type, order, n) < 0)
+ if(H5A_dense_remove_by_idx(loc->file, dxpl_id, &ainfo, idx_type, order, n) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute in dense storage")
-
- /* Decrement # of attributes on object */
- oh->nattrs--;
} /* end if */
else {
H5O_iter_rm_t udata; /* User data for callback */
@@ -1395,9 +1462,10 @@ H5O_attr_remove_by_idx(const H5O_loc_t *loc, H5_index_t idx_type,
HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't locate attribute")
} /* end else */
- /* Update the object header information after removing an attribute */
- if(H5O_attr_remove_update(loc, oh, dxpl_id) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update attribute info")
+ /* Update the attribute information after removing an attribute */
+ if(ainfo_ptr)
+ if(H5O_attr_remove_update(loc, oh, &ainfo, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update attribute info")
/* Update the modification time, if any */
if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE) < 0)
@@ -1417,6 +1485,56 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5O_attr_count_real
+ *
+ * Purpose: Determine the # of attributes on an object
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 9, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+hsize_t
+H5O_attr_count_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
+{
+ hsize_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_attr_count_real)
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(oh);
+
+ /* Check for attributes stored densely */
+ if(oh->version > H5O_VERSION_1) {
+ H5O_ainfo_t ainfo; /* Attribute information for object */
+
+ /* Attempt to get the attribute information from the object header */
+ if(H5O_msg_read_real(f, dxpl_id, oh, H5O_AINFO_ID, &ainfo))
+ ret_value = ainfo.nattrs;
+ else {
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+
+ ret_value = 0;
+ } /* end else */
+ } /* end if */
+ else {
+ unsigned u; /* Local index variable */
+
+ /* Loop over all messages, counting the attributes */
+ for(u = ret_value = 0; u < oh->nmesgs; u++)
+ if(oh->mesg[u].type == H5O_MSG_ATTR)
+ ret_value++;
+ } /* end else */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_attr_count_real */
+
+
+/*-------------------------------------------------------------------------
* Function: H5O_attr_count
*
* Purpose: Determine the # of attributes on an object
@@ -1443,17 +1561,8 @@ H5O_attr_count(const H5O_loc_t *loc, hid_t dxpl_id)
if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
- /* Check for attributes stored densely */
- if(oh->version > H5O_VERSION_1)
- ret_value = (int)oh->nattrs;
- else {
- unsigned u; /* Local index variable */
-
- /* Loop over all messages, counting the attributes */
- for(u = ret_value = 0; u < oh->nmesgs; u++)
- if(oh->mesg[u].type == H5O_MSG_ATTR)
- ret_value++;
- } /* end else */
+ /* Retrieve # of attributes on object */
+ ret_value = (int)H5O_attr_count_real(loc->file, dxpl_id, oh);
done:
if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
@@ -1519,6 +1628,7 @@ htri_t
H5O_attr_exists(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
{
H5O_t *oh = NULL; /* Pointer to actual object header */
+ H5O_ainfo_t ainfo; /* Attribute information for object */
htri_t ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_exists)
@@ -1531,10 +1641,16 @@ H5O_attr_exists(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
+ /* Check for attribute info stored */
+ ainfo.fheap_addr = HADDR_UNDEF;
+ if(oh->version > H5O_VERSION_1 && NULL == H5O_msg_read_real(loc->file, dxpl_id, oh, H5O_AINFO_ID, &ainfo))
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+
/* Check for attributes stored densely */
- if(H5F_addr_defined(oh->attr_fheap_addr)) {
+ if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Check if attribute exists in dense storage */
- if((ret_value = H5A_dense_exists(loc->file, dxpl_id, oh, name)) < 0)
+ if((ret_value = H5A_dense_exists(loc->file, dxpl_id, &ainfo, name)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error checking for existence of attribute")
} /* end if */
else {
diff --git a/src/H5Ocache.c b/src/H5Ocache.c
index 7000e9e..786d1d3 100644
--- a/src/H5Ocache.c
+++ b/src/H5Ocache.c
@@ -48,9 +48,6 @@
* extra I/O operations) */
#define H5O_SPEC_READ_SIZE 512
-/* All the object header status flags that this version of the library knows about */
-#define H5O_HDR_ALL_FLAGS (H5O_HDR_ATTR_CRT_ORDER_TRACKED | H5O_HDR_ATTR_CRT_ORDER_INDEXED | H5O_HDR_ATTR_STORE_PHASE_CHANGE | H5O_HDR_STORE_TIMES)
-
/******************/
/* Local Typedefs */
@@ -324,16 +321,6 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
oh->max_compact = H5O_CRT_ATTR_MAX_COMPACT_DEF;
oh->min_dense = H5O_CRT_ATTR_MIN_DENSE_DEF;
} /* end else */
- H5F_DECODE_LENGTH(f, p, oh->nattrs);
- H5F_addr_decode(f, &p, &(oh->attr_fheap_addr));
- H5F_addr_decode(f, &p, &(oh->name_bt2_addr));
- H5F_addr_decode(f, &p, &(oh->corder_bt2_addr));
-
- /* Only encode max. creation index if they are being tracked */
- if(oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)
- UINT16DECODE(p, oh->max_attr_crt_idx)
- else
- oh->max_attr_crt_idx = 0;
} /* end if */
else {
/* Reset unused time fields */
@@ -342,11 +329,6 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
/* Reset unused attribute fields */
oh->max_compact = 0;
oh->min_dense = 0;
- oh->nattrs = 0;
- oh->attr_fheap_addr = HADDR_UNDEF;
- oh->name_bt2_addr = HADDR_UNDEF;
- oh->corder_bt2_addr = HADDR_UNDEF;
- oh->max_attr_crt_idx = 0;
} /* end else */
/* First chunk size */
@@ -689,14 +671,6 @@ H5O_assert(oh);
UINT16ENCODE(p, oh->max_compact);
UINT16ENCODE(p, oh->min_dense);
} /* end if */
- H5F_ENCODE_LENGTH(f, p, oh->nattrs);
- H5F_addr_encode(f, &p, oh->attr_fheap_addr);
- H5F_addr_encode(f, &p, oh->name_bt2_addr);
- H5F_addr_encode(f, &p, oh->corder_bt2_addr);
-
- /* Only encode max. creation index if they are being tracked */
- if(oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)
- UINT16ENCODE(p, oh->max_attr_crt_idx);
/* Chunk size */
UINT32ENCODE(p, (oh->chunk[0].size - H5O_SIZEOF_HDR(oh)));
diff --git a/src/H5Ocopy.c b/src/H5Ocopy.c
index 6a01355..55ba9bf 100644
--- a/src/H5Ocopy.c
+++ b/src/H5Ocopy.c
@@ -348,28 +348,9 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
oh_dst->ctime = oh_src->ctime;
oh_dst->btime = oh_src->btime;
- /* Copy attribute information */
+ /* Copy attribute storage information */
oh_dst->max_compact = oh_src->max_compact;
oh_dst->min_dense = oh_src->min_dense;
- if(cpy_info->copy_without_attr) {
- oh_dst->nattrs = 0;
- oh_dst->attr_fheap_addr = HADDR_UNDEF;
- oh_dst->name_bt2_addr = HADDR_UNDEF;
- oh_dst->corder_bt2_addr = HADDR_UNDEF;
- } /* end if */
- else {
- oh_dst->nattrs = oh_src->nattrs;
-/* XXX: Bail out for now, if the source object has densely stored attributes */
- if(H5F_addr_defined(oh_src->attr_fheap_addr))
- HGOTO_ERROR(H5E_OHDR, H5E_UNSUPPORTED, FAIL, "densely stored attributes not supported yet")
- else {
- HDassert(!H5F_addr_defined(oh_src->name_bt2_addr));
- oh_dst->attr_fheap_addr = HADDR_UNDEF;
- oh_dst->name_bt2_addr = HADDR_UNDEF;
- oh_dst->corder_bt2_addr = HADDR_UNDEF;
- } /* end else */
- } /* end else */
-
/* Initialize size of chunk array. The destination always has only one
* chunk.
diff --git a/src/H5Odbg.c b/src/H5Odbg.c
index de706c7..a5428c1 100644
--- a/src/H5Odbg.c
+++ b/src/H5Odbg.c
@@ -94,7 +94,6 @@ H5O_assert(const H5O_t *oh)
{
H5O_mesg_t *curr_msg; /* Pointer to current message to examine */
H5O_mesg_t *tmp_msg; /* Pointer to temporary message to examine */
- hsize_t num_attrs; /* Number of attributes on object */
size_t meta_space; /* Size of header metadata */
size_t mesg_space; /* Size of message raw data */
size_t free_space; /* Size of free space in header */
@@ -108,7 +107,6 @@ H5O_assert(const H5O_t *oh)
meta_space = H5O_SIZEOF_HDR(oh) + (H5O_SIZEOF_CHKHDR_OH(oh) * (oh->nchunks - 1));
mesg_space = 0;
free_space = 0;
- num_attrs = 0;
/* Loop over all chunks in object header */
for(u = 0; u < oh->nchunks; u++) {
@@ -140,10 +138,6 @@ H5O_assert(const H5O_t *oh)
/* Loop over all messages in object header */
for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) {
- /* Check for attribute message */
- if(H5O_ATTR_ID == curr_msg->type->id)
- num_attrs++;
-
/* Accumulate information, based on the type of message */
if(H5O_NULL_ID == curr_msg->type->id)
free_space += H5O_SIZEOF_MSGHDR_OH(oh) + curr_msg->raw_size;
@@ -175,8 +169,6 @@ H5O_assert(const H5O_t *oh)
HDassert(!(tmp_msg->raw >= curr_msg->raw && tmp_msg->raw < (curr_msg->raw + curr_msg->raw_size)));
} /* end for */
} /* end for */
- if(oh->version > H5O_VERSION_1 && !H5F_addr_defined(oh->attr_fheap_addr))
- HDassert(oh->nattrs == num_attrs);
/* Sanity check that all the bytes are accounted for */
HDassert(hdr_size == (free_space + meta_space + mesg_space + oh->skipped_mesg_size));
@@ -276,54 +268,59 @@ H5O_debug_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, haddr_t addr, FILE *stream, i
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"Number of links:",
oh->nlink);
+
/* Extra information for later versions */
if(oh->version > H5O_VERSION_1) {
- struct tm *tm; /* Time structure */
- char buf[128]; /* Buffer for formatting time info */
-
- /* Time fields */
- tm = HDlocaltime(&oh->atime);
- HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm);
- HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
- "Access Time:", buf);
- tm = HDlocaltime(&oh->mtime);
- HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm);
- HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
- "Modification Time:", buf);
- tm = HDlocaltime(&oh->ctime);
- HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm);
- HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
- "Change Time:", buf);
- tm = HDlocaltime(&oh->btime);
- HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm);
- HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
- "Birth Time:", buf);
-
- /* Attribute tracking fields */
+ /* Display object's status flags */
HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
"Attribute creation order tracked:",
(oh->flags & H5P_CRT_ORDER_TRACKED) ? "Yes" : "No");
HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
"Attribute creation order indexed:",
(oh->flags & H5P_CRT_ORDER_INDEXED) ? "Yes" : "No");
- HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
- "Max. compact attributes:",
- (unsigned)oh->max_compact);
- HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
- "Min. dense attributes:",
- (unsigned)oh->min_dense);
- HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
- "Number of attributes:",
- oh->nattrs);
- HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
- "Attribute heap address:",
- oh->attr_fheap_addr);
- HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
- "Attribute name index address:",
- oh->name_bt2_addr);
- HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
- "Attribute creation order index address:",
- oh->corder_bt2_addr);
+ HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "Attribute storage phase change values:",
+ (oh->flags & H5O_HDR_ATTR_STORE_PHASE_CHANGE) ? "Non-default" : "Default");
+ HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "Timestamps:",
+ (oh->flags & H5O_HDR_STORE_TIMES) ? "Enabled" : "Disabled");
+ if(oh->flags & ~H5O_HDR_ALL_FLAGS)
+ HDfprintf(stream, "*** UNKNOWN OBJECT HEADER STATUS FLAG: %02x!\n",
+ (unsigned)oh->flags);
+
+ /* Only dump times, if they are tracked */
+ if(oh->flags & H5O_HDR_STORE_TIMES) {
+ struct tm *tm; /* Time structure */
+ char buf[128]; /* Buffer for formatting time info */
+
+ /* Time fields */
+ tm = HDlocaltime(&oh->atime);
+ HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm);
+ HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "Access Time:", buf);
+ tm = HDlocaltime(&oh->mtime);
+ HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm);
+ HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "Modification Time:", buf);
+ tm = HDlocaltime(&oh->ctime);
+ HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm);
+ HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "Change Time:", buf);
+ tm = HDlocaltime(&oh->btime);
+ HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm);
+ HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "Birth Time:", buf);
+ } /* end if */
+
+ /* Attribute tracking fields */
+ if(oh->flags & H5O_HDR_ATTR_STORE_PHASE_CHANGE) {
+ HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
+ "Max. compact attributes:",
+ (unsigned)oh->max_compact);
+ HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
+ "Min. dense attributes:",
+ (unsigned)oh->min_dense);
+ } /* end if */
} /* end if */
HDfprintf(stream, "%*s%-*s %Zu (%Zu)\n", indent, "", fwidth,
diff --git a/src/H5Omessage.c b/src/H5Omessage.c
index bf0d0b0..651cd64 100644
--- a/src/H5Omessage.c
+++ b/src/H5Omessage.c
@@ -73,12 +73,7 @@ typedef struct {
/* Local Prototypes */
/********************/
-static herr_t H5O_msg_write_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
- const H5O_msg_class_t *type, unsigned mesg_flags, unsigned update_flags,
- void *mesg);
static herr_t H5O_msg_reset_real(const H5O_msg_class_t *type, void *native);
-static herr_t H5O_msg_remove_real(const H5O_loc_t *loc, const H5O_msg_class_t *type,
- int sequence, H5O_operator_t op, void *op_data, hbool_t adj_link, hid_t dxpl_id);
static herr_t H5O_msg_remove_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
unsigned sequence, hbool_t *oh_modified, void *_udata/*in,out*/);
static herr_t H5O_copy_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx,
@@ -325,7 +320,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-static herr_t
+herr_t
H5O_msg_write_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *type,
unsigned mesg_flags, unsigned update_flags, void *mesg)
{
@@ -339,10 +334,11 @@ H5O_msg_write_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *ty
HDassert(f);
HDassert(oh);
HDassert(type);
+ HDassert(type != H5O_MSG_ATTR);
HDassert(mesg);
HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS));
- /* Count similar messages */
+ /* Locate message of correct type */
for(idx = 0, idx_msg = &oh->mesg[0]; idx < oh->nmesgs; idx++, idx_msg++)
if(type->id == idx_msg->type->id)
break;
@@ -433,7 +429,7 @@ H5O_msg_read(const H5O_loc_t *loc, unsigned type_id, void *mesg,
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "unable to load object header")
/* Call the "real" read routine */
- if((ret_value = H5O_msg_read_real(loc->file, dxpl_id, oh, type_id, mesg)) == NULL)
+ if(NULL == (ret_value = H5O_msg_read_real(loc->file, dxpl_id, oh, type_id, mesg)))
HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to load object header")
done:
@@ -915,6 +911,7 @@ herr_t
H5O_msg_remove(H5O_loc_t *loc, unsigned type_id, int sequence, hbool_t adj_link,
hid_t dxpl_id)
{
+ H5O_t *oh = NULL; /* Pointer to actual object header */
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
herr_t ret_value; /* Return value */
@@ -929,11 +926,18 @@ H5O_msg_remove(H5O_loc_t *loc, unsigned type_id, int sequence, hbool_t adj_link,
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
HDassert(type);
+ /* Protect the object header to iterate over */
+ if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
+
/* Call the "real" remove routine */
- if((ret_value = H5O_msg_remove_real(loc, type, sequence, NULL, NULL, adj_link, dxpl_id)) < 0)
+ if((ret_value = H5O_msg_remove_real(loc->file, oh, type, sequence, NULL, NULL, adj_link, dxpl_id)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to remove object header message")
done:
+ if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_msg_remove() */
@@ -959,6 +963,7 @@ herr_t
H5O_msg_remove_op(const H5O_loc_t *loc, unsigned type_id, int sequence,
H5O_operator_t op, void *op_data, hbool_t adj_link, hid_t dxpl_id)
{
+ H5O_t *oh = NULL; /* Pointer to actual object header */
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
herr_t ret_value; /* Return value */
@@ -973,11 +978,18 @@ H5O_msg_remove_op(const H5O_loc_t *loc, unsigned type_id, int sequence,
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
HDassert(type);
+ /* Protect the object header to iterate over */
+ if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
+
/* Call the "real" remove routine */
- if((ret_value = H5O_msg_remove_real(loc, type, sequence, op, op_data, adj_link, dxpl_id)) < 0)
+ if((ret_value = H5O_msg_remove_real(loc->file, oh, type, sequence, op, op_data, adj_link, dxpl_id)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to remove object header message")
done:
+ if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_msg_remove_op() */
@@ -1058,9 +1070,6 @@ done:
* the sequence numbers to change for subsequent messages of
* the same type.
*
- * No attempt is made to join adjacent free areas of the
- * object header into a single larger free area.
- *
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
@@ -1069,28 +1078,28 @@ done:
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5O_msg_remove_real(const H5O_loc_t *loc, const H5O_msg_class_t *type, int sequence,
- H5O_operator_t app_op, void *op_data, hbool_t adj_link, hid_t dxpl_id)
+herr_t
+H5O_msg_remove_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type,
+ int sequence, H5O_operator_t app_op, void *op_data, hbool_t adj_link,
+ hid_t dxpl_id)
{
- H5O_t *oh = NULL; /* Pointer to actual object header */
H5O_iter_rm_t udata; /* User data for iterator */
H5O_mesg_operator_t op; /* Wrapper for operator */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5O_msg_remove_real)
+ FUNC_ENTER_NOAPI(H5O_msg_remove_real, FAIL)
/* check args */
- HDassert(loc);
- HDassert(loc->file);
+ HDassert(f);
+ HDassert(oh);
HDassert(type);
/* Make certain we are allowed to modify the file */
- if(0 == (H5F_INTENT(loc->file) & H5F_ACC_RDWR))
- HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file")
+ if(0 == (H5F_INTENT(f) & H5F_ACC_RDWR))
+ HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "no write intent on file")
/* Set up iterator operator data */
- udata.f = loc->file;
+ udata.f = f;
udata.dxpl_id = dxpl_id;
udata.sequence = sequence;
udata.nfailed = 0;
@@ -1098,14 +1107,10 @@ H5O_msg_remove_real(const H5O_loc_t *loc, const H5O_msg_class_t *type, int seque
udata.op_data = op_data;
udata.adj_link = adj_link;
- /* Protect the object header to iterate over */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
-
/* Iterate over the messages, deleting appropriate one(s) */
op.op_type = H5O_MESG_OP_LIB;
op.u.lib_op = H5O_msg_remove_cb;
- if(H5O_msg_iterate_real(loc->file, oh, type, &op, &udata, dxpl_id) < 0)
+ if(H5O_msg_iterate_real(f, oh, type, &op, &udata, dxpl_id) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "error iterating over messages")
/* Fail if we tried to remove any constant messages */
@@ -1113,9 +1118,6 @@ H5O_msg_remove_real(const H5O_loc_t *loc, const H5O_msg_class_t *type, int seque
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to remove constant message(s)")
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
-
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_msg_remove_real() */
diff --git a/src/H5Opkg.h b/src/H5Opkg.h
index 68066cf..bd92478 100644
--- a/src/H5Opkg.h
+++ b/src/H5Opkg.h
@@ -24,7 +24,6 @@
#include "H5Oprivate.h" /* Object headers */
/* Other private headers needed by this file */
-#include "H5Aprivate.h" /* Attributes */
#include "H5ACprivate.h" /* Metadata cache */
/* Object header macros */
@@ -116,13 +115,6 @@
2 + /*max compact attributes */ \
2 /*min dense attributes */ \
) : 0) + \
- (O)->sizeof_size + /*# of attributes */ \
- (O)->sizeof_addr + /*addr of attribute heap */ \
- (O)->sizeof_addr + /*addr of attribute name index */ \
- (O)->sizeof_addr + /*addr of attribute creation order index */ \
- (((O)->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED) ? ( \
- 2 /*max attr. creation index */ \
- ) : 0) + \
4 + /*chunk data size */ \
H5O_SIZEOF_CHKSUM) /*checksum size */ \
)
@@ -197,6 +189,9 @@
} /* end if */ \
} /* end if */
+/* All the object header status flags that this version of the library knows about */
+#define H5O_HDR_ALL_FLAGS (H5O_HDR_ATTR_CRT_ORDER_TRACKED | H5O_HDR_ATTR_CRT_ORDER_INDEXED | H5O_HDR_ATTR_STORE_PHASE_CHANGE | H5O_HDR_STORE_TIMES)
+
/* The "message class" type */
struct H5O_msg_class_t {
@@ -263,11 +258,6 @@ struct H5O_t {
/* Attribute information (stored, for versions > 1) */
unsigned max_compact; /* Maximum # of compact attributes */
unsigned min_dense; /* Minimum # of "dense" attributes */
- hsize_t nattrs; /* Number of attributes on the object */
- haddr_t attr_fheap_addr; /* Address of fractal heap for storing "dense" attributes */
- haddr_t name_bt2_addr; /* Address of v2 B-tree for indexing names of attributes */
- haddr_t corder_bt2_addr; /* Address of v2 B-tree for indexing creation order of attributes */
- H5O_msg_crt_idx_t max_attr_crt_idx; /* Maximum attribute creation index used */
/* Message management (stored, encoded in chunks) */
size_t nmesgs; /*number of messages */
@@ -469,12 +459,17 @@ H5_DLL unsigned H5O_msg_alloc(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
H5_DLL herr_t H5O_msg_append_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
const H5O_msg_class_t *type, unsigned mesg_flags, unsigned update_flags,
void *mesg);
+H5_DLL herr_t H5O_msg_write_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
+ const H5O_msg_class_t *type, unsigned mesg_flags, unsigned update_flags,
+ void *mesg);
H5_DLL void *H5O_msg_read_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
unsigned type_id, void *mesg);
H5_DLL void *H5O_msg_free_real(const H5O_msg_class_t *type, void *mesg);
H5_DLL herr_t H5O_msg_free_mesg(H5O_mesg_t *mesg);
H5_DLL unsigned H5O_msg_count_real(const H5O_t *oh, const H5O_msg_class_t *type);
H5_DLL htri_t H5O_msg_exists_oh(const H5O_t *oh, unsigned type_id);
+H5_DLL herr_t H5O_msg_remove_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type,
+ int sequence, H5O_operator_t op, void *op_data, hbool_t adj_link, hid_t dxpl_id);
H5_DLL void *H5O_msg_copy_file(const H5O_msg_class_t *type, H5F_t *file_src,
void *mesg_src, H5F_t *file_dst, hid_t dxpl_id, hbool_t *shared,
H5O_copy_t *cpy_info, void *udata);
@@ -502,7 +497,7 @@ H5_DLL herr_t H5O_shared_copy_file(H5F_t *file_src, H5F_t *file_dst, hid_t dxpl_
H5_DLL herr_t H5O_shared_debug(const H5O_shared_t *mesg, FILE *stream,
int indent, int fwidth);
-/* Attribute operators */
+/* Attribute message operators */
H5_DLL herr_t H5O_attr_reset(void *_mesg);
H5_DLL herr_t H5O_attr_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg);
H5_DLL herr_t H5O_attr_link(H5F_t *f, hid_t dxpl_id, const void *_mesg);
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 5349827..c916f7e 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -415,6 +415,7 @@ typedef struct H5O_drvinfo_t {
*/
typedef struct H5O_ainfo_t {
/* (creation order info) */
+ hbool_t track_corder; /* Are creation order values tracked on attributes? */
hbool_t index_corder; /* Are creation order values indexed on attributes? */
H5O_msg_crt_idx_t max_crt_idx; /* Maximum attribute creation index used */
haddr_t corder_bt2_addr; /* Address of v2 B-tree for indexing creation order values of "dense" attributes */
@@ -525,5 +526,8 @@ H5_DLL herr_t H5O_link_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg);
/* Shared message operators */
H5_DLL herr_t H5O_shared_copy(void *dst, const H5O_shared_t *src);
+/* Attribute operators */
+H5_DLL hsize_t H5O_attr_count_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh);
+
#endif /* _H5Oprivate_H */
diff --git a/src/H5Otest.c b/src/H5Otest.c
index ac444e5..dc516c6 100644
--- a/src/H5Otest.c
+++ b/src/H5Otest.c
@@ -96,6 +96,7 @@ htri_t
H5O_is_attr_dense_test(hid_t oid)
{
H5O_t *oh = NULL; /* Object header */
+ H5O_ainfo_t ainfo; /* Attribute information for object */
H5O_loc_t *oloc; /* Pointer to object's location */
htri_t ret_value; /* Return value */
@@ -109,8 +110,14 @@ H5O_is_attr_dense_test(hid_t oid)
if(NULL == (oh = H5AC_protect(oloc->file, H5AC_ind_dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
+ /* Check for attribute info stored */
+ ainfo.fheap_addr = HADDR_UNDEF;
+ if(oh->version > H5O_VERSION_1 && NULL == H5O_msg_read_real(oloc->file, H5AC_ind_dxpl_id, oh, H5O_AINFO_ID, &ainfo))
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+
/* Check if dense storage is being used */
- if(H5F_addr_defined(oh->attr_fheap_addr)) {
+ if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Check for any messages in object header */
HDassert(H5O_msg_count_real(oh, H5O_MSG_ATTR) == 0);
@@ -149,6 +156,8 @@ htri_t
H5O_is_attr_empty_test(hid_t oid)
{
H5O_t *oh = NULL; /* Object header */
+ H5O_ainfo_t ainfo; /* Attribute information for object */
+ H5O_ainfo_t *ainfo_ptr = NULL; /* Pointer to attribute information for object */
H5O_loc_t *oloc; /* Pointer to object's location */
hsize_t nattrs; /* Number of attributes */
htri_t ret_value; /* Return value */
@@ -163,23 +172,33 @@ H5O_is_attr_empty_test(hid_t oid)
if(NULL == (oh = H5AC_protect(oloc->file, H5AC_ind_dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
+ /* Check for attribute info stored */
+ ainfo.fheap_addr = HADDR_UNDEF;
+ if(oh->version > H5O_VERSION_1 && NULL == (ainfo_ptr = H5O_msg_read_real(oloc->file, H5AC_ind_dxpl_id, oh, H5O_AINFO_ID, &ainfo)))
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+
/* Retrieve the number of attribute messages in header */
nattrs = H5O_msg_count_real(oh, H5O_MSG_ATTR);
- /* Check for later version of object header format */
+ /* Check for later version of object header format & attribute info available */
if(oh->version > H5O_VERSION_1) {
- /* Check for using dense storage */
- if(H5F_addr_defined(oh->attr_fheap_addr)) {
- /* Check for any messages in object header */
- HDassert(nattrs == 0);
-
- /* Retrieve # of records in name index */
- if(H5B2_get_nrec(oloc->file, H5AC_ind_dxpl_id, H5A_BT2_NAME, oh->name_bt2_addr, &nattrs) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTCOUNT, FAIL, "unable to retrieve # of records from name index")
+ if(ainfo_ptr) {
+ /* Check for using dense storage */
+ if(H5F_addr_defined(ainfo.fheap_addr)) {
+ /* Check for any messages in object header */
+ HDassert(nattrs == 0);
+
+ /* Retrieve # of records in name index */
+ if(H5B2_get_nrec(oloc->file, H5AC_ind_dxpl_id, H5A_BT2_NAME, ainfo.name_bt2_addr, &nattrs) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTCOUNT, FAIL, "unable to retrieve # of records from name index")
+ } /* end if */
+
+ /* Verify that attribute count in object header is correct */
+ HDassert(nattrs == ainfo.nattrs);
} /* end if */
-
- /* Verify that attribute count in object header is correct */
- HDassert(nattrs == oh->nattrs);
+ else
+ HDassert(nattrs == 0);
} /* end if */
/* Set the return value */
@@ -216,6 +235,7 @@ herr_t
H5O_num_attrs_test(hid_t oid, hsize_t *nattrs)
{
H5O_t *oh = NULL; /* Object header */
+ H5O_ainfo_t ainfo; /* Attribute information for object */
H5O_loc_t *oloc; /* Pointer to object's location */
hsize_t obj_nattrs; /* Number of attributes */
herr_t ret_value = SUCCEED; /* Return value */
@@ -230,23 +250,29 @@ H5O_num_attrs_test(hid_t oid, hsize_t *nattrs)
if(NULL == (oh = H5AC_protect(oloc->file, H5AC_ind_dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
+ /* Check for attribute info stored */
+ ainfo.fheap_addr = HADDR_UNDEF;
+ if(oh->version > H5O_VERSION_1 && NULL == H5O_msg_read_real(oloc->file, H5AC_ind_dxpl_id, oh, H5O_AINFO_ID, &ainfo))
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+
/* Retrieve the number of attribute messages in header */
obj_nattrs = H5O_msg_count_real(oh, H5O_MSG_ATTR);
/* Check for later version of object header format */
if(oh->version > H5O_VERSION_1) {
/* Check for using dense storage */
- if(H5F_addr_defined(oh->attr_fheap_addr)) {
+ if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Check for any messages in object header */
HDassert(obj_nattrs == 0);
/* Retrieve # of records in name index */
- if(H5B2_get_nrec(oloc->file, H5AC_ind_dxpl_id, H5A_BT2_NAME, oh->name_bt2_addr, &obj_nattrs) < 0)
+ if(H5B2_get_nrec(oloc->file, H5AC_ind_dxpl_id, H5A_BT2_NAME, ainfo.name_bt2_addr, &obj_nattrs) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTCOUNT, FAIL, "unable to retrieve # of records from name index")
} /* end if */
/* Verify that attribute count in object header is correct */
- HDassert(obj_nattrs == oh->nattrs);
+ HDassert(obj_nattrs == ainfo.nattrs);
} /* end if */
/* Set the number of attributes */
@@ -285,6 +311,7 @@ herr_t
H5O_attr_dense_info_test(hid_t oid, hsize_t *name_count, hsize_t *corder_count)
{
H5O_t *oh = NULL; /* Object header */
+ H5O_ainfo_t ainfo; /* Attribute information for object */
H5O_loc_t *oloc; /* Pointer to object's location */
herr_t ret_value = SUCCEED; /* Return value */
@@ -298,20 +325,26 @@ H5O_attr_dense_info_test(hid_t oid, hsize_t *name_count, hsize_t *corder_count)
if(NULL == (oh = H5AC_protect(oloc->file, H5AC_ind_dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
+ /* Check for attribute info stored */
+ ainfo.fheap_addr = HADDR_UNDEF;
+ if(oh->version > H5O_VERSION_1 && NULL == H5O_msg_read_real(oloc->file, H5AC_ind_dxpl_id, oh, H5O_AINFO_ID, &ainfo))
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+
/* Check for 'dense' attribute storage file addresses being defined */
- if(!H5F_addr_defined(oh->attr_fheap_addr))
+ if(!H5F_addr_defined(ainfo.fheap_addr))
HGOTO_DONE(FAIL)
- if(!H5F_addr_defined(oh->name_bt2_addr))
+ if(!H5F_addr_defined(ainfo.name_bt2_addr))
HGOTO_DONE(FAIL)
/* Retrieve # of records in name index */
- if(H5B2_get_nrec(oloc->file, H5AC_ind_dxpl_id, H5A_BT2_NAME, oh->name_bt2_addr, name_count) < 0)
+ if(H5B2_get_nrec(oloc->file, H5AC_ind_dxpl_id, H5A_BT2_NAME, ainfo.name_bt2_addr, name_count) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTCOUNT, FAIL, "unable to retrieve # of records from name index")
/* Check if there is a creation order index */
- if(H5F_addr_defined(oh->corder_bt2_addr)) {
+ if(H5F_addr_defined(ainfo.corder_bt2_addr)) {
/* Retrieve # of records in creation order index */
- if(H5B2_get_nrec(oloc->file, H5AC_ind_dxpl_id, H5A_BT2_CORDER, oh->corder_bt2_addr, corder_count) < 0)
+ if(H5B2_get_nrec(oloc->file, H5AC_ind_dxpl_id, H5A_BT2_CORDER, ainfo.corder_bt2_addr, corder_count) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTCOUNT, FAIL, "unable to retrieve # of records from creation order index")
} /* end if */
else