summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2006-10-17 20:36:15 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2006-10-17 20:36:15 (GMT)
commit3a2bcc84aca2a8fb3913c560b83cbb028c18bab9 (patch)
treef0da2af79e861321438061fc45c8ae90e63df624
parentf7a8a14bfd9d2c103c5d9be8adb578bec4a1b015 (diff)
downloadhdf5-3a2bcc84aca2a8fb3913c560b83cbb028c18bab9.zip
hdf5-3a2bcc84aca2a8fb3913c560b83cbb028c18bab9.tar.gz
hdf5-3a2bcc84aca2a8fb3913c560b83cbb028c18bab9.tar.bz2
[svn-r12771] Description:
More fixes to make the I/O & memory operations more efficient when loading & flushing object header chunks. Add in concept of a chunk having a "gap" at the end - unused space that is not large enough to hold a full null message that describes it. Clean up formatting a bit. Latest version of object header format not enabled yet, still working on a few bugs... Tested on: Linux/32 2.6 (chicago) Linux/64 2.6 (chicago2)
-rw-r--r--src/H5O.c373
-rw-r--r--src/H5Ocache.c199
-rw-r--r--src/H5Ocont.c28
-rw-r--r--src/H5Opkg.h4
4 files changed, 453 insertions, 151 deletions
diff --git a/src/H5O.c b/src/H5O.c
index 80b963f..bcad188 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -90,8 +90,8 @@ typedef struct {
} H5O_iter_ud1_t;
/* Typedef for "internal library" iteration operations */
-typedef herr_t (*H5O_lib_operator_t)(H5O_mesg_t *mesg/*in,out*/, unsigned idx,
- unsigned * oh_flags_ptr, void *operator_data/*in,out*/);
+typedef herr_t (*H5O_lib_operator_t)(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
+ unsigned idx, unsigned * oh_flags_ptr, void *operator_data/*in,out*/);
/* Some syntactic sugar to make the compiler happy with two different kinds of iterator callbacks */
typedef union {
@@ -147,6 +147,10 @@ static int H5O_append_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
unsigned * oh_flags_ptr);
static herr_t H5O_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_eliminate_gap(H5O_t *oh, unsigned chunkno, unsigned idx,
+ uint8_t *new_gap_loc, size_t new_gap_size);
+static herr_t H5O_add_gap(H5O_t *oh, unsigned chunkno, unsigned idx,
+ uint8_t *new_gap_loc, size_t new_gap_size);
static unsigned H5O_alloc(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
const H5O_msg_class_t *type, size_t size, hbool_t * oh_dirtied_ptr);
static herr_t H5O_alloc_msgs(H5O_t *oh, size_t min_alloc);
@@ -746,7 +750,7 @@ H5O_new(H5F_t *f, hid_t dxpl_id, size_t chunk_size, H5O_loc_t *loc/*out*/,
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Initialize rudimentary information object object header */
- oh->version = H5O_VERSION_1;
+ oh->version = H5F_USE_LATEST_FORMAT(f) ? H5O_VERSION_LATEST : H5O_VERSION_1;
oh->nlink = 0;
/* Compute total size of initial object header */
@@ -754,8 +758,7 @@ H5O_new(H5F_t *f, hid_t dxpl_id, size_t chunk_size, H5O_loc_t *loc/*out*/,
oh_size = H5O_SIZEOF_HDR_OH(oh) + chunk_size;
/* Create the chunk list */
- oh->nchunks = 1;
- oh->alloc_nchunks = H5O_NCHUNKS;
+ oh->nchunks = oh->alloc_nchunks = 1;
if(NULL == (oh->chunk = H5FL_SEQ_MALLOC(H5O_chunk_t, (size_t)oh->alloc_nchunks)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
@@ -763,6 +766,7 @@ H5O_new(H5F_t *f, hid_t dxpl_id, size_t chunk_size, H5O_loc_t *loc/*out*/,
oh->chunk[0].dirty = TRUE;
oh->chunk[0].addr = loc->addr;
oh->chunk[0].size = oh_size;
+ oh->chunk[0].gap = 0;
/* Allocate enough space for the first chunk */
/* (including space for serializing the object header prefix */
@@ -2445,8 +2449,8 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_remove_cb(H5O_mesg_t *mesg/*in,out*/, unsigned idx, unsigned * oh_flags_ptr,
- void *_udata/*in,out*/)
+H5O_remove_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, unsigned idx,
+ unsigned * oh_flags_ptr, void *_udata/*in,out*/)
{
H5O_iter_ud1_t *udata = (H5O_iter_ud1_t *)_udata; /* Operator user data */
htri_t try_remove = FALSE; /* Whether to try removing a message */
@@ -2475,9 +2479,8 @@ H5O_remove_cb(H5O_mesg_t *mesg/*in,out*/, unsigned idx, unsigned * oh_flags_ptr,
* Keep track of how many times we failed trying to remove constant
* messages.
*/
- if(mesg->flags & H5O_FLAG_CONSTANT) {
+ if(mesg->flags & H5O_FLAG_CONSTANT)
udata->nfailed++;
- } /* end if */
else {
/* Free any space referred to in the file from this message */
if(H5O_delete_mesg(udata->f, udata->dxpl_id, mesg, udata->adj_link) < 0)
@@ -2488,11 +2491,27 @@ H5O_remove_cb(H5O_mesg_t *mesg/*in,out*/, unsigned idx, unsigned * oh_flags_ptr,
/* Change message type to nil and zero it */
mesg->type = H5O_MSG_NULL;
+#ifdef QAK
+HDfprintf(stderr, "%s: oh->version = %u\n", FUNC, oh->version);
+HDfprintf(stderr, "%s: mesg->raw_size = %Zu\n", FUNC, mesg->raw_size);
+#endif /* QAK */
HDmemset(mesg->raw, 0, mesg->raw_size);
/* Indicate that the message was modified */
mesg->dirty = TRUE;
+ /* Check if chunk has a gap currently */
+ if(oh->chunk[mesg->chunkno].gap) {
+ /* Eliminate the gap in the chunk */
+ if(H5O_eliminate_gap(oh, mesg->chunkno, idx,
+ ((oh->chunk[mesg->chunkno].image + oh->chunk[mesg->chunkno].size) - (H5O_SIZEOF_CHKSUM_OH(oh) + oh->chunk[mesg->chunkno].gap)),
+ oh->chunk[mesg->chunkno].gap) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTREMOVE, H5O_ITER_ERROR, "can't insert eliminate in chunk")
+
+ /* Set the gap size to zero for the chunk */
+ oh->chunk[mesg->chunkno].gap = 0;
+ } /* end if */
+
/* Indicate that the object header was modified */
*oh_flags_ptr |= H5AC__DIRTIED_FLAG;
} /* end else */
@@ -2542,7 +2561,8 @@ H5O_remove_real(const H5O_loc_t *loc, const H5O_msg_class_t *type, int sequence,
HDassert(loc->file);
HDassert(type);
- if (0==(loc->file->intent & H5F_ACC_RDWR))
+ /* Make certain we are allowed to modify the file */
+ if(0 == (loc->file->intent & H5F_ACC_RDWR))
HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file")
/* Set up iterator operator data */
@@ -2659,7 +2679,8 @@ H5O_move_msgs_forward(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
/* Check if null message is not last in chunk */
chunk = &(oh->chunk[curr_msg->chunkno]);
- if((curr_msg->raw + curr_msg->raw_size + H5O_SIZEOF_CHKSUM_OH(oh)) != (chunk->image + chunk->size)) {
+ if((curr_msg->raw + curr_msg->raw_size)
+ != ((chunk->image + chunk->size) - (H5O_SIZEOF_CHKSUM_OH(oh) + chunk->gap))) {
H5O_mesg_t *nonnull_msg; /* Pointer to current message to operate on */
unsigned v; /* Local index variable */
@@ -2749,18 +2770,46 @@ H5O_move_msgs_forward(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
/* Mark non-null message dirty */
curr_msg->dirty = TRUE;
- /* Adjust null message's size & offset */
- null_msg->raw += curr_msg->raw_size + H5O_SIZEOF_MSGHDR_OH(oh);
- null_msg->raw_size -= curr_msg->raw_size + H5O_SIZEOF_MSGHDR_OH(oh);
+ /* Check if null message is large enough to still exist */
+ if(null_msg->raw_size - curr_msg->raw_size < H5O_SIZEOF_MSGHDR_OH(oh)) {
+ size_t gap_size = null_msg->raw_size - curr_msg->raw_size; /* Size of gap produced */
- /* Mark null message dirty */
- null_msg->dirty = TRUE;
+ /* Adjust the size of the null message being eliminated */
+ null_msg->raw_size -= gap_size;
+
+ /* Add the gap to the chunk */
+ if(H5O_add_gap(oh, null_msg->chunkno, v, null_msg->raw + null_msg->raw_size, gap_size) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert gap in chunk")
+
+ /*
+ * Delete null message from list of messages
+ */
+
+ /* Release any information/memory for message */
+ H5O_free_mesg(null_msg);
+ null_msg = NULL;
+
+ /* Remove null message from list of messages */
+ if(v < (oh->nmesgs - 1))
+ HDmemmove(&oh->mesg[v], &oh->mesg[v + 1], ((oh->nmesgs - 1) - v) * sizeof(H5O_mesg_t));
+
+ /* Decrement # of messages */
+ /* (Don't bother reducing size of message array for now -QAK) */
+ oh->nmesgs--;
+ } /* end if */
+ else {
+ /* Adjust null message's size & offset */
+ null_msg->raw += curr_msg->raw_size + H5O_SIZEOF_MSGHDR_OH(oh);
+ null_msg->raw_size -= curr_msg->raw_size + H5O_SIZEOF_MSGHDR_OH(oh);
+
+ /* Mark null message dirty */
+ null_msg->dirty = TRUE;
+ } /* end else */
/* Create new null message for previous location of non-null message */
- if(oh->nmesgs >= oh->alloc_nmesgs) {
- if(H5O_alloc_msgs(oh, (size_t)0) < 0)
+ if(oh->nmesgs >= oh->alloc_nmesgs)
+ if(H5O_alloc_msgs(oh, (size_t)1) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate more space for messages")
- } /* end if */
/* Get message # for new message */
new_null_msg = oh->nmesgs++;
@@ -2772,6 +2821,18 @@ H5O_move_msgs_forward(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
oh->mesg[new_null_msg].raw = old_raw;
oh->mesg[new_null_msg].raw_size = old_raw_size;
oh->mesg[new_null_msg].chunkno = old_chunkno;
+
+ /* Check for gap in new null message's chunk */
+ if(oh->chunk[old_chunkno].gap > 0) {
+ /* Eliminate the gap in the chunk */
+ if(H5O_eliminate_gap(oh, old_chunkno, new_null_msg,
+ ((oh->chunk[old_chunkno].image + oh->chunk[old_chunkno].size) - (H5O_SIZEOF_CHKSUM_OH(oh) + oh->chunk[old_chunkno].gap)),
+ oh->chunk[old_chunkno].gap) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTREMOVE, FAIL, "can't insert eliminate in chunk")
+
+ /* Set the gap size to zero for the chunk */
+ oh->chunk[old_chunkno].gap = 0;
+ } /* end if */
} /* end else */
/* Indicate that we packed messages */
@@ -2848,6 +2909,9 @@ H5O_merge_null(H5O_t *oh)
H5O_mesg_t *curr_msg2; /* Pointer to current message to operate on */
unsigned v; /* Local index variable */
+ /* Should be no gaps in chunk with null message */
+ HDassert(oh->chunk[curr_msg->chunkno].gap == 0);
+
/* Loop over messages again, looking for null message in same chunk */
for(v = 0, curr_msg2 = &oh->mesg[0]; v < oh->nmesgs; v++, curr_msg2++) {
if(u != v && H5O_NULL_ID == curr_msg2->type->id && curr_msg->chunkno == curr_msg2->chunkno) {
@@ -2955,7 +3019,8 @@ H5O_remove_empty_chunks(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
* its not the "base" chunk), delete that chunk from object header
*/
if(H5O_NULL_ID == null_msg->type->id && null_msg->chunkno > 0 &&
- (H5O_SIZEOF_MSGHDR_OH(oh) + null_msg->raw_size + H5O_SIZEOF_CHKHDR_OH(oh)) == oh->chunk[null_msg->chunkno].size) {
+ (H5O_SIZEOF_MSGHDR_OH(oh) + null_msg->raw_size)
+ == (oh->chunk[null_msg->chunkno].size - H5O_SIZEOF_CHKHDR_OH(oh))) {
H5O_mesg_t *curr_msg; /* Pointer to current message to operate on */
unsigned null_msg_no; /* Message # for null message */
unsigned deleted_chunkno; /* Chunk # to delete */
@@ -3177,7 +3242,9 @@ H5O_alloc_extend_chunk(H5F_t *f,
/* Check for null message at end of proper chunk */
/* (account for possible checksum at end of chunk) */
if(oh->mesg[u].chunkno == chunkno && H5O_NULL_ID == oh->mesg[u].type->id &&
- ((oh->mesg[u].raw + oh->mesg[u].raw_size + H5O_SIZEOF_CHKSUM_OH(oh)) == oh->chunk[chunkno].image + oh->chunk[chunkno].size)) {
+ ((oh->mesg[u].raw + oh->mesg[u].raw_size)
+ == ((oh->chunk[chunkno].image + oh->chunk[chunkno].size) -
+ (oh->chunk[chunkno].gap + H5O_SIZEOF_CHKSUM_OH(oh))))) {
extend_msg = u;
break;
@@ -3185,10 +3252,12 @@ H5O_alloc_extend_chunk(H5F_t *f,
} /* end for */
/* If we can extend an existing null message, adjust the delta appropriately */
- if(extend_msg >= 0)
+ if(extend_msg >= 0) {
+ HDassert(oh->chunk[chunkno].gap == 0);
delta = aligned_size - oh->mesg[extend_msg].raw_size;
+ } /* end if */
else
- delta = aligned_size + H5O_SIZEOF_MSGHDR_OH(oh);
+ delta = (aligned_size + H5O_SIZEOF_MSGHDR_OH(oh)) - oh->chunk[chunkno].gap;
delta = H5O_ALIGN_OH(oh, delta);
/* Determine whether the chunk can be extended */
@@ -3214,7 +3283,7 @@ H5O_alloc_extend_chunk(H5F_t *f,
else {
/* Create a new null message */
if(oh->nmesgs >= oh->alloc_nmesgs)
- if(H5O_alloc_msgs(oh, (size_t)0) < 0)
+ if(H5O_alloc_msgs(oh, (size_t)1) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate more space for messages")
/* Set extension message */
@@ -3224,9 +3293,10 @@ H5O_alloc_extend_chunk(H5F_t *f,
oh->mesg[extend_msg].type = H5O_MSG_NULL;
oh->mesg[extend_msg].dirty = TRUE;
oh->mesg[extend_msg].native = NULL;
- oh->mesg[extend_msg].raw = oh->chunk[chunkno].image +
- oh->chunk[chunkno].size + H5O_SIZEOF_MSGHDR_OH(oh);
- oh->mesg[extend_msg].raw_size = delta - H5O_SIZEOF_MSGHDR_OH(oh);
+ oh->mesg[extend_msg].raw = ((oh->chunk[chunkno].image + oh->chunk[chunkno].size)
+ - (H5O_SIZEOF_CHKSUM_OH(oh) + oh->chunk[chunkno].gap))
+ + H5O_SIZEOF_MSGHDR_OH(oh);
+ oh->mesg[extend_msg].raw_size = (delta + oh->chunk[chunkno].gap) - H5O_SIZEOF_MSGHDR_OH(oh);
oh->mesg[extend_msg].chunkno = chunkno;
} /* end else */
@@ -3235,6 +3305,7 @@ H5O_alloc_extend_chunk(H5F_t *f,
old_size = oh->chunk[chunkno].size;
oh->chunk[chunkno].size += delta;
oh->chunk[chunkno].image = H5FL_BLK_REALLOC(chunk_image, old_image, oh->chunk[chunkno].size);
+ oh->chunk[chunkno].gap = 0;
oh->chunk[chunkno].dirty = TRUE;
if(NULL == oh->chunk[chunkno].image)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
@@ -3421,6 +3492,7 @@ H5O_alloc_new_chunk(H5F_t *f,
oh->chunk[chunkno].dirty = TRUE;
oh->chunk[chunkno].addr = new_chunk_addr;
oh->chunk[chunkno].size = size;
+ oh->chunk[chunkno].gap = 0;
if(NULL == (oh->chunk[chunkno].image = p = H5FL_BLK_CALLOC(chunk_image, size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "memory allocation failed")
@@ -3516,6 +3588,190 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5O_eliminate_gap
+ *
+ * Purpose: Eliminate a gap in a chunk with a null message
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Oct 17 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_eliminate_gap(H5O_t *oh, unsigned chunkno, unsigned idx,
+ uint8_t *gap_loc, size_t gap_size)
+{
+ uint8_t *move_start, *move_end; /* Pointers to area of messages to move */
+ hbool_t null_before_gap; /* Flag whether the null message is before the gap or not */
+ unsigned u; /* Local index variable */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_eliminate_gap)
+
+ /* check args */
+ HDassert(oh);
+ HDassert(oh->version > H5O_VERSION_1);
+ HDassert(gap_loc);
+ HDassert(gap_size);
+
+ /* Check if the null message is before or after the gap produced */
+ null_before_gap = (hbool_t)(oh->mesg[idx].raw < gap_loc);
+
+ /* Set up information about region of messages to move */
+ if(null_before_gap) {
+ move_start = oh->mesg[idx].raw + oh->mesg[idx].raw_size;
+ move_end = gap_loc;
+ } /* end if */
+ else {
+ move_start = gap_loc + gap_size;
+ move_end = oh->mesg[idx].raw - H5O_SIZEOF_MSGHDR_OH(oh);
+ } /* end else */
+ HDassert(move_end > move_start);
+
+ /* Look for other messages that will move, to adjust raw pointers in chunk */
+ for(u = 0; u < oh->nmesgs; u++) {
+ uint8_t *msg_start; /* Start of encoded message in chunk */
+
+ msg_start = oh->mesg[u].raw - H5O_SIZEOF_MSGHDR_OH(oh);
+ if(oh->mesg[u].chunkno == chunkno
+ && (msg_start >= move_start && msg_start < move_end)) {
+ /* Move message's raw pointer in appropriate direction */
+ if(null_before_gap)
+ oh->mesg[u].raw += gap_size;
+ else
+ oh->mesg[u].raw -= gap_size;
+ } /* end if */
+ } /* end for */
+
+ /* Slide raw message info in chunk image */
+ if(null_before_gap)
+ /* Slide messages down */
+ HDmemmove(move_start, move_start + gap_size, (size_t)(move_end - move_start));
+ else {
+ /* Slide messages up */
+ HDmemmove(move_start - gap_size, move_start, (size_t)(move_end - move_start));
+
+ /* Adjust start of null message */
+ oh->mesg[idx].raw -= gap_size;
+ } /* end else */
+
+ /* Zero out addition to null message */
+ HDmemset(oh->mesg[idx].raw + oh->mesg[idx].raw_size, 0, gap_size);
+
+ /* Adjust size of null message */
+ oh->mesg[idx].raw_size += gap_size;
+
+ /* Mark null message as dirty */
+ oh->mesg[idx].dirty = TRUE;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5O_eliminate_gap() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_add_gap
+ *
+ * Purpose: Add a gap to a chunk
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Oct 17 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_add_gap(H5O_t *oh, unsigned chunkno, unsigned idx,
+ uint8_t *new_gap_loc, size_t new_gap_size)
+{
+ hbool_t merged_with_null; /* Whether the gap was merged with a null message */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_add_gap)
+
+ /* check args */
+ HDassert(oh);
+ HDassert(oh->version > H5O_VERSION_1);
+ HDassert(new_gap_loc);
+ HDassert(new_gap_size);
+
+ /* Check for existing null message in chunk */
+ merged_with_null = FALSE;
+ for(u = 0; u < oh->nmesgs && !merged_with_null; u++) {
+ /* Find a null message in the chunk with the new gap */
+ /* (a null message that's not the one we are eliminating) */
+ if(H5O_NULL_ID == oh->mesg[u].type->id && oh->mesg[u].chunkno == chunkno
+ && u != idx) {
+ /* Sanity check - chunks with null messages shouldn't have a gap */
+ HDassert(oh->chunk[chunkno].gap == 0);
+
+ /* Eliminate the gap in the chunk */
+ if(H5O_eliminate_gap(oh, chunkno, u, new_gap_loc, new_gap_size) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't eliminate gap in chunk")
+
+ /* Set flag to indicate that the gap was handled */
+ merged_with_null = TRUE;
+ } /* end if */
+ } /* end for */
+
+ /* If we couldn't find a null message in the chunk, move the gap to the end */
+ if(!merged_with_null) {
+ /* Adjust message offsets after new gap forward in chunk */
+ for(u = 0; u < oh->nmesgs; u++)
+ if(oh->mesg[u].chunkno == chunkno && oh->mesg[u].raw > new_gap_loc)
+ oh->mesg[u].raw -= new_gap_size;
+
+ /* Slide raw message info forward in chunk image */
+ HDmemmove(new_gap_loc, new_gap_loc + new_gap_size,
+ (size_t)((oh->chunk[chunkno].image + (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM_OH(oh))) - (new_gap_loc + new_gap_size)));
+
+ /* Add existing gap size to new gap size */
+ new_gap_size += oh->chunk[chunkno].gap;
+
+ /* Merging with existing gap will allow for a new null message */
+ if(new_gap_size >= H5O_SIZEOF_MSGHDR_OH(oh)) {
+ H5O_mesg_t *null_msg; /* Pointer to new null message */
+
+ /* Check if we need to extend message table to hold the new null message */
+ if(oh->nmesgs >= oh->alloc_nmesgs) {
+ if(H5O_alloc_msgs(oh, (size_t)1) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "can't allocate more space for messages")
+ } /* end if */
+
+ /* Increment new gap size */
+ oh->chunk[chunkno].gap += new_gap_size;
+
+ /* Create new null message, with the tail of the previous null message */
+ null_msg = &(oh->mesg[oh->nmesgs++]);
+ null_msg->type = H5O_MSG_NULL;
+ null_msg->dirty = TRUE;
+ null_msg->native = NULL;
+ null_msg->raw_size = new_gap_size - H5O_SIZEOF_MSGHDR_OH(oh);
+ null_msg->raw = (oh->chunk[chunkno].image + oh->chunk[chunkno].size)
+ - (H5O_SIZEOF_CHKSUM_OH(oh) + null_msg->raw_size);
+ null_msg->chunkno = chunkno;
+
+ /* Zero out new null message's raw data */
+ if(null_msg->raw_size)
+ HDmemset(null_msg->raw, 0, null_msg->raw_size);
+
+ /* Reset size of gap in chunk */
+ oh->chunk[chunkno].gap = 0;
+ } /* end if */
+ else
+ oh->chunk[chunkno].gap = new_gap_size;
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5O_add_gap() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5O_alloc
*
* Purpose: Allocate enough space in the object header for this message.
@@ -3590,32 +3846,48 @@ H5O_alloc(H5F_t *f,
/* Set pointer to newly allocated message */
msg = &(oh->mesg[idx]);
- /* do we need to split the null message? */
+ /* Do we need to split the existing null message? */
if(msg->raw_size > aligned_size) {
- H5O_mesg_t *null_msg; /* Pointer to null message */
size_t mesg_size = aligned_size + H5O_SIZEOF_MSGHDR_OH(oh); /* Total size of newly allocated message */
- HDassert(msg->raw_size - aligned_size >= H5O_SIZEOF_MSGHDR_OH(oh));
+ /* Check for producing a gap in the chunk */
+ if((msg->raw_size - aligned_size) < H5O_SIZEOF_MSGHDR_OH(oh)) {
+ size_t gap_size = msg->raw_size - aligned_size; /* Size of gap produced */
- /* Check if we need to extend message table */
- if(oh->nmesgs >= oh->alloc_nmesgs) {
- if(H5O_alloc_msgs(oh, (size_t)0) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "can't allocate more space for messages")
+ /* Adjust the size of the null message being eliminated */
+ msg->raw_size -= gap_size;
- /* "Retarget" local 'msg' pointer into newly allocated array of messages */
- msg = &oh->mesg[idx];
+ /* Add the gap to the chunk */
+ if(H5O_add_gap(oh, msg->chunkno, idx, msg->raw + msg->raw_size, gap_size) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, UFAIL, "can't insert gap in chunk")
} /* end if */
- null_msg = &(oh->mesg[oh->nmesgs++]);
- null_msg->type = H5O_MSG_NULL;
- null_msg->dirty = TRUE;
- null_msg->native = NULL;
- null_msg->raw = msg->raw + mesg_size;
- null_msg->raw_size = msg->raw_size - mesg_size;
- null_msg->chunkno = msg->chunkno;
+ else {
+ H5O_mesg_t *null_msg; /* Pointer to new null message */
+
+ /* Check if we need to extend message table to hold the new null message */
+ if(oh->nmesgs >= oh->alloc_nmesgs) {
+ if(H5O_alloc_msgs(oh, (size_t)1) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "can't allocate more space for messages")
+
+ /* "Retarget" local 'msg' pointer into newly re-allocated array of messages */
+ msg = &oh->mesg[idx];
+ } /* end if */
+
+ /* Create new null message, with the tail of the previous null message */
+ null_msg = &(oh->mesg[oh->nmesgs++]);
+ null_msg->type = H5O_MSG_NULL;
+ null_msg->dirty = TRUE;
+ null_msg->native = NULL;
+ null_msg->raw = msg->raw + mesg_size;
+ null_msg->raw_size = msg->raw_size - mesg_size;
+ null_msg->chunkno = msg->chunkno;
+ } /* end else */
+
+ /* Set the size of the new "real" message */
msg->raw_size = aligned_size;
} /* end if */
- /* initialize the new message */
+ /* Initialize the new message */
msg->type = type;
msg->dirty = TRUE;
msg->native = NULL;
@@ -4180,7 +4452,7 @@ H5O_iterate_real(const H5O_loc_t *loc, const H5O_msg_class_t *type, H5AC_protect
/* Check for making an "internal" (i.e. within the H5O package) callback */
if(internal) {
/* Call the "internal" iterator callback */
- if((ret_value = (op.lib_op)(idx_msg, sequence, &oh_flags, op_data)) != 0)
+ if((ret_value = (op.lib_op)(oh, idx_msg, sequence, &oh_flags, op_data)) != 0)
break;
} /* end if */
else {
@@ -4206,6 +4478,10 @@ done:
HDassert(prot == H5AC_WRITE);
/* Try to condense object header info */
+ /* (Since this routine is invoked when a message is removed from
+ * an object header, the header will be condensed after each
+ * message removal)
+ */
if(H5O_condense_header(loc->file, oh, dxpl_id) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTPACK, FAIL, "can't pack object header")
@@ -4635,6 +4911,7 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
/* Set dest. chunk information */
oh_dst->chunk[chunkno].dirty = TRUE;
oh_dst->chunk[chunkno].size = chunk_size;
+ oh_dst->chunk[chunkno].gap = oh_src->chunk[chunkno].gap;
} /* end for */
@@ -4715,7 +4992,7 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
/* (Use destination message, in case the message has been removed (i.e
* converted to a nil message) in the destination -QAK)
*/
- if (mesg_dst->flags & H5O_FLAG_SHARED)
+ if(mesg_dst->flags & H5O_FLAG_SHARED)
copy_type = H5O_MSG_SHARED;
else
copy_type = mesg_dst->type;
@@ -5317,6 +5594,10 @@ H5O_debug_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, haddr_t addr, FILE *stream, i
HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", MAX(0, fwidth - 3),
"Size in bytes:",
chunk_size);
+
+ HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", MAX(0, fwidth - 3),
+ "Gap:",
+ oh->chunk[i].gap);
} /* end for */
/* debug each message */
diff --git a/src/H5Ocache.c b/src/H5Ocache.c
index d4e00a3..d0f479d 100644
--- a/src/H5Ocache.c
+++ b/src/H5Ocache.c
@@ -139,6 +139,13 @@ H5O_flush_msgs(H5F_t *f, H5O_t *oh)
*p++ = 0; /*reserved*/
*p++ = 0; /*reserved*/
} /* end for */
+ HDassert(p == curr_msg->raw);
+
+#ifndef NDEBUG
+ /* Make certain that null messages aren't in chunks w/gaps */
+ if(H5O_NULL_ID == curr_msg->type->id)
+ HDassert(oh->chunk[curr_msg->chunkno].gap == 0);
+#endif /* NDEBUG */
/* Encode the message itself */
if(curr_msg->native) {
@@ -154,7 +161,7 @@ H5O_flush_msgs(H5F_t *f, H5O_t *oh)
HDassert(curr_msg->raw >= oh->chunk[curr_msg->chunkno].image);
HDassert(curr_msg->raw_size == H5O_ALIGN_OH(oh, curr_msg->raw_size));
HDassert(curr_msg->raw + curr_msg->raw_size <=
- oh->chunk[curr_msg->chunkno].image + oh->chunk[curr_msg->chunkno].size);
+ oh->chunk[curr_msg->chunkno].image + (oh->chunk[curr_msg->chunkno].size - H5O_SIZEOF_CHKSUM_OH(oh)));
if(curr_msg->flags & H5O_FLAG_SHARED)
encode = H5O_MSG_SHARED->encode;
else
@@ -162,6 +169,8 @@ H5O_flush_msgs(H5F_t *f, H5O_t *oh)
if((encode)(f, curr_msg->raw, curr_msg->native) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode object header message")
} /* end if */
+
+ /* Pass "modifiedness" from message to chunk */
curr_msg->dirty = FALSE;
oh->chunk[curr_msg->chunkno].dirty = TRUE;
} /* end if */
@@ -208,7 +217,6 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
size_t chunk_size; /* Size of first chunk */
haddr_t abs_eoa; /* Absolute end of file address */
haddr_t rel_eoa; /* Relative end of file address */
- uint32_t prefix_chksum = 0; /* Checksum of object header prefix */
H5O_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5O_load, NULL)
@@ -275,10 +283,6 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
/* Determine object header prefix length */
prefix_size = (size_t)(p - read_buf);
- /* Compute partial checksum, for later versions of the format */
- if(oh->version > H5O_VERSION_1)
- prefix_chksum = H5_checksum_lookup3(read_buf, prefix_size, 0);
-
/* Compute first chunk address */
chunk_addr = addr + (hsize_t)prefix_size;
@@ -290,6 +294,10 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
/* Read each chunk from disk */
while(H5F_addr_defined(chunk_addr)) {
unsigned chunkno; /* Current chunk's index */
+#ifndef NDEBUG
+ unsigned nullcnt; /* Count of null messages (for sanity checking gaps in chunks) */
+#endif /* NDEBUG */
+ uint8_t *eom_ptr; /* Pointer to end of messages for a chunk */
/* Increase chunk array size, if necessary */
if(oh->nchunks >= oh->alloc_nchunks) {
@@ -305,6 +313,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
/* Init the chunk data info */
chunkno = oh->nchunks++;
oh->chunk[chunkno].dirty = FALSE;
+ oh->chunk[chunkno].gap = 0;
if(chunkno == 0) {
/* First chunk's 'image' includes room for the object header prefix */
oh->chunk[0].addr = addr;
@@ -354,7 +363,11 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
} /* end if */
/* Decode messages from this chunk */
- while(p < (oh->chunk[chunkno].image + (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM_OH(oh)))) {
+ eom_ptr = oh->chunk[chunkno].image + (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM_OH(oh));
+#ifndef NDEBUG
+ nullcnt = 0;
+#endif /* NDEBUG */
+ while(p < eom_ptr) {
unsigned mesgno; /* Current message to operate on */
size_t mesg_size; /* Size of message read in */
unsigned id; /* ID (type) of current message */
@@ -368,8 +381,10 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
if(oh->version == H5O_VERSION_1)
p += 3; /*reserved*/
- /* Try to detect invalidly formatted object header messages */
- if(p + mesg_size > oh->chunk[chunkno].image + (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM_OH(oh)))
+ /* Try to detect invalidly formatted object header message that
+ * extends past end of chunk.
+ */
+ if(p + mesg_size > eom_ptr)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "corrupt object header")
/* Skip header messages we don't know about */
@@ -377,42 +392,58 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
if(id >= NELMTS(H5O_msg_class_g) || NULL == H5O_msg_class_g[id]) {
/* Increment skipped messages counter */
skipped_msgs++;
-
- /* Advance decode pointer past message */
- p += mesg_size;
-
- /* Go get next message */
- continue;
} /* end if */
-
- /* Check for combining two adjacent 'null' messages */
- if((H5F_get_intent(f) & H5F_ACC_RDWR) &&
- H5O_NULL_ID == id && oh->nmesgs > 0 &&
- H5O_NULL_ID == oh->mesg[oh->nmesgs - 1].type->id &&
- oh->mesg[oh->nmesgs - 1].chunkno == chunkno) {
-
- /* Combine adjacent null messages */
- mesgno = oh->nmesgs - 1;
- oh->mesg[mesgno].raw_size += H5O_SIZEOF_MSGHDR_OH(oh) + mesg_size;
- oh->mesg[mesgno].dirty = TRUE;
- merged_null_msgs++;
- } /* end if */
else {
- /* New message */
- if(oh->nmesgs >= nmesgs)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "corrupt object header - too many messages")
- mesgno = oh->nmesgs++;
- oh->mesg[mesgno].type = H5O_msg_class_g[id];
- oh->mesg[mesgno].dirty = FALSE;
- oh->mesg[mesgno].flags = flags;
- oh->mesg[mesgno].native = NULL;
- oh->mesg[mesgno].raw = p;
- oh->mesg[mesgno].raw_size = mesg_size;
- oh->mesg[mesgno].chunkno = chunkno;
- } /* end else */
+#ifndef NDEBUG
+ /* Increment count of null messages */
+ if(H5O_NULL_ID == id)
+ nullcnt++;
+#endif /* NDEBUG */
+
+ /* Check for combining two adjacent 'null' messages */
+ if((H5F_get_intent(f) & H5F_ACC_RDWR) &&
+ H5O_NULL_ID == id && oh->nmesgs > 0 &&
+ H5O_NULL_ID == oh->mesg[oh->nmesgs - 1].type->id &&
+ oh->mesg[oh->nmesgs - 1].chunkno == chunkno) {
+
+ /* Combine adjacent null messages */
+ mesgno = oh->nmesgs - 1;
+ oh->mesg[mesgno].raw_size += H5O_SIZEOF_MSGHDR_OH(oh) + mesg_size;
+ oh->mesg[mesgno].dirty = TRUE;
+ merged_null_msgs++;
+ } /* end if */
+ else {
+ /* New message */
+ if(oh->nmesgs >= nmesgs)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "corrupt object header - too many messages")
+ mesgno = oh->nmesgs++;
+ oh->mesg[mesgno].type = H5O_msg_class_g[id];
+ oh->mesg[mesgno].dirty = FALSE;
+ oh->mesg[mesgno].flags = flags;
+ oh->mesg[mesgno].native = NULL;
+ oh->mesg[mesgno].raw = p;
+ oh->mesg[mesgno].raw_size = mesg_size;
+ oh->mesg[mesgno].chunkno = chunkno;
+ } /* end else */
+ } /* end else */
/* Advance decode pointer past message */
p += mesg_size;
+
+ /* Check for 'gap' at end of chunk */
+ if((eom_ptr - p) > 0 && (eom_ptr - p) < H5O_SIZEOF_MSGHDR_OH(oh)) {
+ /* Gaps can only occur in later versions of the format */
+ HDassert(oh->version > H5O_VERSION_1);
+
+ /* Gaps should only occur in chunks with no null messages */
+ HDassert(nullcnt == 0);
+
+ /* Set gap information for chunk */
+ oh->chunk[chunkno].gap = (eom_ptr - p);
+
+ /* Increment location in chunk */
+ p += oh->chunk[chunkno].gap;
+ } /* end if */
} /* end while */
/* Check for correct checksum on chunks, in later versions of the format */
@@ -423,11 +454,8 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
/* Metadata checksum */
UINT32DECODE(p, stored_chksum);
- /* Compute checksum on entire header */
- if(chunkno == 0)
- computed_chksum = H5_checksum_metadata(oh->chunk[chunkno].image + prefix_size, chunk_size, prefix_chksum);
- else
- computed_chksum = H5_checksum_metadata(oh->chunk[chunkno].image, (chunk_size - H5O_SIZEOF_CHKSUM), 0);
+ /* Compute checksum on chunk */
+ computed_chksum = H5_checksum_metadata(oh->chunk[chunkno].image, (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM), 0);
/* Verify checksum */
if(stored_chksum != computed_chksum)
@@ -509,10 +537,6 @@ H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t UNUSED addr, H5O_t *
uint8_t *p; /* Pointer to object header prefix buffer */
unsigned u; /* Local index variable */
- /* Encode any dirty messages */
- if(H5O_flush_msgs(f, oh) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to flush object header messages")
-
/* Point to raw data 'image' for first chunk, which has room for the prefix */
p = oh->chunk[0].image;
@@ -521,13 +545,8 @@ H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t UNUSED addr, H5O_t *
* on the entire block of memory needs to be updated if anything is
* modified */
if(oh->version > H5O_VERSION_1) {
- size_t prefix_size; /* Length of object header prefix */
- uint32_t prefix_chksum; /* Prefix checksum value */
- uint32_t full_chksum; /* Full checksum value */
- size_t raw_size; /* Size of raw data in first chunk */
-
/* Verify magic number */
- HDassert(!HDmemcmp(oh->chunk[u].image, H5O_HDR_MAGIC, H5O_SIZEOF_MAGIC));
+ HDassert(!HDmemcmp(oh->chunk[0].image, H5O_HDR_MAGIC, H5O_SIZEOF_MAGIC));
p += H5O_SIZEOF_MAGIC;
/* Version */
@@ -541,24 +560,6 @@ H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t UNUSED addr, H5O_t *
/* Chunk size */
UINT32ENCODE(p, (oh->chunk[0].size - H5O_SIZEOF_HDR_OH(oh)));
-
- /* Determine object header prefix length */
- prefix_size = (size_t)(p - oh->chunk[0].image);
-
- /* Compute partial checksum for later */
- /* (checksum performed in this odd way in order to accomodate
- * reading in the header & first chunk in reasonable way)
- */
- prefix_chksum = H5_checksum_lookup3(oh->chunk[0].image, prefix_size, 0);
-
- /* Finish full checksum, over chunk data */
- raw_size = oh->chunk[0].size - H5O_SIZEOF_HDR_OH(oh);
- full_chksum = H5_checksum_metadata(p, raw_size, prefix_chksum);
- p += raw_size;
-
- /* Metadata checksum */
- UINT32ENCODE(p, full_chksum);
- HDassert((size_t)(p - oh->chunk[0].image) == oh->chunk[0].size);
} /* end if */
else {
/* Version */
@@ -578,26 +579,42 @@ H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t UNUSED addr, H5O_t *
/* Zero to alignment */
HDmemset(p, 0, (size_t)(H5O_SIZEOF_HDR_OH(oh) - 12));
+ p += (size_t)(H5O_SIZEOF_HDR_OH(oh) - 12);
} /* end else */
+ HDassert((size_t)(p - oh->chunk[0].image) == (size_t)(H5O_SIZEOF_HDR_OH(oh) - H5O_SIZEOF_CHKSUM_OH(oh)));
/* Mark chunk 0 as dirty, since the object header prefix has been updated */
/* (this could be more sophisticated and track whether any prefix fields
- * have been changed, which could save I/O accesses - QAK)
+ * have been changed, which could save I/O accesses if the
+ * messages in chunk 0 haven't changed - QAK)
*/
HDassert(H5F_addr_eq(addr, oh->chunk[0].addr));
oh->chunk[0].dirty = TRUE;
+ /* Encode any dirty messages */
+ if(H5O_flush_msgs(f, oh) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to flush object header messages")
+
/* Write each chunk to disk, if it's dirty */
for(u = 0; u < oh->nchunks; u++) {
- /* Sanity check - make certain the magic # is present */
+ /* Sanity checks */
if(oh->version > H5O_VERSION_1)
+ /* Make certain the magic # is present */
HDassert(!HDmemcmp(oh->chunk[u].image, (u == 0 ? H5O_HDR_MAGIC : H5O_CHK_MAGIC), H5O_SIZEOF_MAGIC));
+ else
+ /* Gaps should never occur in version 1 of the format */
+ HDassert(oh->chunk[u].gap == 0);
/* Write out chunk, if it's dirty */
if(oh->chunk[u].dirty) {
- /* Compute checksum, for chunks > 0 & later versions of format */
- if(u > 0 && oh->version > H5O_VERSION_1) {
- uint32_t metadata_chksum; /* Computed metadata checksum value */
+ /* Extra work, for later versions of the format */
+ if(oh->version > H5O_VERSION_1) {
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+
+ /* Check for gap in chunk & zero it out */
+ if(oh->chunk[u].gap)
+ HDmemset((oh->chunk[u].image + oh->chunk[u].size) -
+ (H5O_SIZEOF_CHKSUM + oh->chunk[u].gap), 0, oh->chunk[u].gap);
/* Compute metadata checksum */
metadata_chksum = H5_checksum_metadata(oh->chunk[u].image, (oh->chunk[u].size - H5O_SIZEOF_CHKSUM), 0);
@@ -704,28 +721,28 @@ H5O_clear(H5F_t *f, H5O_t *oh, hbool_t destroy)
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI_NOINIT(H5O_clear);
+ FUNC_ENTER_NOAPI_NOINIT(H5O_clear)
/* check args */
- assert(oh);
+ HDassert(oh);
/* Mark chunks as clean */
- for (u = 0; u < oh->nchunks; u++)
- oh->chunk[u].dirty=FALSE;
+ for(u = 0; u < oh->nchunks; u++)
+ oh->chunk[u].dirty = FALSE;
/* Mark messages as clean */
- for (u = 0; u < oh->nmesgs; u++)
- oh->mesg[u].dirty=FALSE;
+ for(u = 0; u < oh->nmesgs; u++)
+ oh->mesg[u].dirty = FALSE;
/* Mark whole header as clean */
- oh->cache_info.is_dirty=FALSE;
+ oh->cache_info.is_dirty = FALSE;
- if (destroy)
- if (H5O_dest(f, oh) < 0)
+ if(destroy)
+ if(H5O_dest(f, oh) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header data")
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_clear() */
@@ -755,11 +772,9 @@ H5O_size(const H5F_t UNUSED *f, const H5O_t *oh, size_t *size_ptr)
HDassert(oh);
HDassert(size_ptr);
- /* Size of object header "prefix" */
- size = H5O_SIZEOF_HDR_OH(oh);
-
/* Add sizes of all the chunks */
- for(u = 0; u < oh->nchunks; u++)
+ /* (includes size of prefix, in chunk 0) */
+ for(u = 0, size = 0; u < oh->nchunks; u++)
size += oh->chunk[u].size;
*size_ptr = size;
diff --git a/src/H5Ocont.c b/src/H5Ocont.c
index 4d84b1c..b0966d3 100644
--- a/src/H5Ocont.c
+++ b/src/H5Ocont.c
@@ -94,25 +94,27 @@ H5O_cont_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *p)
H5O_cont_t *cont = NULL;
void *ret_value;
- FUNC_ENTER_NOAPI_NOINIT(H5O_cont_decode);
+ FUNC_ENTER_NOAPI_NOINIT(H5O_cont_decode)
/* check args */
- assert(f);
- assert(p);
+ HDassert(f);
+ HDassert(p);
- /* decode */
- if (NULL==(cont = H5FL_MALLOC(H5O_cont_t)))
+ /* Allocate space for the message */
+ if(NULL == (cont = H5FL_MALLOC(H5O_cont_t)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
+
+ /* Decode */
H5F_addr_decode(f, &p, &(cont->addr));
H5F_DECODE_LENGTH(f, p, cont->size);
- cont->chunkno=0;
+ cont->chunkno = 0;
/* Set return value */
- ret_value=cont;
+ ret_value = cont;
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_cont_decode() */
/*-------------------------------------------------------------------------
@@ -264,7 +266,7 @@ static void *
H5O_cont_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 *udata)
{
- H5O_cont_t *cont_src = (H5O_cont_t *) mesg_src;
+ H5O_cont_t *cont_src = (H5O_cont_t *)mesg_src;
H5O_chunk_t *chunk = (H5O_chunk_t *)udata;
H5O_cont_t *cont_dst = NULL;
void *ret_value; /* Return value */
@@ -273,13 +275,15 @@ H5O_cont_copy_file(H5F_t UNUSED *file_src, void *mesg_src, H5F_t UNUSED *file_ds
/* check args */
HDassert(cont_src);
- HDassert(file_dst);
/* Allocate space for the destination cont */
if(NULL == (cont_dst = H5FL_MALLOC(H5O_cont_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- HDmemcpy(cont_dst, cont_src, sizeof(H5O_cont_t));
+ /* Shallow copy all the fields */
+ *cont_dst = *cont_src;
+
+ /* Update the destination address to point to correct address in dest. file */
cont_dst->addr = chunk[cont_src->chunkno].addr;
/* Set return value */
diff --git a/src/H5Opkg.h b/src/H5Opkg.h
index 4886153..2b52b79 100644
--- a/src/H5Opkg.h
+++ b/src/H5Opkg.h
@@ -107,7 +107,8 @@
3) /*reserved */ \
: \
(2 + /*message type */ \
- 2) /*sizeof message data */ \
+ 2 + /*sizeof message data */ \
+ 1) /*flags */ \
)
#define H5O_SIZEOF_MSGHDR_OH(O) \
H5O_SIZEOF_MSGHDR_VERS((O)->version)
@@ -174,6 +175,7 @@ typedef struct H5O_chunk_t {
hbool_t dirty; /*dirty flag */
haddr_t addr; /*chunk file address */
size_t size; /*chunk size */
+ size_t gap; /*space at end of chunk too small for null message */
uint8_t *image; /*image of file */
} H5O_chunk_t;