Refactor H5O code to clean up message allocation, align cache deserialize code

with revise_chunks changes, and remove unused "message locking" code.
This commit is contained in:
Quincey Koziol 2016-11-12 01:05:47 -08:00
parent 70938cbf28
commit 1c6924f18b
7 changed files with 741 additions and 831 deletions

View File

@ -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); 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, 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); 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, 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 *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_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_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); 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 * Purpose: Find the best fit non-null message for a given size of message
* file space. * to allocate.
*
* 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 * Note: The algorithm for finding a message to replace with a
* continuation message is still fairly limited. It's possible * continuation message is still fairly limited. It's possible
@ -735,50 +731,34 @@ done:
* *
* Failure: Negative * Failure: Negative
* *
* Programmer: Robb Matzke * Programmer: Quincey Koziol
* matzke@llnl.gov * koziol@lbl.gov
* Aug 7 1997 * Oct 21 2016
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
static herr_t 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_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 cont_size; /*continuation message size */ size_t multi_size; /* Size of all the messages in the last chunk */
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;
unsigned u; /* Local index variable */ unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT FUNC_ENTER_STATIC
/* check args */ /* Check args */
HDassert(f);
HDassert(oh); HDassert(oh);
HDassert(size > 0); HDassert(size);
size = H5O_ALIGN_OH(oh, size); HDassert(*size > 0);
HDassert(found_msg);
/* /*
* Find the smallest null message that will hold an object * Find the smallest message that could be moved to make room for the
* continuation message. Failing that, find the smallest message * continuation message.
* that could be moved to make room for the continuation message.
* *
* Don't ever move continuation message from one chunk to another. * 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))); 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++) { 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) */ /* Don't consider continuation messages (for now) */
} /* end if */ if(H5O_CONT_ID != curr_msg->type->id) {
else if(curr_msg->locked) {
/* Don't consider locked messages */
} /* end if */
else {
unsigned msg_chunkno = curr_msg->chunkno; /* Chunk that the message is in */ 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_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 */ 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 */ /* Check if message is large enough to hold continuation info */
if(total_size >= cont_size) { if(total_size >= cont_size) {
if(curr_msg->type->id == H5O_ATTR_ID) { hbool_t better = FALSE; /* Whether the current message is better than a previous one */
if(found_attr.msgno < 0 || total_size < found_attr.total_size) {
found_attr.msgno = (int)u; /* Check for first message that can be moved */
found_attr.gap_size = gap_size; if(found_msg->msgno < 0)
found_attr.null_size = null_size; better = TRUE;
found_attr.total_size = total_size;
found_attr.null_msgno = null_msgno;
} /* end if */
} /* end if */
else { else {
if(found_other.msgno < 0 || total_size < found_other.total_size) { /* Prioritize moving non-attributes above attributes */
found_other.msgno = (int)u; /* (Even attributes with an otherwise better fit */
found_other.gap_size = gap_size; if(found_msg->id == H5O_ATTR_ID && curr_msg->type->id != H5O_ATTR_ID)
found_other.null_size = null_size; better = TRUE;
found_other.total_size = total_size; /* Either two attributes, or two non-attributes */
found_other.null_msgno = null_msgno; else {
} /* end if */ /* 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 */
} /* 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) } /* end if */
else if(found_msg->msgno < 0 && msg_chunkno == oh->nchunks - 1)
/* Keep track of the total size of smaller messages in the last /* Keep track of the total size of smaller messages in the last
* chunk, in case we need to move more than 1 message. * chunk, in case we need to move more than 1 message.
*/ */
multi_size += curr_msg->raw_size + (size_t)H5O_SIZEOF_MSGHDR_OH(oh); multi_size += curr_msg->raw_size + (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
} /* end else */ } /* end if */
} /* end for */ } /* 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 * 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 all else fails, move every message in the last chunk.
* *
*/ */
if(multi_size == 0) { if(found_msg->msgno < 0)
if(found_null < 0) { *size += multi_size;
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 */
else 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 * The total chunk size must include the requested space plus enough
@ -944,7 +967,9 @@ 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") 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 */ /* Check if we need to move multiple messages, in order to make room for the new message */
if(multi_size > 0) { 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 /* 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 * should be extremely rare so we don't care too much about minimizing
* the space used. * the space used.
@ -982,7 +1007,7 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size, size_t *new
} /* end if */ } /* end if */
/* Create a null message spanning the entire last chunk */ /* Create a null message spanning the entire last chunk */
found_null = (int)oh->nmesgs++; found_null = oh->nmesgs++;
null_msg = &(oh->mesg[found_null]); null_msg = &(oh->mesg[found_null]);
null_msg->type = H5O_MSG_NULL; null_msg->type = H5O_MSG_NULL;
null_msg->dirty = TRUE; null_msg->dirty = TRUE;
@ -1003,57 +1028,58 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size, size_t *new
/* Release chunk, marking it dirty */ /* Release chunk, marking it dirty */
if(H5O_chunk_unprotect(f, dxpl_id, chk_proxy, TRUE) < 0) if(H5O_chunk_unprotect(f, dxpl_id, chk_proxy, TRUE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk") HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
} else if(found_null < 0) { } /* end if */
else {
/* Move message (that will be replaced with continuation message) /* Move message (that will be replaced with continuation message)
* to new chunk, if necessary. * to new chunk, if necessary.
*/ */
H5O_mesg_t *null_msg; /* Pointer to new null message */ H5O_mesg_t *null_msg; /* Pointer to new null message */
/* Protect chunk */ /* Protect chunk */
if(NULL == (chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, oh->mesg[found_other.msgno].chunkno))) 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") HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
/* Create null message for space that message to copy currently occupies */ /* Create null message for space that message to copy currently occupies */
found_null = (int)oh->nmesgs++; found_null = oh->nmesgs++;
null_msg = &(oh->mesg[found_null]); null_msg = &(oh->mesg[found_null]);
null_msg->type = H5O_MSG_NULL; null_msg->type = H5O_MSG_NULL;
null_msg->native = NULL; null_msg->native = NULL;
null_msg->raw = oh->mesg[found_other.msgno].raw; null_msg->raw = oh->mesg[found_msg->msgno].raw;
null_msg->raw_size = oh->mesg[found_other.msgno].raw_size; null_msg->raw_size = oh->mesg[found_msg->msgno].raw_size;
null_msg->chunkno = oh->mesg[found_other.msgno].chunkno; null_msg->chunkno = oh->mesg[found_msg->msgno].chunkno;
/* Copy the message to move (& its prefix) to its new location */ /* Copy the message to move (& its prefix) to its new location */
HDmemcpy(p, oh->mesg[found_other.msgno].raw - H5O_SIZEOF_MSGHDR_OH(oh), HDmemcpy(p, oh->mesg[found_msg->msgno].raw - H5O_SIZEOF_MSGHDR_OH(oh),
oh->mesg[found_other.msgno].raw_size + (size_t)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 */ /* Switch moved message to point to new location */
oh->mesg[found_other.msgno].raw = p + H5O_SIZEOF_MSGHDR_OH(oh); oh->mesg[found_msg->msgno].raw = p + H5O_SIZEOF_MSGHDR_OH(oh);
oh->mesg[found_other.msgno].chunkno = chunkno; oh->mesg[found_msg->msgno].chunkno = chunkno;
/* Account for copied message in new chunk */ /* Account for copied message in new chunk */
p += (size_t)H5O_SIZEOF_MSGHDR_OH(oh) + oh->mesg[found_other.msgno].raw_size; 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_other.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 */ /* Add any available space after the message to move to the new null message */
if(found_other.gap_size > 0) { if(found_msg->gap_size > 0) {
/* Absorb a gap after the moved message */ /* Absorb a gap after the moved message */
HDassert(oh->chunk[null_msg->chunkno].gap == found_other.gap_size); HDassert(oh->chunk[null_msg->chunkno].gap == found_msg->gap_size);
null_msg->raw_size += found_other.gap_size; null_msg->raw_size += found_msg->gap_size;
oh->chunk[null_msg->chunkno].gap = 0; oh->chunk[null_msg->chunkno].gap = 0;
} /* end if */ } /* end if */
else if(found_other.null_size > 0) { else if(found_msg->null_size > 0) {
H5O_mesg_t *old_null_msg = &oh->mesg[found_other.null_msgno]; /* Pointer to NULL message to eliminate */ H5O_mesg_t *old_null_msg = &oh->mesg[found_msg->null_msgno]; /* Pointer to NULL message to eliminate */
/* Absorb a null message after the moved message */ /* 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))); 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; null_msg->raw_size += found_msg->null_size;
/* Release any information/memory for message */ /* Release any information/memory for message */
H5O_msg_free_mesg(old_null_msg); H5O_msg_free_mesg(old_null_msg);
/* Remove null message from list of messages */ /* Remove null message from list of messages */
if(found_other.null_msgno < (oh->nmesgs - 1)) if(found_msg->null_msgno < (oh->nmesgs - 1))
HDmemmove(old_null_msg, old_null_msg + 1, ((oh->nmesgs - 1) - found_other.null_msgno) * sizeof(H5O_mesg_t)); HDmemmove(old_null_msg, old_null_msg + 1, ((oh->nmesgs - 1) - found_msg->null_msgno) * sizeof(H5O_mesg_t));
/* Decrement # of messages */ /* Decrement # of messages */
/* (Don't bother reducing size of message array for now -QAK) */ /* (Don't bother reducing size of message array for now -QAK) */
@ -1070,7 +1096,7 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size, size_t *new
if(H5O_chunk_unprotect(f, dxpl_id, chk_proxy, TRUE) < 0) if(H5O_chunk_unprotect(f, dxpl_id, chk_proxy, TRUE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk") HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
} /* end if */ } /* end if */
HDassert(found_null >= 0); } /* end if */
/* Create null message for [rest of] space in new chunk */ /* Create null message for [rest of] space in new chunk */
/* (account for chunk's magic # & checksum) */ /* (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; oh->mesg[idx].chunkno = chunkno;
/* Insert the new chunk into the cache */ /* 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") HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't add new chunk to cache")
/* Initialize the continuation information */ /* Initialize the continuation information */
@ -1094,16 +1120,168 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size, size_t *new
cont->chunkno = chunkno; cont->chunkno = chunkno;
/* Split the null message and point at continuation message */ /* 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") HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't split null message")
/* Set new message index value */ /* Set new message index value */
*new_idx = idx; *new_idx = idx;
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: done:
FUNC_LEAVE_NOAPI(ret_value) FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_alloc_new_chunk() */ } /* 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 * Function: H5O_alloc
@ -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") HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "object header message is too large")
aligned_size = H5O_ALIGN_OH(oh, raw_size); aligned_size = H5O_ALIGN_OH(oh, raw_size);
/* look for a null message which is large enough */ /* Find the smallest null message that could hold the new object header message */
for(idx = 0; idx < oh->nmesgs; idx++) idx = oh->nmesgs;
if(H5O_NULL_ID == oh->mesg[idx].type->id && oh->mesg[idx].raw_size >= aligned_size) if(H5O__alloc_find_best_null(oh, aligned_size, &idx) < 0)
break; 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 we didn't find one, then allocate more header space */
if(idx >= oh->nmesgs) { 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; nonnull_size = 0;
for(v = 0, curr_msg = &oh->mesg[0]; v < oh->nmesgs; v++, curr_msg++) { for(v = 0, curr_msg = &oh->mesg[0]; v < oh->nmesgs; v++, curr_msg++) {
if(curr_msg->chunkno == deleted_chunkno) { 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 */ /* Find size of all non-null messages in the chunk pointed to by the continuation message */
if(curr_msg->type->id != H5O_NULL_ID) { if(curr_msg->type->id != H5O_NULL_ID) {
HDassert(curr_msg->type->id != H5O_CONT_ID); HDassert(curr_msg->type->id != H5O_CONT_ID);
@ -1552,8 +1724,6 @@ H5O_move_msgs_forward(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
} /* end else-if */ } /* end else-if */
} /* end 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 */ /* 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++) { 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 if(H5O_NULL_ID == null_msg->type->id && curr_msg->chunkno > null_msg->chunkno
@ -1697,7 +1867,6 @@ H5O_move_msgs_forward(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
break; break;
} /* end if */ } /* end if */
} /* end for */ } /* end for */
} /* end if */
/* If we packed messages, get out of loop and start over */ /* 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) */ /* (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; ret_value = (htri_t)did_packing;
done: done:
if(ret_value < 0) {
if(null_chk_proxy && H5O_chunk_unprotect(f, dxpl_id, null_chk_proxy, null_chk_dirtied) < 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") 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) 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") 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) FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_move_msgs_forward() */ } /* H5O_move_msgs_forward() */

View File

@ -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_free_icr(void *thing);
static herr_t H5O__cache_chk_clear(const H5F_t *f, void *thing, hbool_t about_to_destroy); 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 */ /* Chunk routines */
static herr_t H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len, 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); 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 */ /* Misc. routines */
static herr_t H5O__add_cont_msg(H5O_cont_msgs_t *cont_msg_info, static herr_t H5O__add_cont_msg(H5O_cont_msgs_t *cont_msg_info,
const H5O_cont_t *cont); const H5O_cont_t *cont);
static herr_t H5O_decode_prefix(H5F_t *f, H5O_t *oh, const uint8_t *buf, void *_udata);
/*********************/ /*********************/
@ -158,6 +156,149 @@ H5FL_SEQ_DEFINE(H5O_cont_t);
/* Local Variables */ /* Local Variables */
/*******************/ /*******************/
/*-------------------------------------------------------------------------
* Function: H5O_decode_prefix
*
* Purpose: To decode the object header prefix.
* The coding is extracted fromt H5O__cache_deserialize() to this routine.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Vailin Choi; Aug 2015
*
*-------------------------------------------------------------------------
*/
static herr_t
H5O_decode_prefix(H5F_t *f, H5O_t *oh, const uint8_t *buf, void *_udata)
{
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_NOAPI_NOINIT
/* Check arguments */
HDassert(f);
HDassert(oh);
HDassert(buf);
HDassert(udata);
/* Check for presence of magic number */
/* (indicates version 2 or later) */
if(!HDmemcmp(p, H5O_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC)) {
/* Magic number */
p += H5_SIZEOF_MAGIC;
/* Version */
oh->version = *p++;
if(H5O_VERSION_2 != oh->version)
HGOTO_ERROR(H5E_OHDR, H5E_VERSION, FAIL, "bad object header version number")
/* Flags */
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;
/* Time fields */
if(oh->flags & H5O_HDR_STORE_TIMES) {
uint32_t tmp; /* Temporary value */
UINT32DECODE(p, tmp);
oh->atime = (time_t)tmp;
UINT32DECODE(p, tmp);
oh->mtime = (time_t)tmp;
UINT32DECODE(p, tmp);
oh->ctime = (time_t)tmp;
UINT32DECODE(p, tmp);
oh->btime = (time_t)tmp;
} /* end if */
else
oh->atime = oh->mtime = oh->ctime = oh->btime = 0;
/* Attribute fields */
if(oh->flags & H5O_HDR_ATTR_STORE_PHASE_CHANGE) {
UINT16DECODE(p, oh->max_compact);
UINT16DECODE(p, oh->min_dense);
if(oh->max_compact < oh->min_dense)
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;
oh->min_dense = H5O_CRT_ATTR_MIN_DENSE_DEF;
} /* end else */
/* First chunk size */
switch(oh->flags & H5O_HDR_CHUNK0_SIZE) {
case 0: /* 1 byte size */
oh->chunk0_size = *p++;
break;
case 1: /* 2 byte size */
UINT16DECODE(p, oh->chunk0_size);
break;
case 2: /* 4 byte size */
UINT32DECODE(p, oh->chunk0_size);
break;
case 3: /* 8 byte size */
UINT64DECODE(p, oh->chunk0_size);
break;
default:
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, FAIL, "bad object header chunk size")
} /* end if */
else {
/* Version */
oh->version = *p++;
if(H5O_VERSION_1 != oh->version)
HGOTO_ERROR(H5E_OHDR, H5E_VERSION, FAIL, "bad object header version number")
/* Flags */
oh->flags = H5O_CRT_OHDR_FLAGS_DEF;
/* Reserved */
p++;
/* Number of messages */
UINT16DECODE(p, udata->v1_pfx_nmesgs);
/* Link count */
UINT32DECODE(p, oh->nlink);
/* Reset unused time fields */
oh->atime = oh->mtime = oh->ctime = oh->btime = 0;
/* Reset unused attribute fields */
oh->max_compact = 0;
oh->min_dense = 0;
/* First 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) */
p += 4;
} /* end else */
/* Determine object header prefix length */
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() * Function: H5O__cache_get_load_size()
@ -216,7 +357,6 @@ H5O__cache_deserialize(const void *_image, size_t len, void *_udata,
H5O_t *oh = NULL; /* Object header read in */ H5O_t *oh = NULL; /* Object header read in */
H5O_cache_ud_t *udata = (H5O_cache_ud_t *)_udata; /* User data for callback */ 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 */ 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 */ size_t buf_size; /* Size of prefix+chunk #0 buffer */
void * ret_value = NULL; /* Return value */ void * ret_value = NULL; /* Return value */
@ -238,122 +378,14 @@ H5O__cache_deserialize(const void *_image, size_t len, void *_udata,
oh->sizeof_size = H5F_SIZEOF_SIZE(udata->common.f); oh->sizeof_size = H5F_SIZEOF_SIZE(udata->common.f);
oh->sizeof_addr = H5F_SIZEOF_ADDR(udata->common.f); oh->sizeof_addr = H5F_SIZEOF_ADDR(udata->common.f);
/* Check for presence of magic number */ /* Decode header prefix */
/* (indicates version 2 or later) */ if(H5O_decode_prefix(udata->common.f, oh, image, udata) < 0)
if(!HDmemcmp(image, H5O_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't deserialize object header prefix")
/* Magic number */
image += 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")
/* Flags */
oh->flags = *image++;
if(oh->flags & ~H5O_HDR_ALL_FLAGS)
HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "unknown object header status flag(s)")
/* Number of links to object (unless overridden by refcount message) */
oh->nlink = 1;
/* Time fields */
if(oh->flags & H5O_HDR_STORE_TIMES) {
uint32_t tmp; /* Temporary value */
UINT32DECODE(image, tmp);
oh->atime = (time_t)tmp;
UINT32DECODE(image, tmp);
oh->mtime = (time_t)tmp;
UINT32DECODE(image, tmp);
oh->ctime = (time_t)tmp;
UINT32DECODE(image, tmp);
oh->btime = (time_t)tmp;
} /* end if */
else
oh->atime = oh->mtime = oh->ctime = oh->btime = 0;
/* Attribute fields */
if(oh->flags & H5O_HDR_ATTR_STORE_PHASE_CHANGE) {
UINT16DECODE(image, oh->max_compact);
UINT16DECODE(image, oh->min_dense);
if(oh->max_compact < oh->min_dense)
HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad object header attribute phase change values")
} /* end if */
else {
oh->max_compact = H5O_CRT_ATTR_MAX_COMPACT_DEF;
oh->min_dense = H5O_CRT_ATTR_MIN_DENSE_DEF;
} /* end else */
/* First chunk size */
switch(oh->flags & H5O_HDR_CHUNK0_SIZE) {
case 0: /* 1 byte size */
oh->chunk0_size = *image++;
break;
case 1: /* 2 byte size */
UINT16DECODE(image, oh->chunk0_size);
break;
case 2: /* 4 byte size */
UINT32DECODE(image, oh->chunk0_size);
break;
case 3: /* 8 byte size */
UINT64DECODE(image, oh->chunk0_size);
break;
default:
HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "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")
} /* end if */
else {
/* Version */
oh->version = *image++;
if(H5O_VERSION_1 != oh->version)
HGOTO_ERROR(H5E_OHDR, H5E_VERSION, NULL, "bad object header version number")
/* Flags */
oh->flags = H5O_CRT_OHDR_FLAGS_DEF;
/* Reserved */
image++;
/* Number of messages */
UINT16DECODE(image, udata->v1_pfx_nmesgs);
/* Link count */
UINT32DECODE(image, oh->nlink);
/* Reset unused time fields */
oh->atime = oh->mtime = oh->ctime = oh->btime = 0;
/* Reset unused attribute fields */
oh->max_compact = 0;
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")
/* Reserved, in version 1 (for 8-byte alignment padding) */
image += 4;
} /* end else */
/* Determine object header prefix length */
prefix_size = (size_t)(image - (const uint8_t *)_image);
HDassert((size_t)prefix_size == (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh)));
/* Compute the size of the buffer used */ /* Compute the size of the buffer used */
buf_size = oh->chunk0_size + (size_t)H5O_SIZEOF_HDR(oh); buf_size = oh->chunk0_size + (size_t)H5O_SIZEOF_HDR(oh);
/* Check to see if the buffer provided is large enough to contain both /* 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 * 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 * 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) 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") HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't deserialize object header chunk")
/* Set the fields for the chunk proxy */ /* Set the chunk number for the chunk proxy */
chk_proxy->oh = udata->oh;
H5_CHECKED_ASSIGN(chk_proxy->chunkno, unsigned, udata->oh->nchunks - 1, size_t); H5_CHECKED_ASSIGN(chk_proxy->chunkno, unsigned, udata->oh->nchunks - 1, size_t);
} /* end if */ } /* end if */
else { else {
/* Sanity check */ /* Sanity check */
HDassert(udata->chunkno < udata->oh->nchunks); HDassert(udata->chunkno < udata->oh->nchunks);
/* Set the fields for the chunk proxy */ /* Set the chunk number for the chunk proxy */
chk_proxy->oh = udata->oh;
chk_proxy->chunkno = udata->chunkno; chk_proxy->chunkno = udata->chunkno;
/* Sanity check that the chunk representation we have in memory is /* Sanity check that the chunk representation we have in memory is
* the same as the one being brought in from disk. * 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 */ } /* end else */
/* Increment reference count of object header */ /* Increment reference count of object header */
if(H5O_inc_rc(udata->oh) < 0) if(H5O_inc_rc(udata->oh) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, NULL, "can't increment reference count on object header") HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, NULL, "can't increment reference count on object header")
chk_proxy->oh = udata->oh;
/* Set return value */ /* Set return value */
ret_value = chk_proxy; ret_value = chk_proxy;
done: 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) FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O__cache_chk_deserialize() */ } /* 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); HDassert(chk_proxy->cache_info.type == H5AC_OHDR_CHK);
/* Destroy object header chunk proxy */ /* 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") HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to destroy object header chunk proxy")
done: done:
@ -1453,39 +1488,3 @@ done:
FUNC_LEAVE_NOAPI(ret_value) FUNC_LEAVE_NOAPI(ret_value)
} /* H5O__chunk_serialize() */ } /* 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() */

View File

@ -93,7 +93,8 @@ H5FL_DEFINE(H5O_chunk_proxy_t);
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
herr_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 */ H5O_chunk_proxy_t *chk_proxy = NULL; /* Proxy for chunk, to mark it dirty in the cache */
herr_t ret_value = SUCCEED; /* Return value */ 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))) if(NULL == (chk_proxy = H5FL_CALLOC(H5O_chunk_proxy_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") 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 */ /* Increment reference count on object header */
if(H5O_inc_rc(oh) < 0) if(H5O_inc_rc(oh) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, FAIL, "can't increment reference count on object header") 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 */ /* 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) 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") 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: done:
if(ret_value < 0) if(ret_value < 0)
if(chk_proxy) if(chk_proxy && H5O__chunk_dest(chk_proxy) < 0)
chk_proxy = H5FL_FREE(H5O_chunk_proxy_t, chk_proxy); HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to destroy object header chunk")
FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL) FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
} /* end H5O_chunk_add() */ } /* 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") HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, NULL, "can't increment reference count on object header")
/* Set chunk proxy fields */ /* Set chunk proxy fields */
chk_proxy->f = f;
chk_proxy->oh = oh; chk_proxy->oh = oh;
chk_proxy->chunkno = idx; chk_proxy->chunkno = idx;
} /* end if */ } /* end if */
@ -200,8 +204,8 @@ H5O_chunk_protect(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx)
done: done:
/* Cleanup on error */ /* Cleanup on error */
if(!ret_value) if(!ret_value)
if(0 == idx && chk_proxy) if(0 == idx && chk_proxy && H5O__chunk_dest(chk_proxy) < 0)
chk_proxy = H5FL_FREE(H5O_chunk_proxy_t, chk_proxy); HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, NULL, "unable to destroy object header chunk")
FUNC_LEAVE_NOAPI_TAG(ret_value, NULL) FUNC_LEAVE_NOAPI_TAG(ret_value, NULL)
} /* end H5O_chunk_protect() */ } /* end H5O_chunk_protect() */
@ -409,3 +413,39 @@ done:
FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL) FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
} /* end H5O_chunk_delete() */ } /* 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() */

