summaryrefslogtreecommitdiffstats
path: root/src/H5HFcache.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2016-06-28 21:39:09 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2016-06-28 21:39:09 (GMT)
commitb8f809981bb6c378e2a942aad551620feaa47125 (patch)
tree0cc2f0cae57278923512b9419f9fbdb71f4dd56c /src/H5HFcache.c
parent280907a9bf78cdda0a8c8ce7a290e8bc631a894c (diff)
downloadhdf5-b8f809981bb6c378e2a942aad551620feaa47125.zip
hdf5-b8f809981bb6c378e2a942aad551620feaa47125.tar.gz
hdf5-b8f809981bb6c378e2a942aad551620feaa47125.tar.bz2
[svn-r30112] Description:
Move updated flush dependency code in metadata cache from revise_chunks branch to trunk. Also many of the cleanups from r30111 in the revise_chunks branch. Tested on: MacOSX/64 10.11.5 (amazon) w/serial, parallel & production (h5committest forthcoming)
Diffstat (limited to 'src/H5HFcache.c')
-rw-r--r--src/H5HFcache.c292
1 files changed, 22 insertions, 270 deletions
diff --git a/src/H5HFcache.c b/src/H5HFcache.c
index 38556b7..759fff0 100644
--- a/src/H5HFcache.c
+++ b/src/H5HFcache.c
@@ -118,13 +118,13 @@ static herr_t H5HF__cache_dblock_free_icr(void *thing);
/* Debugging Function Prototypes */
#ifndef NDEBUG
-static herr_t H5HF__cache_verify_hdr_descendants_clean(H5F_t *f, hid_t dxpl_id,
- H5HF_hdr_t *hdr, hbool_t *clean);
-static herr_t H5HF__cache_verify_iblock_descendants_clean(H5F_t *f, hid_t dxpl_id,
+static herr_t H5HF__cache_verify_hdr_descendants_clean(H5F_t *f, H5HF_hdr_t *hdr,
+ hbool_t *clean);
+static herr_t H5HF__cache_verify_iblock_descendants_clean(H5F_t *f,
H5HF_indirect_t *iblock, unsigned *iblock_status, hbool_t *clean);
static herr_t H5HF__cache_verify_iblocks_dblocks_clean(H5F_t *f,
H5HF_indirect_t *iblock, hbool_t *clean, hbool_t *has_dblocks);
-static herr_t H5HF__cache_verify_descendant_iblocks_clean(H5F_t *f, hid_t dxpl_id,
+static herr_t H5HF__cache_verify_descendant_iblocks_clean(H5F_t *f,
H5HF_indirect_t *iblock, hbool_t *clean, hbool_t *has_iblocks);
#endif /* NDEBUG */
@@ -657,7 +657,7 @@ H5HF__cache_hdr_pre_serialize(const H5F_t *f, hid_t dxpl_id, void *_thing,
*
* Do this with a call to H5HF__cache_verify_hdr_descendants_clean().
*/
- if(H5HF__cache_verify_hdr_descendants_clean((H5F_t *)f, dxpl_id, hdr, &descendants_clean) < 0)
+ if(H5HF__cache_verify_hdr_descendants_clean((H5F_t *)f, hdr, &descendants_clean) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "can't verify hdr descendants clean.")
HDassert(descendants_clean);
}
@@ -1165,7 +1165,7 @@ H5HF__cache_iblock_pre_serialize(const H5F_t *f, hid_t dxpl_id, void *_thing,
* there is no need to check to see if it is pinned or protected, or to
* protect it if it is not.
*/
- if(H5HF__cache_verify_iblock_descendants_clean((H5F_t *)f, dxpl_id, iblock, &iblock_status, &descendants_clean) < 0)
+ if(H5HF__cache_verify_iblock_descendants_clean((H5F_t *)f, iblock, &iblock_status, &descendants_clean) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "can't verify descendants clean.")
HDassert(descendants_clean);
}
@@ -2479,8 +2479,8 @@ done:
*/
#ifndef NDEBUG
static herr_t
-H5HF__cache_verify_hdr_descendants_clean(H5F_t *f, hid_t dxpl_id,
- H5HF_hdr_t * hdr, hbool_t *clean)
+H5HF__cache_verify_hdr_descendants_clean(H5F_t *f, H5HF_hdr_t *hdr,
+ hbool_t *clean)
{
haddr_t hdr_addr; /* Address of header */
unsigned hdr_status = 0; /* Header cache entry status */
@@ -2561,122 +2561,11 @@ H5HF__cache_verify_hdr_descendants_clean(H5F_t *f, hid_t dxpl_id,
*clean = TRUE;
else if(root_iblock_status & H5AC_ES__IS_DIRTY)
*clean = FALSE;
- else { /* must examine children */
- hbool_t unprotect_root_iblock = FALSE;
-
- /* At this point, the root iblock may be pinned, protected,
- * both, or neither, and we may or may not have a pointer
- * to root iblock in memory.
- *
- * Before we call H5HF__cache_verify_iblock_descendants_clean(),
- * we must ensure that the root iblock is either pinned or
- * protected or both, and that we have a pointer to it.
- * Do this as follows:
- */
- if(root_iblock == NULL) { /* we don't have ptr to root iblock */
- if(0 == (root_iblock_status & H5AC_ES__IS_PROTECTED)) {
- /* just protect the root iblock -- this will give us
- * the pointer we need to proceed, and ensure that
- * it is locked into the metadata cache for the
- * duration.
- *
- * Note that the udata is only used in the load callback.
- * While the fractal heap makes heavy use of the udata
- * in this case, since we know that the entry is in cache,
- * we can pass NULL udata.
- */
- if(NULL == (root_iblock = (H5HF_indirect_t *)H5AC_protect(f, dxpl_id, H5AC_FHEAP_IBLOCK, root_iblock_addr, NULL, H5C__READ_ONLY_FLAG)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "H5AC_protect() faild.")
- unprotect_root_iblock = TRUE;
- } /* end if */
- else {
- /* the root iblock is protected, and we have no
- * legitimate way of getting a pointer to it.
- *
- * We square this circle by using the
- * H5AC_get_entry_ptr_from_addr() to get the needed
- * pointer.
- *
- * WARNING: This call should be used only in debugging
- * routines, and it should be avoided there when
- * possible.
- *
- * Further, if we ever multi-thread the cache,
- * this routine will have to be either discarded
- * or heavily re-worked.
- *
- * Finally, keep in mind that the entry whose
- * pointer is obtained in this fashion may not
- * be in a stable state.
- *
- * Assuming that the flush dependency code is working
- * as it should, the only reason for the root iblock to
- * be unpinned is if none of its children are in cache.
- * This unfortunately means that if it is protected and
- * not pinned, the fractal heap is in the process of loading
- * or inserting one of its children. The obvious implication
- * is that there is a significant chance that the root
- * iblock is in an unstable state.
- *
- * All this suggests that using H5AC_get_entry_ptr_from_addr()
- * to obtain the pointer to the protected root iblock is
- * questionable here. However, since this is test/debugging
- * code, I expect that we will use this approach until it
- * causes problems, or we think of a better way.
- */
- if(H5AC_get_entry_ptr_from_addr(f, root_iblock_addr, (void **)(&root_iblock)) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "H5AC_get_entry_ptr_from_addr() failed.")
- HDassert(root_iblock);
- } /* end else */
- } /* end if */
- else { /* root_iblock != NULL */
- /* we have the pointer to the root iblock. Protect it
- * if it is neither pinned nor protected -- otherwise we
- * are ready to go.
- */
- H5HF_indirect_t * iblock = NULL;
-
- if(((root_iblock_status & H5AC_ES__IS_PINNED) == 0) &&
- ((root_iblock_status & H5AC_ES__IS_PROTECTED) == 0)) {
- /* the root iblock is neither pinned nor protected -- hence
- * we must protect it before we proceed
- *
- * Note that the udata is only used in the load callback.
- * While the fractal heap makes heavy use of the udata
- * in this case, since we know that the entry is in cache,
- * we can pass NULL udata.
- */
- if(NULL == (iblock = (H5HF_indirect_t *)H5AC_protect(f, dxpl_id, H5AC_FHEAP_IBLOCK, root_iblock_addr, NULL, H5C__READ_ONLY_FLAG)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "H5AC_protect() faild.")
- unprotect_root_iblock = TRUE;
- HDassert(iblock == root_iblock);
- } /* end if */
- } /* end else */
-
- /* at this point, one way or another, the root iblock is locked
- * in memory for the duration of the call. Do some sanity checks,
- * and then call H5HF__cache_verify_iblock_descendants_clean().
- */
- HDassert(hdr->root_iblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
- HDassert(hdr->root_iblock->cache_info.type == H5AC_FHEAP_IBLOCK);
-
- if(H5HF__cache_verify_iblock_descendants_clean(f, dxpl_id, root_iblock, &root_iblock_status, clean) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "can't verify root iblock & descendants clean.")
-
- /* unprotect the root indirect block if required */
- if(unprotect_root_iblock) {
- HDassert(root_iblock);
- if(H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_IBLOCK, root_iblock_addr, root_iblock, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "H5AC_unprotect() faild.")
- } /* end if */
- } /* end else */
} /* end if */
else if((hdr->man_dtable.curr_root_rows == 0) &&
(HADDR_UNDEF != hdr->man_dtable.table_addr)) {
haddr_t root_dblock_addr;
unsigned root_dblock_status = 0;
- hbool_t in_cache;
- hbool_t type_ok;
/* this is scenario 2 -- we have a root dblock */
root_dblock_addr = hdr->man_dtable.table_addr;
@@ -2684,27 +2573,16 @@ H5HF__cache_verify_hdr_descendants_clean(H5F_t *f, hid_t dxpl_id,
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get root dblock status")
if(root_dblock_status & H5AC_ES__IN_CACHE) {
- if(H5AC_verify_entry_type(f, root_dblock_addr, &H5AC_FHEAP_DBLOCK[0], &in_cache, &type_ok) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't check dblock type")
- HDassert(in_cache);
- if(!type_ok)
- HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "root dblock addr doesn't refer to a dblock?!?")
-
/* If a root dblock is in cache, it must have a flush
- * dependency relationship with the header, and it
- * may not be the parent in any flush dependency
- * relationship.
- *
- * We don't test this fully, but we will verify that
- * the root iblock is a child in some flush dependency
- * relationship.
+ * dependency relationship with the header.
*/
if(0 == (root_dblock_status & H5AC_ES__IS_FLUSH_DEP_CHILD))
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "root dblock in cache and not a flush dep child.")
if(0 != (root_dblock_status & H5AC_ES__IS_FLUSH_DEP_PARENT))
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "root dblock in cache and is a flush dep parent.")
- *clean = ! (root_dblock_status & H5AC_ES__IS_DIRTY);
+ if(root_dblock_status & H5AC_ES__IS_DIRTY)
+ *clean = FALSE;
} /* end if */
else /* root dblock not in cache */
*clean = TRUE;
@@ -2757,8 +2635,8 @@ done:
*/
#ifndef NDEBUG
static herr_t
-H5HF__cache_verify_iblock_descendants_clean(H5F_t *f, hid_t dxpl_id,
- H5HF_indirect_t *iblock, unsigned *iblock_status, hbool_t *clean)
+H5HF__cache_verify_iblock_descendants_clean(H5F_t *f, H5HF_indirect_t *iblock,
+ unsigned *iblock_status, hbool_t *clean)
{
hbool_t has_dblocks = FALSE;
hbool_t has_iblocks = FALSE;
@@ -2778,12 +2656,9 @@ H5HF__cache_verify_iblock_descendants_clean(H5F_t *f, hid_t dxpl_id,
if((*clean) && H5HF__cache_verify_iblocks_dblocks_clean(f, iblock, clean, &has_dblocks) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "can't verify dblocks clean.")
- if((*clean) && H5HF__cache_verify_descendant_iblocks_clean(f, dxpl_id, iblock, clean, &has_iblocks) < 0)
+ if((*clean) && H5HF__cache_verify_descendant_iblocks_clean(f, iblock, clean, &has_iblocks) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "can't verify iblocks clean.")
- if((NULL == iblock_status) && H5AC_get_entry_status(f, iblock->addr, iblock_status) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get iblock status")
-
/* verify that flush dependency setup is plausible */
if(0 == (*iblock_status & H5AC_ES__IS_FLUSH_DEP_CHILD))
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "iblock is not a flush dep child.")
@@ -2855,41 +2730,25 @@ H5HF__cache_verify_iblocks_dblocks_clean(H5F_t *f, H5HF_indirect_t *iblock,
dblock_addr = iblock->ents[i].addr;
if(H5F_addr_defined(dblock_addr)) {
- hbool_t in_cache;
- hbool_t type_ok;
-
- if(H5AC_verify_entry_type(f, dblock_addr, &H5AC_FHEAP_DBLOCK[0], &in_cache, &type_ok) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't check dblock type")
-
- if(in_cache) { /* dblock is in cache */
- unsigned dblock_status = 0;
+ unsigned dblock_status = 0;
- if(!type_ok)
- HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "dblock addr doesn't refer to a dblock?!?")
+ if(H5AC_get_entry_status(f, dblock_addr, &dblock_status) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get dblock status")
+ if(dblock_status & H5AC_ES__IN_CACHE) {
+ *has_dblocks = TRUE;
- if(H5AC_get_entry_status(f, dblock_addr, &dblock_status) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get dblock status")
- HDassert(dblock_status & H5AC_ES__IN_CACHE);
-
- *has_dblocks = TRUE;
if(dblock_status & H5AC_ES__IS_DIRTY)
- *clean = FALSE;
+ *clean = FALSE;
/* If a child dblock is in cache, it must have a flush
* dependency relationship with this iblock, and it
* may not be the parent in any flush dependency
* relationship.
- *
- * We don't test this fully, but we will verify that
- * the child iblock is a child in some flush dependency
- * relationship.
*/
if(0 == (dblock_status & H5AC_ES__IS_FLUSH_DEP_CHILD))
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "dblock in cache and not a flush dep child.")
-
if(0 != (dblock_status & H5AC_ES__IS_FLUSH_DEP_PARENT))
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "dblock in cache and is a flush dep parent.")
-
} /* end if */
} /* end if */
@@ -2931,8 +2790,8 @@ done:
*/
#ifndef NDEBUG
static herr_t
-H5HF__cache_verify_descendant_iblocks_clean(H5F_t *f, hid_t dxpl_id,
- H5HF_indirect_t *iblock, hbool_t *clean, hbool_t *has_iblocks)
+H5HF__cache_verify_descendant_iblocks_clean(H5F_t *f, H5HF_indirect_t *iblock,
+ hbool_t *clean, hbool_t *has_iblocks)
{
unsigned first_iblock_index;
unsigned last_iblock_index;
@@ -2970,113 +2829,6 @@ H5HF__cache_verify_descendant_iblocks_clean(H5F_t *f, hid_t dxpl_id,
*has_iblocks = TRUE;
if(child_iblock_status & H5AC_ES__IS_DIRTY)
*clean = FALSE;
-
- /* if the child iblock is in cache and *clean is TRUE,
- * we must continue to explore down the fractal heap tree
- * structure to verify that all descendant blocks are either
- * clean, or not in the metadata cache. We do this with a
- * recursive call to
- * H5HF__cache_verify_iblock_descendants_clean().
- * However, we can't make this call unless the child iblock
- * is somehow locked into the cache -- typically via either
- * pinning or protecting.
- *
- * If the child iblock is pinned, we can look up its pointer
- * on the current iblock's pinned child iblock list, and
- * and use that pointer in the recursive call.
- *
- * If the entry is unprotected and unpinned, we simply
- * protect it.
- *
- * If, however, the the child iblock is already protected,
- * but not pinned, we have a bit of a problem, as we have
- * no legitimate way of looking up its pointer in memory.
- *
- * To solve this problem, I have added a new metadata cache
- * call to obtain the pointer.
- *
- * WARNING: This call should be used only in debugging
- * routines, and it should be avoided there when
- * possible.
- *
- * Further, if we ever multi-thread the cache,
- * this routine will have to be either discarded
- * or heavily re-worked.
- *
- * Finally, keep in mind that the entry whose
- * pointer is obtained in this fashion may not
- * be in a stable state.
- *
- * Assuming that the flush dependency code is working
- * as it should, the only reason for the child entry to
- * be unpinned is if none of its children are in cache.
- * This unfortunately means that if it is protected and
- * not pinned, the fractal heap is in the process of loading
- * or inserting one of its children. The obvious implication
- * is that there is a significant chance that the child
- * iblock is in an unstable state.
- *
- * All this suggests that using the new call to obtain the
- * pointer to the protected child iblock is questionable
- * here. However, since this is test/debugging code, I
- * expect that we will use this approach until it causes
- * problems, or we think of a better way.
- */
- if(*clean) {
- H5HF_indirect_t *child_iblock = NULL;
- hbool_t unprotect_child_iblock = FALSE;
-
- if(0 == (child_iblock_status & H5AC_ES__IS_PINNED)) {
- /* child iblock is not pinned */
- if(0 == (child_iblock_status & H5AC_ES__IS_PROTECTED)) {
- /* child iblock is unprotected, and unpinned */
- /* protect it. Note that the udata is only */
- /* used in the load callback. While the */
- /* fractal heap makes heavy use of the udata */
- /* in this case, since we know that the */
- /* entry is in cache, we can pass NULL udata */
-
- if(NULL == (child_iblock = (H5HF_indirect_t *) H5AC_protect(f, dxpl_id, H5AC_FHEAP_IBLOCK, child_iblock_addr, NULL, H5C__READ_ONLY_FLAG)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "H5AC_protect() faild.")
- unprotect_child_iblock = TRUE;
- } /* end if */
- else {
- /* child iblock is protected -- use */
- /* H5AC_get_entry_ptr_from_addr() to get a */
- /* pointer to the entry. This is very slimy -- */
- /* come up with a better solution. */
- if(H5AC_get_entry_ptr_from_addr(f, child_iblock_addr, (void **)(&child_iblock)) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "H5AC_get_entry_ptr_from_addr() faild.")
- HDassert(child_iblock);
- } /* end else */
- } /* end if */
- else {
- /* child iblock is pinned -- look it up in the */
- /* parent iblocks child_iblocks array. */
- HDassert(iblock->child_iblocks);
- child_iblock = iblock->child_iblocks[i - first_iblock_index];
- } /* end else */
-
- /* At this point, one way or another we should have
- * a pointer to the child iblock. Verify that we
- * that we have the correct one.
- */
- HDassert(child_iblock);
- HDassert(child_iblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
- HDassert(child_iblock->cache_info.type == H5AC_FHEAP_IBLOCK);
- HDassert(child_iblock->addr == child_iblock_addr);
-
- /* now make the recursive call */
- if(H5HF__cache_verify_iblock_descendants_clean(f, dxpl_id, child_iblock, &child_iblock_status, clean) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "can't verify child iblock clean.")
-
- /* if we protected the child iblock, unprotect it now */
- if(unprotect_child_iblock) {
- if(H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_IBLOCK, child_iblock_addr, child_iblock, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "H5AC_unprotect() faild.")
-
- } /* end if */
- } /* end if */
} /* end if */
} /* end if */