summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/H5Adense.c140
-rw-r--r--src/H5Oattribute.c3
-rwxr-xr-xsrc/H5SM.c7
-rwxr-xr-xsrc/H5SMpkg.h2
-rw-r--r--test/tattr.c45
5 files changed, 161 insertions, 36 deletions
diff --git a/src/H5Adense.c b/src/H5Adense.c
index 0d4f02d..d83c3e5 100644
--- a/src/H5Adense.c
+++ b/src/H5Adense.c
@@ -77,6 +77,7 @@ typedef struct H5A_bt2_od_wrt_t {
H5HF_t *fheap; /* Fractal heap handle to operate on */
H5HF_t *shared_fheap; /* Fractal heap handle for shared messages */
H5A_t *attr; /* Attribute to write */
+ haddr_t corder_bt2_addr; /* v2 B-tree address of creation order index */
} H5A_bt2_od_wrt_t;
/*
@@ -539,6 +540,44 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5A_dense_write_bt2_cb2
+ *
+ * Purpose: v2 B-tree 'modify' callback to update the record for a creation
+ * order index
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, February 20, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5A_dense_write_bt2_cb2(void *_record, void *_op_data, hbool_t *changed)
+{
+ H5A_dense_bt2_corder_rec_t *record = (H5A_dense_bt2_corder_rec_t *)_record; /* Record from B-tree */
+ H5O_fheap_id_t *new_heap_id = (H5O_fheap_id_t *)_op_data; /* "op data" from v2 B-tree modify */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_dense_write_bt2_cb2)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(record);
+ HDassert(new_heap_id);
+
+ /* Update record's heap ID */
+ record->id = *new_heap_id;
+
+ /* Note that the record changed */
+ *changed = TRUE;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5A_dense_write_bt2_cb2() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5A_dense_write_bt2_cb
*
* Purpose: v2 B-tree 'modify' callback to update the data for an attribute
@@ -577,6 +616,27 @@ H5A_dense_write_bt2_cb(void *_record, void *_op_data, hbool_t *changed)
/* Update record's heap ID */
record->id = op_data->attr->sh_loc.u.heap_id;
+ /* Check if we need to modify the creation order index with new heap ID */
+ if(H5F_addr_defined(op_data->corder_bt2_addr)) {
+ H5A_bt2_ud_common_t udata; /* User data for v2 B-tree modify */
+
+ /* Create the "udata" information for v2 B-tree record modify */
+ udata.f = op_data->f;
+ udata.dxpl_id = op_data->dxpl_id;
+ udata.fheap = NULL;
+ udata.shared_fheap = NULL;
+ udata.name = NULL;
+ udata.name_hash = 0;
+ udata.flags = 0;
+ udata.corder = op_data->attr->crt_idx;
+ udata.found_op = NULL;
+ udata.found_op_data = NULL;
+
+ /* Modify record for creation order index */
+ if(H5B2_modify(op_data->f, op_data->dxpl_id, H5A_BT2_CORDER, op_data->corder_bt2_addr, &udata, H5A_dense_write_bt2_cb2, &op_data->attr->sh_loc.u.heap_id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to modify record in v2 B-tree")
+ } /* end if */
+
/* Note that the record changed */
*changed = TRUE;
} /* end if */
@@ -698,6 +758,7 @@ 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;
/* 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)
@@ -1131,6 +1192,16 @@ H5A_dense_remove_bt2_cb(const void *_record, void *_udata)
FUNC_ENTER_NOAPI_NOINIT(H5A_dense_remove_bt2_cb)
+ /* Check for removing the link from the creation order index */
+ if(H5F_addr_defined(udata->corder_bt2_addr)) {
+ /* Set up the user data for the v2 B-tree 'record remove' callback */
+ udata->common.corder = attr->crt_idx;
+
+ /* Remove the record from the name index v2 B-tree */
+ if(H5B2_remove(udata->common.f, udata->common.dxpl_id, H5A_BT2_CORDER, udata->corder_bt2_addr, udata, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTREMOVE, FAIL, "unable to remove attribute from creation order index v2 B-tree")
+ } /* end if */
+
/* Check for removing shared attribute */
if(record->flags & H5O_MSG_FLAG_SHARED) {
/* Decrement the reference count on the shared attribute message */
@@ -1148,16 +1219,6 @@ H5A_dense_remove_bt2_cb(const void *_record, void *_udata)
HGOTO_ERROR(H5E_ATTR, H5E_CANTREMOVE, FAIL, "unable to remove attribute from fractal heap")
} /* end else */
- /* Check for removing the link from the creation order index */
- if(H5F_addr_defined(udata->corder_bt2_addr)) {
- /* Set up the user data for the v2 B-tree 'record remove' callback */
- udata->common.corder = attr->crt_idx;
-
- /* Remove the record from the name index v2 B-tree */
- if(H5B2_remove(udata->common.f, udata->common.dxpl_id, H5A_BT2_CORDER, udata->corder_bt2_addr, udata, NULL, NULL) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTREMOVE, FAIL, "unable to remove attribute from creation order index v2 B-tree")
- } /* end if */
-
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A_dense_remove_bt2_cb() */
@@ -1263,6 +1324,7 @@ done:
static herr_t
H5A_dense_remove_by_idx_bt2_cb(const void *_record, void *_bt2_udata)
{
+ H5HF_t *fheap; /* Fractal heap handle */
const H5A_dense_bt2_name_rec_t *record = (const H5A_dense_bt2_name_rec_t *)_record; /* v2 B-tree record */
H5A_bt2_ud_rmbi_t *bt2_udata = (H5A_bt2_ud_rmbi_t *)_bt2_udata; /* User data for callback */
H5A_fh_ud_cp_t fh_udata; /* User data for fractal heap 'op' callback */
@@ -1276,28 +1338,17 @@ H5A_dense_remove_by_idx_bt2_cb(const void *_record, void *_bt2_udata)
fh_udata.record = record;
fh_udata.attr = NULL;
+ /* Get correct fractal heap handle to use for operations */
+ if(record->flags & H5O_MSG_FLAG_SHARED)
+ fheap = bt2_udata->shared_fheap;
+ else
+ fheap = bt2_udata->fheap;
+
/* Call fractal heap 'op' routine, to make copy of attribute to remove */
- if(H5HF_op(bt2_udata->fheap, bt2_udata->dxpl_id, &record->id, H5A_dense_copy_fh_cb, &fh_udata) < 0)
+ if(H5HF_op(fheap, bt2_udata->dxpl_id, &record->id, H5A_dense_copy_fh_cb, &fh_udata) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPERATE, FAIL, "attribute removal callback failed")
HDassert(fh_udata.attr);
- /* Check for removing shared attribute */
- if(record->flags & H5O_MSG_FLAG_SHARED) {
- /* Decrement the reference count on the shared attribute message */
- if(H5SM_try_delete(bt2_udata->f, bt2_udata->dxpl_id, H5O_ATTR_ID, &(fh_udata.attr->sh_loc)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to delete shared attribute")
- } /* end if */
- else {
- /* Perform the deletion action on the attribute */
- /* (takes care of shared & committed datatype/dataspace components) */
- if(H5O_attr_delete(bt2_udata->f, bt2_udata->dxpl_id, &fh_udata.attr) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute")
-
- /* Remove record from fractal heap */
- if(H5HF_remove(bt2_udata->fheap, bt2_udata->dxpl_id, &record->id) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTREMOVE, FAIL, "unable to remove attribute from fractal heap")
- } /* end else */
-
/* Check for removing the link from the "other" index (creation order, when name used and vice versa) */
if(H5F_addr_defined(bt2_udata->other_bt2_addr)) {
H5A_bt2_ud_common_t other_bt2_udata; /* Info for B-tree callbacks */
@@ -1321,6 +1372,7 @@ H5A_dense_remove_by_idx_bt2_cb(const void *_record, void *_bt2_udata)
other_bt2_udata.f = bt2_udata->f;
other_bt2_udata.dxpl_id = bt2_udata->dxpl_id;
other_bt2_udata.fheap = bt2_udata->fheap;
+ other_bt2_udata.shared_fheap = bt2_udata->shared_fheap;
other_bt2_udata.name = fh_udata.attr->name;
other_bt2_udata.name_hash = H5_checksum_lookup3(fh_udata.attr->name, HDstrlen(fh_udata.attr->name), 0);
other_bt2_udata.found_op = NULL;
@@ -1334,6 +1386,23 @@ H5A_dense_remove_by_idx_bt2_cb(const void *_record, void *_bt2_udata)
HGOTO_ERROR(H5E_ATTR, H5E_CANTREMOVE, FAIL, "unable to remove record from 'other' index v2 B-tree")
} /* end if */
+ /* Check for removing shared attribute */
+ if(record->flags & H5O_MSG_FLAG_SHARED) {
+ /* Decrement the reference count on the shared attribute message */
+ if(H5SM_try_delete(bt2_udata->f, bt2_udata->dxpl_id, H5O_ATTR_ID, &(fh_udata.attr->sh_loc)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to delete shared attribute")
+ } /* end if */
+ else {
+ /* Perform the deletion action on the attribute */
+ /* (takes care of shared & committed datatype/dataspace components) */
+ if(H5O_attr_delete(bt2_udata->f, bt2_udata->dxpl_id, fh_udata.attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute")
+
+ /* Remove record from fractal heap */
+ if(H5HF_remove(fheap, bt2_udata->dxpl_id, &record->id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTREMOVE, FAIL, "unable to remove attribute from fractal heap")
+ } /* end else */
+
done:
/* Release resources */
if(fh_udata.attr)
@@ -1363,6 +1432,7 @@ H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
{
H5HF_t *fheap = NULL; /* Fractal heap handle */
H5HF_t *shared_fheap = NULL; /* Fractal heap handle for shared header messages */
+ H5A_attr_table_t atable = {0, NULL}; /* Table of attributes */
const H5B2_class_t *bt2_class = NULL; /* Class of v2 B-tree */
haddr_t bt2_addr; /* Address of v2 B-tree to use for operation */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1442,6 +1512,18 @@ H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
HGOTO_ERROR(H5E_ATTR, H5E_CANTREMOVE, FAIL, "unable to remove attribute from v2 B-tree index")
} /* end if */
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)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "error building table of attributes")
+
+ /* Check for skipping too many attributes */
+ if(n >= atable.nattrs)
+ 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)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute in dense storage")
} /* end else */
done:
@@ -1450,6 +1532,8 @@ done:
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
if(fheap && H5HF_close(fheap, dxpl_id) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
+ 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 H5A_dense_remove_by_idx() */
diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c
index 7aea0df..e3140cd 100644
--- a/src/H5Oattribute.c
+++ b/src/H5Oattribute.c
@@ -308,6 +308,9 @@ H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE, &oh_flags) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
+ /* Indicate that the object header was modified */
+ oh_flags |= H5AC__DIRTIED_FLAG;
+
done:
if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
HDONE_ERROR(H5E_ATTR, H5E_PROTECT, FAIL, "unable to release object header")
diff --git a/src/H5SM.c b/src/H5SM.c
index e0e10c3..58a0730 100755
--- a/src/H5SM.c
+++ b/src/H5SM.c
@@ -50,6 +50,7 @@ static herr_t H5SM_create_index(H5F_t *f, H5SM_index_header_t *header,
static herr_t H5SM_delete_index(H5F_t *f, H5SM_index_header_t *header,
hid_t dxpl_id, hbool_t delete_heap);
static haddr_t H5SM_create_list(H5F_t *f, H5SM_index_header_t *header, hid_t dxpl_id);
+static size_t H5SM_find_in_list(const H5SM_list_t *list, const H5SM_mesg_key_t *key, size_t *empty_pos);
static herr_t H5SM_convert_list_to_btree(H5F_t * f, H5SM_index_header_t * header,
H5SM_list_t **_list, H5HF_t *fheap, hid_t dxpl_id);
static herr_t H5SM_convert_btree_to_list(H5F_t * f, H5SM_index_header_t * header, hid_t dxpl_id);
@@ -1116,13 +1117,13 @@ done:
*
*-------------------------------------------------------------------------
*/
-size_t
-H5SM_find_in_list(H5SM_list_t *list, const H5SM_mesg_key_t *key, size_t *empty_pos)
+static size_t
+H5SM_find_in_list(const H5SM_list_t *list, const H5SM_mesg_key_t *key, size_t *empty_pos)
{
size_t x;
size_t ret_value;
- FUNC_ENTER_NOAPI(H5SM_find_in_list, UFAIL)
+ FUNC_ENTER_NOAPI_NOINIT(H5SM_find_in_list)
HDassert(list);
/* Both key and empty_pos can be NULL, but not both! */
diff --git a/src/H5SMpkg.h b/src/H5SMpkg.h
index 8ae28dc..cf80959 100755
--- a/src/H5SMpkg.h
+++ b/src/H5SMpkg.h
@@ -180,8 +180,6 @@ H5_DLLVAR const H5B2_class_t H5SM_INDEX[1];
/* General routines */
H5_DLL ssize_t H5SM_get_index(const H5SM_master_table_t *table, unsigned type_id);
-H5_DLL size_t H5SM_find_in_list(H5SM_list_t *list,
- const H5SM_mesg_key_t *key, size_t *empty_pos);
/* Encode and decode routines, used for B-tree and cache encoding/decoding */
H5_DLL herr_t H5SM_message_encode(const H5F_t *f, uint8_t *raw,
diff --git a/test/tattr.c b/test/tattr.c
index bfb0a9b..cc28344 100644
--- a/test/tattr.c
+++ b/test/tattr.c
@@ -4393,12 +4393,51 @@ test_attr_delete_by_idx(hbool_t new_format, hid_t fcpl, hid_t fapl)
VERIFY(name_count, (max_compact * 2), "H5O_attr_dense_info_test");
} /* end if */
-#ifdef NOT_YET
/* Check for out of bound deletion */
-HDfprintf(stderr, "new_format = %t, use_index = %t, idx_type = %u, order = %u\n", new_format, use_index, (unsigned)idx_type, (unsigned)order);
ret = H5Adelete_by_idx(my_dataset, ".", idx_type, order, (hsize_t)u, H5P_DEFAULT);
VERIFY(ret, FAIL, "H5Adelete_by_idx");
-#endif /* NOT_YET */
+
+ /* Delete attributes from dense storage */
+ for(u = 0; u < ((max_compact * 2) - 1); u++) {
+ /* Delete first attribute in appropriate order */
+ ret = H5Adelete_by_idx(my_dataset, ".", idx_type, order, (hsize_t)0, H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Adelete_by_idx");
+
+ /* Verify the attribute information for first attribute in appropriate order */
+ HDmemset(&ainfo, 0, sizeof(ainfo));
+ ret = H5Aget_info_by_idx(my_dataset, ".", idx_type, order, (hsize_t)0, &ainfo, H5P_DEFAULT);
+ if(new_format) {
+ if(order == H5_ITER_INC) {
+ VERIFY(ainfo.corder, (u + 1), "H5Aget_info_by_idx");
+ } /* end if */
+ else {
+ VERIFY(ainfo.corder, ((max_compact * 2) - (u + 2)), "H5Aget_info_by_idx");
+ } /* end else */
+ } /* end if */
+
+ /* Verify the name for first attribute in appropriate order */
+ HDmemset(tmpname, 0, (size_t)NAME_BUF_SIZE);
+ ret = H5Aget_name_by_idx(my_dataset, ".", idx_type, order, (hsize_t)0, tmpname, (size_t)NAME_BUF_SIZE, H5P_DEFAULT);
+ if(order == H5_ITER_INC)
+ sprintf(attrname, "attr %02u", (u + 1));
+ else
+ sprintf(attrname, "attr %02u", ((max_compact * 2) - (u + 2)));
+ ret = HDstrcmp(attrname, tmpname);
+ VERIFY(ret, 0, "H5Aget_name_by_idx");
+ } /* end for */
+
+ /* Delete last attribute */
+ ret = H5Adelete_by_idx(my_dataset, ".", idx_type, order, (hsize_t)0, H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Adelete_by_idx");
+
+ /* Verify state of attribute storage (empty) */
+ is_empty = H5O_is_attr_empty_test(my_dataset);
+ VERIFY(is_empty, TRUE, "H5O_is_attr_empty_test");
+
+ /* Check for deletion on empty attribute storage again */
+ ret = H5Adelete_by_idx(my_dataset, ".", idx_type, order, (hsize_t)0, H5P_DEFAULT);
+ VERIFY(ret, FAIL, "H5Adelete_by_idx");
+
} /* end for */
/* Close Datasets */