diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2010-04-15 19:57:02 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2010-04-15 19:57:02 (GMT) |
commit | ebd22f7643d53b234b43393d8ede23e0549caa5f (patch) | |
tree | 62b13c6ef0f705822fd925687073df7988bd8288 /src/H5O.c | |
parent | 227a351e4758ffb0af9882b00831ad6cf1acff3b (diff) | |
download | hdf5-ebd22f7643d53b234b43393d8ede23e0549caa5f.zip hdf5-ebd22f7643d53b234b43393d8ede23e0549caa5f.tar.gz hdf5-ebd22f7643d53b234b43393d8ede23e0549caa5f.tar.bz2 |
[svn-r18571] Description:
Bring r18542 from metadata journaling "merging" branch to trunk:
Bring new object header pin/unpin & protect/unprotect routines and
split-out object header chunk proxy changes from metadata_journaling branch to
"merging" branch, along with some other minor tweaks to clean up compiler
warnings, etc.
Also: clean up chunk protect/unprotect calls when allocating or freeing
space in a chunk, optimize metadata accumulator code to avoid some re-reading
of information from the file, refactor H5O_pin/H5O_unpin from way they are done
on the merging branch back to way they were previously done on trunk, other
minor code cleanups, etc.
Tested on
FreeBSD/32 6.3 (duty) in debug mode
FreeBSD/64 6.3 (liberty) w/C++ & FORTRAN, in debug mode
Linux/64-amd64 2.6 (amani) w/Intel compilers, w/default API=1.6.x,
w/C++ & FORTRAN, in production mode
Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN,
w/szip filter, in production mode
Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN,
in production mode
Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in debug mode
Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in production mode
Mac OS X/32 10.6.3 (amazon) in debug mode
Mac OS X/32 10.6.3 (amazon) w/C++ & FORTRAN, w/threadsafe,
in production mode
Diffstat (limited to 'src/H5O.c')
-rw-r--r-- | src/H5O.c | 509 |
1 files changed, 416 insertions, 93 deletions
@@ -141,6 +141,9 @@ H5FL_SEQ_DEFINE(H5O_chunk_t); /* Declare a free list to manage the chunk image information */ H5FL_BLK_DEFINE(chunk_image); +/* Declare external the free list for H5O_cont_t sequences */ +H5FL_SEQ_EXTERN(H5O_cont_t); + /*****************************/ /* Library Private Variables */ @@ -1173,7 +1176,7 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id, /* Determine correct value for chunk #0 size bits */ /* Avoid compiler warning on 32-bit machines */ #if H5_SIZEOF_SIZE_T > H5_SIZEOF_INT32_T - if(size_hint > 4294967295) + if(size_hint > 4294967295UL) oh->flags |= H5O_HDR_CHUNK0_8; else #endif /* H5_SIZEOF_SIZE_T > H5_SIZEOF_INT32_T */ @@ -1189,7 +1192,7 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id, /* Compute total size of initial object header */ /* (i.e. object header prefix and first chunk) */ - oh_size = H5O_SIZEOF_HDR(oh) + size_hint; + oh_size = (size_t)H5O_SIZEOF_HDR(oh) + size_hint; /* Allocate disk space for header and first chunk */ if(HADDR_UNDEF == (oh_addr = H5MF_alloc(f, H5FD_MEM_OHDR, dxpl_id, (hsize_t)oh_size))) @@ -1201,7 +1204,6 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id, HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* Initialize the first chunk */ - oh->chunk[0].dirty = TRUE; oh->chunk[0].addr = oh_addr; oh->chunk[0].size = oh_size; oh->chunk[0].gap = 0; @@ -1457,13 +1459,18 @@ done: *------------------------------------------------------------------------- */ int -H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, unsigned *oh_flags) +H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, hbool_t *deleted) { haddr_t addr = H5O_OH_GET_ADDR(oh); /* Object header address */ int ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5O_link_oh, FAIL) + /* check args */ + HDassert(f); + HDassert(oh); + HDassert(deleted); + /* Check for adjusting link count */ if(adjust) { if(adjust < 0) { @@ -1475,7 +1482,8 @@ H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, unsigned *oh_flags) oh->nlink += adjust; /* Mark object header as dirty in cache */ - *oh_flags |= H5AC__DIRTIED_FLAG; + if(H5AC_mark_pinned_or_protected_entry_dirty(oh) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, FAIL, "unable to mark object header as dirty") /* Check if the object should be deleted */ if(oh->nlink == 0) { @@ -1486,12 +1494,8 @@ H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, unsigned *oh_flags) HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't mark object for deletion") } /* end if */ else { - /* Delete object right now */ - if(H5O_delete_oh(f, dxpl_id, oh) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file") - /* Mark the object header for deletion */ - *oh_flags = H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; + *deleted = TRUE; } /* end else */ } /* end if */ } /* end if */ @@ -1510,7 +1514,8 @@ H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, unsigned *oh_flags) oh->nlink += adjust; /* Mark object header as dirty in cache */ - *oh_flags |= H5AC__DIRTIED_FLAG; + if(H5AC_mark_pinned_or_protected_entry_dirty(oh) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, FAIL, "unable to mark object header as dirty") } /* end if */ /* Check for operations on refcount message */ @@ -1520,7 +1525,7 @@ H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, unsigned *oh_flags) /* Check for removing refcount message */ if(oh->nlink <= 1) { if(H5O_msg_remove_real(f, oh, H5O_MSG_REFCOUNT, H5O_ALL, NULL, NULL, TRUE, dxpl_id) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete refcount message") + HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete refcount message") oh->has_refcount_msg = FALSE; } /* end if */ /* Update refcount message with new link count */ @@ -1528,7 +1533,7 @@ H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, unsigned *oh_flags) H5O_refcount_t refcount = oh->nlink; if(H5O_msg_write_real(f, dxpl_id, oh, H5O_MSG_REFCOUNT, H5O_MSG_FLAG_DONTSHARE, 0, &refcount) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update refcount message") + HGOTO_ERROR(H5E_OHDR, H5E_CANTUPDATE, FAIL, "unable to update refcount message") } /* end else */ } /* end if */ else { @@ -1537,7 +1542,7 @@ H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, unsigned *oh_flags) H5O_refcount_t refcount = oh->nlink; if(H5O_msg_append_real(f, dxpl_id, oh, H5O_MSG_REFCOUNT, H5O_MSG_FLAG_DONTSHARE, 0, &refcount) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to create new refcount message") + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "unable to create new refcount message") oh->has_refcount_msg = TRUE; } /* end if */ } /* end else */ @@ -1548,7 +1553,7 @@ H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, unsigned *oh_flags) ret_value = (int)oh->nlink; done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_link_oh() */ @@ -1572,9 +1577,8 @@ int H5O_link(const H5O_loc_t *loc, int adjust, hid_t dxpl_id) { H5O_t *oh = NULL; - H5AC_protect_t oh_acc; /* Access mode for protecting object header */ - unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Whether the object was deleted */ - int ret_value; /* Return value */ + hbool_t deleted = FALSE; /* Whether the object was deleted */ + int ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5O_link, FAIL) @@ -1583,29 +1587,30 @@ H5O_link(const H5O_loc_t *loc, int adjust, hid_t dxpl_id) HDassert(loc->file); HDassert(H5F_addr_defined(loc->addr)); - /* Get header */ - oh_acc = adjust ? H5AC_WRITE : H5AC_READ; - if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, oh_acc))) - HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header") + /* Pin the object header */ + if(NULL == (oh = H5O_pin(loc, dxpl_id))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header") /* Call the "real" link routine */ - if((ret_value = H5O_link_oh(loc->file, adjust, dxpl_id, oh, &oh_flags)) < 0) + if((ret_value = H5O_link_oh(loc->file, adjust, dxpl_id, oh, &deleted)) < 0) HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust object link count") done: - if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0) - HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header") + if(oh && H5O_unpin(oh) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header") + if(ret_value >= 0 && deleted && H5O_delete(loc->file, dxpl_id, loc->addr) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file") FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_link() */ /*------------------------------------------------------------------------- - * Function: H5O_pin + * Function: H5O_protect * - * Purpose: Pin an object header down for use during a sequence of message - * operations, which prevents the object header from being - * evicted from the cache. + * Purpose: Wrapper around H5AC_protect for use during a H5O_protect-> + * H5O_msg_append->...->H5O_msg_append->H5O_unprotect sequence of calls + * during an object's creation. * * Return: Success: Pointer to the object header structure for the * object. @@ -1618,12 +1623,15 @@ done: *------------------------------------------------------------------------- */ H5O_t * -H5O_pin(H5O_loc_t *loc, hid_t dxpl_id) +H5O_protect(const H5O_loc_t *loc, hid_t dxpl_id, H5AC_protect_t prot) { - H5O_t *oh = NULL; /* Object header */ - H5O_t *ret_value; /* Return value */ + H5O_t *oh = NULL; /* Object header protected */ + H5O_cache_ud_t udata; /* User data for protecting object header */ + H5O_cont_msgs_t cont_msg_info; /* Continuation message info */ + unsigned file_intent; /* R/W intent on file */ + H5O_t *ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5O_pin, NULL) + FUNC_ENTER_NOAPI(H5O_protect, NULL) /* check args */ HDassert(loc); @@ -1631,29 +1639,228 @@ H5O_pin(H5O_loc_t *loc, hid_t dxpl_id) HDassert(H5F_addr_defined(loc->addr)); /* Check for write access on the file */ - if(0 == (H5F_INTENT(loc->file) & H5F_ACC_RDWR)) + file_intent = H5F_INTENT(loc->file); + if((prot == H5AC_WRITE) && (0 == (file_intent & H5F_ACC_RDWR))) HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "no write intent on file") + /* Construct the user data for protect callback */ + udata.made_attempt = FALSE; + udata.v1_pfx_nmesgs = 0; + udata.common.f = loc->file; + udata.common.dxpl_id = dxpl_id; + udata.common.file_intent = file_intent; + udata.common.merged_null_msgs = 0; + udata.common.mesgs_modified = FALSE; + HDmemset(&cont_msg_info, 0, sizeof(cont_msg_info)); + udata.common.cont_msg_info = &cont_msg_info; + /* Lock the object header into the cache */ - if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE))) + if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, &udata, prot))) HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header") - /* Check if the object header needs to be pinned */ - if(0 == oh->npins) { - /* Mark object header as un-evictable */ - if(H5AC_pin_protected_entry(oh) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, NULL, "unable to pin object header") + /* Check if there are any continuation messages to process */ + if(cont_msg_info.nmsgs > 0) { + size_t curr_msg; /* Current continuation message to process */ + H5O_chk_cache_ud_t chk_udata; /* User data for loading chunk */ + + /* Sanity check - we should only have continuation messages to process + * when the object header is actually loaded from the file. + */ + HDassert(udata.made_attempt == TRUE); + + /* Construct the user data for protecting chunks */ + chk_udata.decoding = TRUE; + chk_udata.oh = oh; + chk_udata.chunkno = UINT_MAX; /* Set to invalid value, for better error detection */ + chk_udata.common.f = loc->file; + chk_udata.common.dxpl_id = dxpl_id; + chk_udata.common.file_intent = file_intent; + chk_udata.common.merged_null_msgs = udata.common.merged_null_msgs; + chk_udata.common.mesgs_modified = udata.common.mesgs_modified; + chk_udata.common.cont_msg_info = &cont_msg_info; + + /* Read in continuation messages, until there are no more */ + curr_msg = 0; + while(curr_msg < cont_msg_info.nmsgs) { + H5O_chunk_proxy_t *chk_proxy; /* Proxy for chunk, to bring it into memory */ +#ifndef NDEBUG + unsigned chkcnt = oh->nchunks; /* Count of chunks (for sanity checking) */ +#endif /* NDEBUG */ + + /* Bring the chunk into the cache */ + /* (which adds to the object header */ + chk_udata.chunk_size = cont_msg_info.msgs[curr_msg].size; + if(NULL == (chk_proxy = (H5O_chunk_proxy_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR_CHK, cont_msg_info.msgs[curr_msg].addr, NULL, &chk_udata, prot))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header chunk") + + /* Sanity check */ + HDassert(chk_proxy->oh == oh); + HDassert(chk_proxy->chunkno == chkcnt); + HDassert(oh->nchunks == (chkcnt + 1)); + + /* Release the chunk from the cache */ + if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR_CHK, cont_msg_info.msgs[curr_msg].addr, chk_proxy, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to release object header chunk") + + /* Advance to next continuation message */ + curr_msg++; + } /* end while */ + + /* Release any continuation messages built up */ + if(cont_msg_info.msgs) + cont_msg_info.msgs = (H5O_cont_t *)H5FL_SEQ_FREE(H5O_cont_t, cont_msg_info.msgs); + + /* Pass back out some of the chunk's user data */ + udata.common.merged_null_msgs = chk_udata.common.merged_null_msgs; + udata.common.mesgs_modified = chk_udata.common.mesgs_modified; } /* end if */ - /* Increment the pin count */ - oh->npins++; + /* Check for incorrect # of object header messages, if we've just loaded + * this object header from the file + */ + if(udata.made_attempt) { + /* Check for incorrect # of messages in v1 object header */ + if(oh->version == H5O_VERSION_1 && + (oh->nmesgs + udata.common.merged_null_msgs) != udata.v1_pfx_nmesgs) { +/* Don't enforce the error on an incorrect # of object header messages bug + * unless strict format checking is enabled. This allows for older + * files, created with a version of the library that had a bug in tracking + * the correct # of header messages to be read in without the library + * erroring out here. -QAK + */ +#ifdef H5_STRICT_FORMAT_CHECKS + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "corrupt object header - incorrect # of messages") +#else /* H5_STRICT_FORMAT_CHECKS */ + /* Mark object header prefix dirty later if we don't have write access */ + /* (object header will have been marked dirty during protect, if we + * have write access -QAK) + */ + if(prot != H5AC_WRITE) + oh->prefix_modified = TRUE; +#ifndef NDEBUG + else { + unsigned oh_status = 0; /* Object header entry cache status */ + + /* Check the object header's status in the metadata cache */ + if(H5AC_get_entry_status(loc->file, loc->addr, &oh_status) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to check metadata cache status for object header") + + /* Make certain that object header is not dirty */ + HDassert(!(oh_status & H5AC_ES__IS_DIRTY)); + } /* end else */ +#endif /* NDEBUG */ +#endif /* H5_STRICT_FORMAT_CHECKS */ + } /* end if */ + + /* Check for any messages that were modified while being read in */ + if(udata.common.mesgs_modified && prot != H5AC_WRITE) + oh->mesgs_modified = TRUE; + } /* end if */ + + /* Take care of loose ends for modifications made while bringing in the + * object header & chunks. + */ + if(prot == H5AC_WRITE) { + /* Check for the object header prefix being modified somehow */ + /* (usually through updating the # of object header messages) */ + if(oh->prefix_modified) { + /* Mark the header as dirty now */ + if(H5AC_mark_pinned_or_protected_entry_dirty(oh) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, NULL, "unable to mark object header as dirty") + + /* Reset flag */ + oh->prefix_modified = FALSE; + } /* end if */ + + /* Check for deferred dirty messages */ + if(oh->mesgs_modified) { + unsigned u; /* Local index variable */ + + /* Loop through all messages, marking their chunks as dirty */ + /* (slightly inefficient, since we don't know exactly which messages + * were modified when the object header & chunks were brought in + * from the file, but this only can happen once per load -QAK) + */ + for(u = 0; u < oh->nmesgs; u++) { + /* Mark each chunk with a dirty message as dirty also */ + if(oh->mesg[u].dirty) { + H5O_chunk_proxy_t *chk_proxy; /* Chunk that message is in */ + + /* Protect chunk */ + if(NULL == (chk_proxy = H5O_chunk_protect(loc->file, dxpl_id, oh, oh->mesg[u].chunkno))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header chunk") + + /* Unprotect chunk, marking it dirty */ + if(H5O_chunk_unprotect(loc->file, dxpl_id, oh, chk_proxy, H5AC__DIRTIED_FLAG) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to unprotect object header chunk") + } /* end if */ + } /* end for */ + + /* Reset flag */ + oh->mesgs_modified = FALSE; + } /* end if */ + } /* end if */ + +#ifdef H5O_DEBUG +H5O_assert(oh); +#endif /* H5O_DEBUG */ + + /* Set return value */ + ret_value = oh; + +done: + if(ret_value == NULL && oh) { + if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to release object header") + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_protect() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_pin + * + * Purpose: Pin an object header down for use during a sequence of message + * operations, which prevents the object header from being + * evicted from the cache. + * + * Return: Success: Pointer to the object header structure for the + * object. + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Jul 13 2008 + * + *------------------------------------------------------------------------- + */ +H5O_t * +H5O_pin(const H5O_loc_t *loc, hid_t dxpl_id) +{ + H5O_t *oh = NULL; /* Object header */ + H5O_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_pin, NULL) + + /* check args */ + HDassert(loc); + + /* Get header */ + if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_WRITE))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to protect object header") + + /* Increment the reference count on the object header */ + /* (which will pin it, if appropriate) */ + if(H5O_inc_rc(oh) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, NULL, "unable to increment reference count on object header") /* Set the return value */ ret_value = oh; done: /* Release the object header from the cache */ - if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, ret_value, H5AC__NO_FLAGS_SET) < 0) + if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0) HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to release object header") FUNC_LEAVE_NOAPI(ret_value) @@ -1670,8 +1877,8 @@ done: * Failure: Negative * * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Dec 31 2002 + * koziol@hdfgroup.org + * Jul 13 2008 * *------------------------------------------------------------------------- */ @@ -1685,15 +1892,10 @@ H5O_unpin(H5O_t *oh) /* check args */ HDassert(oh); - /* Check if this is the last unpin operation */ - if(1 == oh->npins) { - /* Mark object header as evictable again */ - if(H5AC_unpin_entry(oh) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header") - } /* end if */ - - /* Decrement the pin count */ - oh->npins--; + /* Decrement the reference count on the object header */ + /* (which will unpin it, if appropriate) */ + if(H5O_dec_rc(oh) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "unable to decrement reference count on object header") done: FUNC_LEAVE_NOAPI(ret_value) @@ -1701,6 +1903,42 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_unprotect + * + * Purpose: Wrapper around H5AC_unprotect for use during a H5O_protect-> + * H5O_msg_append->...->H5O_msg_append->H5O_unprotect sequence of calls + * during an object's creation. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Dec 31 2002 + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_unprotect(const H5O_loc_t *loc, hid_t dxpl_id, H5O_t *oh, unsigned oh_flags) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_unprotect, FAIL) + + /* check args */ + HDassert(loc); + HDassert(oh); + + /* Unprotect the object header */ + if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, oh->chunk[0].addr, oh, oh_flags) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_unprotect() */ + + +/*------------------------------------------------------------------------- * Function: H5O_touch_oh * * Purpose: If FORCE is non-zero then create a modification time message @@ -1717,6 +1955,8 @@ done: herr_t H5O_touch_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, hbool_t force) { + H5O_chunk_proxy_t *chk_proxy = NULL; /* Chunk that message is in */ + unsigned chk_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting chunk */ time_t now; /* Current time */ herr_t ret_value = SUCCEED; /* Return value */ @@ -1755,6 +1995,10 @@ H5O_touch_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, hbool_t force) oh->mesg[idx].flags = (uint8_t)mesg_flags; } /* end if */ + /* Protect chunk */ + if(NULL == (chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, oh->mesg[idx].chunkno))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk") + /* Allocate 'native' space, if necessary */ if(NULL == oh->mesg[idx].native) { if(NULL == (oh->mesg[idx].native = H5FL_MALLOC(time_t))) @@ -1766,19 +2010,24 @@ H5O_touch_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, hbool_t force) /* Mark the message as dirty */ oh->mesg[idx].dirty = TRUE; + chk_flags |= H5AC__DIRTIED_FLAG; } /* end if */ else { /* XXX: For now, update access time & change fields in the object header */ /* (will need to add some code to update modification time appropriately) */ oh->atime = oh->ctime = now; - } /* end else */ - /* Mark object header as dirty in cache */ - if(H5AC_mark_pinned_or_protected_entry_dirty(oh) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, FAIL, "unable to mark object header as dirty") + /* Mark object header as dirty in cache */ + if(H5AC_mark_pinned_or_protected_entry_dirty(oh) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, FAIL, "unable to mark object header as dirty") + } /* end else */ } /* end if */ done: + /* Release chunk */ + if(chk_proxy && H5O_chunk_unprotect(f, dxpl_id, oh, chk_proxy, chk_flags) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk") + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_touch_oh() */ @@ -1809,13 +2058,9 @@ H5O_touch(const H5O_loc_t *loc, hbool_t force, hid_t dxpl_id) /* check args */ HDassert(loc); - HDassert(loc->file); - HDassert(H5F_addr_defined(loc->addr)); - if(0 == (H5F_INTENT(loc->file) & H5F_ACC_RDWR)) - HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "no write intent on file") /* Get the object header */ - if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE))) + if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_WRITE))) HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header") /* Create/Update the modification time message */ @@ -1826,7 +2071,7 @@ H5O_touch(const H5O_loc_t *loc, hbool_t force, hid_t dxpl_id) oh_flags |= H5AC__DIRTIED_FLAG; done: - if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0) + if(oh && H5O_unprotect(loc, dxpl_id, oh, oh_flags) < 0) HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header") FUNC_LEAVE_NOAPI(ret_value) @@ -1915,6 +2160,8 @@ herr_t H5O_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr) { H5O_t *oh = NULL; /* Object header information */ + H5O_loc_t loc; /* Object location for object to delete */ + unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting object header */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5O_delete, FAIL) @@ -1923,16 +2170,24 @@ H5O_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr) HDassert(f); HDassert(H5F_addr_defined(addr)); + /* Set up the object location */ + loc.file = f; + loc.addr = addr; + loc.holding_file = FALSE; + /* Get the object header information */ - if(NULL == (oh = (H5O_t *)H5AC_protect(f, dxpl_id, H5AC_OHDR, addr, NULL, NULL, H5AC_WRITE))) + if(NULL == (oh = H5O_protect(&loc, dxpl_id, H5AC_WRITE))) HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header") /* Delete object */ if(H5O_delete_oh(f, dxpl_id, oh) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file") + /* Mark object header as deleted */ + oh_flags = H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; + done: - if(oh && H5AC_unprotect(f, dxpl_id, H5AC_OHDR, addr, oh, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0) + if(oh && H5O_unprotect(&loc, dxpl_id, oh, oh_flags) < 0) HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") FUNC_LEAVE_NOAPI(ret_value) @@ -2005,7 +2260,7 @@ H5O_obj_type(const H5O_loc_t *loc, H5O_type_t *obj_type, hid_t dxpl_id) FUNC_ENTER_NOAPI(H5O_obj_type, FAIL) /* Load the object header */ - if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ))) + if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ))) HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header") /* Retrieve the type of the object */ @@ -2013,7 +2268,7 @@ H5O_obj_type(const H5O_loc_t *loc, H5O_type_t *obj_type, hid_t dxpl_id) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type") done: - if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0) + 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) @@ -2083,7 +2338,7 @@ H5O_obj_class(const H5O_loc_t *loc, hid_t dxpl_id) FUNC_ENTER_NOAPI_NOINIT(H5O_obj_class) /* Load the object header */ - if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ))) + if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ))) HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header") /* Test whether entry qualifies as a particular type of object */ @@ -2091,7 +2346,7 @@ H5O_obj_class(const H5O_loc_t *loc, hid_t dxpl_id) HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to determine object type") done: - if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0) + if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0) HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to release object header") FUNC_LEAVE_NOAPI(ret_value) @@ -2354,7 +2609,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5O_get_hdr_info(const H5O_loc_t *oloc, hid_t dxpl_id, H5O_hdr_info_t *hdr) +H5O_get_hdr_info(const H5O_loc_t *loc, hid_t dxpl_id, H5O_hdr_info_t *hdr) { H5O_t *oh = NULL; /* Object header */ herr_t ret_value = SUCCEED; /* Return value */ @@ -2362,14 +2617,14 @@ H5O_get_hdr_info(const H5O_loc_t *oloc, hid_t dxpl_id, H5O_hdr_info_t *hdr) FUNC_ENTER_NOAPI(H5O_get_hdr_info, FAIL) /* Check args */ - HDassert(oloc); + HDassert(loc); HDassert(hdr); /* Reset the object header info structure */ HDmemset(hdr, 0, sizeof(*hdr)); /* Get the object header */ - if(NULL == (oh = (H5O_t *)H5AC_protect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ))) + if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ))) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header") /* Get the information for the object header */ @@ -2377,7 +2632,7 @@ H5O_get_hdr_info(const H5O_loc_t *oloc, hid_t dxpl_id, H5O_hdr_info_t *hdr) HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't retrieve object header info") done: - if(oh && H5AC_unprotect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, oh, H5AC__NO_FLAGS_SET) < 0) + if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0) HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") FUNC_LEAVE_NOAPI(ret_value) @@ -2493,7 +2748,7 @@ H5O_get_info(const H5O_loc_t *loc, hid_t dxpl_id, hbool_t want_ih_info, HDassert(oinfo); /* Get the object header */ - if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ))) + if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ))) HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header") /* Reset the object info structure */ @@ -2581,7 +2836,7 @@ H5O_get_info(const H5O_loc_t *loc, hid_t dxpl_id, hbool_t want_ih_info, } /* end if */ done: - if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0) + 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) @@ -2614,7 +2869,7 @@ H5O_get_create_plist(const H5O_loc_t *loc, hid_t dxpl_id, H5P_genplist_t *oc_pli HDassert(oc_plist); /* Get the object header */ - if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ))) + if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ))) HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header") /* Set property values, if they were used for the object */ @@ -2636,7 +2891,7 @@ H5O_get_create_plist(const H5O_loc_t *loc, hid_t dxpl_id, H5P_genplist_t *oc_pli } /* end if */ done: - if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0) + 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) @@ -2669,14 +2924,14 @@ H5O_get_nlinks(const H5O_loc_t *loc, hid_t dxpl_id, hsize_t *nlinks) HDassert(nlinks); /* Get the object header */ - if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ))) + if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ))) HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header") /* Retrieve the # of link messages seen when the object header was loaded */ *nlinks = oh->link_msgs_seen; done: - if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0) + 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) @@ -2784,22 +3039,22 @@ H5O_get_rc_and_type(const H5O_loc_t *loc, hid_t dxpl_id, unsigned *rc, H5O_type_ /* Check args */ HDassert(loc); - HDassert(rc); - HDassert(otype); /* Get the object header */ - if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ))) + if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ))) HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header") /* Set the object's reference count */ - *rc = oh->nlink; + if(rc) + *rc = oh->nlink; /* Retrieve the type of the object */ - if(H5O_obj_type_real(oh, otype) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type") + if(otype) + if(H5O_obj_type_real(oh, otype) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type") done: - if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0) + 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) @@ -2823,7 +3078,7 @@ H5O_free_visit_visited(void *item, void UNUSED *key, void UNUSED *operator_data/ { FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_free_visit_visited) - (void)H5FL_FREE(H5_obj_t, item); + item = H5FL_FREE(H5_obj_t, item); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5O_free_visit_visited() */ @@ -3062,6 +3317,78 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_inc_rc + * + * Purpose: Increments the reference count on an object header + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Jul 13 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_inc_rc(H5O_t *oh) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_inc_rc, FAIL) + + /* check args */ + HDassert(oh); + + /* Pin the object header when the reference count goes above 0 */ + if(oh->rc == 0) + if(H5AC_pin_protected_entry(oh) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header") + + /* Increment reference count */ + oh->rc++; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_inc_rc() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_dec_rc + * + * Purpose: Decrements the reference count on an object header + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Jul 13 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_dec_rc(H5O_t *oh) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_dec_rc, FAIL) + + /* check args */ + HDassert(oh); + + /* Decrement reference count */ + oh->rc--; + + /* Unpin the object header when the reference count goes back to 0 */ + if(oh->rc == 0) + if(H5AC_unpin_entry(oh) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_dec_rc() */ + + +/*------------------------------------------------------------------------- * Function: H5O_free * * Purpose: Destroys an object header. @@ -3086,12 +3413,8 @@ H5O_free(H5O_t *oh) /* Destroy chunks */ if(oh->chunk) { - for(u = 0; u < oh->nchunks; u++) { - /* Verify that chunk is clean */ - HDassert(oh->chunk[u].dirty == 0); - + for(u = 0; u < oh->nchunks; u++) oh->chunk[u].image = H5FL_BLK_FREE(chunk_image, oh->chunk[u].image); - } /* end for */ oh->chunk = (H5O_chunk_t *)H5FL_SEQ_FREE(H5O_chunk_t, oh->chunk); } /* end if */ |