View File

@ -2254,176 +2254,3 @@ done:
FUNC_LEAVE_NOAPI(ret_value) FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_flush_msgs() */ } /* 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() */

View File

@ -245,7 +245,6 @@ struct H5O_msg_class_t {
struct H5O_mesg_t { struct H5O_mesg_t {
const H5O_msg_class_t *type; /*type of message */ const H5O_msg_class_t *type; /*type of message */
hbool_t dirty; /*raw out of date wrt native */ hbool_t dirty; /*raw out of date wrt native */
hbool_t locked; /*message is locked into chunk */
uint8_t flags; /*message flags */ uint8_t flags; /*message flags */
H5O_msg_crt_idx_t crt_idx; /*message creation index */ H5O_msg_crt_idx_t crt_idx; /*message creation index */
unsigned chunkno; /*chunk number for this mesg */ unsigned chunkno; /*chunk number for this mesg */
@ -254,6 +253,17 @@ struct H5O_mesg_t {
size_t raw_size; /*size with alignment */ 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 { typedef struct H5O_chunk_t {
haddr_t addr; /*chunk file address */ haddr_t addr; /*chunk file address */
size_t size; /*chunk size */ 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 */ H5AC_info_t cache_info; /* Information for metadata cache functions, _must_ be */
/* first field in structure */ /* first field in structure */
H5F_t *f; /* Pointer to file for object header/chunk */
H5O_t *oh; /* Object header for this chunk */ H5O_t *oh; /* Object header for this chunk */
unsigned chunkno; /* Chunk number 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; } H5O_chunk_proxy_t;
/* Callback information for loading object header chunk from disk */ /* 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); const H5O_mesg_operator_t *op, void *op_data, hid_t dxpl_id);
/* Object header chunk routines */ /* 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, H5_DLL H5O_chunk_proxy_t *H5O_chunk_protect(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
unsigned idx); unsigned idx);
H5_DLL herr_t H5O_chunk_unprotect(H5F_t *f, hid_t dxpl_id, 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_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_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_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 */ /* 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, 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 */ /* Object header allocation routines */
H5_DLL herr_t H5O_alloc_msgs(H5O_t *oh, size_t min_alloc); 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, 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); 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); H5_DLL herr_t H5O_condense_header(H5F_t *f, H5O_t *oh, hid_t dxpl_id);

View File

@ -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); 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, H5_DLL herr_t H5O_msg_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
unsigned type_id, void *mesg); 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 */ /* Object metadata flush/refresh routines */
H5_DLL herr_t H5O_flush_common(H5O_loc_t *oloc, hid_t obj_id, hid_t dxpl_id); H5_DLL herr_t H5O_flush_common(H5O_loc_t *oloc, hid_t obj_id, hid_t dxpl_id);

View File

@ -811,148 +811,6 @@ main(void)
FAIL_STACK_ERROR FAIL_STACK_ERROR
PASSED(); 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 */ /* Close the file we created */
if(H5Fclose(file) < 0) if(H5Fclose(file) < 0)
TEST_ERROR TEST_ERROR