summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/H5Oalloc.c859
-rw-r--r--src/H5Ocache.c289
-rw-r--r--src/H5Ochunk.c58
-rw-r--r--src/H5Omessage.c173
-rw-r--r--src/H5Opkg.h20
-rw-r--r--src/H5Oprivate.h3
-rw-r--r--test/ohdr.c142
7 files changed, 727 insertions, 817 deletions
diff --git a/src/H5Oalloc.c b/src/H5Oalloc.c
index 33d2e9d..d22fd92 100644
--- a/src/H5Oalloc.c
+++ b/src/H5Oalloc.c
@@ -67,8 +67,11 @@ static herr_t H5O_alloc_null(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t null_idx
const H5O_msg_class_t *new_type, void *new_native, size_t new_size);
static htri_t H5O_alloc_extend_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
unsigned chunkno, size_t size, size_t *msg_idx);
+static herr_t H5O__alloc_find_best_nonnull(const H5F_t *f, const H5O_t *oh, size_t *size,
+ H5O_msg_alloc_info_t *found_msg);
static herr_t H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size,
size_t *new_idx);
+static herr_t H5O__alloc_find_best_null(const H5O_t *oh, size_t size, size_t *mesg_idx);
static htri_t H5O_move_cont(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned cont_u);
static htri_t H5O_move_msgs_forward(H5F_t *f, hid_t dxpl_id, H5O_t *oh);
static htri_t H5O_merge_null(H5F_t *f, hid_t dxpl_id, H5O_t *oh);
@@ -707,17 +710,10 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5O_alloc_new_chunk
+ * Function: H5O__alloc_find_best_nonnull
*
- * Purpose: Allocates a new chunk for the object header, including
- * file space.
- *
- * One of the other chunks will get an object continuation
- * message. If there isn't room in any other chunk for the
- * object continuation message, then some message from
- * another chunk is moved into this chunk to make room.
- *
- * SIZE need not be aligned.
+ * Purpose: Find the best fit non-null message for a given size of message
+ * to allocate.
*
* Note: The algorithm for finding a message to replace with a
* continuation message is still fairly limited. It's possible
@@ -735,50 +731,34 @@ done:
*
* Failure: Negative
*
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Aug 7 1997
+ * Programmer: Quincey Koziol
+ * koziol@lbl.gov
+ * Oct 21 2016
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size, size_t *new_idx)
+H5O__alloc_find_best_nonnull(const H5F_t *f, const H5O_t *oh, size_t *size,
+ H5O_msg_alloc_info_t *found_msg)
{
- /* Struct for storing information about "best" messages to allocate from */
- typedef struct {
- int msgno; /* Index in message array */
- size_t gap_size; /* Size of any "gap" in the chunk immediately after message */
- size_t null_size; /* Size of any null message in the chunk immediately after message */
- size_t total_size; /* Total size of "available" space around message */
- unsigned null_msgno; /* Message index of null message immediately after message */
- } alloc_info;
-
H5O_mesg_t *curr_msg; /* Pointer to current message to operate on */
- H5O_chunk_proxy_t *chk_proxy; /* Chunk that message is in */
- size_t cont_size; /*continuation message size */
- size_t multi_size = 0; /* Size of all the messages in the last chunk */
- int found_null = (-1); /* Best fit null message */
- alloc_info found_attr = {-1, 0, 0, 0, 0}; /* Best fit attribute message */
- alloc_info found_other = {-1, 0, 0, 0, 0}; /* Best fit other message */
- size_t idx; /* Message number */
- uint8_t *p = NULL; /*ptr into new chunk */
- H5O_cont_t *cont = NULL; /*native continuation message */
- unsigned chunkno; /* Chunk allocated */
- haddr_t new_chunk_addr;
+ size_t cont_size; /* Continuation message size */
+ size_t multi_size; /* Size of all the messages in the last chunk */
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /* check args */
+ /* Check args */
+ HDassert(f);
HDassert(oh);
- HDassert(size > 0);
- size = H5O_ALIGN_OH(oh, size);
+ HDassert(size);
+ HDassert(*size > 0);
+ HDassert(found_msg);
/*
- * Find the smallest null message that will hold an object
- * continuation message. Failing that, find the smallest message
- * that could be moved to make room for the continuation message.
+ * Find the smallest message that could be moved to make room for the
+ * continuation message.
*
* Don't ever move continuation message from one chunk to another.
*
@@ -787,23 +767,10 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size, size_t *new
*
*/
cont_size = H5O_ALIGN_OH(oh, (size_t)(H5F_SIZEOF_ADDR(f) + H5F_SIZEOF_SIZE(f)));
+ multi_size = 0;
for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) {
- if(curr_msg->type->id == H5O_NULL_ID) {
- if(cont_size == curr_msg->raw_size) {
- found_null = (int)u;
- break;
- } /* end if */
- else if(curr_msg->raw_size > cont_size &&
- (found_null < 0 || curr_msg->raw_size < oh->mesg[found_null].raw_size))
- found_null = (int)u;
- } /* end if */
- else if(curr_msg->type->id == H5O_CONT_ID) {
- /* Don't consider continuation messages (for now) */
- } /* end if */
- else if(curr_msg->locked) {
- /* Don't consider locked messages */
- } /* end if */
- else {
+ /* Don't consider continuation messages (for now) */
+ if(H5O_CONT_ID != curr_msg->type->id) {
unsigned msg_chunkno = curr_msg->chunkno; /* Chunk that the message is in */
uint8_t *end_chunk_data = (oh->chunk[msg_chunkno].image + oh->chunk[msg_chunkno].size) - (H5O_SIZEOF_CHKSUM_OH(oh) + oh->chunk[msg_chunkno].gap); /* End of message data in chunk */
uint8_t *end_msg = curr_msg->raw + curr_msg->raw_size; /* End of current message */
@@ -837,34 +804,51 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size, size_t *new
/* Check if message is large enough to hold continuation info */
if(total_size >= cont_size) {
- if(curr_msg->type->id == H5O_ATTR_ID) {
- if(found_attr.msgno < 0 || total_size < found_attr.total_size) {
- found_attr.msgno = (int)u;
- found_attr.gap_size = gap_size;
- found_attr.null_size = null_size;
- found_attr.total_size = total_size;
- found_attr.null_msgno = null_msgno;
- } /* end if */
- } /* end if */
+ hbool_t better = FALSE; /* Whether the current message is better than a previous one */
+
+ /* Check for first message that can be moved */
+ if(found_msg->msgno < 0)
+ better = TRUE;
else {
- if(found_other.msgno < 0 || total_size < found_other.total_size) {
- found_other.msgno = (int)u;
- found_other.gap_size = gap_size;
- found_other.null_size = null_size;
- found_other.total_size = total_size;
- found_other.null_msgno = null_msgno;
- } /* end if */
+ /* Prioritize moving non-attributes above attributes */
+ /* (Even attributes with an otherwise better fit */
+ if(found_msg->id == H5O_ATTR_ID && curr_msg->type->id != H5O_ATTR_ID)
+ better = TRUE;
+ /* Either two attributes, or two non-attributes */
+ else {
+ /* Take a smaller one */
+ if(total_size < found_msg->total_size)
+ better = TRUE;
+ /* If they are the same size, choose the earliest one
+ * in the chunk array */
+ /* (Could also bias toward message earlier / later
+ * chunk in, but shouldn't be a big deal - QAK, 2016/10/21)
+ */
+ else if(total_size == found_msg->total_size) {
+ if(msg_chunkno < found_msg->chunkno)
+ better = TRUE;
+ } /* end else-if */
+ } /* end else */
} /* end else */
+
+ /* If we found a better message, keep its info */
+ if(better) {
+ found_msg->msgno = (int)u;
+ found_msg->id = curr_msg->type->id;
+ found_msg->chunkno = msg_chunkno;
+ found_msg->gap_size = gap_size;
+ found_msg->null_size = null_size;
+ found_msg->total_size = total_size;
+ found_msg->null_msgno = null_msgno;
+ } /* end if */
} /* end if */
- else if(found_null < 0 && found_attr.msgno < 0 && found_other.msgno < 0 && msg_chunkno == oh->nchunks - 1)
+ else if(found_msg->msgno < 0 && msg_chunkno == oh->nchunks - 1)
/* Keep track of the total size of smaller messages in the last
* chunk, in case we need to move more than 1 message.
*/
multi_size += curr_msg->raw_size + (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
- } /* end else */
+ } /* end if */
} /* end for */
- if(found_null >= 0 || found_attr.msgno >= 0 || found_other.msgno >= 0)
- multi_size = 0;
/*
* If we must move some other message to make room for the null
@@ -876,17 +860,56 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size, size_t *new
* If all else fails, move every message in the last chunk.
*
*/
- if(multi_size == 0) {
- if(found_null < 0) {
- if(found_other.msgno < 0)
- found_other = found_attr;
-
- HDassert(found_other.msgno >= 0);
- size += (size_t)H5O_SIZEOF_MSGHDR_OH(oh) + oh->mesg[found_other.msgno].raw_size;
- } /* end if */
- } /* end if */
+ if(found_msg->msgno < 0)
+ *size += multi_size;
else
- size += multi_size;
+ *size += (size_t)H5O_SIZEOF_MSGHDR_OH(oh) + oh->mesg[found_msg->msgno].raw_size;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5O__alloc_find_best_nonnull() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O__alloc_chunk
+ *
+ * Purpose: Allocates and initializes a new chunk for the object header,
+ * including file space.
+ *
+ * Return: Success: SUCCEED, with chunk number for the
+ * new chunk and a pointer to the location in its
+ * image where the first message should be placed.
+ *
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@lbl.gov
+ * Oct 21 2016
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O__alloc_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size,
+ size_t found_null, const H5O_msg_alloc_info_t *found_msg, size_t *new_idx)
+{
+ H5O_mesg_t *curr_msg; /* Pointer to current message to operate on */
+ H5O_chunk_proxy_t *chk_proxy; /* Chunk that message is in */
+ size_t cont_size; /*continuation message size */
+ size_t idx; /* Message number */
+ uint8_t *p = NULL; /* Pointer into new chunk image */
+ H5O_cont_t *cont = NULL; /*native continuation message */
+ unsigned chunkno; /* Chunk allocated */
+ haddr_t new_chunk_addr; /* Address of new chunk in file */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* check args */
+ HDassert(f);
+ HDassert(oh);
+ HDassert(found_msg);
+ HDassert(new_idx);
/*
* The total chunk size must include the requested space plus enough
@@ -944,133 +967,136 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size, size_t *new
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate more space for messages")
/* Check if we need to move multiple messages, in order to make room for the new message */
- if(multi_size > 0) {
- /* Move all non-null messages in the last chunk to the new chunk. This
- * should be extremely rare so we don't care too much about minimizing
- * the space used.
- */
- H5O_mesg_t *null_msg; /* Pointer to new null message */
-
- /* Protect last chunk */
- if(NULL == (chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, chunkno - 1)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
-
- /* Copy each message to the new location */
- for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++)
- if(curr_msg->chunkno == chunkno - 1) {
- if(curr_msg->type->id == H5O_NULL_ID) {
- /* Delete the null message */
- if(u < oh->nmesgs - 1)
- HDmemmove(curr_msg, curr_msg + 1, ((oh->nmesgs - 1) - u) * sizeof(H5O_mesg_t));
- oh->nmesgs--;
+ cont_size = H5O_ALIGN_OH(oh, (size_t)(H5F_SIZEOF_ADDR(f) + H5F_SIZEOF_SIZE(f)));
+ if(found_null >= oh->nmesgs) {
+ if(found_msg->msgno < 0) {
+ /* Move all non-null messages in the last chunk to the new chunk. This
+ * should be extremely rare so we don't care too much about minimizing
+ * the space used.
+ */
+ H5O_mesg_t *null_msg; /* Pointer to new null message */
+
+ /* Protect last chunk */
+ if(NULL == (chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, chunkno - 1)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
+
+ /* Copy each message to the new location */
+ for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++)
+ if(curr_msg->chunkno == chunkno - 1) {
+ if(curr_msg->type->id == H5O_NULL_ID) {
+ /* Delete the null message */
+ if(u < oh->nmesgs - 1)
+ HDmemmove(curr_msg, curr_msg + 1, ((oh->nmesgs - 1) - u) * sizeof(H5O_mesg_t));
+ oh->nmesgs--;
+ } /* end if */
+ else {
+ HDassert(curr_msg->type->id != H5O_CONT_ID);
+
+ /* Copy the raw data */
+ HDmemcpy(p, curr_msg->raw - (size_t)H5O_SIZEOF_MSGHDR_OH(oh),
+ curr_msg->raw_size + (size_t)H5O_SIZEOF_MSGHDR_OH(oh));
+
+ /* Update the message info */
+ curr_msg->chunkno = chunkno;
+ curr_msg->raw = p + H5O_SIZEOF_MSGHDR_OH(oh);
+
+ /* Account for copied message in new chunk */
+ p += (size_t)H5O_SIZEOF_MSGHDR_OH(oh) + curr_msg->raw_size;
+ size -= (size_t)H5O_SIZEOF_MSGHDR_OH(oh) + curr_msg->raw_size;
+ } /* end else */
} /* end if */
- else {
- HDassert(curr_msg->type->id != H5O_CONT_ID);
- /* Copy the raw data */
- HDmemcpy(p, curr_msg->raw - (size_t)H5O_SIZEOF_MSGHDR_OH(oh),
- curr_msg->raw_size + (size_t)H5O_SIZEOF_MSGHDR_OH(oh));
+ /* Create a null message spanning the entire last chunk */
+ found_null = oh->nmesgs++;
+ null_msg = &(oh->mesg[found_null]);
+ null_msg->type = H5O_MSG_NULL;
+ null_msg->dirty = TRUE;
+ null_msg->native = NULL;
+ null_msg->raw = oh->chunk[chunkno - 1].image
+ + ((chunkno == 1) ? H5O_SIZEOF_HDR(oh) : H5O_SIZEOF_CHKHDR_OH(oh))
+ - H5O_SIZEOF_CHKSUM_OH(oh) + H5O_SIZEOF_MSGHDR_OH(oh);
+ null_msg->raw_size = oh->chunk[chunkno - 1].size
+ - ((chunkno == 1) ? (size_t)H5O_SIZEOF_HDR(oh) : (size_t)H5O_SIZEOF_CHKHDR_OH(oh))
+ - (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
+ null_msg->chunkno = chunkno - 1;
- /* Update the message info */
- curr_msg->chunkno = chunkno;
- curr_msg->raw = p + H5O_SIZEOF_MSGHDR_OH(oh);
+ HDassert(null_msg->raw_size >= cont_size);
- /* Account for copied message in new chunk */
- p += (size_t)H5O_SIZEOF_MSGHDR_OH(oh) + curr_msg->raw_size;
- size -= (size_t)H5O_SIZEOF_MSGHDR_OH(oh) + curr_msg->raw_size;
- } /* end else */
- } /* end if */
+ /* Remove any gap in the chunk */
+ oh->chunk[chunkno - 1].gap = 0;
- /* Create a null message spanning the entire last chunk */
- found_null = (int)oh->nmesgs++;
- null_msg = &(oh->mesg[found_null]);
- null_msg->type = H5O_MSG_NULL;
- null_msg->dirty = TRUE;
- null_msg->native = NULL;
- null_msg->raw = oh->chunk[chunkno - 1].image
- + ((chunkno == 1) ? H5O_SIZEOF_HDR(oh) : H5O_SIZEOF_CHKHDR_OH(oh))
- - H5O_SIZEOF_CHKSUM_OH(oh) + H5O_SIZEOF_MSGHDR_OH(oh);
- null_msg->raw_size = oh->chunk[chunkno - 1].size
- - ((chunkno == 1) ? (size_t)H5O_SIZEOF_HDR(oh) : (size_t)H5O_SIZEOF_CHKHDR_OH(oh))
- - (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
- null_msg->chunkno = chunkno - 1;
-
- HDassert(null_msg->raw_size >= cont_size);
-
- /* Remove any gap in the chunk */
- oh->chunk[chunkno - 1].gap = 0;
-
- /* Release chunk, marking it dirty */
- if(H5O_chunk_unprotect(f, dxpl_id, chk_proxy, TRUE) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
- } else if(found_null < 0) {
- /* Move message (that will be replaced with continuation message)
- * to new chunk, if necessary.
- */
- H5O_mesg_t *null_msg; /* Pointer to new null message */
-
- /* Protect chunk */
- if(NULL == (chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, oh->mesg[found_other.msgno].chunkno)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
-
- /* Create null message for space that message to copy currently occupies */
- found_null = (int)oh->nmesgs++;
- null_msg = &(oh->mesg[found_null]);
- null_msg->type = H5O_MSG_NULL;
- null_msg->native = NULL;
- null_msg->raw = oh->mesg[found_other.msgno].raw;
- null_msg->raw_size = oh->mesg[found_other.msgno].raw_size;
- null_msg->chunkno = oh->mesg[found_other.msgno].chunkno;
-
- /* Copy the message to move (& its prefix) to its new location */
- HDmemcpy(p, oh->mesg[found_other.msgno].raw - H5O_SIZEOF_MSGHDR_OH(oh),
- oh->mesg[found_other.msgno].raw_size + (size_t)H5O_SIZEOF_MSGHDR_OH(oh));
-
- /* Switch moved message to point to new location */
- oh->mesg[found_other.msgno].raw = p + H5O_SIZEOF_MSGHDR_OH(oh);
- oh->mesg[found_other.msgno].chunkno = chunkno;
-
- /* Account for copied message in new chunk */
- p += (size_t)H5O_SIZEOF_MSGHDR_OH(oh) + oh->mesg[found_other.msgno].raw_size;
- size -= (size_t)H5O_SIZEOF_MSGHDR_OH(oh) + oh->mesg[found_other.msgno].raw_size;
-
- /* Add any available space after the message to move to the new null message */
- if(found_other.gap_size > 0) {
- /* Absorb a gap after the moved message */
- HDassert(oh->chunk[null_msg->chunkno].gap == found_other.gap_size);
- null_msg->raw_size += found_other.gap_size;
- oh->chunk[null_msg->chunkno].gap = 0;
+ /* Release chunk, marking it dirty */
+ if(H5O_chunk_unprotect(f, dxpl_id, chk_proxy, TRUE) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
} /* end if */
- else if(found_other.null_size > 0) {
- H5O_mesg_t *old_null_msg = &oh->mesg[found_other.null_msgno]; /* Pointer to NULL message to eliminate */
+ else {
+ /* Move message (that will be replaced with continuation message)
+ * to new chunk, if necessary.
+ */
+ H5O_mesg_t *null_msg; /* Pointer to new null message */
+
+ /* Protect chunk */
+ if(NULL == (chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, oh->mesg[found_msg->msgno].chunkno)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
- /* Absorb a null message after the moved message */
- HDassert((null_msg->raw + null_msg->raw_size) == (old_null_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh)));
- null_msg->raw_size += found_other.null_size;
+ /* Create null message for space that message to copy currently occupies */
+ found_null = oh->nmesgs++;
+ null_msg = &(oh->mesg[found_null]);
+ null_msg->type = H5O_MSG_NULL;
+ null_msg->native = NULL;
+ null_msg->raw = oh->mesg[found_msg->msgno].raw;
+ null_msg->raw_size = oh->mesg[found_msg->msgno].raw_size;
+ null_msg->chunkno = oh->mesg[found_msg->msgno].chunkno;
+
+ /* Copy the message to move (& its prefix) to its new location */
+ HDmemcpy(p, oh->mesg[found_msg->msgno].raw - H5O_SIZEOF_MSGHDR_OH(oh),
+ oh->mesg[found_msg->msgno].raw_size + (size_t)H5O_SIZEOF_MSGHDR_OH(oh));
+
+ /* Switch moved message to point to new location */
+ oh->mesg[found_msg->msgno].raw = p + H5O_SIZEOF_MSGHDR_OH(oh);
+ oh->mesg[found_msg->msgno].chunkno = chunkno;
+
+ /* Account for copied message in new chunk */
+ p += (size_t)H5O_SIZEOF_MSGHDR_OH(oh) + oh->mesg[found_msg->msgno].raw_size;
+ size -= (size_t)H5O_SIZEOF_MSGHDR_OH(oh) + oh->mesg[found_msg->msgno].raw_size;
+
+ /* Add any available space after the message to move to the new null message */
+ if(found_msg->gap_size > 0) {
+ /* Absorb a gap after the moved message */
+ HDassert(oh->chunk[null_msg->chunkno].gap == found_msg->gap_size);
+ null_msg->raw_size += found_msg->gap_size;
+ oh->chunk[null_msg->chunkno].gap = 0;
+ } /* end if */
+ else if(found_msg->null_size > 0) {
+ H5O_mesg_t *old_null_msg = &oh->mesg[found_msg->null_msgno]; /* Pointer to NULL message to eliminate */
- /* Release any information/memory for message */
- H5O_msg_free_mesg(old_null_msg);
+ /* Absorb a null message after the moved message */
+ HDassert((null_msg->raw + null_msg->raw_size) == (old_null_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh)));
+ null_msg->raw_size += found_msg->null_size;
- /* Remove null message from list of messages */
- if(found_other.null_msgno < (oh->nmesgs - 1))
- HDmemmove(old_null_msg, old_null_msg + 1, ((oh->nmesgs - 1) - found_other.null_msgno) * sizeof(H5O_mesg_t));
+ /* Release any information/memory for message */
+ H5O_msg_free_mesg(old_null_msg);
- /* Decrement # of messages */
- /* (Don't bother reducing size of message array for now -QAK) */
- oh->nmesgs--;
+ /* Remove null message from list of messages */
+ if(found_msg->null_msgno < (oh->nmesgs - 1))
+ HDmemmove(old_null_msg, old_null_msg + 1, ((oh->nmesgs - 1) - found_msg->null_msgno) * sizeof(H5O_mesg_t));
- /* Adjust message index for new NULL message */
- found_null--;
- } /* end if */
+ /* Decrement # of messages */
+ /* (Don't bother reducing size of message array for now -QAK) */
+ oh->nmesgs--;
+
+ /* Adjust message index for new NULL message */
+ found_null--;
+ } /* end if */
- /* Mark the new null message as dirty */
- null_msg->dirty = TRUE;
+ /* Mark the new null message as dirty */
+ null_msg->dirty = TRUE;
- /* Release chunk, marking it dirty */
- if(H5O_chunk_unprotect(f, dxpl_id, chk_proxy, TRUE) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
+ /* Release chunk, marking it dirty */
+ if(H5O_chunk_unprotect(f, dxpl_id, chk_proxy, TRUE) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
+ } /* end if */
} /* end if */
- HDassert(found_null >= 0);
/* Create null message for [rest of] space in new chunk */
/* (account for chunk's magic # & checksum) */
@@ -1083,7 +1109,7 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size, size_t *new
oh->mesg[idx].chunkno = chunkno;
/* Insert the new chunk into the cache */
- if(H5O_chunk_add(f, dxpl_id, oh, chunkno) < 0)
+ if(H5O_chunk_add(f, dxpl_id, oh, chunkno, oh->mesg[found_null].chunkno) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't add new chunk to cache")
/* Initialize the continuation information */
@@ -1094,7 +1120,7 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size, size_t *new
cont->chunkno = chunkno;
/* Split the null message and point at continuation message */
- if(H5O_alloc_null(f, dxpl_id, oh, (size_t)found_null, H5O_MSG_CONT, cont, cont_size) < 0)
+ if(H5O_alloc_null(f, dxpl_id, oh, found_null, H5O_MSG_CONT, cont, cont_size) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't split null message")
/* Set new message index value */
@@ -1102,10 +1128,162 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size, size_t *new
done:
FUNC_LEAVE_NOAPI(ret_value)
+} /* H5O__alloc_chunk() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_alloc_new_chunk
+ *
+ * Purpose: Allocates a new chunk for the object header, including
+ * file space.
+ *
+ * One of the other chunks will get an object continuation
+ * message. If there isn't room in any other chunk for the
+ * object continuation message, then some message from
+ * another chunk is moved into this chunk to make room.
+ *
+ * SIZE need not be aligned.
+ *
+ * Note: The algorithm for finding a message to replace with a
+ * continuation message is still fairly limited. It's possible
+ * that two (or more) messages smaller than a continuation message
+ * might occupy a chunk and need to be moved in order to make
+ * room for the continuation message.
+ *
+ * Also, we aren't checking for NULL messages in front of another
+ * message right now...
+ *
+ * Return: Success: Index number of the null message for the
+ * new chunk. The null message will be at
+ * least SIZE bytes not counting the message
+ * ID or size fields.
+ *
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Aug 7 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size, size_t *new_idx)
+{
+ size_t cont_size; /*continuation message size */
+ size_t idx; /* Message number */
+ H5O_msg_alloc_info_t found_msg; /* Best fit non-null message */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* check args */
+ HDassert(oh);
+ HDassert(size > 0);
+ size = H5O_ALIGN_OH(oh, size);
+
+ /* Find the smallest null message that could hold a continuation message */
+ idx = oh->nmesgs;
+ cont_size = H5O_ALIGN_OH(oh, (size_t)(H5F_SIZEOF_ADDR(f) + H5F_SIZEOF_SIZE(f)));
+ if(H5O__alloc_find_best_null(oh, cont_size, &idx) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "error while locating best null header message")
+
+ /* If we couldn't find a null message, locate the best message to move to new chunk */
+ if(idx >= oh->nmesgs) {
+ found_msg.msgno = -1;
+ if(H5O__alloc_find_best_nonnull(f, oh, &size, &found_msg) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "error while locating best non-null header message")
+ } /* end if */
+
+ /* Allocate and initialize new chunk in the file */
+ if(H5O__alloc_chunk(f, dxpl_id, oh, size, idx, &found_msg, new_idx) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, FAIL, "can't allocate new object header chunk")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_alloc_new_chunk() */
/*-------------------------------------------------------------------------
+ * Function: H5O__alloc_find_best_null
+ *
+ * Purpose: Find the best fit null message for a given size of message
+ * to allocate.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@lbl.gov
+ * Oct 21 2016
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O__alloc_find_best_null(const H5O_t *oh, size_t size, size_t *mesg_idx)
+{
+ size_t idx; /* Index of message which fits allocation */
+ int found_null; /* Best fit null message */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* check args */
+ HDassert(oh);
+ HDassert(size > 0);
+ HDassert(mesg_idx);
+
+ /* Find the smallest null message that could hold the new object header message */
+ found_null = -1;
+ for(idx = 0; idx < oh->nmesgs; idx++) {
+ if(H5O_NULL_ID == oh->mesg[idx].type->id) {
+ /* If we found an exact fit, use it */
+ if(oh->mesg[idx].raw_size == size) {
+ /* Keep first exact fit */
+ if(found_null < 0)
+ found_null = idx;
+ else
+ /* If we've got more than one exact fit, choose the one in the earliest chunk */
+ if(oh->mesg[idx].chunkno < oh->mesg[found_null].chunkno) {
+ found_null = idx;
+
+ /* If we found an exact fit in object header chunk #0, we can get out */
+ /* (Could extend this to look for earliest message in
+ * chunk #0 - QAK, 2016/10/21)
+ */
+ if(0 == oh->mesg[idx].chunkno)
+ break;
+ } /* end if */
+ } /* end if */
+ /* Look for null message that's larger than needed */
+ else if(oh->mesg[idx].raw_size > size) {
+ /* Keep first one found */
+ if(found_null < 0)
+ found_null = idx;
+ else
+ /* Check for better fit */
+ if(oh->mesg[idx].raw_size < oh->mesg[found_null].raw_size)
+ found_null = idx;
+ else {
+ /* If they are the same size, choose the one in the earliest chunk */
+ if(oh->mesg[idx].raw_size == oh->mesg[found_null].raw_size) {
+ if(oh->mesg[idx].chunkno < oh->mesg[found_null].chunkno)
+ found_null = idx;
+ } /* end if */
+ } /* end else */
+ } /* end else-if */
+ /* Ignore too-small null messages */
+ else
+ ;
+ } /* end if */
+ } /* end for */
+ if(found_null >= 0)
+ *mesg_idx = found_null;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5O__alloc_find_best_null() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5O_alloc
*
* Purpose: Allocate enough space in the object header for this message.
@@ -1143,10 +1321,10 @@ H5O_alloc(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *type,
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "object header message is too large")
aligned_size = H5O_ALIGN_OH(oh, raw_size);
- /* look for a null message which is large enough */
- for(idx = 0; idx < oh->nmesgs; idx++)
- if(H5O_NULL_ID == oh->mesg[idx].type->id && oh->mesg[idx].raw_size >= aligned_size)
- break;
+ /* Find the smallest null message that could hold the new object header message */
+ idx = oh->nmesgs;
+ if(H5O__alloc_find_best_null(oh, aligned_size, &idx) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "error while locating best null header message")
/* if we didn't find one, then allocate more header space */
if(idx >= oh->nmesgs) {
@@ -1307,12 +1485,6 @@ H5O_move_cont(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned cont_u)
nonnull_size = 0;
for(v = 0, curr_msg = &oh->mesg[0]; v < oh->nmesgs; v++, curr_msg++) {
if(curr_msg->chunkno == deleted_chunkno) {
- /* If there's a locked message, we can't move all messages out of
- * chunk to delete, so get out now.
- */
- if(curr_msg->locked)
- HGOTO_DONE(FALSE)
-
/* Find size of all non-null messages in the chunk pointed to by the continuation message */
if(curr_msg->type->id != H5O_NULL_ID) {
HDassert(curr_msg->type->id != H5O_CONT_ID);
@@ -1552,152 +1724,149 @@ H5O_move_msgs_forward(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
} /* end else-if */
} /* end if */
- /* Don't let locked messages be moved into earlier chunk */
- if(!curr_msg->locked) {
- /* Loop over messages again, looking for large enough null message in earlier chunk */
- for(v = 0, null_msg = &oh->mesg[0]; v < oh->nmesgs; v++, null_msg++) {
- if(H5O_NULL_ID == null_msg->type->id && curr_msg->chunkno > null_msg->chunkno
- && curr_msg->raw_size <= null_msg->raw_size) {
- unsigned old_chunkno; /* Old message information */
- uint8_t *old_raw;
-
- /* Keep old information about non-null message */
- old_chunkno = curr_msg->chunkno;
- old_raw = curr_msg->raw;
-
- /* Protect chunks */
- if(NULL == (null_chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, null_msg->chunkno)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
- if(NULL == (curr_chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, curr_msg->chunkno)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
+ /* Loop over messages again, looking for large enough null message in earlier chunk */
+ for(v = 0, null_msg = &oh->mesg[0]; v < oh->nmesgs; v++, null_msg++) {
+ if(H5O_NULL_ID == null_msg->type->id && curr_msg->chunkno > null_msg->chunkno
+ && curr_msg->raw_size <= null_msg->raw_size) {
+ unsigned old_chunkno; /* Old message information */
+ uint8_t *old_raw;
+
+ /* Keep old information about non-null message */
+ old_chunkno = curr_msg->chunkno;
+ old_raw = curr_msg->raw;
+
+ /* Protect chunks */
+ if(NULL == (null_chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, null_msg->chunkno)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
+ if(NULL == (curr_chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, curr_msg->chunkno)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
+
+ /* Copy raw data for non-null message to new chunk */
+ HDmemcpy(null_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh), curr_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh), curr_msg->raw_size + (size_t)H5O_SIZEOF_MSGHDR_OH(oh));
+
+ /* Point non-null message at null message's space */
+ curr_msg->chunkno = null_msg->chunkno;
+ curr_msg->raw = null_msg->raw;
+ curr_chk_dirtied = TRUE;
+
+ /* Change information for null message */
+ if(curr_msg->raw_size == null_msg->raw_size) {
+ /* Point null message at old non-null space */
+ /* (Instead of freeing it and allocating new message) */
+ null_msg->chunkno = old_chunkno;
+ null_msg->raw = old_raw;
+
+ /* Mark null message dirty */
+ null_msg->dirty = TRUE;
+ null_chk_dirtied = TRUE;
+
+ /* Release current chunk, marking it dirty */
+ if(H5O_chunk_unprotect(f, dxpl_id, curr_chk_proxy, curr_chk_dirtied) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
+ curr_chk_proxy = NULL;
+ curr_chk_dirtied = FALSE;
+
+ /* Check for gap in null message's chunk */
+ if(oh->chunk[old_chunkno].gap > 0) {
+ /* Eliminate the gap in the chunk */
+ if(H5O_eliminate_gap(oh, &null_chk_dirtied, 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 eliminate gap in chunk")
+ } /* end if */
- /* Copy raw data for non-null message to new chunk */
- HDmemcpy(null_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh), curr_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh), curr_msg->raw_size + (size_t)H5O_SIZEOF_MSGHDR_OH(oh));
+ /* Release null chunk, marking it dirty */
+ if(H5O_chunk_unprotect(f, dxpl_id, null_chk_proxy, null_chk_dirtied) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
+ null_chk_proxy = NULL;
+ null_chk_dirtied = FALSE;
+ } /* end if */
+ else {
+ size_t new_null_msg; /* Message index for new null message */
- /* Point non-null message at null message's space */
- curr_msg->chunkno = null_msg->chunkno;
- curr_msg->raw = null_msg->raw;
- curr_chk_dirtied = TRUE;
+ /* Check if null message is large enough to still exist */
+ if((null_msg->raw_size - curr_msg->raw_size) < (size_t)H5O_SIZEOF_MSGHDR_OH(oh)) {
+ size_t gap_size = null_msg->raw_size - curr_msg->raw_size; /* Size of gap produced */
- /* Change information for null message */
- if(curr_msg->raw_size == null_msg->raw_size) {
- /* Point null message at old non-null space */
- /* (Instead of freeing it and allocating new message) */
- null_msg->chunkno = old_chunkno;
- null_msg->raw = old_raw;
+ /* Adjust the size of the null message being eliminated */
+ null_msg->raw_size = curr_msg->raw_size;
/* Mark null message dirty */
null_msg->dirty = TRUE;
null_chk_dirtied = TRUE;
- /* Release current chunk, marking it dirty */
- if(H5O_chunk_unprotect(f, dxpl_id, curr_chk_proxy, curr_chk_dirtied) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
- curr_chk_proxy = NULL;
- curr_chk_dirtied = FALSE;
-
- /* Check for gap in null message's chunk */
- if(oh->chunk[old_chunkno].gap > 0) {
- /* Eliminate the gap in the chunk */
- if(H5O_eliminate_gap(oh, &null_chk_dirtied, 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 eliminate gap in chunk")
- } /* end if */
+ /* Add the gap to the chunk */
+ if(H5O_add_gap(f, oh, null_msg->chunkno, &null_chk_dirtied, v, null_msg->raw + null_msg->raw_size, gap_size) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert gap in chunk")
- /* Release null chunk, marking it dirty */
- if(H5O_chunk_unprotect(f, dxpl_id, null_chk_proxy, null_chk_dirtied) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
- null_chk_proxy = NULL;
- null_chk_dirtied = FALSE;
+ /* Re-use message # for new null message taking place of non-null message */
+ new_null_msg = v;
} /* end if */
else {
- size_t new_null_msg; /* Message index for new null message */
-
- /* Check if null message is large enough to still exist */
- if((null_msg->raw_size - curr_msg->raw_size) < (size_t)H5O_SIZEOF_MSGHDR_OH(oh)) {
- size_t gap_size = null_msg->raw_size - curr_msg->raw_size; /* Size of gap produced */
+ /* Adjust null message's size & offset */
+ null_msg->raw += curr_msg->raw_size + (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
+ null_msg->raw_size -= curr_msg->raw_size + (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
- /* Adjust the size of the null message being eliminated */
- null_msg->raw_size = curr_msg->raw_size;
-
- /* Mark null message dirty */
- null_msg->dirty = TRUE;
- null_chk_dirtied = TRUE;
+ /* Mark null message dirty */
+ null_msg->dirty = TRUE;
+ null_chk_dirtied = TRUE;
- /* Add the gap to the chunk */
- if(H5O_add_gap(f, oh, null_msg->chunkno, &null_chk_dirtied, v, null_msg->raw + null_msg->raw_size, gap_size) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert gap in chunk")
+ /* Create new null message for previous location of non-null message */
+ 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")
- /* Re-use message # for new null message taking place of non-null message */
- new_null_msg = v;
- } /* end if */
- else {
- /* Adjust null message's size & offset */
- null_msg->raw += curr_msg->raw_size + (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
- null_msg->raw_size -= curr_msg->raw_size + (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
-
- /* Mark null message dirty */
- null_msg->dirty = TRUE;
- null_chk_dirtied = TRUE;
-
- /* Create new null message for previous location of non-null message */
- 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")
-
- /* "Retarget" 'curr_msg' pointer into newly re-allocated array of messages */
- curr_msg = &oh->mesg[u];
- } /* end if */
-
- /* Get message # for new null message */
- new_null_msg = oh->nmesgs++;
- } /* end else */
-
- /* Release null message's chunk, marking it dirty */
- if(H5O_chunk_unprotect(f, dxpl_id, null_chk_proxy, null_chk_dirtied) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
- null_chk_proxy = NULL;
- null_chk_dirtied = FALSE;
-
- /* Initialize new null message to take over non-null message's location */
- oh->mesg[new_null_msg].type = H5O_MSG_NULL;
- oh->mesg[new_null_msg].native = NULL;
- oh->mesg[new_null_msg].raw = old_raw;
- oh->mesg[new_null_msg].raw_size = curr_msg->raw_size;
- oh->mesg[new_null_msg].chunkno = old_chunkno;
-
- /* Mark new null message dirty */
- oh->mesg[new_null_msg].dirty = TRUE;
- curr_chk_dirtied = TRUE;
-
- /* 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, &curr_chk_dirtied, &oh->mesg[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 eliminate gap in chunk")
+ /* "Retarget" 'curr_msg' pointer into newly re-allocated array of messages */
+ curr_msg = &oh->mesg[u];
} /* end if */
- /* Release new null message's chunk, marking it dirty */
- if(H5O_chunk_unprotect(f, dxpl_id, curr_chk_proxy, curr_chk_dirtied) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
- curr_chk_proxy = NULL;
- curr_chk_dirtied = FALSE;
+ /* Get message # for new null message */
+ new_null_msg = oh->nmesgs++;
} /* end else */
- /* Indicate that we packed messages */
- packed_msg = TRUE;
+ /* Release null message's chunk, marking it dirty */
+ if(H5O_chunk_unprotect(f, dxpl_id, null_chk_proxy, null_chk_dirtied) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
+ null_chk_proxy = NULL;
+ null_chk_dirtied = FALSE;
+
+ /* Initialize new null message to take over non-null message's location */
+ oh->mesg[new_null_msg].type = H5O_MSG_NULL;
+ oh->mesg[new_null_msg].native = NULL;
+ oh->mesg[new_null_msg].raw = old_raw;
+ oh->mesg[new_null_msg].raw_size = curr_msg->raw_size;
+ oh->mesg[new_null_msg].chunkno = old_chunkno;
+
+ /* Mark new null message dirty */
+ oh->mesg[new_null_msg].dirty = TRUE;
+ curr_chk_dirtied = TRUE;
- /* Break out of loop */
- /* (If it's possible to move message to even earlier chunk
- * we'll get it on the next pass - QAK)
- */
- break;
- } /* end if */
- } /* end for */
- } /* end if */
+ /* 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, &curr_chk_dirtied, &oh->mesg[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 eliminate gap in chunk")
+ } /* end if */
+
+ /* Release new null message's chunk, marking it dirty */
+ if(H5O_chunk_unprotect(f, dxpl_id, curr_chk_proxy, curr_chk_dirtied) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
+ curr_chk_proxy = NULL;
+ curr_chk_dirtied = FALSE;
+ } /* end else */
+
+ /* Indicate that we packed messages */
+ packed_msg = TRUE;
+
+ /* Break out of loop */
+ /* (If it's possible to move message to even earlier chunk
+ * we'll get it on the next pass - QAK)
+ */
+ break;
+ } /* end if */
+ } /* end for */
/* If we packed messages, get out of loop and start over */
/* (Don't know if this has any benefit one way or the other -QAK) */
@@ -1715,10 +1884,14 @@ H5O_move_msgs_forward(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
ret_value = (htri_t)did_packing;
done:
- if(null_chk_proxy && H5O_chunk_unprotect(f, dxpl_id, null_chk_proxy, null_chk_dirtied) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect null object header chunk")
- if(curr_chk_proxy && H5O_chunk_unprotect(f, dxpl_id, curr_chk_proxy, curr_chk_dirtied) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect current object header chunk")
+ if(ret_value < 0) {
+ if(null_chk_proxy && H5O_chunk_unprotect(f, dxpl_id, null_chk_proxy, null_chk_dirtied) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect null object header chunk")
+ if(curr_chk_proxy && H5O_chunk_unprotect(f, dxpl_id, curr_chk_proxy, curr_chk_dirtied) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect current object header chunk")
+ } /* end if */
+ else
+ HDassert(!null_chk_proxy && !curr_chk_proxy);
FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_move_msgs_forward() */
diff --git a/src/H5Ocache.c b/src/H5Ocache.c
index 0bb0bdf..f1a128d 100644
--- a/src/H5Ocache.c
+++ b/src/H5Ocache.c
@@ -88,9 +88,6 @@ static herr_t H5O__cache_chk_serialize(const H5F_t *f, void *image, size_t len,
static herr_t H5O__cache_chk_free_icr(void *thing);
static herr_t H5O__cache_chk_clear(const H5F_t *f, void *thing, hbool_t about_to_destroy);
-/* Chunk proxy routines */
-static herr_t H5O__chunk_proxy_dest(H5O_chunk_proxy_t *chunk_proxy);
-
/* Chunk routines */
static herr_t H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len,
const uint8_t *image, H5O_common_cache_ud_t *udata, hbool_t *dirty);
@@ -99,6 +96,7 @@ static herr_t H5O__chunk_serialize(const H5F_t *f, H5O_t *oh, unsigned chunkno);
/* Misc. routines */
static herr_t H5O__add_cont_msg(H5O_cont_msgs_t *cont_msg_info,
const H5O_cont_t *cont);
+static herr_t H5O_decode_prefix(H5F_t *f, H5O_t *oh, const uint8_t *buf, void *_udata);
/*********************/
@@ -160,99 +158,48 @@ H5FL_SEQ_DEFINE(H5O_cont_t);
/*-------------------------------------------------------------------------
- * Function: H5O__cache_get_load_size()
+ * Function: H5O_decode_prefix
*
- * Purpose: Tell the metadata cache how much data to read from file in
- * the first speculative read for the object header. Note that we do
- * not have to be concerned about reading past the end of file, as the
- * cache will clamp the read to avoid this if needed.
+ * Purpose: To decode the object header prefix.
+ * The coding is extracted fromt H5O__cache_deserialize() to this routine.
*
- * Return: Success: SUCCEED
- * Failure: FAIL
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: John Mainzer
- * 7/28/14
+ * Programmer: Vailin Choi; Aug 2015
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O__cache_get_load_size(const void H5_ATTR_UNUSED *_udata, size_t *image_len)
-{
- FUNC_ENTER_STATIC_NOERR
-
- /* Check arguments */
- HDassert(image_len);
-
- *image_len = H5O_SPEC_READ_SIZE;
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5O__cache_get_load_size() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5O__cache_deserialize
- *
- * Purpose: Attempt to deserialize the object header contained in the
- * supplied buffer, load the data into an instance of H5O_t, and
- * return a pointer to the new instance.
- *
- * Note that the object header is read with with a speculative read.
- * If the initial read is too small, make note of this fact and return
- * without error. H5C_load_entry() will note the size discrepency
- * and retry the deserialize operation with the correct size read.
- *
- * Return: Success: Pointer to in core representation
- * Failure: NULL
- *
- * Programmer: John Mainzer
- * 7/28/14
- *
- *-------------------------------------------------------------------------
- */
-static void *
-H5O__cache_deserialize(const void *_image, size_t len, void *_udata,
- hbool_t *dirty)
+H5O_decode_prefix(H5F_t *f, H5O_t *oh, const uint8_t *buf, void *_udata)
{
- H5O_t *oh = NULL; /* Object header read in */
- H5O_cache_ud_t *udata = (H5O_cache_ud_t *)_udata; /* User data for callback */
- const uint8_t *image = (const uint8_t *)_image; /* Pointer into buffer to decode */
- size_t prefix_size; /* Size of object header prefix */
- size_t buf_size; /* Size of prefix+chunk #0 buffer */
- void * ret_value = NULL; /* Return value */
+ H5O_cache_ud_t *udata = (H5O_cache_ud_t *)_udata; /* User data for callback */
+ const uint8_t *p = buf; /* Pointer into buffer to decode */
+ size_t prefix_size; /* Size of object header prefix */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_STATIC
+ FUNC_ENTER_NOAPI_NOINIT
/* Check arguments */
- HDassert(image);
- HDassert(len > 0);
+ HDassert(f);
+ HDassert(oh);
+ HDassert(buf);
HDassert(udata);
- HDassert(udata->common.f);
- HDassert(udata->common.cont_msg_info);
- HDassert(dirty);
-
- /* Allocate space for the object header data structure */
- if(NULL == (oh = H5FL_CALLOC(H5O_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- /* File-specific, non-stored information */
- oh->sizeof_size = H5F_SIZEOF_SIZE(udata->common.f);
- oh->sizeof_addr = H5F_SIZEOF_ADDR(udata->common.f);
/* Check for presence of magic number */
/* (indicates version 2 or later) */
- if(!HDmemcmp(image, H5O_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC)) {
+ if(!HDmemcmp(p, H5O_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC)) {
/* Magic number */
- image += H5_SIZEOF_MAGIC;
+ p += H5_SIZEOF_MAGIC;
/* Version */
- oh->version = *image++;
- if(H5O_VERSION_2 != oh->version)
- HGOTO_ERROR(H5E_OHDR, H5E_VERSION, NULL, "bad object header version number")
+ oh->version = *p++;
+ if(H5O_VERSION_2 != oh->version)
+ HGOTO_ERROR(H5E_OHDR, H5E_VERSION, FAIL, "bad object header version number")
/* Flags */
- oh->flags = *image++;
- if(oh->flags & ~H5O_HDR_ALL_FLAGS)
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "unknown object header status flag(s)")
+ oh->flags = *p++;
+ if(oh->flags & ~H5O_HDR_ALL_FLAGS)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unknown object header status flag(s)")
/* Number of links to object (unless overridden by refcount message) */
oh->nlink = 1;
@@ -261,13 +208,13 @@ H5O__cache_deserialize(const void *_image, size_t len, void *_udata,
if(oh->flags & H5O_HDR_STORE_TIMES) {
uint32_t tmp; /* Temporary value */
- UINT32DECODE(image, tmp);
+ UINT32DECODE(p, tmp);
oh->atime = (time_t)tmp;
- UINT32DECODE(image, tmp);
+ UINT32DECODE(p, tmp);
oh->mtime = (time_t)tmp;
- UINT32DECODE(image, tmp);
+ UINT32DECODE(p, tmp);
oh->ctime = (time_t)tmp;
- UINT32DECODE(image, tmp);
+ UINT32DECODE(p, tmp);
oh->btime = (time_t)tmp;
} /* end if */
else
@@ -275,11 +222,10 @@ H5O__cache_deserialize(const void *_image, size_t len, void *_udata,
/* Attribute fields */
if(oh->flags & H5O_HDR_ATTR_STORE_PHASE_CHANGE) {
- UINT16DECODE(image, oh->max_compact);
- UINT16DECODE(image, oh->min_dense);
-
+ UINT16DECODE(p, oh->max_compact);
+ UINT16DECODE(p, oh->min_dense);
if(oh->max_compact < oh->min_dense)
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad object header attribute phase change values")
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad object header attribute phase change values")
} /* end if */
else {
oh->max_compact = H5O_CRT_ATTR_MAX_COMPACT_DEF;
@@ -289,44 +235,44 @@ H5O__cache_deserialize(const void *_image, size_t len, void *_udata,
/* First chunk size */
switch(oh->flags & H5O_HDR_CHUNK0_SIZE) {
case 0: /* 1 byte size */
- oh->chunk0_size = *image++;
+ oh->chunk0_size = *p++;
break;
case 1: /* 2 byte size */
- UINT16DECODE(image, oh->chunk0_size);
+ UINT16DECODE(p, oh->chunk0_size);
break;
case 2: /* 4 byte size */
- UINT32DECODE(image, oh->chunk0_size);
+ UINT32DECODE(p, oh->chunk0_size);
break;
case 3: /* 8 byte size */
- UINT64DECODE(image, oh->chunk0_size);
+ UINT64DECODE(p, oh->chunk0_size);
break;
default:
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad size for chunk 0")
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad size for chunk 0")
} /* end switch */
if(oh->chunk0_size > 0 && oh->chunk0_size < H5O_SIZEOF_MSGHDR_OH(oh))
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad object header chunk size")
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad object header chunk size")
} /* end if */
else {
/* Version */
- oh->version = *image++;
+ oh->version = *p++;
if(H5O_VERSION_1 != oh->version)
- HGOTO_ERROR(H5E_OHDR, H5E_VERSION, NULL, "bad object header version number")
+ HGOTO_ERROR(H5E_OHDR, H5E_VERSION, FAIL, "bad object header version number")
/* Flags */
oh->flags = H5O_CRT_OHDR_FLAGS_DEF;
/* Reserved */
- image++;
+ p++;
/* Number of messages */
- UINT16DECODE(image, udata->v1_pfx_nmesgs);
+ UINT16DECODE(p, udata->v1_pfx_nmesgs);
/* Link count */
- UINT32DECODE(image, oh->nlink);
+ UINT32DECODE(p, oh->nlink);
/* Reset unused time fields */
oh->atime = oh->mtime = oh->ctime = oh->btime = 0;
@@ -336,24 +282,110 @@ H5O__cache_deserialize(const void *_image, size_t len, void *_udata,
oh->min_dense = 0;
/* First chunk size */
- UINT32DECODE(image, oh->chunk0_size);
-
- if((udata->v1_pfx_nmesgs > 0 &&
- oh->chunk0_size < H5O_SIZEOF_MSGHDR_OH(oh)) ||
- (udata->v1_pfx_nmesgs == 0 && oh->chunk0_size > 0))
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad object header chunk size")
+ UINT32DECODE(p, oh->chunk0_size);
+ if((udata->v1_pfx_nmesgs > 0 && oh->chunk0_size < H5O_SIZEOF_MSGHDR_OH(oh)) ||
+ (udata->v1_pfx_nmesgs == 0 && oh->chunk0_size > 0))
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad object header chunk size")
/* Reserved, in version 1 (for 8-byte alignment padding) */
- image += 4;
+ p += 4;
} /* end else */
/* Determine object header prefix length */
- prefix_size = (size_t)(image - (const uint8_t *)_image);
+ prefix_size = (size_t)(p - buf);
HDassert((size_t)prefix_size == (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh)));
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5O_decode_prefix() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O__cache_get_load_size()
+ *
+ * Purpose: Tell the metadata cache how much data to read from file in
+ * the first speculative read for the object header. Note that we do
+ * not have to be concerned about reading past the end of file, as the
+ * cache will clamp the read to avoid this if needed.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 7/28/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O__cache_get_load_size(const void H5_ATTR_UNUSED *_udata, size_t *image_len)
+{
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(image_len);
+
+ *image_len = H5O_SPEC_READ_SIZE;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O__cache_get_load_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O__cache_deserialize
+ *
+ * Purpose: Attempt to deserialize the object header contained in the
+ * supplied buffer, load the data into an instance of H5O_t, and
+ * return a pointer to the new instance.
+ *
+ * Note that the object header is read with with a speculative read.
+ * If the initial read is too small, make note of this fact and return
+ * without error. H5C_load_entry() will note the size discrepency
+ * and retry the deserialize operation with the correct size read.
+ *
+ * Return: Success: Pointer to in core representation
+ * Failure: NULL
+ *
+ * Programmer: John Mainzer
+ * 7/28/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5O__cache_deserialize(const void *_image, size_t len, void *_udata,
+ hbool_t *dirty)
+{
+ H5O_t *oh = NULL; /* Object header read in */
+ H5O_cache_ud_t *udata = (H5O_cache_ud_t *)_udata; /* User data for callback */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into buffer to decode */
+ size_t buf_size; /* Size of prefix+chunk #0 buffer */
+ void * ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check arguments */
+ HDassert(image);
+ HDassert(len > 0);
+ HDassert(udata);
+ HDassert(udata->common.f);
+ HDassert(udata->common.cont_msg_info);
+ HDassert(dirty);
+
+ /* Allocate space for the object header data structure */
+ if(NULL == (oh = H5FL_CALLOC(H5O_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* File-specific, non-stored information */
+ oh->sizeof_size = H5F_SIZEOF_SIZE(udata->common.f);
+ oh->sizeof_addr = H5F_SIZEOF_ADDR(udata->common.f);
+
+ /* Decode header prefix */
+ if(H5O_decode_prefix(udata->common.f, oh, image, udata) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't deserialize object header prefix")
+
/* Compute the size of the buffer used */
buf_size = oh->chunk0_size + (size_t)H5O_SIZEOF_HDR(oh);
+
/* Check to see if the buffer provided is large enough to contain both
* the prefix and the first chunk. If it isn't, make note of the desired
* size, but otherwise do nothing. H5C_load_entry() will notice the
@@ -768,32 +800,35 @@ H5O__cache_chk_deserialize(const void *image, size_t len, void *_udata,
if(H5O__chunk_deserialize(udata->oh, udata->common.addr, udata->size, (const uint8_t *)image, &(udata->common), dirty) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't deserialize object header chunk")
- /* Set the fields for the chunk proxy */
- chk_proxy->oh = udata->oh;
+ /* Set the chunk number for the chunk proxy */
H5_CHECKED_ASSIGN(chk_proxy->chunkno, unsigned, udata->oh->nchunks - 1, size_t);
} /* end if */
else {
/* Sanity check */
HDassert(udata->chunkno < udata->oh->nchunks);
- /* Set the fields for the chunk proxy */
- chk_proxy->oh = udata->oh;
+ /* Set the chunk number for the chunk proxy */
chk_proxy->chunkno = udata->chunkno;
/* Sanity check that the chunk representation we have in memory is
* the same as the one being brought in from disk.
*/
- HDassert(0 == HDmemcmp(image, chk_proxy->oh->chunk[chk_proxy->chunkno].image, chk_proxy->oh->chunk[chk_proxy->chunkno].size));
+ HDassert(0 == HDmemcmp(image, udata->oh->chunk[chk_proxy->chunkno].image, udata->oh->chunk[chk_proxy->chunkno].size));
} /* end else */
/* Increment reference count of object header */
if(H5O_inc_rc(udata->oh) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, NULL, "can't increment reference count on object header")
+ chk_proxy->oh = udata->oh;
/* Set return value */
ret_value = chk_proxy;
done:
+ if(NULL == ret_value)
+ if(chk_proxy && H5O__chunk_dest(chk_proxy) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, NULL, "unable to destroy object header chunk")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O__cache_chk_deserialize() */
@@ -920,7 +955,7 @@ H5O__cache_chk_free_icr(void *_thing)
HDassert(chk_proxy->cache_info.type == H5AC_OHDR_CHK);
/* Destroy object header chunk proxy */
- if(H5O__chunk_proxy_dest(chk_proxy) < 0)
+ if(H5O__chunk_dest(chk_proxy) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to destroy object header chunk proxy")
done:
@@ -1453,39 +1488,3 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5O__chunk_serialize() */
-
-/*-------------------------------------------------------------------------
- * Function: H5O__chunk_proxy_dest
- *
- * Purpose: Destroy a chunk proxy object
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * July 13, 2008
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5O__chunk_proxy_dest(H5O_chunk_proxy_t *chk_proxy)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_STATIC
-
- /* Check arguments */
- HDassert(chk_proxy);
-
- /* Decrement reference count of object header */
- if(chk_proxy->oh && H5O_dec_rc(chk_proxy->oh) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "can't decrement reference count on object header")
-
- /* Release the chunk proxy object */
- chk_proxy = H5FL_FREE(H5O_chunk_proxy_t, chk_proxy);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5O__chunk_proxy_dest() */
-
diff --git a/src/H5Ochunk.c b/src/H5Ochunk.c
index 18561b3..f6eb135 100644
--- a/src/H5Ochunk.c
+++ b/src/H5Ochunk.c
@@ -93,7 +93,8 @@ H5FL_DEFINE(H5O_chunk_proxy_t);
*-------------------------------------------------------------------------
*/
herr_t
-H5O_chunk_add(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx)
+H5O_chunk_add(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx,
+ unsigned cont_chunkno)
{
H5O_chunk_proxy_t *chk_proxy = NULL; /* Proxy for chunk, to mark it dirty in the cache */
herr_t ret_value = SUCCEED; /* Return value */
@@ -110,14 +111,16 @@ H5O_chunk_add(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx)
if(NULL == (chk_proxy = H5FL_CALLOC(H5O_chunk_proxy_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- /* Set the values in the chunk proxy */
- chk_proxy->oh = oh;
- chk_proxy->chunkno = idx;
-
/* Increment reference count on object header */
if(H5O_inc_rc(oh) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, FAIL, "can't increment reference count on object header")
+ /* Set the values in the chunk proxy */
+ chk_proxy->f = f;
+ chk_proxy->oh = oh;
+ chk_proxy->chunkno = idx;
+ chk_proxy->cont_chunkno = cont_chunkno;
+
/* Insert the chunk proxy into the cache */
if(H5AC_insert_entry(f, dxpl_id, H5AC_OHDR_CHK, oh->chunk[idx].addr, chk_proxy, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "unable to cache object header chunk")
@@ -126,8 +129,8 @@ H5O_chunk_add(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx)
done:
if(ret_value < 0)
- if(chk_proxy)
- chk_proxy = H5FL_FREE(H5O_chunk_proxy_t, chk_proxy);
+ if(chk_proxy && H5O__chunk_dest(chk_proxy) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to destroy object header chunk")
FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
} /* end H5O_chunk_add() */
@@ -172,6 +175,7 @@ H5O_chunk_protect(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, NULL, "can't increment reference count on object header")
/* Set chunk proxy fields */
+ chk_proxy->f = f;
chk_proxy->oh = oh;
chk_proxy->chunkno = idx;
} /* end if */
@@ -200,8 +204,8 @@ H5O_chunk_protect(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx)
done:
/* Cleanup on error */
if(!ret_value)
- if(0 == idx && chk_proxy)
- chk_proxy = H5FL_FREE(H5O_chunk_proxy_t, chk_proxy);
+ if(0 == idx && chk_proxy && H5O__chunk_dest(chk_proxy) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, NULL, "unable to destroy object header chunk")
FUNC_LEAVE_NOAPI_TAG(ret_value, NULL)
} /* end H5O_chunk_protect() */
@@ -409,3 +413,39 @@ done:
FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
} /* end H5O_chunk_delete() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5O__chunk_dest
+ *
+ * Purpose: Destroy a chunk proxy object
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 13, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O__chunk_dest(H5O_chunk_proxy_t *chk_proxy)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check arguments */
+ HDassert(chk_proxy);
+
+ /* Decrement reference count of object header */
+ if(chk_proxy->oh && H5O_dec_rc(chk_proxy->oh) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "can't decrement reference count on object header")
+
+ /* Release the chunk proxy object */
+ chk_proxy = H5FL_FREE(H5O_chunk_proxy_t, chk_proxy);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5O__chunk_dest() */
+
diff --git a/src/H5Omessage.c b/src/H5Omessage.c
index d42896c..7063ef6 100644
--- a/src/H5Omessage.c
+++ b/src/H5Omessage.c
@@ -2254,176 +2254,3 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_flush_msgs() */
-
-/*-------------------------------------------------------------------------
- * Function: H5O_msg_chunkno
- *
- * Purpose: Queries the object header chunk index for a message.
- *
- * Return: Success: >=0 value indicating the chunk number for
- * the message
- * Failure: <0
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Apr 22 2010
- *
- *-------------------------------------------------------------------------
- */
-int
-H5O_msg_get_chunkno(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id)
-{
- H5O_t *oh = NULL; /* Object header to use */
- const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
- H5O_mesg_t *idx_msg; /* Pointer to message to modify */
- unsigned idx; /* Index of message to modify */
- int ret_value = -1; /* Return value */
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* check args */
- HDassert(loc);
- HDassert(loc->file);
- HDassert(H5F_addr_defined(loc->addr));
- 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);
-
- /* Get the object header */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
-
- /* Locate message of correct type */
- for(idx = 0, idx_msg = &oh->mesg[0]; idx < oh->nmesgs; idx++, idx_msg++)
- if(type == idx_msg->type)
- break;
- if(idx == oh->nmesgs)
- HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "message type not found")
-
- /* Set return value */
- H5_CHECKED_ASSIGN(ret_value, int, idx_msg->chunkno, unsigned);
-
-done:
- if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_msg_get_chunkno() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5O_msg_lock
- *
- * Purpose: Locks a message into a particular chunk, preventing it from
- * being moved into another chunk.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Apr 22 2010
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5O_msg_lock(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id)
-{
- H5O_t *oh = NULL; /* Object header to use */
- const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
- H5O_mesg_t *idx_msg; /* Pointer to message to modify */
- unsigned idx; /* Index of message to modify */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* check args */
- HDassert(loc);
- HDassert(loc->file);
- HDassert(H5F_addr_defined(loc->addr));
- 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);
-
- /* Get the object header */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
-
- /* Locate message of correct type */
- for(idx = 0, idx_msg = &oh->mesg[0]; idx < oh->nmesgs; idx++, idx_msg++)
- if(type == idx_msg->type)
- break;
- if(idx == oh->nmesgs)
- HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "message type not found")
-
- /* Fail if the message is already locked */
- if(idx_msg->locked)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOCK, FAIL, "message already locked")
-
- /* Make the message locked */
- idx_msg->locked = TRUE;
-
-done:
- if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_msg_lock() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5O_msg_unlock
- *
- * Purpose: Unlocks a message, allowing it to be moved into another chunk.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Apr 22 2010
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5O_msg_unlock(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id)
-{
- H5O_t *oh = NULL; /* Object header to use */
- const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
- H5O_mesg_t *idx_msg; /* Pointer to message to modify */
- unsigned idx; /* Index of message to modify */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* check args */
- HDassert(loc);
- HDassert(loc->file);
- HDassert(H5F_addr_defined(loc->addr));
- 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);
-
- /* Get the object header */
- if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
-
- /* Locate message of correct type */
- for(idx = 0, idx_msg = &oh->mesg[0]; idx < oh->nmesgs; idx++, idx_msg++)
- if(type == idx_msg->type)
- break;
- if(idx == oh->nmesgs)
- HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "message type not found")
-
- /* Fail if the message is not locked */
- if(!idx_msg->locked)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTUNLOCK, FAIL, "message not locked")
-
- /* Make the message unlocked */
- idx_msg->locked = FALSE;
-
-done:
- if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_msg_unlock() */
-
diff --git a/src/H5Opkg.h b/src/H5Opkg.h
index a719872..659bf6e 100644
--- a/src/H5Opkg.h
+++ b/src/H5Opkg.h
@@ -245,7 +245,6 @@ struct H5O_msg_class_t {
struct H5O_mesg_t {
const H5O_msg_class_t *type; /*type of message */
hbool_t dirty; /*raw out of date wrt native */
- hbool_t locked; /*message is locked into chunk */
uint8_t flags; /*message flags */
H5O_msg_crt_idx_t crt_idx; /*message creation index */
unsigned chunkno; /*chunk number for this mesg */
@@ -254,6 +253,17 @@ struct H5O_mesg_t {
size_t raw_size; /*size with alignment */
};
+/* Struct for storing information about "best" message to move to new chunk */
+typedef struct H5O_msg_alloc_info_t {
+ int msgno; /* Index in message array */
+ unsigned id; /* Message type ID on disk */
+ unsigned chunkno; /* Index in chunk array */
+ size_t gap_size; /* Size of any "gap" in the chunk immediately after message */
+ size_t null_size; /* Size of any null message in the chunk immediately after message */
+ size_t total_size; /* Total size of "available" space around message */
+ unsigned null_msgno; /* Message index of null message immediately after message */
+} H5O_msg_alloc_info_t;
+
typedef struct H5O_chunk_t {
haddr_t addr; /*chunk file address */
size_t size; /*chunk size */
@@ -369,8 +379,10 @@ typedef struct H5O_chunk_proxy_t {
H5AC_info_t cache_info; /* Information for metadata cache functions, _must_ be */
/* first field in structure */
+ H5F_t *f; /* Pointer to file for object header/chunk */
H5O_t *oh; /* Object header for this chunk */
unsigned chunkno; /* Chunk number for this chunk */
+ unsigned cont_chunkno; /* Chunk number for the chunk containing the continuation message that points to this chunk */
} H5O_chunk_proxy_t;
/* Callback information for loading object header chunk from disk */
@@ -559,7 +571,8 @@ H5_DLL herr_t H5O_msg_iterate_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *t
const H5O_mesg_operator_t *op, void *op_data, hid_t dxpl_id);
/* Object header chunk routines */
-H5_DLL herr_t H5O_chunk_add(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx);
+H5_DLL herr_t H5O_chunk_add(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx,
+ unsigned cont_chunkno);
H5_DLL H5O_chunk_proxy_t *H5O_chunk_protect(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
unsigned idx);
H5_DLL herr_t H5O_chunk_unprotect(H5F_t *f, hid_t dxpl_id,
@@ -567,6 +580,7 @@ H5_DLL herr_t H5O_chunk_unprotect(H5F_t *f, hid_t dxpl_id,
H5_DLL herr_t H5O_chunk_update_idx(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx);
H5_DLL herr_t H5O_chunk_resize(H5O_t *oh, H5O_chunk_proxy_t *chk_proxy);
H5_DLL herr_t H5O_chunk_delete(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx);
+H5_DLL herr_t H5O__chunk_dest(H5O_chunk_proxy_t *chunk_proxy);
/* Collect storage info for btree and heap */
H5_DLL herr_t H5O_attr_bh_info(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
@@ -574,6 +588,8 @@ H5_DLL herr_t H5O_attr_bh_info(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
/* Object header allocation routines */
H5_DLL herr_t H5O_alloc_msgs(H5O_t *oh, size_t min_alloc);
+H5_DLL herr_t H5O__alloc_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size,
+ size_t found_null, const H5O_msg_alloc_info_t *found_msg, size_t *new_idx);
H5_DLL herr_t H5O_alloc(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
const H5O_msg_class_t *type, const void *mesg, size_t *mesg_idx);
H5_DLL herr_t H5O_condense_header(H5F_t *f, H5O_t *oh, hid_t dxpl_id);
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 0acac8c..e8ba267 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -898,9 +898,6 @@ H5_DLL void* H5O_msg_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
unsigned type_id, const unsigned char *buf);
H5_DLL herr_t H5O_msg_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
unsigned type_id, void *mesg);
-H5_DLL int H5O_msg_get_chunkno(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id);
-H5_DLL herr_t H5O_msg_lock(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id);
-H5_DLL herr_t H5O_msg_unlock(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id);
/* Object metadata flush/refresh routines */
H5_DLL herr_t H5O_flush_common(H5O_loc_t *oloc, hid_t obj_id, hid_t dxpl_id);
diff --git a/test/ohdr.c b/test/ohdr.c
index 5642c41..e613a98 100644
--- a/test/ohdr.c
+++ b/test/ohdr.c
@@ -811,148 +811,6 @@ main(void)
FAIL_STACK_ERROR
PASSED();
- /*
- * Test moving message to first chunk
- */
- TESTING("locking messages");
- HDmemset(&oh_loc, 0, sizeof(oh_loc));
- if(H5O_create(f, H5AC_ind_read_dxpl_id, (size_t)64, (size_t)0, H5P_GROUP_CREATE_DEFAULT, &oh_loc/*out*/) < 0)
- FAIL_STACK_ERROR
- if(1 != H5O_link(&oh_loc, 1, H5AC_ind_read_dxpl_id))
- FAIL_STACK_ERROR
-
- /* Create second object header, to guarantee that first object header uses multiple chunks */
- HDmemset(&oh_loc2, 0, sizeof(oh_loc2));
- if(H5O_create(f, H5AC_ind_read_dxpl_id, (size_t)64, (size_t)0, H5P_GROUP_CREATE_DEFAULT, &oh_loc2/*out*/) < 0)
- FAIL_STACK_ERROR
- if(1 != H5O_link(&oh_loc2, 1, H5AC_ind_read_dxpl_id))
- FAIL_STACK_ERROR
-
- /* Fill object header with messages, creating multiple chunks */
- for(i = 0; i < 10; i++) {
- time_new = (i + 1) * 1000 + 10;
- if(H5O_msg_create(&oh_loc, H5O_MTIME_NEW_ID, 0, 0, &time_new, H5AC_ind_read_dxpl_id) < 0)
- FAIL_STACK_ERROR
- } /* end for */
-
- /* Get # of object header chunks */
- if(H5O_get_hdr_info(&oh_loc, H5AC_ind_read_dxpl_id, &hdr_info) < 0)
- FAIL_STACK_ERROR
- if(hdr_info.nchunks != 2)
- TEST_ERROR
-
- /* Add message to lock to object header */
- time_new = 11111111;
- if(H5O_msg_create(&oh_loc, H5O_MTIME_ID, 0, 0, &time_new, H5AC_ind_read_dxpl_id) < 0)
- FAIL_STACK_ERROR
-
- /* Verify chunk index for message */
- if((chunkno = H5O_msg_get_chunkno(&oh_loc, H5O_MTIME_ID, H5AC_ind_read_dxpl_id)) < 0)
- FAIL_STACK_ERROR
- if(chunkno != 1)
- TEST_ERROR
-
- /* Lock the message into the chunk */
- if(H5O_msg_lock(&oh_loc, H5O_MTIME_ID, H5AC_ind_read_dxpl_id) < 0)
- FAIL_STACK_ERROR
-
- /* Attempt to lock the message twice */
- H5E_BEGIN_TRY {
- ret = H5O_msg_lock(&oh_loc, H5O_MTIME_ID, H5AC_ind_read_dxpl_id);
- } H5E_END_TRY;
- if(ret >= 0)
- TEST_ERROR
-
- /* Delete all the other messages, which would move the message into
- * chunk #0, if it wasn't locked
- */
- if(H5O_msg_remove(&oh_loc, H5O_MTIME_NEW_ID, H5O_ALL, TRUE, H5AC_ind_read_dxpl_id) < 0)
- FAIL_STACK_ERROR
-
- /* Verify chunk index for message */
- if((chunkno = H5O_msg_get_chunkno(&oh_loc, H5O_MTIME_ID, H5AC_ind_read_dxpl_id)) < 0)
- FAIL_STACK_ERROR
- if(chunkno != 1)
- TEST_ERROR
-
- /* Unlock the message */
- if(H5O_msg_unlock(&oh_loc, H5O_MTIME_ID, H5AC_ind_read_dxpl_id) < 0)
- FAIL_STACK_ERROR
-
- /* Attempt to unlock the message twice */
- H5E_BEGIN_TRY {
- ret = H5O_msg_unlock(&oh_loc, H5O_MTIME_ID, H5AC_ind_read_dxpl_id);
- } H5E_END_TRY;
- if(ret >= 0)
- TEST_ERROR
-
- /* Close object headers */
- if(H5O_close(&oh_loc2) < 0)
- FAIL_STACK_ERROR
- if(H5O_close(&oh_loc) < 0)
- FAIL_STACK_ERROR
-
- /* Open first object header */
- HDmemset(&oh_loc, 0, sizeof(oh_loc));
- if(H5O_create(f, H5AC_ind_read_dxpl_id, (size_t)64, (size_t)0, H5P_GROUP_CREATE_DEFAULT, &oh_loc/*out*/) < 0)
- FAIL_STACK_ERROR
- if(1 != H5O_link(&oh_loc, 1, H5AC_ind_read_dxpl_id))
- FAIL_STACK_ERROR
-
- /* Create second object header, to guarantee that first object header uses multiple chunks */
- HDmemset(&oh_loc2, 0, sizeof(oh_loc2));
- if(H5O_create(f, H5AC_ind_read_dxpl_id, (size_t)64, (size_t)0, H5P_GROUP_CREATE_DEFAULT, &oh_loc2/*out*/) < 0)
- FAIL_STACK_ERROR
- if(1 != H5O_link(&oh_loc2, 1, H5AC_ind_read_dxpl_id))
- FAIL_STACK_ERROR
-
- /* Add message to move to object header */
- time_new = 11111111;
- if(H5O_msg_create(&oh_loc, H5O_MTIME_ID, 0, 0, &time_new, H5AC_ind_read_dxpl_id) < 0)
- FAIL_STACK_ERROR
-
- /* Verify chunk index for message */
- if((chunkno = H5O_msg_get_chunkno(&oh_loc, H5O_MTIME_ID, H5AC_ind_read_dxpl_id)) < 0)
- FAIL_STACK_ERROR
- if(chunkno != 0)
- TEST_ERROR
-
- /* Lock the message into the chunk */
- if(H5O_msg_lock(&oh_loc, H5O_MTIME_ID, H5AC_ind_read_dxpl_id) < 0)
- FAIL_STACK_ERROR
-
- /* Fill object header with messages, creating multiple chunks */
- /* (would normally move locked message to new chunk) */
- for(i = 0; i < 10; i++) {
- time_new = (i + 1) * 1000 + 10;
- if(H5O_msg_create(&oh_loc, H5O_MTIME_NEW_ID, 0, 0, &time_new, H5AC_ind_read_dxpl_id) < 0)
- FAIL_STACK_ERROR
- } /* end for */
-
- /* Get # of object header chunks */
- if(H5O_get_hdr_info(&oh_loc, H5AC_ind_read_dxpl_id, &hdr_info) < 0)
- FAIL_STACK_ERROR
- if(hdr_info.nchunks != 2)
- TEST_ERROR
-
- /* Verify chunk index for message */
- if((chunkno = H5O_msg_get_chunkno(&oh_loc, H5O_MTIME_ID, H5AC_ind_read_dxpl_id)) < 0)
- FAIL_STACK_ERROR
- if(chunkno != 0)
- TEST_ERROR
-
- /* Unlock the message */
- if(H5O_msg_unlock(&oh_loc, H5O_MTIME_ID, H5AC_ind_read_dxpl_id) < 0)
- FAIL_STACK_ERROR
-
- /* Close object headers */
- if(H5O_close(&oh_loc2) < 0)
- FAIL_STACK_ERROR
- if(H5O_close(&oh_loc) < 0)
- FAIL_STACK_ERROR
-
- PASSED();
-
/* Close the file we created */
if(H5Fclose(file) < 0)
TEST_ERROR