summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2007-03-08 20:10:12 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2007-03-08 20:10:12 (GMT)
commit74a30fff3e0fcd8919ced487abd03eefd27d57c1 (patch)
tree2df0a0d2cfc51cce067f25e503e6dfd26c8e827d /src
parent25bb6f5dd8af42d2facaab26f0cdeb7fc76456ae (diff)
downloadhdf5-74a30fff3e0fcd8919ced487abd03eefd27d57c1.zip
hdf5-74a30fff3e0fcd8919ced487abd03eefd27d57c1.tar.gz
hdf5-74a30fff3e0fcd8919ced487abd03eefd27d57c1.tar.bz2
[svn-r13477] Description:
The main purpose of this checkin was to eliminate the space used for tracking creation time indices when there is no way they can be used (i.e. attributes can't be shared in the file and the user hasn't turned on attribute creation tracking), however there were some other minor changes which crept in: - Fix a cache locking deadlock when a shared attribute and one of its components end up in the same fractal heap direct block. (This is fixed the "slow" way for right now, until John has time to add support for readers/writer locking to the cache. - Optimize attribute copying when a copy will be kept during a v2 B-tree search. - When freeing a block on disk, attempt to merge it with the metadata and "small data" aggregators. Tested on: Mac OS X/32 10.4.8 (amazon) FreeBSD/32 6.2 (duty)
Diffstat (limited to 'src')
-rw-r--r--src/H5Abtree2.c87
-rw-r--r--src/H5Adense.c17
-rw-r--r--src/H5Aint.c3
-rw-r--r--src/H5Apkg.h5
-rw-r--r--src/H5F.c29
-rw-r--r--src/H5FD.c51
-rw-r--r--src/H5Fpkg.h3
-rw-r--r--src/H5Fprivate.h3
-rw-r--r--src/H5Gobj.c27
-rw-r--r--src/H5O.c17
-rw-r--r--src/H5Oattribute.c6
-rw-r--r--src/H5Ocache.c33
-rw-r--r--src/H5Omessage.c80
-rw-r--r--src/H5Opkg.h18
-rw-r--r--src/H5Oprivate.h6
-rwxr-xr-xsrc/H5SM.c12
-rw-r--r--src/H5Tcommit.c2
17 files changed, 338 insertions, 61 deletions
diff --git a/src/H5Abtree2.c b/src/H5Abtree2.c
index 57e669e..02e1bed 100644
--- a/src/H5Abtree2.c
+++ b/src/H5Abtree2.c
@@ -44,11 +44,17 @@
/* Local Macros */
/****************/
+#ifndef QAK
+/* Size of stack buffer for serialized attributes */
+#define H5A_ATTR_BUF_SIZE 128
+#endif /* QAK */
+
/******************/
/* Local Typedefs */
/******************/
+#ifdef QAK
/*
* Data exchange structure for dense attribute storage. This structure is
* passed through the fractal heap layer to compare attributes.
@@ -59,12 +65,13 @@ typedef struct H5A_fh_ud_cmp_t {
hid_t dxpl_id; /* DXPL for operation */
const char *name; /* Name of attribute to compare */
const H5A_dense_bt2_name_rec_t *record; /* v2 B-tree record for attribute */
- H5B2_found_t found_op; /* Callback when correct attribute is found */
+ H5A_bt2_found_t found_op; /* Callback when correct attribute is found */
void *found_op_data; /* Callback data when correct attribute is found */
/* upward */
int cmp; /* Comparison of two attribute names */
} H5A_fh_ud_cmp_t;
+#endif /* QAK */
/********************/
@@ -101,7 +108,9 @@ static herr_t H5A_dense_btree2_name_debug(FILE *stream, const H5F_t *f, hid_t dx
int indent, int fwidth, const void *record, const void *_udata);
/* Fractal heap function callbacks */
+#ifdef QAK
static herr_t H5A_dense_fh_name_cmp(const void *obj, size_t obj_len, void *op_data);
+#endif /* QAK */
/*********************/
@@ -136,6 +145,11 @@ const H5B2_class_t H5A_BT2_CORDER[1]={{ /* B-tree class information */
/* Library Private Variables */
/*****************************/
+#ifndef QAK
+/* Declare extern a free list to manage blocks of type conversion data */
+H5FL_BLK_EXTERN(ser_attr);
+#endif /* QAK */
+
/*******************/
/* Local Variables */
@@ -157,11 +171,13 @@ const H5B2_class_t H5A_BT2_CORDER[1]={{ /* B-tree class information */
*
*-------------------------------------------------------------------------
*/
+#ifdef QAK
static herr_t
H5A_dense_fh_name_cmp(const void *obj, size_t UNUSED obj_len, void *_udata)
{
H5A_fh_ud_cmp_t *udata = (H5A_fh_ud_cmp_t *)_udata; /* User data for 'op' callback */
H5A_t *attr = NULL; /* Pointer to attribute created from heap object */
+ hbool_t took_ownership = FALSE; /* Whether the "found" operator took ownership of the attribute */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5A_dense_fh_name_cmp)
@@ -183,17 +199,18 @@ H5A_dense_fh_name_cmp(const void *obj, size_t UNUSED obj_len, void *_udata)
attr->crt_idx = udata->record->corder;
/* Make callback */
- if((udata->found_op)(attr, udata->found_op_data) < 0)
+ if((udata->found_op)(attr, &took_ownership, udata->found_op_data) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTOPERATE, FAIL, "attribute found callback failed")
} /* end if */
done:
/* Release the space allocated for the attrbute */
- if(attr)
+ if(attr && !took_ownership)
H5O_msg_free(H5O_ATTR_ID, attr);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A_dense_fh_name_cmp() */
+#endif /* QAK */
/*-------------------------------------------------------------------------
@@ -284,13 +301,16 @@ H5A_dense_btree2_name_compare(const void *_bt2_udata, const void *_bt2_rec)
else if(bt2_udata->name_hash > bt2_rec->hash)
ret_value = 1;
else {
+#ifdef QAK
H5A_fh_ud_cmp_t fh_udata; /* User data for fractal heap 'op' callback */
+#endif /* QAK */
H5HF_t *fheap; /* Fractal heap handle to use for finding object */
herr_t status; /* Status from fractal heap 'op' routine */
/* Sanity check */
HDassert(bt2_udata->name_hash == bt2_rec->hash);
+#ifdef QAK
/* Prepare user data for callback */
/* down */
fh_udata.f = bt2_udata->f;
@@ -302,6 +322,7 @@ H5A_dense_btree2_name_compare(const void *_bt2_udata, const void *_bt2_rec)
/* up */
fh_udata.cmp = 0;
+#endif /* QAK */
/* Check for attribute in shared storage */
if(bt2_rec->flags)
@@ -310,12 +331,72 @@ H5A_dense_btree2_name_compare(const void *_bt2_udata, const void *_bt2_rec)
fheap = bt2_udata->fheap;
HDassert(fheap);
+#ifdef QAK
/* Check if the user's attribute and the B-tree's attribute have the same name */
status = H5HF_op(fheap, bt2_udata->dxpl_id, &bt2_rec->id, H5A_dense_fh_name_cmp, &fh_udata);
HDassert(status >= 0);
/* Callback will set comparison value */
ret_value = fh_udata.cmp;
+#else /* QAK */
+/* XXX: This hack is due to a shared attribute and one of its components
+ * ending up in the same fractal heap direct block. Once John's change
+ * to the metadata cache that allows re-entrant read "protects" is in
+ * place, the previous code can be uncommented. -QAK
+ */
+ {
+ H5A_t *attr; /* Pointer to attribute created from heap object */
+ uint8_t attr_buf[H5A_ATTR_BUF_SIZE]; /* Buffer for serializing message */
+ void *attr_ptr; /* Pointer to serialized message */
+ hbool_t took_ownership = FALSE; /* Whether the "found" operator took ownership of the attribute */
+ size_t attr_size; /* Length of existing encoded attribute */
+
+ /* Get length of encoded attribute */
+ status = H5HF_get_obj_len(fheap, bt2_udata->dxpl_id, &bt2_rec->id, &attr_size);
+ HDassert(status >= 0);
+
+ /* Allocate space for serialized message, if necessary */
+ if(attr_size > sizeof(attr_buf)) {
+ attr_ptr = H5FL_BLK_MALLOC(ser_attr, attr_size);
+ HDassert(attr_ptr);
+ } /* end if */
+ else
+ attr_ptr = attr_buf;
+
+ /* Read the encoded attribute */
+ status = H5HF_read(fheap, bt2_udata->dxpl_id, &bt2_rec->id, attr_ptr);
+ HDassert(status >= 0);
+
+ /* Decode attribute information */
+ attr = (H5A_t *)H5O_msg_decode(bt2_udata->f, bt2_udata->dxpl_id, H5O_ATTR_ID, (const unsigned char *)attr_ptr);
+ HDassert(attr);
+
+ /* Release space, if we allocated it */
+ if(attr_ptr != attr_buf)
+ (void)H5FL_BLK_FREE(ser_attr, attr_ptr);
+
+ /* Compare the string values */
+ ret_value = HDstrcmp(bt2_udata->name, attr->name);
+
+ /* Check for correct attribute & callback to make */
+ if(ret_value == 0 && bt2_udata->found_op) {
+ /* Check whether we should "reconstitute" the shared message info */
+ if(bt2_rec->flags & H5O_MSG_FLAG_SHARED)
+ H5SM_reconstitute(&(attr->sh_loc), bt2_rec->id);
+
+ /* Set the creation order index for the attribute */
+ attr->crt_idx = bt2_rec->corder;
+
+ /* Make callback */
+ status = (bt2_udata->found_op)(attr, &took_ownership, bt2_udata->found_op_data);
+ HDassert(status >= 0);
+ } /* end if */
+
+ /* Release the space allocated for the attrbute */
+ if(!took_ownership)
+ H5O_msg_free(H5O_ATTR_ID, attr);
+ }
+#endif /* QAK */
} /* end else */
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Adense.c b/src/H5Adense.c
index 1dc7ad9..a1f9587 100644
--- a/src/H5Adense.c
+++ b/src/H5Adense.c
@@ -289,13 +289,11 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5A_dense_fnd_cb(const void *_attr, void *_user_attr)
+H5A_dense_fnd_cb(const H5A_t *attr, hbool_t *took_ownership, void *_user_attr)
{
- const H5A_t *attr = (const H5A_t *)_attr; /* Record from B-tree */
- H5A_t **user_attr = (H5A_t **)_user_attr; /* User data from v2 B-tree attribute lookup */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5A_t const **user_attr = (H5A_t const **)_user_attr; /* User data from v2 B-tree attribute lookup */
- FUNC_ENTER_NOAPI_NOINIT(H5A_dense_fnd_cb)
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_dense_fnd_cb)
/*
* Check arguments.
@@ -303,12 +301,11 @@ H5A_dense_fnd_cb(const void *_attr, void *_user_attr)
HDassert(attr);
HDassert(user_attr);
- /* Copy attribute information */
- if(NULL == (*user_attr = H5A_copy(NULL, attr)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute")
+ /* Take over attribute ownership */
+ *user_attr = attr;
+ *took_ownership = TRUE;
-done:
- FUNC_LEAVE_NOAPI(ret_value)
+ FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5A_dense_fnd_cb() */
diff --git a/src/H5Aint.c b/src/H5Aint.c
index a8bcedd..953dda2 100644
--- a/src/H5Aint.c
+++ b/src/H5Aint.c
@@ -194,7 +194,8 @@ H5A_compact_build_table(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5_index_t idx_type,
udata.dxpl_id = dxpl_id;
udata.atable = atable;
udata.curr_attr = 0;
- udata.bogus_crt_idx = (oh->version == H5O_VERSION_1) ? TRUE : FALSE;
+ udata.bogus_crt_idx = (oh->version == H5O_VERSION_1 ||
+ !(oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)) ? TRUE : FALSE;
/* Iterate over existing attributes, checking for attribute with same name */
op.op_type = H5O_MESG_OP_LIB;
diff --git a/src/H5Apkg.h b/src/H5Apkg.h
index 8d95ce9..f5d843b 100644
--- a/src/H5Apkg.h
+++ b/src/H5Apkg.h
@@ -95,6 +95,9 @@ typedef struct H5A_dense_bt2_corder_rec_t {
H5O_msg_crt_idx_t corder; /* 'creation order' field value */
} H5A_dense_bt2_corder_rec_t;
+/* Define the 'found' callback function pointer for matching an attribute record in a v2 B-tree */
+typedef herr_t (*H5A_bt2_found_t)(const H5A_t *attr, hbool_t *took_ownership, void *op_data);
+
/*
* Common data exchange structure for dense attribute storage. This structure
* is passed through the v2 B-tree layer to the methods for the objects
@@ -110,7 +113,7 @@ typedef struct H5A_bt2_ud_common_t {
uint32_t name_hash; /* Hash of name of attribute to compare */
uint8_t flags; /* Flags for attribute storage location */
H5O_msg_crt_idx_t corder; /* Creation order value of attribute to compare */
- H5B2_found_t found_op; /* Callback when correct attribute is found */
+ H5A_bt2_found_t found_op; /* Callback when correct attribute is found */
void *found_op_data; /* Callback data when correct attribute is found */
} H5A_bt2_ud_common_t;
diff --git a/src/H5F.c b/src/H5F.c
index 96fe355..6f8796b 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -850,7 +850,6 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf)
f->shared->extension_addr = HADDR_UNDEF;
f->shared->sohm_addr = HADDR_UNDEF;
f->shared->sohm_vers = HDF5_SHAREDHEADER_VERSION;
- f->shared->sohm_nindexes = 0;
f->shared->driver_addr = HADDR_UNDEF;
f->shared->lf = lf;
@@ -2909,6 +2908,34 @@ H5F_decr_nopen_objs(H5F_t *f)
/*-------------------------------------------------------------------------
+ * Function: H5F_store_msg_crt_idx
+ *
+ * Purpose: Retrieve the 'store message creation index' flag for the file.
+ *
+ * Return: Success: Non-negative, the 'store message creation index' flag
+ *
+ * Failure: (can't happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Mar 6 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+hbool_t
+H5F_store_msg_crt_idx(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_store_msg_crt_idx)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->store_msg_crt_idx)
+} /* end H5F_store_msg_crt_idx() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5F_block_read
*
* Purpose: Reads some data from a file/server/etc into a buffer.
diff --git a/src/H5FD.c b/src/H5FD.c
index ce8d91f..d1cb7c1 100644
--- a/src/H5FD.c
+++ b/src/H5FD.c
@@ -2444,6 +2444,54 @@ HDfprintf(stderr, "%s: type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)type
/* Check if we increased the size of the largest block on the list */
file->maxsize = MAX(file->maxsize, last->size);
+ /* Check if this free block adjoins the "metadata aggregator" */
+ if(file->feature_flags & H5FD_FEAT_AGGREGATE_METADATA && file->eoma != 0) {
+ hbool_t adjoins = FALSE; /* Whether the block adjoined the metadata aggregator */
+
+ /* Does the new block adjoin the end of the metadata aggregator */
+ if((file->eoma + file->cur_meta_block_size) == last->addr) {
+ last->addr = file->eoma;
+ adjoins = TRUE;
+ } /* end if */
+ /* Does the new block adjoin the beginning of the metadata aggregator */
+ else if((last->addr + last->size) == file->eoma)
+ adjoins = TRUE;
+
+ /* Reset metadata aggregator information, if adjoined */
+ if(adjoins) {
+#ifdef H5FD_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Adjoined metadata aggregator\n", FUNC);
+#endif /* H5FD_ALLOC_DEBUG */
+ last->size += file->cur_meta_block_size;
+ file->eoma = 0;
+ file->cur_meta_block_size = 0;
+ } /* end if */
+ } /* end if */
+
+ /* Check if this free block adjoins the "small data aggregator" */
+ if(file->feature_flags & H5FD_FEAT_AGGREGATE_SMALLDATA && file->eosda != 0) {
+ hbool_t adjoins = FALSE; /* Whether the block adjoined the small-data aggregator */
+
+ /* Does the new block adjoin the end of the small-data aggregator */
+ if((file->eosda + file->cur_sdata_block_size) == last->addr) {
+ last->addr = file->eosda;
+ adjoins = TRUE;
+ } /* end if */
+ /* Does the new block adjoin the beginning of the small-data aggregator */
+ else if((last->addr + last->size) == file->eosda)
+ adjoins = TRUE;
+
+ /* Reset small-data aggregator information, if adjoined */
+ if(adjoins) {
+#ifdef H5FD_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Adjoined small data aggregator\n", FUNC);
+#endif /* H5FD_ALLOC_DEBUG */
+ last->size += file->cur_sdata_block_size;
+ file->eosda = 0;
+ file->cur_sdata_block_size = 0;
+ } /* end if */
+ } /* end if */
+
/* Check if this free block is at the end of file allocated space.
* Truncate it if this is true. */
if(file->cls->get_eoa) {
@@ -2451,6 +2499,9 @@ HDfprintf(stderr, "%s: type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)type
eoa = file->cls->get_eoa(file, type);
if(eoa == (last->addr + last->size)) {
+#ifdef H5FD_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Reducing file size to = %a\n", FUNC, last->addr);
+#endif /* H5FD_ALLOC_DEBUG */
if(file->cls->set_eoa(file, type, last->addr) < 0)
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "set end of space allocation request failed")
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index 616bb81..10f219f 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -72,7 +72,7 @@ typedef struct H5F_file_t {
uint8_t consist_flags; /* File Consistency Flags */
unsigned flags; /* Access Permissions for file */
- /* Cached values from FCPL */
+ /* Cached values from FCPL/superblock */
unsigned sym_leaf_k; /* Size of leaves in symbol tables */
unsigned btree_k[H5B_NUM_BTREE_ID]; /* B-tree key values for each type */
size_t sizeof_addr; /* Size of addresses in file */
@@ -102,6 +102,7 @@ typedef struct H5F_file_t {
hsize_t alignment; /* Alignment */
unsigned gc_ref; /* Garbage-collect references? */
hbool_t latest_format; /* Always use the latest format? */
+ hbool_t store_msg_crt_idx; /* Store creation index for object header messages? */
int ncwfs; /* Num entries on cwfs list */
struct H5HG_heap_t **cwfs; /* Global heap cache */
struct H5G_t *root_grp; /* Open root group */
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index 264218f..14e3c85 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -266,6 +266,7 @@ typedef struct H5F_t H5F_t;
#define H5F_USE_LATEST_FORMAT(F) ((F)->shared->latest_format)
#define H5F_INTENT(F) ((F)->intent)
#define H5F_GET_FC_DEGREE(F) ((F)->shared->fc_degree)
+#define H5F_STORE_MSG_CRT_IDX(F) ((F)->shared->store_msg_crt_idx)
#else /* H5F_PACKAGE */
#define H5F_FCPL(F) (H5F_get_fcpl(F))
#define H5F_SIZEOF_ADDR(F) (H5F_sizeof_addr(F))
@@ -283,6 +284,7 @@ typedef struct H5F_t H5F_t;
#define H5F_USE_LATEST_FORMAT(F) (H5F_use_latest_format(F))
#define H5F_INTENT(F) (H5F_get_intent(F))
#define H5F_GET_FC_DEGREE(F) (H5F_get_fc_degree(F))
+#define H5F_STORE_MSG_CRT_IDX(F) (H5F_store_msg_crt_idx(F))
#endif /* H5F_PACKAGE */
@@ -446,6 +448,7 @@ H5_DLL size_t H5F_sieve_buf_size(const H5F_t *f);
H5_DLL unsigned H5F_gc_ref(const H5F_t *f);
H5_DLL hbool_t H5F_use_latest_format(const H5F_t *f);
H5_DLL H5F_close_degree_t H5F_get_fc_degree(const H5F_t *f);
+H5_DLL hbool_t H5F_store_msg_crt_idx(const H5F_t *f);
/* Functions that operate on blocks of bytes wrt super block */
H5_DLL herr_t H5F_block_read(const H5F_t *f, H5FD_mem_t type, haddr_t addr,
diff --git a/src/H5Gobj.c b/src/H5Gobj.c
index f8bc556..81dbf2d 100644
--- a/src/H5Gobj.c
+++ b/src/H5Gobj.c
@@ -163,17 +163,17 @@ H5G_obj_create(H5F_t *f, hid_t dxpl_id, const H5O_ginfo_t *ginfo,
size_t link_size; /* Size of a link message */
/* Calculate message size infomation, for creating group's object header */
- linfo_size = H5O_msg_mesg_size(f, H5O_LINFO_ID, linfo, (size_t)0);
+ linfo_size = H5O_msg_size_f(f, gcpl_id, H5O_LINFO_ID, linfo, (size_t)0);
HDassert(linfo_size);
- ginfo_size = H5O_msg_mesg_size(f, H5O_GINFO_ID, ginfo, (size_t)0);
+ ginfo_size = H5O_msg_size_f(f, gcpl_id, H5O_GINFO_ID, ginfo, (size_t)0);
HDassert(ginfo_size);
lnk.type = H5L_TYPE_HARD;
lnk.corder = 0;
lnk.corder_valid = ginfo->track_corder;
lnk.name = &null_char;
- link_size = H5O_msg_mesg_size(f, H5O_LINK_ID, &lnk, (size_t)ginfo->est_name_len);
+ link_size = H5O_msg_size_f(f, gcpl_id, H5O_LINK_ID, &lnk, (size_t)ginfo->est_name_len);
HDassert(link_size);
/* Compute size of header to use for creation */
@@ -887,6 +887,7 @@ H5G_obj_remove_update_linfo(H5O_loc_t *oloc, H5O_linfo_t *linfo, hid_t dxpl_id)
/* Check if we should switch from dense storage back to link messages */
if(linfo->nlinks < ginfo.min_dense) {
+ struct H5O_t *oh = NULL; /* Pointer to group's object header */
H5G_link_table_t ltable; /* Table of links */
hbool_t can_convert = TRUE; /* Whether converting to link messages is possible */
size_t u; /* Local index */
@@ -895,24 +896,22 @@ H5G_obj_remove_update_linfo(H5O_loc_t *oloc, H5O_linfo_t *linfo, hid_t dxpl_id)
if(H5G_dense_build_table(oloc->file, dxpl_id, linfo, H5_INDEX_NAME, H5_ITER_NATIVE, &ltable) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over links")
+ /* Get a pointer to the object header itself */
+ if((oh = H5O_protect(oloc, dxpl_id)) == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to protect dataset object header")
+
/* Inspect links in table for ones that can't be converted back
* into link message form (currently only links which can't fit
* into an object header message)
*/
for(u = 0; u < linfo->nlinks; u++)
- if(H5O_msg_mesg_size(oloc->file, H5O_LINK_ID, &(ltable.lnks[u]), (size_t)0) >= H5O_MESG_MAX_SIZE) {
+ if(H5O_msg_size_oh(oloc->file, oh, H5O_LINK_ID, &(ltable.lnks[u]), (size_t)0) >= H5O_MESG_MAX_SIZE) {
can_convert = FALSE;
break;
} /* end if */
/* If ok, insert links as link messages */
if(can_convert) {
- struct H5O_t *oh = NULL; /* Pointer to group's object header */
-
- /* Get a pointer to the object header itself */
- if((oh = H5O_protect(oloc, dxpl_id)) == NULL)
- HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to protect dataset object header")
-
/* Insert link messages into group */
for(u = 0; u < linfo->nlinks; u++)
if(H5O_msg_append(oloc->file, dxpl_id, oh, H5O_LINK_ID, 0, H5O_UPDATE_TIME, &(ltable.lnks[u])) < 0) {
@@ -923,15 +922,15 @@ H5G_obj_remove_update_linfo(H5O_loc_t *oloc, H5O_linfo_t *linfo, hid_t dxpl_id)
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create message")
} /* end if */
- /* Release object header */
- if(H5O_unprotect(oloc, oh) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to unprotect dataset object header")
-
/* Remove the dense storage */
if(H5G_dense_delete(oloc->file, dxpl_id, linfo, FALSE) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete dense link storage")
} /* end if */
+ /* Release object header */
+ if(H5O_unprotect(oloc, oh) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to unprotect dataset object header")
+
/* Free link table information */
if(H5G_link_release_table(&ltable) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table")
diff --git a/src/H5O.c b/src/H5O.c
index f4dd5d9..0741621 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -634,9 +634,10 @@ herr_t
H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id,
H5O_loc_t *loc/*out*/)
{
- H5O_t *oh = NULL;
+ H5O_t *oh = NULL; /* Object header created */
haddr_t oh_addr; /* Address of initial object header */
size_t oh_size; /* Size of initial object header */
+ hbool_t store_msg_crt_idx; /* Whether to always store message creation indices for this file */
herr_t ret_value = SUCCEED; /* return value */
FUNC_ENTER_NOAPI(H5O_create, FAIL)
@@ -653,8 +654,12 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id,
if(NULL == (oh = H5FL_CALLOC(H5O_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- /* Initialize rudimentary information object object header */
- oh->version = H5F_USE_LATEST_FORMAT(f) ? H5O_VERSION_LATEST : H5O_VERSION_1;
+ /* Initialize file-specific information for object header */
+ store_msg_crt_idx = H5F_STORE_MSG_CRT_IDX(f);
+ if(H5F_USE_LATEST_FORMAT(f) || store_msg_crt_idx)
+ oh->version = H5O_VERSION_LATEST;
+ else
+ oh->version = H5O_VERSION_1;
oh->sizeof_size = H5F_SIZEOF_SIZE(f);
oh->sizeof_addr = H5F_SIZEOF_ADDR(f);
@@ -676,7 +681,11 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id,
else
oh->atime = oh->mtime = oh->ctime = oh->btime = 0;
- /* Initialize attribute tracking fields */
+ /* Make certain attribute creation order tracking is enabled if
+ * attributes can be shared in this file.
+ */
+ if(store_msg_crt_idx)
+ oh->flags |= H5O_HDR_ATTR_CRT_ORDER_TRACKED;
/* Retrieve attribute storage phase change values from property list */
if(H5P_get(oc_plist, H5O_CRT_ATTR_MAX_COMPACT_NAME, &oh->max_compact) < 0)
diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c
index 9637055..3e97862 100644
--- a/src/H5Oattribute.c
+++ b/src/H5Oattribute.c
@@ -258,8 +258,8 @@ H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
/* Increment attribute count on object */
oh->nattrs++;
- /* Later versions of the object header track the creation index on all messages */
- if(oh->version > H5O_VERSION_1) {
+ /* 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")
@@ -1145,7 +1145,7 @@ H5O_attr_remove_update(const H5O_loc_t *loc, H5O_t *oh, hid_t dxpl_id)
* can't fit into an object header message)
*/
for(u = 0; u < oh->nattrs; u++)
- if(H5O_msg_mesg_size(loc->file, H5O_ATTR_ID, &(atable.attrs[u]), (size_t)0) >= H5O_MESG_MAX_SIZE) {
+ if(H5O_msg_size_oh(loc->file, oh, H5O_ATTR_ID, &(atable.attrs[u]), (size_t)0) >= H5O_MESG_MAX_SIZE) {
can_convert = FALSE;
break;
} /* end if */
diff --git a/src/H5Ocache.c b/src/H5Ocache.c
index c4430e6..7000e9e 100644
--- a/src/H5Ocache.c
+++ b/src/H5Ocache.c
@@ -150,7 +150,9 @@ H5O_flush_msgs(H5F_t *f, H5O_t *oh)
} /* end for */
/* Only encode creation index for version 2+ of format */
else {
- UINT16ENCODE(p, curr_msg->crt_idx);
+ /* Only encode creation index if they are being tracked */
+ if(oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)
+ UINT16ENCODE(p, curr_msg->crt_idx);
} /* end else */
HDassert(p == curr_msg->raw);
@@ -262,7 +264,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
if(NULL == (oh = H5FL_CALLOC(H5O_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- /* Generic, non-stored information */
+ /* File-specific, non-stored information */
oh->sizeof_size = H5F_SIZEOF_SIZE(f);
oh->sizeof_addr = H5F_SIZEOF_ADDR(f);
@@ -326,7 +328,12 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
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));
- UINT16DECODE(p, oh->max_attr_crt_idx);
+
+ /* 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 */
@@ -449,17 +456,28 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
H5O_msg_crt_idx_t crt_idx = H5O_MAX_CRT_ORDER_IDX; /* Creation index for current message */
/* Decode message prefix info */
+
+ /* Version # */
if(oh->version == H5O_VERSION_1)
UINT16DECODE(p, id)
else
id = *p++;
+
+ /* Message size */
UINT16DECODE(p, mesg_size);
HDassert(mesg_size == H5O_ALIGN_OH(oh, mesg_size));
+
+ /* Message flags */
flags = *p++;
+
+ /* Reserved bytes/creation index */
if(oh->version == H5O_VERSION_1)
p += 3; /*reserved*/
- else
- UINT16DECODE(p, crt_idx);
+ else {
+ /* Only encode creation index if they are being tracked */
+ if(oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)
+ UINT16DECODE(p, crt_idx);
+ } /* end else */
/* Try to detect invalidly formatted object header message that
* extends past end of chunk.
@@ -675,7 +693,10 @@ H5O_assert(oh);
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);
- UINT16ENCODE(p, oh->max_attr_crt_idx);
+
+ /* 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/H5Omessage.c b/src/H5Omessage.c
index cccf8b8..bf0d0b0 100644
--- a/src/H5Omessage.c
+++ b/src/H5Omessage.c
@@ -37,6 +37,7 @@
#include "H5Aprivate.h" /* Attributes */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fprivate.h" /* File access */
+#include "H5Iprivate.h" /* IDs */
#include "H5MMprivate.h" /* Memory management */
#include "H5Opkg.h" /* Object headers */
#include "H5SMprivate.h" /* Shared object header messages */
@@ -1327,7 +1328,7 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5O_msg_mesg_size
+ * Function: H5O_msg_size_f
*
* Purpose: Calculate the final size of an encoded message in an object
* header.
@@ -1344,12 +1345,15 @@ done:
*-------------------------------------------------------------------------
*/
size_t
-H5O_msg_mesg_size(const H5F_t *f, unsigned type_id, const void *mesg, size_t extra_raw)
+H5O_msg_size_f(const H5F_t *f, hid_t ocpl_id, unsigned type_id,
+ const void *mesg, size_t extra_raw)
{
- const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
- size_t ret_value; /* Return value */
+ const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
+ H5P_genplist_t *ocpl; /* Object Creation Property list */
+ uint8_t oh_flags; /* Object header status flags */
+ size_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5O_msg_mesg_size, 0)
+ FUNC_ENTER_NOAPI(H5O_msg_size_f, 0)
/* Check args */
HDassert(type_id < NELMTS(H5O_msg_class_g));
@@ -1359,6 +1363,15 @@ H5O_msg_mesg_size(const H5F_t *f, unsigned type_id, const void *mesg, size_t ext
HDassert(f);
HDassert(mesg);
+ /* Get the property list */
+ if(NULL == (ocpl = H5I_object(ocpl_id)))
+ HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, 0, "not a property list")
+
+ /* Get any object header status flags set by properties */
+ if(H5P_get(ocpl, H5O_CRT_OHDR_FLAGS_NAME, &oh_flags) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, 0, "can't get object header flags")
+
+
/* Compute the raw data size for the mesg */
if((ret_value = (type->raw_size)(f, FALSE, mesg)) == 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOUNT, 0, "unable to determine size of message")
@@ -1370,11 +1383,64 @@ H5O_msg_mesg_size(const H5F_t *f, unsigned type_id, const void *mesg, size_t ext
ret_value = H5O_ALIGN_F(f, ret_value);
/* Add space for message header */
- ret_value += H5O_SIZEOF_MSGHDR_F(f);
+ ret_value += H5O_SIZEOF_MSGHDR_F(f,
+ (H5F_STORE_MSG_CRT_IDX(f) || oh_flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED));
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_msg_size_f() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_msg_size_oh
+ *
+ * Purpose: Calculate the final size of an encoded message in an object
+ * header.
+ *
+ * Note: This routine assumes that the message is already used in
+ * an object header.
+ *
+ * Return: Size of message on success, 0 on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Mar 7 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+size_t
+H5O_msg_size_oh(const H5F_t *f, const H5O_t *oh, unsigned type_id,
+ const void *mesg, size_t extra_raw)
+{
+ const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
+ size_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_msg_size_oh, 0)
+
+ /* Check args */
+ HDassert(type_id < NELMTS(H5O_msg_class_g));
+ type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
+ HDassert(type);
+ HDassert(type->raw_size);
+ HDassert(f);
+ HDassert(mesg);
+
+ /* Compute the raw data size for the mesg */
+ if((ret_value = (type->raw_size)(f, FALSE, mesg)) == 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCOUNT, 0, "unable to determine size of message")
+
+ /* Add in "extra" raw space */
+ ret_value += extra_raw;
+
+ /* Adjust size for alignment, if necessary */
+ ret_value = H5O_ALIGN_OH(oh, ret_value);
+
+ /* Add space for message header */
+ ret_value += H5O_SIZEOF_MSGHDR_OH(oh);
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_msg_mesg_size() */
+} /* end H5O_msg_size_oh() */
/*-------------------------------------------------------------------------
diff --git a/src/H5Opkg.h b/src/H5Opkg.h
index 716260e..68066cf 100644
--- a/src/H5Opkg.h
+++ b/src/H5Opkg.h
@@ -120,7 +120,9 @@
(O)->sizeof_addr + /*addr of attribute heap */ \
(O)->sizeof_addr + /*addr of attribute name index */ \
(O)->sizeof_addr + /*addr of attribute creation order index */ \
- 2 + /*max attr. creation index */ \
+ (((O)->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED) ? ( \
+ 2 /*max attr. creation index */ \
+ ) : 0) + \
4 + /*chunk data size */ \
H5O_SIZEOF_CHKSUM) /*checksum size */ \
)
@@ -128,7 +130,7 @@
/*
* Size of object header message prefix
*/
-#define H5O_SIZEOF_MSGHDR_VERS(V) \
+#define H5O_SIZEOF_MSGHDR_VERS(V,C) \
(((V) == H5O_VERSION_1) \
? \
H5O_ALIGN_OLD(2 + /*message type */ \
@@ -139,12 +141,14 @@
(1 + /*message type */ \
2 + /*sizeof message data */ \
1 + /*flags */ \
- 2) /*creation index */ \
+ ((C) ? ( \
+ 2 /*creation index */ \
+ ) : 0)) \
)
#define H5O_SIZEOF_MSGHDR_OH(O) \
- H5O_SIZEOF_MSGHDR_VERS((O)->version)
-#define H5O_SIZEOF_MSGHDR_F(F) \
- H5O_SIZEOF_MSGHDR_VERS(H5F_USE_LATEST_FORMAT(F) ? H5O_VERSION_LATEST : H5O_VERSION_1)
+ H5O_SIZEOF_MSGHDR_VERS((O)->version, (O)->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)
+#define H5O_SIZEOF_MSGHDR_F(F, C) \
+ H5O_SIZEOF_MSGHDR_VERS((H5F_USE_LATEST_FORMAT(F) || H5F_STORE_MSG_CRT_IDX(F)) ? H5O_VERSION_LATEST : H5O_VERSION_1, (C))
/*
* Size of chunk "header" for each chunk
@@ -241,7 +245,7 @@ struct H5O_t {
H5AC_info_t cache_info; /* Information for H5AC cache functions, _must_ be */
/* first field in structure */
- /* General information (not stored) */
+ /* File-specific information (not stored) */
size_t sizeof_size; /* Size of file sizes */
size_t sizeof_addr; /* Size of file addresses */
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 0d1f918..5349827 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -477,8 +477,10 @@ H5_DLL herr_t H5O_msg_iterate(const H5O_loc_t *loc, unsigned type_id, H5O_operat
void *op_data, hid_t dxpl_id);
H5_DLL size_t H5O_msg_raw_size(const H5F_t *f, unsigned type_id,
hbool_t disable_shared, const void *mesg);
-H5_DLL size_t H5O_msg_mesg_size(const H5F_t *f, unsigned type_id, const void *mesg,
- size_t extra_raw);
+H5_DLL size_t H5O_msg_size_f(const H5F_t *f, hid_t ocpl_id, unsigned type_id,
+ const void *mesg, size_t extra_raw);
+H5_DLL size_t H5O_msg_size_oh(const H5F_t *f, const H5O_t *oh, unsigned type_id,
+ const void *mesg, size_t extra_raw);
H5_DLL htri_t H5O_msg_is_shared(unsigned type_id, const void *mesg);
H5_DLL htri_t H5O_msg_can_share(unsigned type_id, const void *mesg);
H5_DLL herr_t H5O_msg_set_share(unsigned type_id, H5O_shared_t *share, void *mesg);
diff --git a/src/H5SM.c b/src/H5SM.c
index 8192c21..f923664 100755
--- a/src/H5SM.c
+++ b/src/H5SM.c
@@ -197,6 +197,12 @@ H5SM_init(H5F_t *f, H5P_genplist_t * fc_plist, const H5O_loc_t *ext_loc, hid_t d
/* Record the address of the master table in the file */
f->shared->sohm_addr = table_addr;
+ /* Check for sharing attributes in this file, which means that creation
+ * indices must be tracked on object header message in the file.
+ */
+ if(type_flags_used & H5O_MESG_ATTR_FLAG)
+ f->shared->store_msg_crt_idx = TRUE;
+
/* Write shared message information to the superblock extension */
sohm_table.addr = f->shared->sohm_addr;
sohm_table.version = f->shared->sohm_vers;
@@ -1535,6 +1541,12 @@ H5SM_get_info(const H5O_loc_t *ext_loc, H5P_genplist_t *fc_plist, hid_t dxpl_id)
/* Sanity check */
HDassert(sohm_l2b == table->indexes[u].list_max);
HDassert(sohm_b2l == table->indexes[u].btree_min);
+
+ /* Check for sharing attributes in this file, which means that creation
+ * indices must be tracked on object header message in the file.
+ */
+ if(index_flags[u] & H5O_MESG_ATTR_FLAG)
+ shared->store_msg_crt_idx = TRUE;
} /* end for */
/* Set values in the property list */
diff --git a/src/H5Tcommit.c b/src/H5Tcommit.c
index b198a37..684b9ff 100644
--- a/src/H5Tcommit.c
+++ b/src/H5Tcommit.c
@@ -270,7 +270,7 @@ H5T_commit(H5F_t *file, H5T_t *type, hid_t dxpl_id, hid_t tcpl_id, hid_t UNUSED
loc_init = TRUE;
/* Calculate message size infomation, for creating object header */
- dtype_size = H5O_msg_mesg_size(file, H5O_DTYPE_ID, type, (size_t)0);
+ dtype_size = H5O_msg_size_f(file, tcpl_id, H5O_DTYPE_ID, type, (size_t)0);
HDassert(dtype_size);
/*