summaryrefslogtreecommitdiffstats
path: root/src/H5Omessage.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Omessage.c')
-rw-r--r--src/H5Omessage.c250
1 files changed, 166 insertions, 84 deletions
diff --git a/src/H5Omessage.c b/src/H5Omessage.c
index 6eedc1f..7c5a38d 100644
--- a/src/H5Omessage.c
+++ b/src/H5Omessage.c
@@ -348,30 +348,42 @@ H5O_msg_write_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *ty
/* Check for modifying a constant message */
if(idx_msg->flags & H5O_MSG_FLAG_CONSTANT)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to modify constant message")
- else if(idx_msg->flags & H5O_MSG_FLAG_SHARED) {
- /* This message is shared, but it's being modified. This is valid if
- * it's shared in the heap .
- * First, make sure it's not a committed message; these can't ever
- * be modified.
+ /* This message is shared, but it's being modified. */
+ else if((idx_msg->flags & H5O_MSG_FLAG_SHARED) || (idx_msg->flags & H5O_MSG_FLAG_SHAREABLE)) {
+ htri_t status; /* Status of "try share" call */
+
+ /* First, sanity check to make sure it's not a committed message;
+ * these can't ever be modified.
+ */
+ HDassert(((H5O_shared_t *)idx_msg->native)->type != H5O_SHARE_TYPE_COMMITTED);
+
+ /* Also, sanity check that a message doesn't switch status from being
+ * shared (or sharable) to being unsharable. (Which could cause
+ * a message to increase in size in the object header)
*/
- HDassert(!(((H5O_shared_t *)idx_msg->native)->flags & H5O_COMMITTED_FLAG));
+ HDassert(!(mesg_flags & H5O_MSG_FLAG_DONTSHARE));
/* Remove the old message from the SOHM index */
- if(H5SM_try_delete(f, dxpl_id, idx_msg->type->id, (H5O_shared_t *)idx_msg->native) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to delete message from SOHM table")
-
- /* Should this message be written as a SOHM? */
- if(!(mesg_flags & H5O_MSG_FLAG_DONTSHARE)) {
- htri_t shared_mesg; /* Whether the message should be shared */
-
-/* XXX: Maybe this should be before the "try_delete" call? */
-/* (and the try_delete would need to use a copy of the message's shared info) */
- if((shared_mesg = H5SM_try_share(f, dxpl_id, idx_msg->type->id, mesg)) > 0)
- /* Mark the message as shared */
- mesg_flags |= H5O_MSG_FLAG_SHARED;
- else if(shared_mesg < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "error while trying to share message")
- } /* end if */
+ /* (It would be more efficient to try to share the message first, then
+ * delete it (avoiding thrashing the index in the case the ref.
+ * count on the message is one), but this causes problems when
+ * the location of the object changes (from in another object's
+ * header to the SOHM heap), so just delete it first -QAK)
+ */
+ if(H5SM_delete(f, dxpl_id, oh, (H5O_shared_t *)idx_msg->native) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete message from SOHM index")
+
+ /* If we're replacing a shared message, the new message must be shared
+ * (or else it may increase in size!), so pass in NULL for the OH
+ * location.
+ *
+ * XXX: This doesn't handle freeing extra space in object header from
+ * a message shrinking.
+ */
+ if((status = H5SM_try_share(f, dxpl_id, ((mesg_flags & H5O_MSG_FLAG_SHARED) ? NULL : oh), idx_msg->type->id, mesg, &mesg_flags)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "error while trying to share message")
+ if(status == FALSE && (mesg_flags & H5O_MSG_FLAG_SHARED))
+ HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "message changed sharing status")
} /* end if */
/* Copy the information for the message */
@@ -491,7 +503,7 @@ H5O_msg_read_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id,
* Decode the message if necessary. If the message is shared then retrieve
* native message through the shared interface.
*/
- H5O_LOAD_NATIVE(f, dxpl_id, &(oh->mesg[idx]), NULL)
+ H5O_LOAD_NATIVE(f, dxpl_id, oh, &(oh->mesg[idx]), NULL)
/*
* The object header caches the native message (along with
@@ -572,7 +584,8 @@ H5O_msg_reset_real(const H5O_msg_class_t *type, void *native)
if(type->reset) {
if((type->reset)(native) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "reset method failed")
- } else
+ } /* end if */
+ else
HDmemset(native, 0, type->native_size);
} /* end if */
@@ -1244,7 +1257,7 @@ H5O_msg_iterate_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type,
for(sequence = 0, idx = 0, idx_msg = &oh->mesg[0]; idx < oh->nmesgs && !ret_value; idx++, idx_msg++) {
if(type == idx_msg->type) {
/* Decode the message if necessary. */
- H5O_LOAD_NATIVE(f, dxpl_id, idx_msg, FAIL)
+ H5O_LOAD_NATIVE(f, dxpl_id, oh, idx_msg, FAIL)
/* Check for making an "internal" (i.e. within the H5O package) callback */
if(op->op_type == H5O_MESG_OP_LIB)
@@ -1321,7 +1334,7 @@ H5O_msg_raw_size(const H5F_t *f, unsigned type_id, hbool_t disable_shared,
HDassert(mesg);
/* Compute the raw data size for the mesg */
- if((ret_value = (type->raw_size)(f, disable_shared, mesg)) == 0)
+ if(0 == (ret_value = (type->raw_size)(f, disable_shared, mesg)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOUNT, 0, "unable to determine size of message")
done:
@@ -1466,7 +1479,7 @@ htri_t
H5O_msg_can_share(unsigned type_id, const void *mesg)
{
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
- htri_t ret_value = FALSE;
+ htri_t ret_value;
FUNC_ENTER_NOAPI_NOFUNC(H5O_msg_can_share)
@@ -1477,16 +1490,14 @@ H5O_msg_can_share(unsigned type_id, const void *mesg)
HDassert(mesg);
/* If there is a can_share callback, use it */
- if((type->can_share))
+ if(type->can_share)
ret_value = (type->can_share)(mesg);
else {
/* Otherwise, the message can be shared if messages of this type are
- * shareable in general; i.e., if they have a set_share callback
+ * shareable in general; i.e., if they have the "is_sharable" flag
+ * in the "share_flags" class member set.
*/
- if(type->set_share)
- ret_value = TRUE;
- else
- ret_value = FALSE;
+ ret_value = (type->share_flags & H5O_SHARE_IS_SHARABLE) ? TRUE : FALSE;
} /* end else */
FUNC_LEAVE_NOAPI(ret_value)
@@ -1494,6 +1505,43 @@ H5O_msg_can_share(unsigned type_id, const void *mesg)
/*-------------------------------------------------------------------------
+ * Function: H5O_msg_can_share_in_ohdr
+ *
+ * Purpose: Check if the message class allows its messages to be shared
+ * in the object's header.
+ *
+ * Return: Object can be shared: TRUE
+ * Object cannot be shared: FALSE
+ *
+ * Programmer: Quincey Koziol
+ * March 15 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5O_msg_can_share_in_ohdr(unsigned type_id)
+{
+ const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
+ htri_t ret_value;
+
+ FUNC_ENTER_NOAPI_NOFUNC(H5O_msg_can_share_in_ohdr)
+
+ /* Check args */
+ HDassert(type_id < NELMTS(H5O_msg_class_g));
+ type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
+ HDassert(type);
+
+ /* Otherwise, the message can be shared if messages of this type are
+ * shareable in general; i.e., if they have the "is_sharable" flag
+ * in the "share_flags" class member set.
+ */
+ ret_value = (type->share_flags & H5O_SHARE_IN_OHDR) ? TRUE : FALSE;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_msg_can_share_in_ohdr() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5O_msg_is_shared
*
* Purpose: Call the 'is_shared' method for a
@@ -1522,11 +1570,11 @@ H5O_msg_is_shared(unsigned type_id, const void *mesg)
HDassert(type);
HDassert(mesg);
- /* If message class isn't sharable, then obviously it's not a shared message! */
- if(!(type->is_sharable))
- ret_value = FALSE;
+ /* If messages in a class aren't sharable, then obviously this message isn't shared! :-) */
+ if(type->share_flags & H5O_SHARE_IS_SHARABLE)
+ ret_value = H5O_IS_STORED_SHARED(((const H5O_shared_t *)mesg)->type);
else
- ret_value = H5O_IS_SHARED(((const H5O_shared_t *)mesg)->flags);
+ ret_value = FALSE;
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_msg_is_shared() */
@@ -1547,27 +1595,36 @@ H5O_msg_is_shared(unsigned type_id, const void *mesg)
*-------------------------------------------------------------------------
*/
herr_t
-H5O_msg_set_share(unsigned type_id, H5O_shared_t *share, void *mesg)
+H5O_msg_set_share(unsigned type_id, const H5O_shared_t *share, void *mesg)
{
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
- herr_t ret_value; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5O_msg_set_share, FAIL)
/* Check args */
- HDassert(share);
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
HDassert(type);
- HDassert(type->set_share);
+ HDassert(type->share_flags & H5O_SHARE_IS_SHARABLE);
HDassert(mesg);
- HDassert(share->flags != H5O_NOT_SHARED);
+ HDassert(share);
+ HDassert(share->type != H5O_SHARE_TYPE_UNSHARED);
- /* Set this message as the shared message for the message, wiping out
- * any information that was there before
+ /* If there's a special action for this class that needs to be performed
+ * when setting the shared component, do that
*/
- if((ret_value = (type->set_share)(mesg, share)) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to set shared message information")
+ if(type->set_share) {
+ if((type->set_share)(mesg, share) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to set shared message information")
+ } /* end if */
+ else {
+ /* Set this message as the shared component for the message, wiping out
+ * any information that was there before
+ */
+ if(H5O_set_shared((H5O_shared_t *)mesg, share) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to set shared message information")
+ } /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1592,30 +1649,63 @@ herr_t
H5O_msg_reset_share(unsigned type_id, void *mesg)
{
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
- H5O_shared_t sh_mesg; /* Shared message */
- herr_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5O_msg_reset_share, FAIL)
+ FUNC_ENTER_NOAPI_NOFUNC(H5O_msg_reset_share)
/* Check args */
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
HDassert(type);
- HDassert(type->set_share);
+ HDassert(type->share_flags & H5O_SHARE_IS_SHARABLE);
HDassert(mesg);
- /* Initialize the shared message to zero. */
- HDmemset(&sh_mesg, 0, sizeof(H5O_shared_t));
+ /* Reset the shared component in the message to zero. */
+ HDmemset((H5O_shared_t *)mesg, 0, sizeof(H5O_shared_t));
- /* Set this message as the shared message for the message, wiping out
- * any information that was there before
- */
- if((ret_value = (type->set_share)(mesg, &sh_mesg)) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to reset shared message information")
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O_msg_reset_share() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_msg_get_crt_index
+ *
+ * Purpose: Call the 'get creation index' method for a message.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * March 15 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_msg_get_crt_index(unsigned type_id, const void *mesg, H5O_msg_crt_idx_t *crt_idx)
+{
+ const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5O_msg_get_crt_index, FAIL)
+
+ /* Check args */
+ HDassert(type_id < NELMTS(H5O_msg_class_g));
+ type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
+ HDassert(type);
+ HDassert(mesg);
+ HDassert(crt_idx);
+
+ /* If there is a "get_crt_index callback, use it */
+ if(type->get_crt_index) {
+ /* Retrieve the creation index from the native message */
+ if((type->get_crt_index)(mesg, crt_idx) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to retrieve creation index")
+ } /* end if */
+ else
+ *crt_idx = 0;
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_msg_reset_share() */
+} /* end H5O_msg_get_crt_index() */
/*-------------------------------------------------------------------------
@@ -1664,9 +1754,6 @@ done:
* Purpose: Decode a binary object description and return a new
* object handle.
*
- * Note: This routine is not guaranteed to work with all possible
- * header messages, use with care.
- *
* Return: Success: Pointer to object(data type or space)
*
* Failure: NULL
@@ -1720,10 +1807,9 @@ done:
*/
void *
H5O_msg_copy_file(const H5O_msg_class_t *type, H5F_t *file_src,
- void *native_src, H5F_t *file_dst, hid_t dxpl_id,
- hbool_t *shared, H5O_copy_t *cpy_info, void *udata)
+ void *native_src, H5F_t *file_dst, hbool_t *recompute_size,
+ H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id)
{
- htri_t is_shared; /* Whether message is shared */
void *native_mesg = NULL;
void *ret_value;
@@ -1735,19 +1821,15 @@ H5O_msg_copy_file(const H5O_msg_class_t *type, H5F_t *file_src,
HDassert(file_src);
HDassert(native_src);
HDassert(file_dst);
+ HDassert(recompute_size);
HDassert(cpy_info);
/* The copy_file callback will return an H5O_shared_t only if the message
* to be copied is a committed datatype.
*/
- if(NULL == (native_mesg = (type->copy_file)(file_src, native_src, file_dst, dxpl_id, cpy_info, udata)))
+ if(NULL == (native_mesg = (type->copy_file)(file_src, native_src, file_dst, recompute_size, cpy_info, udata, dxpl_id)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy object header message to file")
- /* Check if new message is shared */
- if((is_shared = H5O_msg_is_shared(type->id, native_mesg)) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to query message's shared status")
- *shared = is_shared;
-
/* Set return value */
ret_value = native_mesg;
@@ -1794,20 +1876,14 @@ H5O_msg_alloc(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *type,
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, UFAIL, "error determining if message is shared")
else if(shared_mesg > 0) {
/* Increment message's reference count */
- if(type->link && (type->link)(f, dxpl_id, native) < 0)
+ if(type->link && (type->link)(f, dxpl_id, oh, native) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, UFAIL, "unable to adjust shared message ref count")
*mesg_flags |= H5O_MSG_FLAG_SHARED;
} /* end if */
else {
- /* Avoid unsharable messages */
- if(!(*mesg_flags & H5O_MSG_FLAG_DONTSHARE)) {
- /* Attempt to share message */
- if((shared_mesg = H5SM_try_share(f, dxpl_id, type->id, native)) > 0)
- /* Mark the message as shared */
- *mesg_flags |= H5O_MSG_FLAG_SHARED;
- else if(shared_mesg < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, UFAIL, "error determining if message should be shared")
- } /* end if */
+ /* Attempt to share message */
+ if(H5SM_try_share(f, dxpl_id, oh, type->id, native, mesg_flags) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, UFAIL, "error determining if message should be shared")
} /* end else */
/* Allocate space in the object header for the message */
@@ -1891,6 +1967,10 @@ done:
* (while the shared message code needs to delete messages in
* the heap).
*
+ * open_oh is a pointer to a currently open object header so
+ * that the library doesn't try to re-protect it. If there is
+ * no such object header, it should be NULL.
+ *
* Return: Success: Non-negative
* Failure: Negative
*
@@ -1900,7 +1980,8 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5O_msg_delete(H5F_t *f, hid_t dxpl_id, unsigned type_id, const void *mesg)
+H5O_msg_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned type_id,
+ void *mesg)
{
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1914,7 +1995,7 @@ H5O_msg_delete(H5F_t *f, hid_t dxpl_id, unsigned type_id, const void *mesg)
HDassert(type);
/* delete */
- if((type->del) && (type->del)(f, dxpl_id, mesg) < 0)
+ if((type->del) && (type->del)(f, dxpl_id, open_oh, mesg) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message")
done:
@@ -1938,7 +2019,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_mesg_t *mesg)
+H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5O_mesg_t *mesg)
{
const H5O_msg_class_t *type = mesg->type; /* Type of object to free */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1948,13 +2029,14 @@ H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_mesg_t *mesg)
/* Check args */
HDassert(f);
HDassert(mesg);
+ HDassert(oh);
/* Check if there is a file space deletion callback for this type of message */
if(type->del) {
/* Decode the message if necessary. */
- H5O_LOAD_NATIVE(f, dxpl_id, mesg, FAIL)
+ H5O_LOAD_NATIVE(f, dxpl_id, oh, mesg, FAIL)
- if((type->del)(f, dxpl_id, mesg->native) < 0)
+ if((type->del)(f, dxpl_id, oh, mesg->native) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message")
} /* end if */