From e4d94d794375da9b6b8e407c8b3bd367b3d9ae06 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Wed, 7 Feb 2007 20:12:08 -0500 Subject: [svn-r13267] Description: Add more support for creation order index operations to attributes: get deletions & compact<->dense storage transitions working. Tested on: FreeBSD/32 6.2 (duty) Mac OS X/32 10.4.8 (amazon) --- src/H5Adense.c | 134 ++++++++++++------------ src/H5Apkg.h | 10 ++ src/H5Edefin.h | 5 +- src/H5Einit.h | 5 +- src/H5Epubgen.h | 5 +- src/H5Eterm.h | 5 +- src/H5Gdense.c | 14 ++- test/tattr.c | 316 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 404 insertions(+), 90 deletions(-) diff --git a/src/H5Adense.c b/src/H5Adense.c index 460e82a..e56b0cb 100644 --- a/src/H5Adense.c +++ b/src/H5Adense.c @@ -722,6 +722,9 @@ H5A_dense_copy_fh_cb(const void *obj, size_t UNUSED obj_len, void *_udata) if(NULL == (udata->attr = (H5A_t *)H5O_msg_decode(udata->f, udata->dxpl_id, H5O_ATTR_ID, (const unsigned char *)obj))) HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, FAIL, "can't decode attribute") + /* Set the creation order index for the attribute */ + udata->attr->crt_idx = udata->record->corder; + /* Check whether we should "reconstitute" the shared message info */ if(udata->record->flags & H5O_MSG_FLAG_SHARED) H5SM_reconstitute(&(udata->attr->sh_loc), udata->record->id); @@ -1082,31 +1085,43 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5A_dense_remove_bt2_cb(const void *_record, void *_bt2_udata) +H5A_dense_remove_bt2_cb(const void *_record, void *_udata) { const H5A_dense_bt2_name_rec_t *record = (const H5A_dense_bt2_name_rec_t *)_record; - H5A_bt2_ud_common_t *bt2_udata = (H5A_bt2_ud_common_t *)_bt2_udata; /* User data for callback */ + H5A_bt2_ud_rm_t *udata = (H5A_bt2_ud_rm_t *)_udata; /* User data for callback */ + H5A_t *attr = *(H5A_t **)udata->common.found_op_data; /* Pointer to attribute to remove */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5A_dense_remove_bt2_cb) - /* Check for inserting shared attribute */ + /* 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, &((*(H5A_t **)bt2_udata->found_op_data)->sh_loc)) < 0) + if(H5SM_try_delete(udata->common.f, udata->common.dxpl_id, H5O_ATTR_ID, &(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, *(H5A_t **)bt2_udata->found_op_data) < 0) + if(H5O_attr_delete(udata->common.f, udata->common.dxpl_id, 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) + if(H5HF_remove(udata->common.fheap, udata->common.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 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() */ @@ -1128,7 +1143,7 @@ done: herr_t H5A_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *name) { - H5A_bt2_ud_common_t udata; /* User data for v2 B-tree record removal */ + H5A_bt2_ud_rm_t udata; /* User data for v2 B-tree record removal */ H5HF_t *fheap = NULL; /* Fractal heap handle */ H5HF_t *shared_fheap = NULL; /* Fractal heap handle for shared header messages */ H5A_t *attr_copy = NULL; /* Copy of attribute to remove */ @@ -1169,16 +1184,15 @@ H5A_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *name) } /* end if */ /* Set up the user data for the v2 B-tree 'record remove' callback */ - udata.f = f; - udata.dxpl_id = dxpl_id; - udata.fheap = fheap; - udata.shared_fheap = shared_fheap; - udata.name = name; - udata.name_hash = H5_checksum_lookup3(name, HDstrlen(name), 0); - udata.flags = 0; - udata.corder = 0; - udata.found_op = H5A_dense_fnd_cb; /* v2 B-tree comparison callback */ - udata.found_op_data = &attr_copy; + udata.common.f = f; + udata.common.dxpl_id = dxpl_id; + udata.common.fheap = fheap; + udata.common.shared_fheap = shared_fheap; + udata.common.name = 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; /* 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) @@ -1302,37 +1316,38 @@ H5A_dense_delete_bt2_cb(const void *_record, void *_bt2_udata) { const H5A_dense_bt2_name_rec_t *record = (const H5A_dense_bt2_name_rec_t *)_record; /* Record from B-tree */ H5A_bt2_ud_common_t *bt2_udata = (H5A_bt2_ud_common_t *)_bt2_udata; /* User data for callback */ - H5HF_t *fheap; /* Fractal heap handle for attribute storage */ - H5A_fh_ud_cp_t fh_udata; /* User data for fractal heap 'op' callback */ + H5A_t *attr = NULL; /* Attribute being removed */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5A_dense_delete_bt2_cb) /* Check for shared attribute */ - if(record->flags & H5O_MSG_FLAG_SHARED) - fheap = bt2_udata->shared_fheap; - else - fheap = bt2_udata->fheap; - - /* Prepare user data for callback */ - /* down */ - fh_udata.f = bt2_udata->f; - fh_udata.dxpl_id = bt2_udata->dxpl_id; - fh_udata.record = record; - /* up */ - fh_udata.attr = NULL; - - /* Call fractal heap 'op' routine, to copy the attribute information */ - 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, "heap op callback failed") - - /* Check for shared attribute */ if(record->flags & H5O_MSG_FLAG_SHARED) { + H5O_shared_t sh_mesg; /* Temporary shared message info */ + + /* "reconstitute" the shared message info for the attribute */ + H5SM_reconstitute(&sh_mesg, record->id); + /* 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) + if(H5SM_try_delete(bt2_udata->f, bt2_udata->dxpl_id, H5O_ATTR_ID, &sh_mesg) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to delete shared attribute") } /* end if */ else { + H5A_fh_ud_cp_t fh_udata; /* User data for fractal heap 'op' callback */ + + /* Prepare user data for callback */ + /* down */ + fh_udata.f = bt2_udata->f; + fh_udata.dxpl_id = bt2_udata->dxpl_id; + fh_udata.record = record; + /* up */ + fh_udata.attr = NULL; + + /* Call fractal heap 'op' routine, to copy the attribute information */ + if(H5HF_op(bt2_udata->fheap, bt2_udata->dxpl_id, &record->id, H5A_dense_copy_fh_cb, &fh_udata) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPERATE, FAIL, "heap op callback failed") + attr = fh_udata.attr; + /* 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) @@ -1341,8 +1356,8 @@ H5A_dense_delete_bt2_cb(const void *_record, void *_bt2_udata) done: /* Release resources */ - if(fh_udata.attr) - H5O_msg_free_real(H5O_MSG_ATTR, fh_udata.attr); + if(attr) + H5O_msg_free_real(H5O_MSG_ATTR, attr); FUNC_LEAVE_NOAPI(ret_value) } /* end H5A_dense_delete_bt2_cb() */ @@ -1366,8 +1381,6 @@ H5A_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_t *oh) { H5A_bt2_ud_common_t udata; /* v2 B-tree user data for deleting attributes */ H5HF_t *fheap = NULL; /* Fractal heap handle */ - H5HF_t *shared_fheap = NULL; /* Fractal heap handle for shared header messages */ - htri_t attr_sharable; /* Flag indicating attributes are sharable */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5A_dense_delete, FAIL) @@ -1382,31 +1395,11 @@ H5A_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_t *oh) if(NULL == (fheap = H5HF_open(f, dxpl_id, oh->attr_fheap_addr))) HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") - /* Check if attributes are shared in this file */ - if((attr_sharable = H5SM_type_shared(f, H5O_ATTR_ID, dxpl_id)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't determine if attributes are shared") - - /* Get handle for shared message heap, if attributes are sharable */ - if(attr_sharable) { - haddr_t shared_fheap_addr; /* Address of fractal heap to use */ - - /* Retrieve the address of the shared message's fractal heap */ - if(H5SM_get_fheap_addr(f, dxpl_id, H5O_ATTR_ID, &shared_fheap_addr) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get shared message heap address") - - /* Check if there are any shared messages currently */ - if(H5F_addr_defined(shared_fheap_addr)) { - /* Open the fractal heap for shared header messages */ - if(NULL == (shared_fheap = H5HF_open(f, dxpl_id, shared_fheap_addr))) - HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") - } /* end if */ - } /* end if */ - /* Create the "udata" information for v2 B-tree 'delete' */ udata.f = f; udata.dxpl_id = dxpl_id; udata.fheap = fheap; - udata.shared_fheap = shared_fheap; + udata.shared_fheap = NULL; udata.name = NULL; udata.name_hash = 0; udata.flags = 0; @@ -1420,15 +1413,18 @@ H5A_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_t *oh) oh->name_bt2_addr = HADDR_UNDEF; /* Release resources */ - if(shared_fheap) { - if(H5HF_close(shared_fheap, dxpl_id) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap") - shared_fheap = NULL; - } /* end if */ if(H5HF_close(fheap, dxpl_id) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap") fheap = NULL; + /* Check if we should delete the creation order index v2 B-tree */ + if(H5F_addr_defined(oh->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) + HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete v2 B-tree for creation order index") + oh->corder_bt2_addr = HADDR_UNDEF; + } /* end if */ + /* Delete fractal heap */ if(H5HF_delete(f, dxpl_id, oh->attr_fheap_addr) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete fractal heap") @@ -1436,8 +1432,6 @@ H5A_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_t *oh) done: /* Release resources */ - if(shared_fheap && H5HF_close(shared_fheap, dxpl_id) < 0) - 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") diff --git a/src/H5Apkg.h b/src/H5Apkg.h index 3fa7c75..708672a 100644 --- a/src/H5Apkg.h +++ b/src/H5Apkg.h @@ -124,6 +124,16 @@ typedef struct H5A_bt2_ud_ins_t { H5O_fheap_id_t id; /* Heap ID of attribute to insert */ } H5A_bt2_ud_ins_t; +/* + * Data exchange structure for dense attribute storage. This structure is + * passed through the v2 B-tree layer when removing attributes. + */ +typedef struct H5A_bt2_ud_rm_t { + /* downward */ + H5A_bt2_ud_common_t common; /* Common info for B-tree user data (must be first) */ + haddr_t corder_bt2_addr; /* v2 B-tree address of creation order index */ +} H5A_bt2_ud_rm_t; + /* Data structure to hold table of attributes for an object */ typedef struct { size_t nattrs; /* # of attributes in table */ diff --git a/src/H5Edefin.h b/src/H5Edefin.h index 5638305..35579ea 100644 --- a/src/H5Edefin.h +++ b/src/H5Edefin.h @@ -1,5 +1,4 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright by The HDF Group. * * Copyright by the Board of Trustees of the University of Illinois. * * All rights reserved. * * * @@ -9,8 +8,8 @@ * of the source code distribution tree; Copyright.html can be found at the * * root level of an installed copy of the electronic HDF5 document set and * * is linked from the top-level documents page. It can also be found at * - * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * - * access to either file, you may request a copy from help@hdfgroup.org. * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Generated automatically by bin/make_err -- do not edit */ diff --git a/src/H5Einit.h b/src/H5Einit.h index ac02d48..8b2429a 100644 --- a/src/H5Einit.h +++ b/src/H5Einit.h @@ -1,5 +1,4 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright by The HDF Group. * * Copyright by the Board of Trustees of the University of Illinois. * * All rights reserved. * * * @@ -9,8 +8,8 @@ * of the source code distribution tree; Copyright.html can be found at the * * root level of an installed copy of the electronic HDF5 document set and * * is linked from the top-level documents page. It can also be found at * - * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * - * access to either file, you may request a copy from help@hdfgroup.org. * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Generated automatically by bin/make_err -- do not edit */ diff --git a/src/H5Epubgen.h b/src/H5Epubgen.h index 8386e0f..ccd1d52 100644 --- a/src/H5Epubgen.h +++ b/src/H5Epubgen.h @@ -1,5 +1,4 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright by The HDF Group. * * Copyright by the Board of Trustees of the University of Illinois. * * All rights reserved. * * * @@ -9,8 +8,8 @@ * of the source code distribution tree; Copyright.html can be found at the * * root level of an installed copy of the electronic HDF5 document set and * * is linked from the top-level documents page. It can also be found at * - * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * - * access to either file, you may request a copy from help@hdfgroup.org. * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Generated automatically by bin/make_err -- do not edit */ diff --git a/src/H5Eterm.h b/src/H5Eterm.h index dedc313..1c4e762 100644 --- a/src/H5Eterm.h +++ b/src/H5Eterm.h @@ -1,5 +1,4 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright by The HDF Group. * * Copyright by the Board of Trustees of the University of Illinois. * * All rights reserved. * * * @@ -9,8 +8,8 @@ * of the source code distribution tree; Copyright.html can be found at the * * root level of an installed copy of the electronic HDF5 document set and * * is linked from the top-level documents page. It can also be found at * - * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * - * access to either file, you may request a copy from help@hdfgroup.org. * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Generated automatically by bin/make_err -- do not edit */ diff --git a/src/H5Gdense.c b/src/H5Gdense.c index 51a70d0..865c93f 100644 --- a/src/H5Gdense.c +++ b/src/H5Gdense.c @@ -120,7 +120,6 @@ typedef struct { /* downward */ H5G_bt2_ud_common_t common; /* Common info for B-tree user data (must be first) */ hbool_t rem_from_fheap; /* Whether to remove the link from the fractal heap */ - hbool_t rem_from_corder_index; /* Whether to remove the link from the creation order index */ haddr_t corder_bt2_addr; /* Address of v2 B-tree indexing creation order */ H5RS_str_t *grp_full_path_r; /* Full path of group where link is removed */ hbool_t replace_names; /* Whether to replace the names of open objects */ @@ -134,7 +133,6 @@ typedef struct { /* downward */ H5F_t *f; /* Pointer to file that fractal heap is in */ hid_t dxpl_id; /* DXPL for operation */ - hbool_t rem_from_corder_index; /* Whether to remove the link from the creation order index */ haddr_t corder_bt2_addr; /* Address of v2 B-tree indexing creation order */ H5RS_str_t *grp_full_path_r; /* Full path of group where link is removed */ hbool_t replace_names; /* Whether to replace the names of open objects */ @@ -1347,7 +1345,7 @@ H5G_dense_remove_fh_cb(const void *obj, size_t UNUSED obj_len, void *_udata) HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode link") /* Check for removing the link from the creation order index */ - if(udata->rem_from_corder_index) { + if(H5F_addr_defined(udata->corder_bt2_addr)) { H5G_bt2_ud_common_t bt2_udata; /* Info for B-tree callbacks */ /* Set up the user data for the v2 B-tree 'record remove' callback */ @@ -1355,7 +1353,6 @@ H5G_dense_remove_fh_cb(const void *obj, size_t UNUSED obj_len, void *_udata) bt2_udata.corder = lnk->corder; /* Remove the record from the name index v2 B-tree */ - HDassert(H5F_addr_defined(udata->corder_bt2_addr)); if(H5B2_remove(udata->f, udata->dxpl_id, H5G_BT2_CORDER, udata->corder_bt2_addr, &bt2_udata, NULL, NULL) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTREMOVE, FAIL, "unable to remove link from creation order index v2 B-tree") @@ -1406,7 +1403,6 @@ H5G_dense_remove_bt2_cb(const void *_record, void *_bt2_udata) /* Set up the user data for fractal heap 'op' callback */ fh_udata.f = bt2_udata->common.f; fh_udata.dxpl_id = bt2_udata->common.dxpl_id; - fh_udata.rem_from_corder_index = bt2_udata->rem_from_corder_index; fh_udata.corder_bt2_addr = bt2_udata->corder_bt2_addr; fh_udata.grp_full_path_r = bt2_udata->grp_full_path_r; fh_udata.replace_names = bt2_udata->replace_names; @@ -1469,7 +1465,6 @@ H5G_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, udata.common.found_op = NULL; udata.common.found_op_data = NULL; udata.rem_from_fheap = TRUE; - udata.rem_from_corder_index = H5F_addr_defined(linfo->corder_bt2_addr); udata.corder_bt2_addr = linfo->corder_bt2_addr; udata.grp_full_path_r = grp_full_path_r; udata.replace_names = TRUE; @@ -1569,7 +1564,7 @@ H5G_dense_remove_by_idx_bt2_cb(const void *_record, void *_bt2_udata) HGOTO_ERROR(H5E_SYM, H5E_CANTOPERATE, FAIL, "link removal callback failed") HDassert(fh_udata.lnk); - /* Check for removing the link from the creation order index */ + /* 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)) { H5G_bt2_ud_common_t other_bt2_udata; /* Info for B-tree callbacks */ const H5B2_class_t *other_bt2_class; /* Class of "other" v2 B-tree */ @@ -1778,7 +1773,7 @@ H5G_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_linfo_t *linfo, hbool_t adj_link) udata.common.found_op = NULL; udata.common.found_op_data = NULL; udata.rem_from_fheap = FALSE; /* handled in "bulk" below by deleting entire heap */ - udata.rem_from_corder_index = FALSE; + udata.corder_bt2_addr = linfo->corder_bt2_addr; udata.grp_full_path_r = NULL; udata.replace_names = FALSE; @@ -1803,7 +1798,10 @@ H5G_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_linfo_t *linfo, hbool_t adj_link) HDassert(H5F_addr_defined(linfo->corder_bt2_addr)); if(H5B2_delete(f, dxpl_id, H5G_BT2_CORDER, linfo->corder_bt2_addr, NULL, NULL) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete v2 B-tree for creation order index") + linfo->corder_bt2_addr = HADDR_UNDEF; } /* end if */ + else + HDassert(!H5F_addr_defined(linfo->corder_bt2_addr)); /* Delete the fractal heap */ if(H5HF_delete(f, dxpl_id, linfo->link_fheap_addr) < 0) diff --git a/test/tattr.c b/test/tattr.c index 8c71e40..1e2807b 100644 --- a/test/tattr.c +++ b/test/tattr.c @@ -3056,6 +3056,321 @@ test_attr_corder_create_dense(hid_t fcpl, hid_t fapl) /**************************************************************** ** +** test_attr_corder_transition(): Test basic H5A (attribute) code. +** Tests attribute storage transitions on objects with attribute creation order info +** +****************************************************************/ +static void +test_attr_corder_transition(hid_t fcpl, hid_t fapl) +{ + hid_t fid; /* HDF5 File ID */ + hid_t dataset; /* Dataset ID */ + hid_t sid; /* Dataspace ID */ + hid_t attr; /* Attribute ID */ + hid_t dcpl; /* Dataset creation property list ID */ + unsigned max_compact; /* Maximum # of links to store in group compactly */ + unsigned min_dense; /* Minimum # of links to store in group "densely" */ + htri_t is_empty; /* Are there any attributes? */ + htri_t is_dense; /* Are attributes stored densely? */ + hsize_t nattrs; /* Number of attributes on object */ + hsize_t name_count; /* # of records in name index */ + hsize_t corder_count; /* # of records in creation order index */ + char attrname[NAME_BUF_SIZE]; /* Name of attribute */ + unsigned u; /* Local index variable */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing Storage Transitions of Attributes with Creation Order Info\n")); + + /* Create file */ + fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl); + CHECK(fid, FAIL, "H5Fcreate"); + + /* Create dataset creation property list */ + dcpl = H5Pcreate(H5P_DATASET_CREATE); + CHECK(dcpl, FAIL, "H5Pcreate"); + + /* Set attribute creation order tracking & indexing for object */ + ret = H5Pset_attr_creation_order(dcpl, (H5P_CRT_ORDER_TRACKED | H5P_CRT_ORDER_INDEXED)); + CHECK(ret, FAIL, "H5Pset_attr_creation_order"); + + /* Create dataspace for dataset & attributes */ + sid = H5Screate(H5S_SCALAR); + CHECK(sid, FAIL, "H5Screate"); + + /* Create a dataset */ + dataset = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl); + CHECK(dataset, FAIL, "H5Dcreate"); + + /* Check on dataset's attribute storage status */ + is_empty = H5O_is_attr_empty_test(dataset); + VERIFY(is_empty, TRUE, "H5O_is_attr_empty_test"); + is_dense = H5O_is_attr_dense_test(dataset); + VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test"); + + /* Query the attribute creation properties */ + ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense); + CHECK(ret, FAIL, "H5Pget_attr_phase_change"); + + /* Close Dataset */ + ret = H5Dclose(dataset); + CHECK(ret, FAIL, "H5Dclose"); + + /* Close property list */ + ret = H5Pclose(dcpl); + CHECK(ret, FAIL, "H5Pclose"); + + /* Close file */ + ret = H5Fclose(fid); + CHECK(ret, FAIL, "H5Fclose"); + + + /* Re-open file */ + fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl); + CHECK(fid, FAIL, "H5Fopen"); + + /* Open dataset created */ + dataset = H5Dopen(fid, DSET1_NAME); + CHECK(dataset, FAIL, "H5Dopen"); + + /* Create several attributes, but keep storage in compact form */ + for(u = 0; u < max_compact; u++) { + /* Create attribute */ + sprintf(attrname, "attr %02u", u); + attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT); + CHECK(attr, FAIL, "H5Acreate"); + + /* Write data into the attribute */ + ret = H5Awrite(attr, H5T_NATIVE_UINT, &u); + CHECK(ret, FAIL, "H5Awrite"); + + /* Close attribute */ + ret = H5Aclose(attr); + CHECK(ret, FAIL, "H5Aclose"); + + /* Verify state of object */ + ret = H5O_num_attrs_test(dataset, &nattrs); + CHECK(ret, FAIL, "H5O_num_attrs_test"); + VERIFY(nattrs, (u + 1), "H5O_num_attrs_test"); + is_empty = H5O_is_attr_empty_test(dataset); + VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test"); + is_dense = H5O_is_attr_dense_test(dataset); + VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test"); + } /* end for */ + + /* Create another attribute, to push into dense storage */ + sprintf(attrname, "attr %02u", max_compact); + attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT); + CHECK(attr, FAIL, "H5Acreate"); + + /* Write data into the attribute */ + ret = H5Awrite(attr, H5T_NATIVE_UINT, &u); + CHECK(ret, FAIL, "H5Awrite"); + + /* Close attribute */ + ret = H5Aclose(attr); + CHECK(ret, FAIL, "H5Aclose"); + + /* Verify state of object */ + ret = H5O_num_attrs_test(dataset, &nattrs); + CHECK(ret, FAIL, "H5O_num_attrs_test"); + VERIFY(nattrs, (max_compact + 1), "H5O_num_attrs_test"); + is_empty = H5O_is_attr_empty_test(dataset); + VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test"); + is_dense = H5O_is_attr_dense_test(dataset); + VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test"); + + /* Retrieve & verify # of records in the name & creation order indices */ + ret = H5O_attr_dense_info_test(dataset, &name_count, &corder_count); + CHECK(ret, FAIL, "H5O_attr_dense_info_test"); + VERIFY(name_count, corder_count, "H5O_attr_dense_info_test"); + + /* Delete several attributes from object, until attribute storage resumes compact form */ + for(u = max_compact; u >= min_dense; u--) { + sprintf(attrname, "attr %02u", u); + ret = H5Adelete(dataset, attrname); + CHECK(ret, FAIL, "H5Adelete"); + + /* Verify state of object */ + ret = H5O_num_attrs_test(dataset, &nattrs); + CHECK(ret, FAIL, "H5O_num_attrs_test"); + VERIFY(nattrs, u, "H5O_num_attrs_test"); + is_empty = H5O_is_attr_empty_test(dataset); + VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test"); + is_dense = H5O_is_attr_dense_test(dataset); + VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test"); + + /* Retrieve & verify # of records in the name & creation order indices */ + ret = H5O_attr_dense_info_test(dataset, &name_count, &corder_count); + CHECK(ret, FAIL, "H5O_attr_dense_info_test"); + VERIFY(name_count, corder_count, "H5O_attr_dense_info_test"); + } /* end for */ + + /* Delete another attribute, to push attribute storage into compact form */ + sprintf(attrname, "attr %02u", (min_dense - 1)); + ret = H5Adelete(dataset, attrname); + CHECK(ret, FAIL, "H5Adelete"); + + /* Verify state of object */ + ret = H5O_num_attrs_test(dataset, &nattrs); + CHECK(ret, FAIL, "H5O_num_attrs_test"); + VERIFY(nattrs, (min_dense - 1), "H5O_num_attrs_test"); + is_empty = H5O_is_attr_empty_test(dataset); + VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test"); + is_dense = H5O_is_attr_dense_test(dataset); + VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test"); + + /* Re-add attributes to get back into dense form */ + for(u = (min_dense - 1); u < (max_compact + 1); u++) { + /* Create attribute */ + sprintf(attrname, "attr %02u", u); + attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT); + CHECK(attr, FAIL, "H5Acreate"); + + /* Write data into the attribute */ + ret = H5Awrite(attr, H5T_NATIVE_UINT, &u); + CHECK(ret, FAIL, "H5Awrite"); + + /* Close attribute */ + ret = H5Aclose(attr); + CHECK(ret, FAIL, "H5Aclose"); + } /* end for */ + + /* Verify state of object */ + ret = H5O_num_attrs_test(dataset, &nattrs); + CHECK(ret, FAIL, "H5O_num_attrs_test"); + VERIFY(nattrs, (max_compact + 1), "H5O_num_attrs_test"); + is_empty = H5O_is_attr_empty_test(dataset); + VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test"); + is_dense = H5O_is_attr_dense_test(dataset); + VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test"); + + /* Retrieve & verify # of records in the name & creation order indices */ + ret = H5O_attr_dense_info_test(dataset, &name_count, &corder_count); + CHECK(ret, FAIL, "H5O_attr_dense_info_test"); + VERIFY(name_count, corder_count, "H5O_attr_dense_info_test"); + + /* Close Dataset */ + ret = H5Dclose(dataset); + CHECK(ret, FAIL, "H5Dclose"); + + /* Close file */ + ret = H5Fclose(fid); + CHECK(ret, FAIL, "H5Fclose"); + + + /* Re-open file */ + fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl); + CHECK(fid, FAIL, "H5Fopen"); + + /* Open dataset created */ + dataset = H5Dopen(fid, DSET1_NAME); + CHECK(dataset, FAIL, "H5Dopen"); + + /* Check on dataset's attribute storage status */ + ret = H5O_num_attrs_test(dataset, &nattrs); + CHECK(ret, FAIL, "H5O_num_attrs_test"); + VERIFY(nattrs, (max_compact + 1), "H5O_num_attrs_test"); + is_empty = H5O_is_attr_empty_test(dataset); + VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test"); + is_dense = H5O_is_attr_dense_test(dataset); + VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test"); + + /* Retrieve & verify # of records in the name & creation order indices */ + ret = H5O_attr_dense_info_test(dataset, &name_count, &corder_count); + CHECK(ret, FAIL, "H5O_attr_dense_info_test"); + VERIFY(name_count, corder_count, "H5O_attr_dense_info_test"); + + /* Delete several attributes from object, until attribute storage resumes compact form */ + for(u = max_compact; u >= min_dense; u--) { + sprintf(attrname, "attr %02u", u); + ret = H5Adelete(dataset, attrname); + CHECK(ret, FAIL, "H5Adelete"); + + /* Verify state of object */ + ret = H5O_num_attrs_test(dataset, &nattrs); + CHECK(ret, FAIL, "H5O_num_attrs_test"); + VERIFY(nattrs, u, "H5O_num_attrs_test"); + is_empty = H5O_is_attr_empty_test(dataset); + VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test"); + is_dense = H5O_is_attr_dense_test(dataset); + VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test"); + + /* Retrieve & verify # of records in the name & creation order indices */ + ret = H5O_attr_dense_info_test(dataset, &name_count, &corder_count); + CHECK(ret, FAIL, "H5O_attr_dense_info_test"); + VERIFY(name_count, corder_count, "H5O_attr_dense_info_test"); + } /* end for */ + + /* Delete another attribute, to push attribute storage into compact form */ + sprintf(attrname, "attr %02u", (min_dense - 1)); + ret = H5Adelete(dataset, attrname); + CHECK(ret, FAIL, "H5Adelete"); + + /* Verify state of object */ + ret = H5O_num_attrs_test(dataset, &nattrs); + CHECK(ret, FAIL, "H5O_num_attrs_test"); + VERIFY(nattrs, (min_dense - 1), "H5O_num_attrs_test"); + is_empty = H5O_is_attr_empty_test(dataset); + VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test"); + is_dense = H5O_is_attr_dense_test(dataset); + VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test"); + + /* Re-add attributes to get back into dense form */ + for(u = (min_dense - 1); u < (max_compact + 1); u++) { + /* Create attribute */ + sprintf(attrname, "attr %02u", u); + attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT); + CHECK(attr, FAIL, "H5Acreate"); + + /* Write data into the attribute */ + ret = H5Awrite(attr, H5T_NATIVE_UINT, &u); + CHECK(ret, FAIL, "H5Awrite"); + + /* Close attribute */ + ret = H5Aclose(attr); + CHECK(ret, FAIL, "H5Aclose"); + } /* end for */ + + /* Verify state of object */ + ret = H5O_num_attrs_test(dataset, &nattrs); + CHECK(ret, FAIL, "H5O_num_attrs_test"); + VERIFY(nattrs, (max_compact + 1), "H5O_num_attrs_test"); + is_empty = H5O_is_attr_empty_test(dataset); + VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test"); + is_dense = H5O_is_attr_dense_test(dataset); + VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test"); + + /* Retrieve & verify # of records in the name & creation order indices */ + ret = H5O_attr_dense_info_test(dataset, &name_count, &corder_count); + CHECK(ret, FAIL, "H5O_attr_dense_info_test"); + VERIFY(name_count, corder_count, "H5O_attr_dense_info_test"); + + /* Delete all attributes */ + for(u = max_compact; u > 0; u--) { + sprintf(attrname, "attr %02u", u); + ret = H5Adelete(dataset, attrname); + CHECK(ret, FAIL, "H5Adelete"); + } /* end for */ + sprintf(attrname, "attr %02u", 0); + ret = H5Adelete(dataset, attrname); + CHECK(ret, FAIL, "H5Adelete"); + + /* Close Dataset */ + ret = H5Dclose(dataset); + CHECK(ret, FAIL, "H5Dclose"); + + /* Close dataspace */ + ret = H5Sclose(sid); + CHECK(ret, FAIL, "H5Sclose"); + + /* Close file */ + ret = H5Fclose(fid); + CHECK(ret, FAIL, "H5Fclose"); +} /* test_attr_corder_transition() */ + +/**************************************************************** +** ** test_attr_shared_write(): Test basic H5A (attribute) code. ** Tests writing mix of shared & un-shared attributes in "compact" & "dense" storage ** @@ -4657,6 +4972,7 @@ test_attr(void) test_attr_corder_create_basic(my_fcpl, fapl2); /* Test creating an object w/attribute creation order info */ test_attr_corder_create_compact(my_fcpl, fapl2); /* Test compact attribute storage on an object w/attribute creation order info */ test_attr_corder_create_dense(my_fcpl, fapl2); /* Test dense attribute storage on an object w/attribute creation order info */ + test_attr_corder_transition(my_fcpl, fapl2); /* Test attribute storage transitions on an object w/attribute creation order info */ } /* end for */ /* More complex tests with both "new format" and "shared" attributes */ -- cgit v0.12