summaryrefslogtreecommitdiffstats
path: root/src/H5O.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5O.c')
-rw-r--r--src/H5O.c509
1 files changed, 416 insertions, 93 deletions
diff --git a/src/H5O.c b/src/H5O.c
index 87b86ab..5abf7d9 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -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 */