diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2007-05-14 20:24:08 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2007-05-14 20:24:08 (GMT) |
commit | 31ff357f3190a869147378a9a136510be2caafd7 (patch) | |
tree | 5220b17a8e4b6c434b799108719a1dc15d6c0326 /src/H5Omessage.c | |
parent | 1726061075e9adc99ac2286fb542438acc79c4ab (diff) | |
download | hdf5-31ff357f3190a869147378a9a136510be2caafd7.zip hdf5-31ff357f3190a869147378a9a136510be2caafd7.tar.gz hdf5-31ff357f3190a869147378a9a136510be2caafd7.tar.bz2 |
[svn-r13753] Description:
Check in "unique, but sharable" optimization to ISOHM code, which
allows object header messages that are only used in one object to remain in
the sole user's header, but migrates messages that are used in more than one
header into the ISOHM heap.
Tested on:
Mac OS X/32 10.4.9 (amazon)
FreeBSD/32 6.2 (duty)
Linux/32 2.6 (chicago)
Linux/64 2.6 (chicago2)
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 */ |