From a127510b7b3049d0e136b677b180c8e644bdc7ea Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Fri, 9 Mar 2007 23:56:53 -0500 Subject: [svn-r13486] Description: Move attribute tracking information out of object header prefix and make it into a message that is inserted only when attributes are present on the object. Tested on: FreeBSD/32 6.2 (duty) --- src/H5Adense.c | 138 ++++---- src/H5Aint.c | 17 +- src/H5Apkg.h | 28 +- src/H5Aprivate.h | 4 - src/H5O.c | 33 +- src/H5Oainfo.c | 154 +++++++-- src/H5Oattr.c | 53 +-- src/H5Oattribute.c | 466 ++++++++++++++++---------- src/H5Ocache.c | 26 -- src/H5Ocopy.c | 21 +- src/H5Odbg.c | 93 +++-- src/H5Omessage.c | 64 ++-- src/H5Opkg.h | 23 +- src/H5Oprivate.h | 4 + src/H5Otest.c | 75 +++-- test/stab.c | 8 +- test/tsohm.c | 1 - tools/testfiles/h5mkgrp_nested_latest.ls | 4 +- tools/testfiles/h5mkgrp_nested_mult_latest.ls | 8 +- tools/testfiles/h5mkgrp_several_latest.ls | 4 +- tools/testfiles/h5mkgrp_single_latest.ls | 2 +- 21 files changed, 700 insertions(+), 526 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 diff --git a/test/stab.c b/test/stab.c index 6540916..4f61aa5 100644 --- a/test/stab.c +++ b/test/stab.c @@ -427,9 +427,9 @@ lifecycle(hid_t fapl) /* Check that the object header is only one chunk and the space has been allocated correctly */ if(H5Gget_objinfo(gid, ".", FALSE, &obj_stat) < 0) TEST_ERROR #ifdef H5_HAVE_LARGE_HSIZET - if(obj_stat.ohdr.size != 240) TEST_ERROR + if(obj_stat.ohdr.size != 208) TEST_ERROR #else /* H5_HAVE_LARGE_HSIZET */ - if(obj_stat.ohdr.size != 220) TEST_ERROR + if(obj_stat.ohdr.size != 188) TEST_ERROR #endif /* H5_HAVE_LARGE_HSIZET */ if(obj_stat.ohdr.free != 0) TEST_ERROR if(obj_stat.ohdr.nmesgs != 6) TEST_ERROR @@ -453,9 +453,9 @@ lifecycle(hid_t fapl) /* Check that the object header is still one chunk and the space has been allocated correctly */ if(H5Gget_objinfo(gid, ".", FALSE, &obj_stat) < 0) TEST_ERROR #ifdef H5_HAVE_LARGE_HSIZET - if(obj_stat.ohdr.size != 240) TEST_ERROR + if(obj_stat.ohdr.size != 208) TEST_ERROR #else /* H5_HAVE_LARGE_HSIZET */ - if(obj_stat.ohdr.size != 220) TEST_ERROR + if(obj_stat.ohdr.size != 188) TEST_ERROR #endif /* H5_HAVE_LARGE_HSIZET */ if(obj_stat.ohdr.free != 112) TEST_ERROR if(obj_stat.ohdr.nmesgs != 3) TEST_ERROR diff --git a/test/tsohm.c b/test/tsohm.c index 0612794..d0c0629 100644 --- a/test/tsohm.c +++ b/test/tsohm.c @@ -1055,7 +1055,6 @@ static void sohm_attr_helper(hid_t fcpl_id) } - /*------------------------------------------------------------------------- * Function: test_sohm_attrs * diff --git a/tools/testfiles/h5mkgrp_nested_latest.ls b/tools/testfiles/h5mkgrp_nested_latest.ls index 2ad3c78..d305312 100644 --- a/tools/testfiles/h5mkgrp_nested_latest.ls +++ b/tools/testfiles/h5mkgrp_nested_latest.ls @@ -3,10 +3,10 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_nested_latest.h5' ############################# Opened "../testfiles/h5mkgrp_nested_latest.h5" with sec2 driver. /one Group - Location: 1:528 + Location: 1:464 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX /one/two Group - Location: 1:288 + Location: 1:256 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX diff --git a/tools/testfiles/h5mkgrp_nested_mult_latest.ls b/tools/testfiles/h5mkgrp_nested_mult_latest.ls index e89f07f..9d3a6c0 100644 --- a/tools/testfiles/h5mkgrp_nested_mult_latest.ls +++ b/tools/testfiles/h5mkgrp_nested_mult_latest.ls @@ -3,18 +3,18 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_nested_mult_latest.h5' ############################# Opened "../testfiles/h5mkgrp_nested_mult_latest.h5" with sec2 driver. /one Group - Location: 1:528 + Location: 1:464 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX /one/two Group - Location: 1:288 + Location: 1:256 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX /three Group - Location: 1:1008 + Location: 1:880 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX /three/four Group - Location: 1:768 + Location: 1:672 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX diff --git a/tools/testfiles/h5mkgrp_several_latest.ls b/tools/testfiles/h5mkgrp_several_latest.ls index 02e39f3..13798cf 100644 --- a/tools/testfiles/h5mkgrp_several_latest.ls +++ b/tools/testfiles/h5mkgrp_several_latest.ls @@ -3,10 +3,10 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_several_latest.h5' ############################# Opened "../testfiles/h5mkgrp_several_latest.h5" with sec2 driver. /one Group - Location: 1:288 + Location: 1:256 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX /two Group - Location: 1:528 + Location: 1:464 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX diff --git a/tools/testfiles/h5mkgrp_single_latest.ls b/tools/testfiles/h5mkgrp_single_latest.ls index 4de7a37..dd3c95a 100644 --- a/tools/testfiles/h5mkgrp_single_latest.ls +++ b/tools/testfiles/h5mkgrp_single_latest.ls @@ -3,6 +3,6 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_single_latest.h5' ############################# Opened "../testfiles/h5mkgrp_single_latest.h5" with sec2 driver. /latest Group - Location: 1:288 + Location: 1:256 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX -- cgit v0.12