summaryrefslogtreecommitdiffstats
path: root/src/H5O.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2008-07-20 02:32:47 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2008-07-20 02:32:47 (GMT)
commitd08619bfe1a3cbc593bdaae5a5bd393e1d33f150 (patch)
tree57ec6ef4e2167462f2a10b5739b0f79f2299584d /src/H5O.c
parent90497050b818e914ab814e40811b1c0ff98384ea (diff)
downloadhdf5-d08619bfe1a3cbc593bdaae5a5bd393e1d33f150.zip
hdf5-d08619bfe1a3cbc593bdaae5a5bd393e1d33f150.tar.gz
hdf5-d08619bfe1a3cbc593bdaae5a5bd393e1d33f150.tar.bz2
[svn-r15388] Description:
Convert object header cache client to use the new metadata journaling cache, which included adding a new client for handling continuation chunks. Added "real" protect calls around modifying chunks in object headers. Switched a few more metadata cache library API routines to drop the file pointer, when it is not needed (pinning/unpinning entries, etc.) Fixed bug in journaling cache handling of 'image_len' callbacks and also changed cache to retry deserializing entries when the entry's size is larger than the speculative size initially tried. Retrying for 'image_len' callbacks has problems with the 'multi' VFD, so the h5dump and FORTRAN 'multi' tests are commented out, until the changes to the 'multi' VFD from the file free space branch are brought back into the trunk. Currently, the 'h5recover' tool has a bug which requires it to be run twice before replaying the journal "sticks". However, this is from an earlier checkin, since the code in the branch already has this behavior... :-( Tested on: FreeBSD/32 6.2 (duty) in debug mode FreeBSD/64 6.2 (liberty) w/C++ & FORTRAN, in debug mode Linux/32 2.6 (kagiso) w/PGI compilers, w/C++ & FORTRAN, w/threadsafe, in debug mode Linux/64-amd64 2.6 (smirom) w/default API=1.6.x, w/C++ & FORTRAN, in production mode Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN, in production mode Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN, w/szip filter, in production mode Mac OS X/32 10.5.4 (amazon) in debug mode Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in production mode
Diffstat (limited to 'src/H5O.c')
-rw-r--r--src/H5O.c595
1 files changed, 487 insertions, 108 deletions
diff --git a/src/H5O.c b/src/H5O.c
index e42f1eb..7901b20 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -46,13 +46,18 @@
#include "H5MFprivate.h" /* File memory management */
#include "H5Opkg.h" /* Object headers */
#include "H5SMprivate.h" /* Shared object header messages */
-#include "H5AC2private.h" /* Metadata cache */
/****************/
/* Local Macros */
/****************/
+/* Set the object header size to speculatively read in */
+/* (needs to be more than the object header prefix size to work at all and
+ * should be larger than the largest object type's default object header
+ * size to save the extra I/O operations) */
+#define H5O_SPEC_READ_SIZE 512
+
/******************/
/* Local Typedefs */
@@ -156,6 +161,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 */
@@ -1159,7 +1167,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;
@@ -1188,8 +1195,9 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id,
oh->mesg[0].chunkno = 0;
/* Cache object header */
- if(H5AC_set(f, dxpl_id, H5AC_OHDR, oh_addr, oh, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to cache object header")
+ if(H5AC2_set(f, dxpl_id, H5AC2_OHDR, oh_addr, (size_t)oh_size, oh, H5AC2__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "unable to cache object header")
+ oh = NULL;
/* Set up object location */
loc->file = f;
@@ -1201,7 +1209,7 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id,
done:
if(ret_value < 0 && oh)
- if(H5O_dest(f, oh) < 0)
+ if(H5O_dest(oh) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header data")
FUNC_LEAVE_NOAPI(ret_value)
@@ -1416,10 +1424,9 @@ done:
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 */
+ H5O_t *oh = NULL; /* Object header to query/modify */
+ hbool_t deleted = FALSE; /* Whether the object was deleted */
+ int ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5O_link, FAIL)
@@ -1428,19 +1435,31 @@ 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 = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, oh_acc)))
+ /* Get header */
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, (adjust ? H5AC2_WRITE : H5AC2_READ))))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
+ /* Pin the object header */
+ if(H5O_pin(oh) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
+
+ /* Unprotect the object header */
+ if(H5O_unprotect(loc, dxpl_id, oh, H5AC2__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header")
+
/* Check for adjusting link count */
if(adjust) {
if(adjust < 0) {
/* Check for too large of an adjustment */
if((unsigned)(-adjust) > oh->nlink)
HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "link count would be negative")
+
+ /* Adjust the link count for the object header */
oh->nlink += adjust;
- oh_flags |= H5AC__DIRTIED_FLAG;
+
+ /* Mark object header as dirty in cache */
+ if(H5AC2_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) {
@@ -1451,12 +1470,8 @@ H5O_link(const H5O_loc_t *loc, int adjust, hid_t dxpl_id)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't mark object for deletion")
} /* end if */
else {
- /* Delete object right now */
- if(H5O_delete_oh(loc->file, dxpl_id, oh) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file")
-
- /* Mark the object header as deleted */
- oh_flags = H5C__DELETED_FLAG;
+ /* Mark the object header for deletion */
+ deleted = TRUE;
} /* end else */
} /* end if */
} else {
@@ -1470,8 +1485,12 @@ H5O_link(const H5O_loc_t *loc, int adjust, hid_t dxpl_id)
} /* end if */
} /* end if */
+ /* Adjust the link count for the object header */
oh->nlink += adjust;
- oh_flags |= H5AC__DIRTIED_FLAG;
+
+ /* Mark object header as dirty in cache */
+ if(H5AC2_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 */
@@ -1509,8 +1528,10 @@ H5O_link(const H5O_loc_t *loc, int adjust, hid_t dxpl_id)
ret_value = oh->nlink;
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_PROTECT, 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() */
@@ -1519,7 +1540,7 @@ done:
/*-------------------------------------------------------------------------
* Function: H5O_protect
*
- * Purpose: Wrapper around H5AC_protect for use during a H5O_protect->
+ * Purpose: Wrapper around H5AC2_protect for use during a H5O_protect->
* H5O_msg_append->...->H5O_msg_append->H5O_unprotect sequence of calls
* during an object's creation.
*
@@ -1535,9 +1556,13 @@ done:
*-------------------------------------------------------------------------
*/
H5O_t *
-H5O_protect(H5O_loc_t *loc, hid_t dxpl_id)
+H5O_protect(const H5O_loc_t *loc, hid_t dxpl_id, H5AC2_protect_t prot)
{
- H5O_t *ret_value; /* Return value */
+ H5O_t *oh; /* 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_protect, NULL)
@@ -1547,38 +1572,260 @@ H5O_protect(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))
- HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, NULL, "no write intent on file")
+ file_intent = H5F_INTENT(loc->file);
+ if((prot == H5AC2_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 == (ret_value = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "unable to load object header")
+ if(NULL == (oh = (H5O_t *)H5AC2_protect(loc->file, dxpl_id, H5AC2_OHDR, loc->addr, (size_t)H5O_SPEC_READ_SIZE, &udata, prot)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load 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 */
+ if(NULL == (chk_proxy = (H5O_chunk_proxy_t *)H5AC2_protect(loc->file, dxpl_id, H5AC2_OHDR_CHK, cont_msg_info.msgs[curr_msg].addr, cont_msg_info.msgs[curr_msg].size, &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(H5AC2_unprotect(loc->file, dxpl_id, H5AC2_OHDR_CHK, cont_msg_info.msgs[curr_msg].addr, (size_t)0, chk_proxy, H5AC2__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)
+ H5FL_SEQ_FREE(H5O_cont_t, cont_msg_info.msgs);
+
+ /* Pass the 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 */
+
+ /* 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 != H5AC2_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(H5AC2_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 dirty */
+ HDassert(!(oh_status & H5AC2_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 != H5AC2_WRITE)
+ oh->mesgs_modified = TRUE;
+ } /* end if */
- /* Mark object header as un-evictable */
- if(H5AC_pin_protected_entry(loc->file, ret_value) < 0) {
- if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, ret_value, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_PROTECT, NULL, "unable to release object header")
+ /* Take care of loose ends for modifications made while bringing in the
+ * object header & chunks.
+ */
+ if(prot == H5AC2_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(H5AC2_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, H5AC2__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to unprotect object header chunk")
+ } /* end if */
+ } /* end for */
- HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, NULL, "unable to pin object header")
+ /* Reset flag */
+ oh->mesgs_modified = FALSE;
+ } /* end if */
} /* end if */
- /* Release the object header from the cache */
- if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, ret_value, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_PROTECT, NULL, "unable to release object header")
+#ifdef H5O_DEBUG
+H5O_assert(oh);
+#endif /* H5O_DEBUG */
+
+ /* Set return value */
+ ret_value = oh;
+
done:
+ if(ret_value == NULL && oh) {
+ if(H5AC2_unprotect(loc->file, dxpl_id, H5AC2_OHDR, loc->addr, (size_t)0, oh, H5AC2__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: Wrapper around H5AC2_pin_entry
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jul 13 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_pin(H5O_t *oh)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_pin, FAIL)
+
+ /* check args */
+ HDassert(oh);
+
+ /* 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, FAIL, "unable to increment reference count on object header")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_pin() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_unpin
+ *
+ * Purpose: Wrapper around H5AC2_unpin_entry
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jul 13 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_unpin(H5O_t *oh)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_unpin, FAIL)
+
+ /* check args */
+ HDassert(oh);
+
+ /* 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)
+} /* end H5O_unpin() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5O_unprotect
*
- * Purpose: Wrapper around H5AC_unprotect for use during a H5O_protect->
+ * Purpose: Wrapper around H5AC2_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
@@ -1588,7 +1835,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5O_unprotect(H5O_loc_t *loc, H5O_t *oh)
+H5O_unprotect(const H5O_loc_t *loc, hid_t dxpl_id, H5O_t *oh, unsigned oh_flags)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -1596,13 +1843,11 @@ H5O_unprotect(H5O_loc_t *loc, H5O_t *oh)
/* check args */
HDassert(loc);
- HDassert(loc->file);
- HDassert(H5F_addr_defined(loc->addr));
HDassert(oh);
- /* Mark object header as evictable again */
- if(H5AC_unpin_entry(loc->file, oh) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
+ /* Unprotect the object header */
+ if(H5AC2_unprotect(loc->file, dxpl_id, H5AC2_OHDR, oh->chunk[0].addr, (size_t)0, oh, oh_flags) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1626,6 +1871,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 = H5AC2__NO_FLAGS_SET; /* Flags for unprotecting chunk */
time_t now; /* Current time */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1664,6 +1911,10 @@ H5O_touch_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, hbool_t force)
oh->mesg[idx].flags = 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)))
@@ -1675,19 +1926,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 |= H5AC2__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(f, oh) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, FAIL, "unable to mark object header as dirty")
+ /* Mark object header as dirty in cache */
+ if(H5AC2_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() */
@@ -1708,35 +1964,31 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5O_touch(H5O_loc_t *loc, hbool_t force, hid_t dxpl_id)
+H5O_touch(const H5O_loc_t *loc, hbool_t force, hid_t dxpl_id)
{
- H5O_t *oh = NULL;
- unsigned oh_flags = H5AC__NO_FLAGS_SET;
- herr_t ret_value = SUCCEED; /* Return value */
+ H5O_t *oh = NULL; /* Object header to modify */
+ unsigned oh_flags = H5AC2__NO_FLAGS_SET; /* Flags for unprotecting object header */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5O_touch, FAIL)
/* 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 = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC2_WRITE)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Create/Update the modification time message */
if(H5O_touch_oh(loc->file, dxpl_id, oh, force) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to update object modificaton time")
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to update object modificaton time")
/* Mark object header as changed */
- oh_flags |= H5AC__DIRTIED_FLAG;
+ oh_flags |= H5AC2__DIRTIED_FLAG;
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
+ 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)
} /* end H5O_touch() */
@@ -1824,24 +2076,34 @@ 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 = H5AC2__NO_FLAGS_SET; /* Flags for unprotecting object header */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5O_delete,FAIL)
+ FUNC_ENTER_NOAPI(H5O_delete, FAIL)
/* Check args */
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 = H5AC_protect(f, dxpl_id, H5AC_OHDR, addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
+ if(NULL == (oh = H5O_protect(&loc, dxpl_id, H5AC2_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 = H5AC2__DIRTIED_FLAG | H5AC2__DELETED_FLAG;
+
done:
- if(oh && H5AC_unprotect(f, dxpl_id, H5AC_OHDR, addr, oh, H5AC__DIRTIED_FLAG | H5C__DELETED_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)
@@ -1918,16 +2180,16 @@ 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 = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC2_READ)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Retrieve the type of the object */
if(H5O_obj_type_real(oh, obj_type) < 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) != SUCCEED)
- HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
+ if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC2__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_obj_type() */
@@ -1996,16 +2258,16 @@ 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 = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "unable to load object header")
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC2_READ)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header")
/* Test whether entry qualifies as a particular type of object */
if(NULL == (ret_value = H5O_obj_class_real(oh)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to determine object type")
+ 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) != SUCCEED)
- HDONE_ERROR(H5E_OHDR, H5E_PROTECT, NULL, "unable to release object header")
+ if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC2__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_obj_class() */
@@ -2267,7 +2529,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5O_get_info(H5O_loc_t *oloc, hid_t dxpl_id, hbool_t want_ih_info, H5O_info_t *oinfo)
+H5O_get_info(const H5O_loc_t *loc, hid_t dxpl_id, hbool_t want_ih_info, H5O_info_t *oinfo)
{
H5O_t *oh = NULL; /* Object header */
H5O_chunk_t *curr_chunk; /* Pointer to current message being operated on */
@@ -2278,21 +2540,21 @@ H5O_get_info(H5O_loc_t *oloc, hid_t dxpl_id, hbool_t want_ih_info, H5O_info_t *o
FUNC_ENTER_NOAPI(H5O_get_info, FAIL)
/* Check args */
- HDassert(oloc);
+ HDassert(loc);
HDassert(oinfo);
/* Get the object header */
- if(NULL == (oh = H5AC_protect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC2_READ)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Reset the object info structure */
HDmemset(oinfo, 0, sizeof(*oinfo));
/* Retrieve the file's fileno */
- H5F_GET_FILENO(oloc->file, oinfo->fileno);
+ H5F_GET_FILENO(loc->file, oinfo->fileno);
/* Set the object's address */
- oinfo->addr = oloc->addr;
+ oinfo->addr = loc->addr;
/* Retrieve the type of the object */
if(H5O_obj_type_real(oh, &oinfo->type) < 0)
@@ -2301,10 +2563,10 @@ H5O_get_info(H5O_loc_t *oloc, hid_t dxpl_id, hbool_t want_ih_info, H5O_info_t *o
/* Retrieve btree and heap storage info, if requested */
if(want_ih_info) {
if(oinfo->type == H5O_TYPE_GROUP) {
- if(H5O_group_bh_info(oloc->file, dxpl_id, oh, &(oinfo->meta_size.obj)/*out*/) < 0)
+ if(H5O_group_bh_info(loc->file, dxpl_id, oh, &(oinfo->meta_size.obj)/*out*/) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't retrieve group btree & heap info")
} else if(oinfo->type == H5O_TYPE_DATASET) {
- if(H5O_dset_bh_info(oloc->file, dxpl_id, oh, &(oinfo->meta_size.obj)/*out*/) < 0)
+ if(H5O_dset_bh_info(loc->file, dxpl_id, oh, &(oinfo->meta_size.obj)/*out*/) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't retrieve chunked dataset btree info")
}
} /* end if */
@@ -2330,9 +2592,9 @@ H5O_get_info(H5O_loc_t *oloc, hid_t dxpl_id, hbool_t want_ih_info, H5O_info_t *o
oinfo->btime = 0;
/* Might be information for modification time */
- if(NULL == H5O_msg_read_real(oloc->file, dxpl_id, oh, H5O_MTIME_ID, &oinfo->ctime)) {
+ if(NULL == H5O_msg_read_real(loc->file, dxpl_id, oh, H5O_MTIME_ID, &oinfo->ctime)) {
H5E_clear_stack(NULL);
- if(NULL == H5O_msg_read_real(oloc->file, dxpl_id, oh, H5O_MTIME_NEW_ID, &oinfo->ctime)) {
+ if(NULL == H5O_msg_read_real(loc->file, dxpl_id, oh, H5O_MTIME_NEW_ID, &oinfo->ctime)) {
H5E_clear_stack(NULL);
oinfo->ctime = 0;
} /* end if */
@@ -2378,11 +2640,11 @@ H5O_get_info(H5O_loc_t *oloc, hid_t dxpl_id, hbool_t want_ih_info, H5O_info_t *o
} /* end for */
/* Retrieve # of attributes */
- oinfo->num_attrs = H5O_attr_count_real(oloc->file, dxpl_id, oh);
+ oinfo->num_attrs = H5O_attr_count_real(loc->file, dxpl_id, oh);
/* Get B-tree & heap metadata storage size, if requested */
if(want_ih_info) {
- if((oinfo->num_attrs > 0) && (H5O_attr_bh_info(oloc->file, dxpl_id, oh, &oinfo->meta_size.attr/*out*/) < 0))
+ if((oinfo->num_attrs > 0) && (H5O_attr_bh_info(loc->file, dxpl_id, oh, &oinfo->meta_size.attr/*out*/) < 0))
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve attribute btree & heap info")
} /* end if */
@@ -2400,8 +2662,8 @@ H5O_get_info(H5O_loc_t *oloc, hid_t dxpl_id, hbool_t want_ih_info, H5O_info_t *o
HDassert(oinfo->hdr.space.total == (oinfo->hdr.space.free + oinfo->hdr.space.meta + oinfo->hdr.space.mesg));
done:
- if(oh && H5AC_unprotect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
+ if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC2__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_get_info() */
@@ -2421,7 +2683,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5O_get_create_plist(const H5O_loc_t *oloc, hid_t dxpl_id, H5P_genplist_t *oc_plist)
+H5O_get_create_plist(const H5O_loc_t *loc, hid_t dxpl_id, H5P_genplist_t *oc_plist)
{
H5O_t *oh = NULL; /* Object header */
herr_t ret_value = SUCCEED; /* Return value */
@@ -2429,12 +2691,12 @@ H5O_get_create_plist(const H5O_loc_t *oloc, hid_t dxpl_id, H5P_genplist_t *oc_pl
FUNC_ENTER_NOAPI(H5O_get_create_plist, FAIL)
/* Check args */
- HDassert(oloc);
+ HDassert(loc);
HDassert(oc_plist);
/* Get the object header */
- if(NULL == (oh = H5AC_protect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC2_READ)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Set property values, if they were used for the object */
if(oh->version > H5O_VERSION_1) {
@@ -2455,8 +2717,8 @@ H5O_get_create_plist(const H5O_loc_t *oloc, hid_t dxpl_id, H5P_genplist_t *oc_pl
} /* end if */
done:
- if(oh && H5AC_unprotect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
+ if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC2__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_get_create_plist() */
@@ -2476,7 +2738,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5O_get_nlinks(const H5O_loc_t *oloc, hid_t dxpl_id, hsize_t *nlinks)
+H5O_get_nlinks(const H5O_loc_t *loc, hid_t dxpl_id, hsize_t *nlinks)
{
H5O_t *oh = NULL; /* Object header */
herr_t ret_value = SUCCEED; /* Return value */
@@ -2484,19 +2746,19 @@ H5O_get_nlinks(const H5O_loc_t *oloc, hid_t dxpl_id, hsize_t *nlinks)
FUNC_ENTER_NOAPI(H5O_get_nlinks, FAIL)
/* Check args */
- HDassert(oloc);
+ HDassert(loc);
HDassert(nlinks);
/* Get the object header */
- if(NULL == (oh = H5AC_protect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC2_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(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
+ if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC2__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_get_nlinks() */
@@ -2594,7 +2856,7 @@ H5O_get_oh_addr(const H5O_t *oh)
*-------------------------------------------------------------------------
*/
herr_t
-H5O_get_rc_and_type(const H5O_loc_t *oloc, hid_t dxpl_id, unsigned *rc, H5O_type_t *otype)
+H5O_get_rc_and_type(const H5O_loc_t *loc, hid_t dxpl_id, unsigned *rc, H5O_type_t *otype)
{
H5O_t *oh = NULL; /* Object header */
herr_t ret_value = SUCCEED; /* Return value */
@@ -2602,13 +2864,13 @@ H5O_get_rc_and_type(const H5O_loc_t *oloc, hid_t dxpl_id, unsigned *rc, H5O_type
FUNC_ENTER_NOAPI(H5O_get_rc_and_type, FAIL)
/* Check args */
- HDassert(oloc);
+ HDassert(loc);
HDassert(rc);
HDassert(otype);
/* Get the object header */
- if(NULL == (oh = H5AC_protect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC2_READ)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Set the object's reference count */
*rc = oh->nlink;
@@ -2618,8 +2880,8 @@ H5O_get_rc_and_type(const H5O_loc_t *oloc, hid_t dxpl_id, unsigned *rc, H5O_type
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type")
done:
- if(oh && H5AC_unprotect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
+ if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC2__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_get_rc_and_type() */
@@ -2875,4 +3137,121 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_visit() */
+
+/*-------------------------------------------------------------------------
+ * 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(H5AC2_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(H5AC2_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_dest
+ *
+ * Purpose: Destroys an object header.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Jan 15 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_dest(H5O_t *oh)
+{
+ unsigned u; /* Local index variable */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_dest)
+
+ /* check args */
+ HDassert(oh);
+
+ /* Destroy chunks */
+ if(oh->chunk) {
+ for(u = 0; u < oh->nchunks; u++)
+ oh->chunk[u].image = H5FL_BLK_FREE(chunk_image, oh->chunk[u].image);
+
+ oh->chunk = (H5O_chunk_t *)H5FL_SEQ_FREE(H5O_chunk_t, oh->chunk);
+ } /* end if */
+
+ /* Destroy messages */
+ if(oh->mesg) {
+ for(u = 0; u < oh->nmesgs; u++)
+ H5O_msg_free_mesg(&oh->mesg[u]);
+
+ oh->mesg = (H5O_mesg_t *)H5FL_SEQ_FREE(H5O_mesg_t, oh->mesg);
+ } /* end if */
+
+ /* destroy object header */
+ H5FL_FREE(H5O_t, oh);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O_dest() */