diff options
Diffstat (limited to 'src/H5Omessage.c')
-rw-r--r-- | src/H5Omessage.c | 250 |
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 */ |