[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)
This commit is contained in:
Quincey Koziol 2016-06-28 16:39:09 -05:00
parent 280907a9bf
commit b8f809981b
18 changed files with 3407 additions and 2928 deletions

View File

@ -2075,113 +2075,6 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC__open_trace_file() */
/*************************************************************************/
/*************************** Debugging Functions: ************************/
/*************************************************************************/
/*-------------------------------------------------------------------------
*
* Function: H5AC_get_entry_ptr_from_addr()
*
* Purpose: Debugging function that attempts to look up an entry in the
* cache by its file address, and if found, returns a pointer
* to the entry in *entry_ptr_ptr. If the entry is not in the
* cache, *entry_ptr_ptr is set to NULL.
*
* WARNING: This call should be used only in debugging
* routines, and it should be avoided 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.
*
* Note that this function is only defined if NDEBUG
* is not defined.
*
* As heavy use of this function is almost certainly a
* bad idea, the metadata cache tracks the number of
* successful calls to this function, and (if
* H5C_DO_SANITY_CHECKS is defined) displays any
* non-zero count on cache shutdown.
*
* This function is just a wrapper that calls the H5C
* version of the function.
*
* Return: FAIL if error is detected, SUCCEED otherwise.
*
* Programmer: John Mainzer, 5/30/14
*
*-------------------------------------------------------------------------
*/
#ifndef NDEBUG
herr_t
H5AC_get_entry_ptr_from_addr(const H5F_t *f, haddr_t addr, void **entry_ptr_ptr)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
if(H5C_get_entry_ptr_from_addr(f, addr, entry_ptr_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C_get_entry_ptr_from_addr() failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_get_entry_ptr_from_addr() */
#endif /* NDEBUG */
/*-------------------------------------------------------------------------
*
* Function: H5AC_verify_entry_type()
*
* Purpose: Debugging function that attempts to look up an entry in the
* cache by its file address, and if found, test to see if its
* type field contains the expected value.
*
* If the specified entry is in cache, *in_cache_ptr is set
* to TRUE, and *type_ok_ptr is set to TRUE or FALSE
* depending on whether the entries type field matches the
* expected_type parameter
*
* If the target entry is not in cache, *in_cache_ptr is
* set to FALSE, and *type_ok_ptr is undefined.
*
* Note that this function is only defined if NDEBUG
* is not defined.
*
* This function is just a wrapper that calls the H5C
* version of the function.
*
* Return: FAIL if error is detected, SUCCEED otherwise.
*
* Programmer: John Mainzer, 5/30/14
*
*-------------------------------------------------------------------------
*/
#ifndef NDEBUG
herr_t
H5AC_verify_entry_type(const H5F_t *f, haddr_t addr, const H5AC_class_t *expected_type,
hbool_t *in_cache_ptr, hbool_t *type_ok_ptr)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
if(H5C_verify_entry_type(f, addr, expected_type, in_cache_ptr, type_ok_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C_verify_entry_type() failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_verify_entry_type() */
#endif /* NDEBUG */
/*************************************************************************/
/**************************** Private Functions: *************************/

View File

@ -311,6 +311,7 @@ H5_DLLVAR hid_t H5AC_rawdata_dxpl_id;
#define H5AC__TAKE_OWNERSHIP_FLAG H5C__TAKE_OWNERSHIP_FLAG
#define H5AC__FLUSH_LAST_FLAG H5C__FLUSH_LAST_FLAG
#define H5AC__FLUSH_COLLECTIVELY_FLAG H5C__FLUSH_COLLECTIVELY_FLAG
#define H5AC__EVICT_ALLOW_LAST_PINS_FLAG H5C__EVICT_ALLOW_LAST_PINS_FLAG
/* #defines of flags used to report entry status in the
@ -380,11 +381,6 @@ H5_DLL herr_t H5AC_add_candidate(H5AC_t * cache_ptr, haddr_t addr);
#ifndef NDEBUG /* debugging functions */
H5_DLL herr_t H5AC_stats(const H5F_t *f);
H5_DLL herr_t H5AC_dump_cache(const H5F_t *f);
H5_DLL herr_t H5AC_get_entry_ptr_from_addr(const H5F_t *f, haddr_t addr,
void ** entry_ptr_ptr);
H5_DLL herr_t H5AC_verify_entry_type(const H5F_t * f, haddr_t addr,
const H5AC_class_t * expected_type, hbool_t * in_cache_ptr,
hbool_t * type_ok_ptr);
#endif /* NDEBUG */ /* end debugging functions */
#endif /* !_H5ACprivate_H */

1909
src/H5C.c

File diff suppressed because it is too large Load Diff

View File

@ -45,22 +45,13 @@
/* Package Private Macros */
/**************************/
/* With the introduction of the fractal heap, it is now possible for
* entries to be dirtied, resized, and/or moved in the flush callbacks.
* As a result, on flushes, it may be necessary to make multiple passes
* through the slist before it is empty. The H5C__MAX_PASSES_ON_FLUSH
* #define is used to set an upper limit on the number of passes.
* The current value was obtained via personal communication with
* Quincey. I have applied a fudge factor of 2.
*
* -- JRM
*/
#define H5C__MAX_PASSES_ON_FLUSH 4
/* Cache configuration settings */
#define H5C__HASH_TABLE_LEN (64 * 1024) /* must be a power of 2 */
#define H5C__H5C_T_MAGIC 0x005CAC0E
/* Initial allocated size of the "flush_dep_parent" array */
#define H5C_FLUSH_DEP_PARENT_INIT 8
/* Cache client ID for epoch markers */
/* Note that H5C__MAX_EPOCH_MARKERS is defined in H5Cprivate.h, not here because
* it is needed to dimension arrays in H5C_t.
@ -4063,11 +4054,6 @@ if ( ( (entry_ptr) == NULL ) || \
* field is intended to allow marking of output of with
* the processes mpi rank.
*
* get_entry_ptr_from_addr_counter: Counter used to track the number of
* times the H5C_get_entry_ptr_from_addr() function has been
* called successfully. This field is only defined when
* NDEBUG is not #defined.
*
****************************************************************************/
struct H5C_t {
uint32_t magic;
@ -4252,10 +4238,6 @@ struct H5C_t {
#endif /* H5C_COLLECT_CACHE_STATS */
char prefix[H5C__PREFIX_LEN];
#ifndef NDEBUG
int64_t get_entry_ptr_from_addr_counter;
#endif /* NDEBUG */
};
#ifdef H5_HAVE_PARALLEL

View File

@ -97,14 +97,6 @@
#define H5C__DEFAULT_MAX_CACHE_SIZE ((size_t)(4 * 1024 * 1024))
#define H5C__DEFAULT_MIN_CLEAN_SIZE ((size_t)(2 * 1024 * 1024))
/* Maximum height of flush dependency relationships between entries. This is
* currently tuned to the extensible array (H5EA) data structure, which only
* requires 6 levels of dependency (i.e. heights 0-6) (actually, the extensible
* array needs 4 levels, plus another 2 levels are needed: one for the layer
* under the extensible array and one for the layer above it).
*/
#define H5C__NUM_FLUSH_DEP_HEIGHTS 6
/* Values for cache entry magic field */
#define H5C__H5C_CACHE_ENTRY_T_MAGIC 0x005CAC0A
#define H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC 0xDeadBeef
@ -209,6 +201,7 @@
#define H5C__TAKE_OWNERSHIP_FLAG 0x0800
#define H5C__FLUSH_LAST_FLAG 0x1000
#define H5C__FLUSH_COLLECTIVELY_FLAG 0x2000
#define H5C__EVICT_ALLOW_LAST_PINS_FLAG 0x4000
#define H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG 0x8000
/* Definitions for cache "tag" property */
@ -1473,33 +1466,29 @@ typedef int H5C_ring_t;
*
* Fields supporting the 'flush dependency' feature:
*
* Entries in the cache may have a 'flush dependency' on another entry in the
* Entries in the cache may have 'flush dependencies' on other entries in the
* cache. A flush dependency requires that all dirty child entries be flushed
* to the file before a dirty parent entry (of those child entries) can be
* flushed to the file. This can be used by cache clients to create data
* structures that allow Single-Writer/Multiple-Reader (SWMR) access for the
* data structure.
*
* The leaf child entry will have a "height" of 0, with any parent entries
* having a height of 1 greater than the maximum height of any of their child
* entries (flush dependencies are allowed to create asymmetric trees of
* relationships).
* flush_dep_parent: Pointer to the array of flush dependency parent entries
* for this entry.
*
* flush_dep_parent: Pointer to the parent entry for an entry in a flush
* dependency relationship.
* flush_dep_nparents: Number of flush dependency parent entries for this
* entry, i.e. the number of valid elements in flush_dep_parent.
*
* child_flush_dep_height_rc: An array of reference counts for child entries,
* where the number of children of each height is tracked.
* flush_dep_parent_nalloc: The number of allocated elements in
* flush_dep_parent_nalloc.
*
* flush_dep_height: The height of the entry, which is one greater than the
* maximum height of any of its child entries..
* flush_dep_nchildren: Number of flush dependency children for this entry. If
* this field is nonzero, then this entry must be pinned and
* therefore cannot be evicted.
*
* pinned_from_client: Whether the entry was pinned by an explicit pin request
* from a cache client.
*
* pinned_from_cache: Whether the entry was pinned implicitly as a
* request of being a parent entry in a flush dependency
* relationship.
* flush_dep_ndirty_children: Number of flush dependency children that are
* either dirty or have a nonzero flush_dep_ndirty_children. If
* this field is nonzero, then this entry cannot be flushed.
*
*
* Fields supporting the hash table:
@ -1644,9 +1633,11 @@ typedef struct H5C_cache_entry_t {
H5C_ring_t ring;
/* fields supporting the 'flush dependency' feature: */
struct H5C_cache_entry_t * flush_dep_parent;
uint64_t child_flush_dep_height_rc[H5C__NUM_FLUSH_DEP_HEIGHTS];
unsigned flush_dep_height;
struct H5C_cache_entry_t ** flush_dep_parent;
unsigned flush_dep_nparents;
unsigned flush_dep_parent_nalloc;
unsigned flush_dep_nchildren;
unsigned flush_dep_ndirty_children;
hbool_t pinned_from_client;
hbool_t pinned_from_cache;
@ -2041,13 +2032,5 @@ H5_DLL herr_t H5C_mark_entries_as_clean(H5F_t *f, hid_t dxpl_id, int32_t ce_arra
haddr_t *ce_array_ptr);
#endif /* H5_HAVE_PARALLEL */
#ifndef NDEBUG /* debugging functions */
H5_DLL herr_t H5C_get_entry_ptr_from_addr(const H5F_t *f, haddr_t addr,
void **entry_ptr_ptr);
H5_DLL herr_t H5C_verify_entry_type(const H5F_t *f, haddr_t addr,
const H5C_class_t *expected_type, hbool_t *in_cache_ptr,
hbool_t *type_ok_ptr);
#endif /* NDEBUG */
#endif /* !_H5Cprivate_H */

View File

@ -277,9 +277,9 @@ H5C_get_entry_status(const H5F_t *f,
if(is_corked_ptr != NULL)
*is_corked_ptr = entry_ptr->is_corked;
if(is_flush_dep_parent_ptr != NULL)
*is_flush_dep_parent_ptr = (entry_ptr->flush_dep_height > 0);
*is_flush_dep_parent_ptr = (entry_ptr->flush_dep_nchildren > 0);
if(is_flush_dep_child_ptr != NULL)
*is_flush_dep_child_ptr = (entry_ptr->flush_dep_parent != NULL);
*is_flush_dep_child_ptr = (entry_ptr->flush_dep_nparents > 0);
} /* end else */
done:

View File

@ -74,6 +74,11 @@ typedef herr_t (*H5EA__unprotect_func_t)(void *thing, hid_t dxpl_id,
/* Local Prototypes */
/********************/
static herr_t
H5EA__lookup_elmt(const H5EA_t *ea, hid_t dxpl_id, hsize_t idx, hbool_t will_extend,
unsigned thing_acc, void **thing, uint8_t **thing_elmt_buf,
hsize_t *thing_elmt_idx, H5EA__unprotect_func_t *thing_unprot_func);
/*********************/
/* Package Variables */
@ -133,10 +138,6 @@ H5EA_create(H5F_t *f, hid_t dxpl_id, const H5EA_create_t *cparam, void *ctx_udat
H5EA_hdr_t *hdr = NULL; /* The extensible array header information */
haddr_t ea_addr; /* Array header address */
#ifdef QAK
HDfprintf(stderr, "%s: Called\n", FUNC);
#endif /* QAK */
/*
* Check arguments.
*/
@ -213,9 +214,6 @@ H5EA_open(H5F_t *f, hid_t dxpl_id, haddr_t ea_addr, void *ctx_udata))
HDassert(H5F_addr_defined(ea_addr));
/* Load the array header into memory */
#ifdef QAK
HDfprintf(stderr, "%s: ea_addr = %a\n", FUNC, ea_addr);
#endif /* QAK */
if(NULL == (hdr = H5EA__hdr_protect(f, dxpl_id, ea_addr, ctx_udata, H5AC__READ_ONLY_FLAG)))
H5E_THROW(H5E_CANTPROTECT, "unable to load extensible array header, address = %llu", (unsigned long long)ea_addr)
@ -272,10 +270,6 @@ H5EA_get_nelmts(const H5EA_t *ea, hsize_t *nelmts))
/* Local variables */
#ifdef QAK
HDfprintf(stderr, "%s: Called\n", FUNC);
#endif /* QAK */
/*
* Check arguments.
*/
@ -307,10 +301,6 @@ H5EA_get_addr(const H5EA_t *ea, haddr_t *addr))
/* Local variables */
#ifdef QAK
HDfprintf(stderr, "%s: Called\n", FUNC);
#endif /* QAK */
/*
* Check arguments.
*/
@ -325,7 +315,7 @@ END_FUNC(PRIV) /* end H5EA_get_addr() */
/*-------------------------------------------------------------------------
* Function: H5EA_lookup_elmt
* Function: H5EA__lookup_elmt
*
* Purpose: Retrieve the metadata object and the element buffer for a
* given element in the array.
@ -340,9 +330,9 @@ END_FUNC(PRIV) /* end H5EA_get_addr() */
*/
BEGIN_FUNC(STATIC, ERR,
herr_t, SUCCEED, FAIL,
H5EA__lookup_elmt(const H5EA_t *ea, hid_t dxpl_id, hsize_t idx, unsigned thing_acc,
void **thing, uint8_t **thing_elmt_buf, hsize_t *thing_elmt_idx,
H5EA__unprotect_func_t *thing_unprot_func))
H5EA__lookup_elmt(const H5EA_t *ea, hid_t dxpl_id, hsize_t idx, hbool_t will_extend,
unsigned thing_acc, void **thing, uint8_t **thing_elmt_buf,
hsize_t *thing_elmt_idx, H5EA__unprotect_func_t *thing_unprot_func))
/* Local variables */
H5EA_hdr_t *hdr = ea->hdr; /* Header for EA */
@ -355,11 +345,6 @@ H5EA__lookup_elmt(const H5EA_t *ea, hid_t dxpl_id, hsize_t idx, unsigned thing_a
hbool_t stats_changed = FALSE; /* Whether array statistics changed */
hbool_t hdr_dirty = FALSE; /* Whether the array header changed */
#ifdef QAK
HDfprintf(stderr, "%s: Called\n", FUNC);
HDfprintf(stderr, "%s: Index %Hu\n", FUNC, idx);
#endif /* QAK */
/*
* Check arguments.
*/
@ -383,9 +368,6 @@ HDfprintf(stderr, "%s: Index %Hu\n", FUNC, idx);
/* Check if we should create the index block */
if(!H5F_addr_defined(hdr->idx_blk_addr)) {
#ifdef QAK
HDfprintf(stderr, "%s: Index block address not defined!\n", FUNC, idx);
#endif /* QAK */
/* Check if we are allowed to create the thing */
if(0 == (thing_acc & H5AC__READ_ONLY_FLAG)) { /* i.e. r/w access */
/* Create the index block */
@ -397,9 +379,6 @@ HDfprintf(stderr, "%s: Index block address not defined!\n", FUNC, idx);
else
H5_LEAVE(SUCCEED)
} /* end if */
#ifdef QAK
HDfprintf(stderr, "%s: Index block address is: %a\n", FUNC, hdr->idx_blk_addr);
#endif /* QAK */
/* Protect index block */
if(NULL == (iblock = H5EA__iblock_protect(hdr, dxpl_id, thing_acc)))
@ -420,26 +399,14 @@ HDfprintf(stderr, "%s: Index block address is: %a\n", FUNC, hdr->idx_blk_addr);
/* Get super block index where element is located */
sblk_idx = H5EA__dblock_sblk_idx(hdr, idx);
#ifdef QAK
HDfprintf(stderr, "%s: sblk_idx = %u, iblock->nsblks = %Zu\n", FUNC, sblk_idx, iblock->nsblks);
#endif /* QAK */
/* Adjust index to offset in super block */
elmt_idx = idx - (hdr->cparam.idx_blk_elmts + hdr->sblk_info[sblk_idx].start_idx);
#ifdef QAK
HDfprintf(stderr, "%s: after adjusting for super block elements, elmt_idx = %Hu\n", FUNC, elmt_idx);
#endif /* QAK */
/* Check for data block containing element address in the index block */
if(sblk_idx < iblock->nsblks) {
#ifdef QAK
HDfprintf(stderr, "%s: Element in data block pointed to by address in index block\n", FUNC);
#endif /* QAK */
/* Compute the data block index in index block */
dblk_idx = (size_t)(hdr->sblk_info[sblk_idx].start_dblk + (elmt_idx / hdr->sblk_info[sblk_idx].dblk_nelmts));
#ifdef QAK
HDfprintf(stderr, "%s: dblk_idx = %u, iblock->ndblk_addrs = %Zu\n", FUNC, dblk_idx, iblock->ndblk_addrs);
#endif /* QAK */
HDassert(dblk_idx < iblock->ndblk_addrs);
/* Check if the data block has been allocated on disk yet */
@ -470,6 +437,13 @@ HDfprintf(stderr, "%s: dblk_idx = %u, iblock->ndblk_addrs = %Zu\n", FUNC, dblk_i
/* Adjust index to offset in data block */
elmt_idx %= hdr->sblk_info[sblk_idx].dblk_nelmts;
/* Check if there is already a dependency on the header */
if(will_extend && !dblock->has_hdr_depend) {
if(H5EA__create_flush_depend((H5AC_info_t *)hdr, (H5AC_info_t *)dblock) < 0)
H5E_THROW(H5E_CANTDEPEND, "unable to create flush dependency between data block and header, index = %llu", (unsigned long long)idx)
dblock->has_hdr_depend = TRUE;
} /* end if */
/* Set 'thing' info to refer to the data block */
*thing = dblock;
*thing_elmt_buf = (uint8_t *)dblock->elmts;
@ -490,9 +464,6 @@ HDfprintf(stderr, "%s: dblk_idx = %u, iblock->ndblk_addrs = %Zu\n", FUNC, dblk_i
/* Create super block */
sblk_addr = H5EA__sblock_create(hdr, dxpl_id, iblock, &stats_changed, sblk_idx);
#ifdef QAK
HDfprintf(stderr, "%s: New super block address is: %a\n", FUNC, sblk_addr);
#endif /* QAK */
if(!H5F_addr_defined(sblk_addr))
H5E_THROW(H5E_CANTCREATE, "unable to create extensible array super block")
@ -510,9 +481,6 @@ HDfprintf(stderr, "%s: New super block address is: %a\n", FUNC, sblk_addr);
/* Compute the data block index in super block */
dblk_idx = (size_t)(elmt_idx / sblock->dblk_nelmts);
#ifdef QAK
HDfprintf(stderr, "%s: dblk_idx = %u, sblock->ndblks = %Zu\n", FUNC, dblk_idx, sblock->ndblks);
#endif /* QAK */
HDassert(dblk_idx < sblock->ndblks);
/* Check if the data block has been allocated on disk yet */
@ -531,21 +499,20 @@ HDfprintf(stderr, "%s: dblk_idx = %u, sblock->ndblks = %Zu\n", FUNC, dblk_idx, s
/* Set data block address in index block */
sblock->dblk_addrs[dblk_idx] = dblk_addr;
sblock_cache_flags |= H5AC__DIRTIED_FLAG;
/* Create flush dependency on header, if extending the array and one doesn't already exist */
if(will_extend && !sblock->has_hdr_depend) {
if(H5EA__create_flush_depend((H5AC_info_t *)sblock->hdr, (H5AC_info_t *)sblock) < 0)
H5E_THROW(H5E_CANTDEPEND, "unable to create flush dependency between super block and header, address = %llu", (unsigned long long)sblock->addr)
sblock->has_hdr_depend = TRUE;
} /* end if */
} /* end if */
else
H5_LEAVE(SUCCEED)
} /* end if */
#ifdef QAK
if(sblock->dblk_npages)
HDfprintf(stderr, "%s: Check 1.0: elmt_idx = %Hu\n", FUNC, elmt_idx);
#endif /* QAK */
/* Adjust index to offset in data block */
elmt_idx %= sblock->dblk_nelmts;
#ifdef QAK
if(sblock->dblk_npages)
HDfprintf(stderr, "%s: Check 2.0: elmt_idx = %Hu\n", FUNC, elmt_idx);
#endif /* QAK */
/* Check if the data block is paged */
if(sblock->dblk_npages) {
@ -566,14 +533,6 @@ if(sblock->dblk_npages)
dblk_page_addr = sblock->dblk_addrs[dblk_idx] +
H5EA_DBLOCK_PREFIX_SIZE(sblock) +
(page_idx * sblock->dblk_page_size);
#ifdef QAK
HDfprintf(stderr, "%s: sblock->addr = %a\n", FUNC, sblock->addr);
HDfprintf(stderr, "%s: sblock->dblk_addrs[%Zu] = %a\n", FUNC, dblk_idx, sblock->dblk_addrs[dblk_idx]);
HDfprintf(stderr, "%s: H5EA_DBLOCK_PREFIX_SIZE(sblock) = %u\n", FUNC, (unsigned)H5EA_DBLOCK_PREFIX_SIZE(sblock));
HDfprintf(stderr, "%s: sblock->page_init[%Zu] = %t\n", FUNC, page_init_idx, H5VM_bit_get(sblock->page_init, page_init_idx));
HDfprintf(stderr, "%s: page_idx = %Zu, elmt_idx = %Hu, dblk_page_addr = %a\n", FUNC, page_idx, elmt_idx, dblk_page_addr);
HDfprintf(stderr, "%s: sblock->dblk_page_size = %Zu\n", FUNC, sblock->dblk_page_size);
#endif /* QAK */
/* Check if page has been initialized yet */
if(!H5VM_bit_get(sblock->page_init, page_init_idx)) {
@ -595,6 +554,13 @@ HDfprintf(stderr, "%s: sblock->dblk_page_size = %Zu\n", FUNC, sblock->dblk_page_
if(NULL == (dblk_page = H5EA__dblk_page_protect(hdr, dxpl_id, sblock, dblk_page_addr, thing_acc)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block page, address = %llu", (unsigned long long)dblk_page_addr)
/* Check if there is already a dependency on the header */
if(will_extend && !dblk_page->has_hdr_depend) {
if(H5EA__create_flush_depend((H5AC_info_t *)hdr, (H5AC_info_t *)dblk_page) < 0)
H5E_THROW(H5E_CANTDEPEND, "unable to create flush dependency between data block page and header, index = %llu", (unsigned long long)idx)
dblk_page->has_hdr_depend = TRUE;
} /* end if */
/* Set 'thing' info to refer to the data block page */
*thing = dblk_page;
*thing_elmt_buf = (uint8_t *)dblk_page->elmts;
@ -606,6 +572,13 @@ HDfprintf(stderr, "%s: sblock->dblk_page_size = %Zu\n", FUNC, sblock->dblk_page_
if(NULL == (dblock = H5EA__dblock_protect(hdr, dxpl_id, sblock, sblock->dblk_addrs[dblk_idx], sblock->dblk_nelmts, thing_acc)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block, address = %llu", (unsigned long long)sblock->dblk_addrs[dblk_idx])
/* Check if there is already a dependency on the header */
if(will_extend && !dblock->has_hdr_depend) {
if(H5EA__create_flush_depend((H5AC_info_t *)hdr, (H5AC_info_t *)dblock) < 0)
H5E_THROW(H5E_CANTDEPEND, "unable to create flush dependency between data block and header, index = %llu", (unsigned long long)idx)
dblock->has_hdr_depend = TRUE;
} /* end if */
/* Set 'thing' info to refer to the data block */
*thing = dblock;
*thing_elmt_buf = (uint8_t *)dblock->elmts;
@ -615,6 +588,10 @@ HDfprintf(stderr, "%s: sblock->dblk_page_size = %Zu\n", FUNC, sblock->dblk_page_
} /* end else */
} /* end else */
/* Sanity checks */
HDassert(*thing != NULL);
HDassert(*thing_unprot_func != NULL);
CATCH
/* Reset 'thing' info on error */
if(ret_value < 0) {
@ -644,7 +621,7 @@ CATCH
if(dblk_page && *thing != dblk_page && H5EA__dblk_page_unprotect(dblk_page, dxpl_id, H5AC__NO_FLAGS_SET) < 0)
H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array data block page")
END_FUNC(STATIC) /* end H5EA_lookup_elmt() */
END_FUNC(STATIC) /* end H5EA__lookup_elmt() */
/*-------------------------------------------------------------------------
@ -670,13 +647,9 @@ H5EA_set(const H5EA_t *ea, hid_t dxpl_id, hsize_t idx, const void *elmt))
uint8_t *thing_elmt_buf; /* Pointer to the element buffer for the array metadata */
hsize_t thing_elmt_idx; /* Index of the element in the element buffer for the array metadata */
H5EA__unprotect_func_t thing_unprot_func; /* Function pointer for unprotecting the array metadata */
hbool_t will_extend; /* Flag indicating if setting the element will extend the array */
unsigned thing_cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting array metadata */
#ifdef QAK
HDfprintf(stderr, "%s: Called\n", FUNC);
HDfprintf(stderr, "%s: Index %Hu\n", FUNC, idx);
#endif /* QAK */
/*
* Check arguments.
*/
@ -687,7 +660,8 @@ HDfprintf(stderr, "%s: Index %Hu\n", FUNC, idx);
hdr->f = ea->f;
/* Look up the array metadata containing the element we want to set */
if(H5EA__lookup_elmt(ea, dxpl_id, idx, H5AC__NO_FLAGS_SET, &thing, &thing_elmt_buf, &thing_elmt_idx, &thing_unprot_func) < 0)
will_extend = (idx >= hdr->stats.stored.max_idx_set);
if(H5EA__lookup_elmt(ea, dxpl_id, idx, will_extend, H5AC__NO_FLAGS_SET, &thing, &thing_elmt_buf, &thing_elmt_idx, &thing_unprot_func) < 0)
H5E_THROW(H5E_CANTPROTECT, "unable to protect array metadata")
/* Sanity check */
@ -700,10 +674,7 @@ HDfprintf(stderr, "%s: Index %Hu\n", FUNC, idx);
thing_cache_flags |= H5AC__DIRTIED_FLAG;
/* Update max. element set in array, if appropriate */
#ifdef QAK
HDfprintf(stderr, "%s: idx = %Hu, hdr->stats.max_idx_set = %Hu\n", FUNC, idx, hdr->stats.max_idx_set);
#endif /* QAK */
if(idx >= hdr->stats.stored.max_idx_set) {
if(will_extend) {
/* Update the max index for the array */
hdr->stats.stored.max_idx_set = idx + 1;
if(H5EA__hdr_modified(hdr) < 0)
@ -740,11 +711,6 @@ H5EA_get(const H5EA_t *ea, hid_t dxpl_id, hsize_t idx, void *elmt))
void *thing = NULL; /* Pointer to the array metadata containing the array index we are interested in */
H5EA__unprotect_func_t thing_unprot_func; /* Function pointer for unprotecting the array metadata */
#ifdef QAK
HDfprintf(stderr, "%s: Called\n", FUNC);
HDfprintf(stderr, "%s: Index %Hu\n", FUNC, idx);
#endif /* QAK */
/*
* Check arguments.
*/
@ -753,9 +719,6 @@ HDfprintf(stderr, "%s: Index %Hu\n", FUNC, idx);
/* Check for element beyond max. element in array */
if(idx >= hdr->stats.stored.max_idx_set) {
#ifdef QAK
HDfprintf(stderr, "%s: Element beyond max. index set, hdr->stats.max_idx_set = %Hu, idx = %Hu\n", FUNC, hdr->stats.max_idx_set, idx);
#endif /* QAK */
/* Call the class's 'fill' callback */
if((hdr->cparam.cls->fill)(elmt, (size_t)1) < 0)
H5E_THROW(H5E_CANTSET, "can't set element to class's fill value")
@ -764,15 +727,11 @@ HDfprintf(stderr, "%s: Element beyond max. index set, hdr->stats.max_idx_set = %
uint8_t *thing_elmt_buf; /* Pointer to the element buffer for the array metadata */
hsize_t thing_elmt_idx; /* Index of the element in the element buffer for the array metadata */
#ifdef QAK
HDfprintf(stderr, "%s: Index block address is: %a\n", FUNC, hdr->idx_blk_addr);
#endif /* QAK */
/* Set the shared array header's file context for this operation */
hdr->f = ea->f;
/* Look up the array metadata containing the element we want to set */
if(H5EA__lookup_elmt(ea, dxpl_id, idx, H5AC__READ_ONLY_FLAG, &thing, &thing_elmt_buf, &thing_elmt_idx, &thing_unprot_func) < 0)
if(H5EA__lookup_elmt(ea, dxpl_id, idx, FALSE, H5AC__READ_ONLY_FLAG, &thing, &thing_elmt_buf, &thing_elmt_idx, &thing_unprot_func) < 0)
H5E_THROW(H5E_CANTPROTECT, "unable to protect array metadata")
/* Check if the thing holding the element has been created yet */
@ -815,10 +774,6 @@ H5EA_depend(H5AC_info_t *parent_entry, H5EA_t *ea))
/* Local variables */
H5EA_hdr_t *hdr = ea->hdr; /* Header for EA */
#ifdef QAK
HDfprintf(stderr, "%s: Called\n", FUNC);
#endif /* QAK */
/*
* Check arguments.
*/
@ -836,49 +791,6 @@ CATCH
END_FUNC(PRIV) /* end H5EA_depend() */
/*-------------------------------------------------------------------------
* Function: H5EA_undepend
*
* Purpose: Remove a child flush dependency between the extensible array's
* header and another piece of metadata in the file.
*
* Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
* koziol@hdfgroup.org
* May 27 2009
*
*-------------------------------------------------------------------------
*/
BEGIN_FUNC(PRIV, ERR,
herr_t, SUCCEED, FAIL,
H5EA_undepend(H5AC_info_t *parent_entry, H5EA_t *ea))
/* Local variables */
H5EA_hdr_t *hdr = ea->hdr; /* Header for EA */
#ifdef QAK
HDfprintf(stderr, "%s: Called\n", FUNC);
#endif /* QAK */
/*
* Check arguments.
*/
HDassert(ea);
HDassert(hdr);
/* Set the shared array header's file context for this operation */
hdr->f = ea->f;
/* Remove flush dependency between parent entry and extensible array header */
if(H5EA__destroy_flush_depend(parent_entry, (H5AC_info_t *)hdr) < 0)
H5E_THROW(H5E_CANTUNDEPEND, "unable to destroy flush dependency on file metadata")
CATCH
END_FUNC(PRIV) /* end H5EA_undepend() */
/*-------------------------------------------------------------------------
* Function: H5EA_close
@ -901,10 +813,6 @@ H5EA_close(H5EA_t *ea, hid_t dxpl_id))
hbool_t pending_delete = FALSE; /* Whether the array is pending deletion */
haddr_t ea_addr = HADDR_UNDEF; /* Address of array (for deletion) */
#ifdef QAK
HDfprintf(stderr, "%s: Called\n", FUNC);
#endif /* QAK */
/*
* Check arguments.
*/
@ -1009,9 +917,6 @@ H5EA_delete(H5F_t *f, hid_t dxpl_id, haddr_t ea_addr, void *ctx_udata))
HDassert(H5F_addr_defined(ea_addr));
/* Lock the array header into memory */
#ifdef QAK
HDfprintf(stderr, "%s: ea_addr = %a\n", FUNC, ea_addr);
#endif /* QAK */
if(NULL == (hdr = H5EA__hdr_protect(f, dxpl_id, ea_addr, ctx_udata, H5AC__NO_FLAGS_SET)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array header, address = %llu", (unsigned long long)ea_addr)

View File

@ -1179,13 +1179,25 @@ H5EA__cache_sblock_notify(H5AC_notify_action_t action, void *_thing))
break;
case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
/* do nothing */
/* Destroy flush dependency on extensible array header, if set */
if(sblock->has_hdr_depend) {
if(H5EA__destroy_flush_depend((H5AC_info_t *)sblock->hdr, (H5AC_info_t *)sblock) < 0)
H5E_THROW(H5E_CANTUNDEPEND, "unable to destroy flush dependency between super block and header, address = %llu", (unsigned long long)sblock->addr)
sblock->has_hdr_depend = FALSE;
} /* end if */
break;
case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
/* Destroy flush dependency on index block */
if(H5EA__destroy_flush_depend((H5AC_info_t *)sblock->parent, (H5AC_info_t *)sblock) < 0)
H5E_THROW(H5E_CANTUNDEPEND, "unable to destroy flush dependency between super block and index block, address = %llu", (unsigned long long)sblock->addr)
/* Destroy flush dependency on extensible array header, if set */
if(sblock->has_hdr_depend) {
if(H5EA__destroy_flush_depend((H5AC_info_t *)sblock->hdr, (H5AC_info_t *)sblock) < 0)
H5E_THROW(H5E_CANTUNDEPEND, "unable to destroy flush dependency between super block and header, address = %llu", (unsigned long long)sblock->addr)
sblock->has_hdr_depend = FALSE;
} /* end if */
break;
default:
@ -1534,13 +1546,25 @@ H5EA__cache_dblock_notify(H5AC_notify_action_t action, void *_thing))
break;
case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
/* do nothing */
/* Destroy flush dependency on extensible array header, if set */
if(dblock->has_hdr_depend) {
if(H5EA__destroy_flush_depend((H5AC_info_t *)dblock->hdr, (H5AC_info_t *)dblock) < 0)
H5E_THROW(H5E_CANTUNDEPEND, "unable to destroy flush dependency between direct block and header, address = %llu", (unsigned long long)dblock->addr)
dblock->has_hdr_depend = FALSE;
} /* end if */
break;
case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
/* Destroy flush dependency on parent */
if(H5EA__destroy_flush_depend((H5AC_info_t *)dblock->parent, (H5AC_info_t *)dblock) < 0)
H5E_THROW(H5E_CANTUNDEPEND, "unable to destroy flush dependency between data block and parent, address = %llu", (unsigned long long)dblock->addr)
/* Destroy flush dependency on extensible array header, if set */
if(dblock->has_hdr_depend) {
if(H5EA__destroy_flush_depend((H5AC_info_t *)dblock->hdr, (H5AC_info_t *)dblock) < 0)
H5E_THROW(H5E_CANTUNDEPEND, "unable to destroy flush dependency between direct block and header, address = %llu", (unsigned long long)dblock->addr)
dblock->has_hdr_depend = FALSE;
} /* end if */
break;
default:
@ -1856,13 +1880,25 @@ H5EA__cache_dblk_page_notify(H5AC_notify_action_t action, void *_thing))
break;
case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
/* do nothing */
/* Destroy flush dependency on extensible array header, if set */
if(dblk_page->has_hdr_depend) {
if(H5EA__destroy_flush_depend((H5AC_info_t *)dblk_page->hdr, (H5AC_info_t *)dblk_page) < 0)
H5E_THROW(H5E_CANTUNDEPEND, "unable to destroy flush dependency between data block page and header, address = %llu", (unsigned long long)dblk_page->addr)
dblk_page->has_hdr_depend = FALSE;
} /* end if */
break;
case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
/* Destroy flush dependency on parent */
if(H5EA__destroy_flush_depend((H5AC_info_t *)dblk_page->parent, (H5AC_info_t *)dblk_page) < 0)
H5E_THROW(H5E_CANTUNDEPEND, "unable to destroy flush dependency between data block page and parent, address = %llu", (unsigned long long)dblk_page->addr)
/* Destroy flush dependency on extensible array header, if set */
if(dblk_page->has_hdr_depend) {
if(H5EA__destroy_flush_depend((H5AC_info_t *)dblk_page->hdr, (H5AC_info_t *)dblk_page) < 0)
H5E_THROW(H5E_CANTUNDEPEND, "unable to destroy flush dependency between data block page and header, address = %llu", (unsigned long long)dblk_page->addr)
dblk_page->has_hdr_depend = FALSE;
} /* end if */
break;
default:

View File

@ -156,10 +156,6 @@ H5EA__dblk_page_create(H5EA_hdr_t *hdr, hid_t dxpl_id, H5EA_sblock_t *parent,
/* Local variables */
H5EA_dblk_page_t *dblk_page = NULL; /* Extensible array data block page */
#ifdef QAK
HDfprintf(stderr, "%s: Called, addr = %a\n", FUNC, addr);
#endif /* QAK */
/* Sanity check */
HDassert(hdr);
@ -170,9 +166,6 @@ HDfprintf(stderr, "%s: Called, addr = %a\n", FUNC, addr);
/* Set info about data block page on disk */
dblk_page->addr = addr;
dblk_page->size = H5EA_DBLK_PAGE_SIZE(hdr);
#ifdef QAK
HDfprintf(stderr, "%s: dblk_page->size = %Zu\n", FUNC, dblk_page->size);
#endif /* QAK */
/* Clear any elements in data block page to fill value */
if((hdr->cparam.cls->fill)(dblk_page->elmts, (size_t)hdr->dblk_page_nelmts) < 0)
@ -215,10 +208,6 @@ H5EA__dblk_page_protect(H5EA_hdr_t *hdr, hid_t dxpl_id, H5EA_sblock_t *parent,
/* Local variables */
H5EA_dblk_page_cache_ud_t udata; /* Information needed for loading data block page */
#ifdef QAK
HDfprintf(stderr, "%s: Called\n", FUNC);
#endif /* QAK */
/* Sanity check */
HDassert(hdr);
HDassert(H5F_addr_defined(dblk_page_addr));
@ -261,10 +250,6 @@ H5EA__dblk_page_unprotect(H5EA_dblk_page_t *dblk_page, hid_t dxpl_id,
/* Local variables */
#ifdef QAK
HDfprintf(stderr, "%s: Called\n", FUNC);
#endif /* QAK */
/* Sanity check */
HDassert(dblk_page);
@ -296,6 +281,7 @@ H5EA__dblk_page_dest(H5EA_dblk_page_t *dblk_page))
/* Sanity check */
HDassert(dblk_page);
HDassert(!dblk_page->has_hdr_depend);
/* Check if header field has been initialized */
if(dblk_page->hdr) {

View File

@ -169,10 +169,6 @@ H5EA__dblock_create(H5EA_hdr_t *hdr, hid_t dxpl_id, void *parent,
H5EA_dblock_t *dblock = NULL; /* Extensible array data block */
haddr_t dblock_addr; /* Extensible array data block address */
#ifdef QAK
HDfprintf(stderr, "%s: Called, hdr->dblk_page_nelmts = %Zu, nelmts = %Zu\n", FUNC, hdr->dblk_page_nelmts, nelmts);
#endif /* QAK */
/* Sanity check */
HDassert(hdr);
HDassert(stats_changed);
@ -184,15 +180,9 @@ HDfprintf(stderr, "%s: Called, hdr->dblk_page_nelmts = %Zu, nelmts = %Zu\n", FUN
/* Set size of data block on disk */
dblock->size = H5EA_DBLOCK_SIZE(dblock);
#ifdef QAK
HDfprintf(stderr, "%s: dblock->size = %Zu\n", FUNC, dblock->size);
#endif /* QAK */
/* Set offset of block in array's address space */
dblock->block_off = dblk_off;
#ifdef QAK
HDfprintf(stderr, "%s: dblock->block_off = %Hu\n", FUNC, dblock->block_off);
#endif /* QAK */
/* Allocate space for the data block on disk */
if(HADDR_UNDEF == (dblock_addr = H5MF_alloc(hdr->f, H5FD_MEM_EARRAY_DBLOCK, dxpl_id, (hsize_t)dblock->size)))
@ -262,25 +252,12 @@ H5EA__dblock_sblk_idx(const H5EA_hdr_t *hdr, hsize_t idx))
HDassert(hdr);
HDassert(idx >= hdr->cparam.idx_blk_elmts);
#ifdef QAK
HDfprintf(stderr, "%s: Entering - idx = %Hu\n", FUNC, idx);
#endif /* QAK */
/* Adjust index for elements in index block */
idx -= hdr->cparam.idx_blk_elmts;
#ifdef QAK
HDfprintf(stderr, "%s: after adjusting for index block elements, idx = %Hu\n", FUNC, idx);
#endif /* QAK */
/* Determine the superblock information for the index */
H5_CHECK_OVERFLOW(idx, /*From:*/hsize_t, /*To:*/uint64_t);
#ifdef QAK
HDfprintf(stderr, "%s: hdr->cparam.data_blk_min_elmts = %u\n", FUNC, (unsigned)hdr->cparam.data_blk_min_elmts);
#endif /* QAK */
sblk_idx = H5VM_log2_gen((uint64_t)((idx / hdr->cparam.data_blk_min_elmts) + 1));
#ifdef QAK
HDfprintf(stderr, "%s: sblk_idx = %u\n", FUNC, sblk_idx);
HDfprintf(stderr, "%s: hdr->sblk_info[%u] = {%Hu, %Zu, %Hu, %Hu}\n", FUNC, sblk_idx, hdr->sblk_info[sblk_idx].ndblks, hdr->sblk_info[sblk_idx].dblk_nelmts, hdr->sblk_info[sblk_idx].start_idx, hdr->sblk_info[sblk_idx].start_dblk);
#endif /* QAK */
/* Set return value */
ret_value = sblk_idx;
@ -309,10 +286,6 @@ H5EA__dblock_protect(H5EA_hdr_t *hdr, hid_t dxpl_id, void *parent,
/* Local variables */
H5EA_dblock_cache_ud_t udata; /* Information needed for loading data block */
#ifdef QAK
HDfprintf(stderr, "%s: Called\n", FUNC);
#endif /* QAK */
/* Sanity check */
HDassert(hdr);
HDassert(H5F_addr_defined(dblk_addr));
@ -355,10 +328,6 @@ H5EA__dblock_unprotect(H5EA_dblock_t *dblock, hid_t dxpl_id, unsigned cache_flag
/* Local variables */
#ifdef QAK
HDfprintf(stderr, "%s: Called\n", FUNC);
#endif /* QAK */
/* Sanity check */
HDassert(dblock);
@ -392,10 +361,6 @@ H5EA__dblock_delete(H5EA_hdr_t *hdr, hid_t dxpl_id, void *parent,
/* Local variables */
H5EA_dblock_t *dblock = NULL; /* Pointer to data block */
#ifdef QAK
HDfprintf(stderr, "%s: Called\n", FUNC);
#endif /* QAK */
/* Sanity check */
HDassert(hdr);
HDassert(parent);
@ -420,16 +385,10 @@ HDfprintf(stderr, "%s: Called\n", FUNC);
/* Iterate over pages in data block */
for(u = 0; u < npages; u++) {
#ifdef QAK
HDfprintf(stderr, "%s: Expunging data block page from cache\n", FUNC);
#endif /* QAK */
/* Evict the data block page from the metadata cache */
/* (OK to call if it doesn't exist in the cache) */
if(H5AC_expunge_entry(hdr->f, dxpl_id, H5AC_EARRAY_DBLK_PAGE, dblk_page_addr, H5AC__NO_FLAGS_SET) < 0)
H5E_THROW(H5E_CANTEXPUNGE, "unable to remove array data block page from metadata cache")
#ifdef QAK
HDfprintf(stderr, "%s: Done expunging data block page from cache\n", FUNC);
#endif /* QAK */
/* Advance to next page address */
dblk_page_addr += dblk_page_size;
@ -463,6 +422,7 @@ H5EA__dblock_dest(H5EA_dblock_t *dblock))
/* Sanity check */
HDassert(dblock);
HDassert(!dblock->has_hdr_depend);
/* Check if shared header field has been initialized */
if(dblock->hdr) {

View File

@ -241,6 +241,7 @@ typedef struct H5EA_sblock_t {
/* Internal array information (not stored) */
H5EA_hdr_t *hdr; /* Shared array header info */
hbool_t has_hdr_depend; /* Whether this object has a flush dependency on the header */
H5EA_iblock_t *parent; /* Parent object for super block (index block) */
haddr_t addr; /* Address of this index block on disk */
size_t size; /* Size of index block on disk */
@ -265,6 +266,7 @@ typedef struct H5EA_dblock_t {
/* Internal array information (not stored) */
H5EA_hdr_t *hdr; /* Shared array header info */
hbool_t has_hdr_depend; /* Whether this object has a flush dependency on the header */
void *parent; /* Parent object for data block (index or super block) */
haddr_t addr; /* Address of this data block on disk */
size_t size; /* Size of data block on disk */
@ -284,6 +286,7 @@ typedef struct H5EA_dbk_page_t {
/* Internal array information (not stored) */
H5EA_hdr_t *hdr; /* Shared array header info */
hbool_t has_hdr_depend; /* Whether this object has a flush dependency on the header */
H5EA_sblock_t *parent; /* Parent object for data block page (super block) */
haddr_t addr; /* Address of this data block page on disk */
size_t size; /* Size of data block page on disk */

View File

@ -133,9 +133,6 @@ H5EA__sblock_alloc(H5EA_hdr_t *hdr, H5EA_iblock_t *parent, unsigned sblk_idx))
sblock->ndblks = hdr->sblk_info[sblk_idx].ndblks;
HDassert(sblock->ndblks);
sblock->dblk_nelmts = hdr->sblk_info[sblk_idx].dblk_nelmts;
#ifdef QAK
HDfprintf(stderr, "%s: hdr->dblk_page_nelmts = %Zu, sblock->ndblks = %Zu, sblock->dblk_nelmts = %Zu\n", FUNC, hdr->dblk_page_nelmts, sblock->ndblks, sblock->dblk_nelmts);
#endif /* QAK */
/* Allocate buffer for data block addresses in super block */
if(NULL == (sblock->dblk_addrs = H5FL_SEQ_MALLOC(haddr_t, sblock->ndblks)))
@ -199,10 +196,6 @@ H5EA__sblock_create(H5EA_hdr_t *hdr, hid_t dxpl_id, H5EA_iblock_t *parent,
haddr_t sblock_addr; /* Extensible array super block address */
haddr_t tmp_addr = HADDR_UNDEF; /* Address value to fill data block addresses with */
#ifdef QAK
HDfprintf(stderr, "%s: Called\n", FUNC);
#endif /* QAK */
/* Sanity check */
HDassert(hdr);
HDassert(stats_changed);
@ -213,15 +206,9 @@ HDfprintf(stderr, "%s: Called\n", FUNC);
/* Set size of super block on disk */
sblock->size = H5EA_SBLOCK_SIZE(sblock);
#ifdef QAK
HDfprintf(stderr, "%s: sblock->size = %Zu\n", FUNC, sblock->size);
#endif /* QAK */
/* Set offset of block in array's address space */
sblock->block_off = hdr->sblk_info[sblk_idx].start_idx;
#ifdef QAK
HDfprintf(stderr, "%s: sblock->block_off = %Hu\n", FUNC, sblock->block_off);
#endif /* QAK */
/* Allocate space for the super block on disk */
if(HADDR_UNDEF == (sblock_addr = H5MF_alloc(hdr->f, H5FD_MEM_EARRAY_SBLOCK, dxpl_id, (hsize_t)sblock->size)))
@ -281,11 +268,6 @@ H5EA__sblock_protect(H5EA_hdr_t *hdr, hid_t dxpl_id, H5EA_iblock_t *parent,
/* Local variables */
H5EA_sblock_cache_ud_t udata; /* Information needed for loading super block */
#ifdef QAK
HDfprintf(stderr, "%s: Called\n", FUNC);
#endif /* QAK */
/* Sanity check */
HDassert(hdr);
HDassert(H5F_addr_defined(sblk_addr));
@ -327,10 +309,6 @@ H5EA__sblock_unprotect(H5EA_sblock_t *sblock, hid_t dxpl_id, unsigned cache_flag
/* Local variables */
#ifdef QAK
HDfprintf(stderr, "%s: Called\n", FUNC);
#endif /* QAK */
/* Sanity check */
HDassert(sblock);
@ -365,10 +343,6 @@ H5EA__sblock_delete(H5EA_hdr_t *hdr, hid_t dxpl_id, H5EA_iblock_t *parent,
H5EA_sblock_t *sblock = NULL; /* Pointer to super block */
size_t u; /* Local index variable */
#ifdef QAK
HDfprintf(stderr, "%s: Called\n", FUNC);
#endif /* QAK */
/* Sanity check */
HDassert(hdr);
HDassert(H5F_addr_defined(sblk_addr));
@ -415,9 +389,7 @@ H5EA__sblock_dest(H5EA_sblock_t *sblock))
/* Sanity check */
HDassert(sblock);
#ifdef QAK
HDfprintf(stderr, "%s: sblock->hdr->dblk_page_nelmts = %Zu, sblock->ndblks = %Zu, sblock->dblk_nelmts = %Zu\n", FUNC, sblock->hdr->dblk_page_nelmts, sblock->ndblks, sblock->dblk_nelmts);
#endif /* QAK */
HDassert(!sblock->has_hdr_depend);
/* Check if shared header field has been initialized */
if(sblock->hdr) {

View File

@ -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;
unsigned dblock_status = 0;
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(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(in_cache) { /* dblock is in cache */
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")
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 */

File diff suppressed because it is too large Load Diff

View File

@ -206,6 +206,9 @@ static herr_t notify_free_icr(void *thing);
static herr_t notify_notify(H5C_notify_action_t action, void *thing);
static void mark_flush_dep_dirty(test_entry_t * entry_ptr);
static void mark_flush_dep_clean(test_entry_t * entry_ptr);
/* Generic callback routines */
static herr_t get_load_size(const void *udata_ptr, size_t *image_len_ptr,
int32_t entry_type);
@ -738,6 +741,8 @@ deserialize(const void *image, size_t len, void *udata, hbool_t *dirty,
HDassert(entry->size == len);
HDassert((entry->type == VARIABLE_ENTRY_TYPE) || (entry->size == entry_sizes[type]));
HDassert(dirty != NULL);
HDassert( entry->flush_dep_npar == 0 );
HDassert( entry->flush_dep_nchd == 0 );
/* for now *dirty will always be FALSE */
*dirty = FALSE;
@ -1334,6 +1339,11 @@ serialize(const H5F_t H5_ATTR_UNUSED *f, void *image_ptr, size_t len, void *thin
*/
entry->is_dirty = FALSE;
if(entry->flush_dep_npar > 0) {
HDassert(entry->flush_dep_ndirty_chd == 0);
mark_flush_dep_clean(entry);
} /* end if */
/* since the entry is about to be written to disk, we can mark it
* as initialized.
*/
@ -2369,11 +2379,9 @@ reset_entries(void)
base_addr[j].destroyed = FALSE;
base_addr[j].expunged = FALSE;
base_addr[j].flush_dep_par_type = -1;
base_addr[j].flush_dep_par_idx = -1;
for ( k = 0; k < H5C__NUM_FLUSH_DEP_HEIGHTS; k++ )
base_addr[j].child_flush_dep_height_rc[k] = 0;
base_addr[j].flush_dep_height = 0;
base_addr[j].flush_dep_npar = 0;
base_addr[j].flush_dep_nchd = 0;
base_addr[j].flush_dep_ndirty_chd = 0;
base_addr[j].pinned_from_client = FALSE;
base_addr[j].pinned_from_cache = FALSE;
@ -2473,12 +2481,16 @@ resize_entry(H5F_t * file_ptr,
failure_mssg = "entry to be resized is not pinned or protected.";
} else {
hbool_t was_dirty = entry_ptr->is_dirty;
entry_ptr->size = new_size;
result = H5C_resize_entry((void *)entry_ptr, new_size);
entry_ptr->is_dirty = TRUE;
if(entry_ptr->flush_dep_npar > 0 && !was_dirty)
mark_flush_dep_dirty(entry_ptr);
if ( result != SUCCEED ) {
pass = FALSE;
@ -2817,105 +2829,119 @@ verify_entry_status(H5C_t * cache_ptr,
/* Check flush dependency fields */
/* Flush dependency parent type & index */
if ( pass ) {
if ( entry_ptr->flush_dep_par_type != expected[i].flush_dep_par_type ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) flush_dep_par_type actual/expected = %d/%d.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
entry_ptr->flush_dep_par_type,
expected[i].flush_dep_par_type);
failure_mssg = msg;
} /* end if */
} /* end if */
if ( pass ) {
if ( entry_ptr->flush_dep_par_idx != expected[i].flush_dep_par_idx ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) flush_dep_par_idx actual/expected = %d/%d.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
entry_ptr->flush_dep_par_idx,
expected[i].flush_dep_par_idx);
failure_mssg = msg;
} /* end if */
} /* end if */
if ( ( pass ) && ( in_cache ) && expected[i].flush_dep_par_idx >= 0 ) {
test_entry_t * par_base_addr = entries[expected[i].flush_dep_par_type];
if ( entry_ptr->header.flush_dep_parent != (H5C_cache_entry_t *)&(par_base_addr[expected[i].flush_dep_par_idx]) ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) header flush_dep_parent actual/expected = %p/%p.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
(void *)entry_ptr->header.flush_dep_parent,
(void *)&(par_base_addr[expected[i].flush_dep_par_idx]));
failure_mssg = msg;
} /* end if */
} /* end if */
/* Flush dependency child ref. counts */
for(u = 0; u < H5C__NUM_FLUSH_DEP_HEIGHTS; u++) {
if ( pass ) {
if ( entry_ptr->child_flush_dep_height_rc[u] != expected[i].child_flush_dep_height_rc[u] ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) child_flush_dep_height_rc[%u] actual/expected = %llu/%llu.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
u,
(unsigned long long)(entry_ptr->child_flush_dep_height_rc[u]),
(unsigned long long)expected[i].child_flush_dep_height_rc[u]);
failure_mssg = msg;
} /* end if */
} /* end if */
if ( ( pass ) && ( in_cache ) ) {
if ( entry_ptr->header.child_flush_dep_height_rc[u] != expected[i].child_flush_dep_height_rc[u] ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) header child_flush_dep_height_rc[%u] actual/expected = %llu/%llu.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
u,
(unsigned long long)entry_ptr->header.child_flush_dep_height_rc[u],
(unsigned long long)expected[i].child_flush_dep_height_rc[u]);
failure_mssg = msg;
} /* end if */
} /* end if */
} /* end for */
/* Flush dependency height */
/* # of flush dependency parents */
if ( pass ) {
if ( entry_ptr->flush_dep_height != expected[i].flush_dep_height ) {
if ( entry_ptr->flush_dep_npar != expected[i].flush_dep_npar ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) flush_dep_height actual/expected = %u/%u.\n",
"%d entry (%d, %d) flush_dep_npar actual/expected = %u/%u.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
entry_ptr->flush_dep_height,
expected[i].flush_dep_height);
entry_ptr->flush_dep_npar,
expected[i].flush_dep_npar);
failure_mssg = msg;
} /* end if */
} /* end if */
if ( ( pass ) && ( in_cache ) ) {
if ( entry_ptr->header.flush_dep_height != expected[i].flush_dep_height ) {
if ( entry_ptr->header.flush_dep_nparents != expected[i].flush_dep_npar ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) header flush_dep_height actual/expected = %u/%u.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
entry_ptr->header.flush_dep_height,
expected[i].flush_dep_height);
"%d entry (%d, %d) header flush_dep_nparents actual/expected = %u/%u.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
entry_ptr->header.flush_dep_nparents,
expected[i].flush_dep_npar);
failure_mssg = msg;
} /* end if */
} /* end if */
/* Flush dependency parent type & index. Note this algorithm assumes
* that the parents in both arrays are in the same order. */
if ( pass ) {
for ( u = 0; u < entry_ptr->flush_dep_npar; u++ ) {
if ( entry_ptr->flush_dep_par_type[u] != expected[i].flush_dep_par_type[u] ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) flush_dep_par_type[%u] actual/expected = %d/%d.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
u,
entry_ptr->flush_dep_par_type[u],
expected[i].flush_dep_par_type[u]);
failure_mssg = msg;
} /* end if */
} /* end for */
} /* end if */
if ( pass ) {
for ( u = 0; u < entry_ptr->flush_dep_npar; u++ ) {
if ( entry_ptr->flush_dep_par_idx[u] != expected[i].flush_dep_par_idx[u] ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) flush_dep_par_idx[%u] actual/expected = %d/%d.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
u,
entry_ptr->flush_dep_par_idx[u],
expected[i].flush_dep_par_idx[u]);
failure_mssg = msg;
} /* end if */
} /* end for */
} /* end if */
/* # of flush dependency children and dirty children */
if ( pass ) {
if ( entry_ptr->flush_dep_nchd != expected[i].flush_dep_nchd ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) flush_dep_nchd actual/expected = %u/%u.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
entry_ptr->flush_dep_nchd,
expected[i].flush_dep_nchd);
failure_mssg = msg;
} /* end if */
} /* end if */
if ( ( pass ) && ( in_cache ) ) {
if ( entry_ptr->header.flush_dep_nchildren != expected[i].flush_dep_nchd ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) header flush_dep_nchildren actual/expected = %u/%u.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
entry_ptr->header.flush_dep_nchildren,
expected[i].flush_dep_nchd);
failure_mssg = msg;
} /* end if */
} /* end if */
if ( pass ) {
if ( entry_ptr->flush_dep_ndirty_chd != expected[i].flush_dep_ndirty_chd ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) flush_dep_ndirty_chd actual/expected = %u/%u.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
entry_ptr->flush_dep_ndirty_chd,
expected[i].flush_dep_ndirty_chd);
failure_mssg = msg;
} /* end if */
} /* end if */
if ( ( pass ) && ( in_cache ) ) {
if ( entry_ptr->header.flush_dep_ndirty_children != expected[i].flush_dep_ndirty_chd ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) header flush_dep_ndirty_children actual/expected = %u/%u.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
entry_ptr->header.flush_dep_ndirty_children,
expected[i].flush_dep_ndirty_chd);
failure_mssg = msg;
} /* end if */
} /* end if */
@ -3656,6 +3682,8 @@ insert_entry(H5F_t * file_ptr,
HDassert( entry_ptr->type == type );
HDassert( entry_ptr == entry_ptr->self );
HDassert( !(entry_ptr->is_protected) );
HDassert( entry_ptr->flush_dep_npar == 0 );
HDassert( entry_ptr->flush_dep_nchd == 0 );
insert_pinned = (hbool_t)((flags & H5C__PIN_ENTRY_FLAG) != 0 );
@ -3742,6 +3770,7 @@ mark_entry_dirty(int32_t type,
herr_t result;
test_entry_t * base_addr;
test_entry_t * entry_ptr;
hbool_t was_dirty;
if ( pass ) {
@ -3757,8 +3786,12 @@ mark_entry_dirty(int32_t type,
HDassert( entry_ptr->header.is_protected ||
entry_ptr->header.is_pinned );
was_dirty = entry_ptr->is_dirty;
entry_ptr->is_dirty = TRUE;
if(entry_ptr->flush_dep_npar > 0 && !was_dirty)
mark_flush_dep_dirty(entry_ptr);
result = H5C_mark_entry_dirty((void *)entry_ptr);
if ( ( result < 0 ) ||
@ -3850,11 +3883,14 @@ move_entry(H5C_t * cache_ptr,
}
if ( ! done ) {
hbool_t was_dirty = entry_ptr->is_dirty;
entry_ptr->is_dirty = TRUE;
result = H5C_move_entry(cache_ptr, &(types[type]),
old_addr, new_addr);
if(entry_ptr->flush_dep_npar > 0 && !was_dirty)
mark_flush_dep_dirty(entry_ptr);
result = H5C_move_entry(cache_ptr, &(types[type]), old_addr, new_addr);
}
if ( ! done ) {
@ -4243,9 +4279,15 @@ unprotect_entry(H5F_t * file_ptr,
HDassert ( ( ! pin_flag_set ) || ( ! (entry_ptr->is_pinned) ) );
HDassert ( ( ! unpin_flag_set ) || ( entry_ptr->is_pinned ) );
if(flags & H5C__DIRTIED_FLAG)
if(flags & H5C__DIRTIED_FLAG) {
hbool_t was_dirty = entry_ptr->is_dirty;
entry_ptr->is_dirty = TRUE;
if(entry_ptr->flush_dep_npar > 0 && !was_dirty)
mark_flush_dep_dirty(entry_ptr);
} /* end if */
result = H5C_unprotect(file_ptr, H5AC_ind_read_dxpl_id,
entry_ptr->addr, (void *)entry_ptr, flags);
@ -5722,43 +5764,26 @@ create_flush_dependency(int32_t par_type,
if ( ( result < 0 ) ||
( !par_entry_ptr->header.is_pinned ) ||
( !(par_entry_ptr->header.flush_dep_height > 0) ) ) {
( !(par_entry_ptr->header.flush_dep_nchildren > 0) ) ) {
pass = FALSE;
failure_mssg = "error in H5C_create_flush_dependency().";
} /* end if */
/* Update information about entries */
chd_entry_ptr->flush_dep_par_type = par_type;
chd_entry_ptr->flush_dep_par_idx = par_idx;
par_entry_ptr->child_flush_dep_height_rc[chd_entry_ptr->flush_dep_height]++;
HDassert( chd_entry_ptr->flush_dep_npar < MAX_FLUSH_DEP_PARS );
chd_entry_ptr->flush_dep_par_type[chd_entry_ptr->flush_dep_npar] = par_type;
chd_entry_ptr->flush_dep_par_idx[chd_entry_ptr->flush_dep_npar] = par_idx;
chd_entry_ptr->flush_dep_npar++;
par_entry_ptr->flush_dep_nchd++;
if(chd_entry_ptr->is_dirty || chd_entry_ptr->flush_dep_ndirty_chd > 0) {
HDassert(par_entry_ptr->flush_dep_ndirty_chd < par_entry_ptr->flush_dep_nchd);
par_entry_ptr->flush_dep_ndirty_chd++;
} /* end if */
par_entry_ptr->pinned_from_cache = TRUE;
if( !par_is_pinned )
par_entry_ptr->is_pinned = TRUE;
/* Check flush dependency heights */
while(chd_entry_ptr->flush_dep_height >= par_entry_ptr->flush_dep_height) {
unsigned prev_par_flush_dep_height = par_entry_ptr->flush_dep_height; /* Save the previous height */
par_entry_ptr->flush_dep_height = chd_entry_ptr->flush_dep_height + 1;
/* Check for parent entry being in flush dependency relationship */
if(par_entry_ptr->flush_dep_par_idx >= 0) {
/* Move parent & child entries up the flushd dependency 'chain' */
chd_entry_ptr = par_entry_ptr;
par_base_addr = entries[chd_entry_ptr->flush_dep_par_type];
par_entry_ptr = &(par_base_addr[chd_entry_ptr->flush_dep_par_idx]);
/* Adjust the ref. counts in new parent */
HDassert(par_entry_ptr->child_flush_dep_height_rc[prev_par_flush_dep_height] > 0);
par_entry_ptr->child_flush_dep_height_rc[prev_par_flush_dep_height]--;
par_entry_ptr->child_flush_dep_height_rc[chd_entry_ptr->flush_dep_height]++;
} /* end if */
} /* end if */
} /* end if */
return;
} /* create_flush_dependency() */
@ -5793,18 +5818,16 @@ destroy_flush_dependency(int32_t par_type,
test_entry_t * par_entry_ptr; /* Parent entry */
test_entry_t * chd_base_addr; /* Base entry of child's entry array */
test_entry_t * chd_entry_ptr; /* Child entry */
unsigned chd_flush_dep_height; /* Child flush dep. height */
unsigned i; /* Local index variable */
/* Get parent entry */
par_base_addr = entries[par_type];
par_entry_ptr = &(par_base_addr[par_idx]);
/* Sanity check parent entry */
HDassert( par_entry_ptr->index == par_idx );
HDassert( par_entry_ptr->type == par_type );
HDassert( par_entry_ptr->is_pinned );
HDassert( par_entry_ptr->pinned_from_cache );
HDassert( par_entry_ptr->flush_dep_height > 0 );
HDassert( par_entry_ptr->flush_dep_nchd > 0 );
HDassert( par_entry_ptr == par_entry_ptr->self );
/* Get parent entry */
@ -5814,7 +5837,7 @@ destroy_flush_dependency(int32_t par_type,
/* Sanity check child entry */
HDassert( chd_entry_ptr->index == chd_idx );
HDassert( chd_entry_ptr->type == chd_type );
HDassert( chd_entry_ptr->flush_dep_height < par_entry_ptr->flush_dep_height );
HDassert( chd_entry_ptr->flush_dep_npar > 0 );
HDassert( chd_entry_ptr == chd_entry_ptr->self );
if ( H5C_destroy_flush_dependency(par_entry_ptr, chd_entry_ptr) < 0 ) {
@ -5823,55 +5846,123 @@ destroy_flush_dependency(int32_t par_type,
} /* end if */
/* Update information about entries */
chd_entry_ptr->flush_dep_par_type = -1;
chd_entry_ptr->flush_dep_par_idx = -1;
par_entry_ptr->child_flush_dep_height_rc[chd_entry_ptr->flush_dep_height]--;
/* Check flush dependency heights */
chd_flush_dep_height = chd_entry_ptr->flush_dep_height;
while( 0 == par_entry_ptr->child_flush_dep_height_rc[chd_flush_dep_height] ) {
unsigned prev_par_flush_dep_height = par_entry_ptr->flush_dep_height; /* Save the previous height */
int i; /* Local index variable */
/* Check for new flush dependency height of parent */
for(i = (H5C__NUM_FLUSH_DEP_HEIGHTS - 1); i >= 0; i--)
if(par_entry_ptr->child_flush_dep_height_rc[i] > 0)
break;
HDassert((i + 1) <= (int)prev_par_flush_dep_height);
if((unsigned)(i + 1) < prev_par_flush_dep_height) {
par_entry_ptr->flush_dep_height = (unsigned)(i + 1);
if(i < 0) {
par_entry_ptr->pinned_from_cache = FALSE;
par_entry_ptr->is_pinned = par_entry_ptr->pinned_from_client;
} /* end if */
/* Check for parent entry being in flush dependency relationship */
if(par_entry_ptr->flush_dep_par_idx >= 0) {
/* Move parent & child entries up the flushd dependency 'chain' */
chd_entry_ptr = par_entry_ptr;
par_base_addr = entries[chd_entry_ptr->flush_dep_par_type];
par_entry_ptr = &(par_base_addr[chd_entry_ptr->flush_dep_par_idx]);
/* Adjust the ref. counts in new parent */
HDassert(par_entry_ptr->child_flush_dep_height_rc[prev_par_flush_dep_height] > 0);
par_entry_ptr->child_flush_dep_height_rc[prev_par_flush_dep_height]--;
par_entry_ptr->child_flush_dep_height_rc[chd_entry_ptr->flush_dep_height]++;
chd_flush_dep_height = prev_par_flush_dep_height;
} /* end if */
else
break;
} /* end if */
else
for(i=0; i<chd_entry_ptr->flush_dep_npar; i++)
if(chd_entry_ptr->flush_dep_par_type[i] == par_type
&& chd_entry_ptr->flush_dep_par_idx[i] == par_idx)
break;
} /* end while */
HDassert(i < chd_entry_ptr->flush_dep_npar);
if(i < chd_entry_ptr->flush_dep_npar - 1)
HDmemmove(&chd_entry_ptr->flush_dep_par_type[i],
&chd_entry_ptr->flush_dep_par_type[i+1],
(chd_entry_ptr->flush_dep_npar - i - 1)
* sizeof(chd_entry_ptr->flush_dep_par_type[0]));
if(i < chd_entry_ptr->flush_dep_npar - 1)
HDmemmove(&chd_entry_ptr->flush_dep_par_idx[i],
&chd_entry_ptr->flush_dep_par_idx[i+1],
(chd_entry_ptr->flush_dep_npar - i - 1)
* sizeof(chd_entry_ptr->flush_dep_par_idx[0]));
chd_entry_ptr->flush_dep_npar--;
par_entry_ptr->flush_dep_nchd--;
if(par_entry_ptr->flush_dep_nchd == 0) {
par_entry_ptr->pinned_from_cache = FALSE;
par_entry_ptr->is_pinned = par_entry_ptr->pinned_from_client;
} /* end if */
if(chd_entry_ptr->is_dirty || chd_entry_ptr->flush_dep_ndirty_chd > 0) {
HDassert(par_entry_ptr->flush_dep_ndirty_chd > 0);
par_entry_ptr->flush_dep_ndirty_chd--;
if(!par_entry_ptr->is_dirty
&& par_entry_ptr->flush_dep_ndirty_chd == 0)
mark_flush_dep_clean(par_entry_ptr);
} /* end if */
} /* end if */
return;
} /* destroy_flush_dependency() */
/*-------------------------------------------------------------------------
* Function: mark_flush_dep_dirty()
*
* Purpose: Recursively propagate the flush_dep_ndirty_children flag
* up the dependency chain in response to entry either
* becoming dirty or having its flush_dep_ndirty_children
* increased from 0.
*
* Return: <none>
*
* Programmer: Neil Fortner
* 12/4/12
*
*-------------------------------------------------------------------------
*/
static void
mark_flush_dep_dirty(test_entry_t * entry_ptr)
{
/* Sanity checks */
HDassert(entry_ptr);
/* Iterate over the parent entries */
if(entry_ptr->flush_dep_npar) {
test_entry_t *par_base_addr; /* Base entry of parent's entry array */
test_entry_t *par_entry_ptr; /* Parent entry */
unsigned u; /* Local index variable */
for(u = 0; u < entry_ptr->flush_dep_npar; u++) {
/* Get parent entry */
par_base_addr = entries[entry_ptr->flush_dep_par_type[u]];
par_entry_ptr = &(par_base_addr[entry_ptr->flush_dep_par_idx[u]]);
/* Sanity check */
HDassert(par_entry_ptr->flush_dep_ndirty_chd
< par_entry_ptr->flush_dep_nchd);
/* Adjust the parent's number of dirty children */
par_entry_ptr->flush_dep_ndirty_chd++;
} /* end for */
} /* end if */
} /* end mark_flush_dep_dirty() */
/*-------------------------------------------------------------------------
* Function: mark_flush_dep_clean()
*
* Purpose: Recursively propagate the flush_dep_ndirty_children flag
* up the dependency chain in response to entry either
* becoming clean or having its flush_dep_ndirty_children
* reduced to 0.
*
* Return: <none>
*
* Programmer: Neil Fortner
* 12/4/12
*
*-------------------------------------------------------------------------
*/
static void
mark_flush_dep_clean(test_entry_t * entry_ptr)
{
/* Sanity checks */
HDassert(entry_ptr);
HDassert(!entry_ptr->is_dirty && entry_ptr->flush_dep_ndirty_chd == 0);
/* Iterate over the parent entries */
if(entry_ptr->flush_dep_npar) {
test_entry_t *par_base_addr; /* Base entry of parent's entry array */
test_entry_t *par_entry_ptr; /* Parent entry */
unsigned u; /* Local index variable */
for(u = 0; u < entry_ptr->flush_dep_npar; u++) {
/* Get parent entry */
par_base_addr = entries[entry_ptr->flush_dep_par_type[u]];
par_entry_ptr = &(par_base_addr[entry_ptr->flush_dep_par_idx[u]]);
/* Sanity check */
HDassert(par_entry_ptr->flush_dep_ndirty_chd > 0);
/* Adjust the parent's number of dirty children */
par_entry_ptr->flush_dep_ndirty_chd--;
} /* end for */
} /* end if */
} /* end mark_flush_dep_clean() */
/*** H5AC level utility functions ***/

View File

@ -152,6 +152,9 @@
* cache entry.
*/
#define MAX_FLUSH_DEP_PARS 8 /* Maximum number of flush dependency
* parents in the test */
typedef struct flush_op
{
int op_code; /* integer op code indicating the
@ -340,13 +343,11 @@ typedef struct test_entry_t
hbool_t expunged; /* entry has been expunged since the
* last time it was reset.
*/
int flush_dep_par_type; /* Entry type of flush dependency parent */
int flush_dep_par_idx; /* Index of flush dependency parent */
uint64_t child_flush_dep_height_rc[H5C__NUM_FLUSH_DEP_HEIGHTS];
/* flush dependency heights of flush
* dependency children
*/
unsigned flush_dep_height; /* flush dependency height of entry */
int flush_dep_par_type[MAX_FLUSH_DEP_PARS]; /* Entry types of flush dependency parents */
int flush_dep_par_idx[MAX_FLUSH_DEP_PARS]; /* Indices of flush dependency parents */
unsigned flush_dep_npar; /* Number of flush dependency parents */
unsigned flush_dep_nchd; /* Number of flush dependency children */
unsigned flush_dep_ndirty_chd; /* Number of dirty flush dependency children (including granchildren, etc.) */
hbool_t pinned_from_client; /* entry was pinned by client call */
hbool_t pinned_from_cache; /* entry was pinned by cache internally */
unsigned flush_order; /* Order that entry was flushed in */
@ -520,13 +521,11 @@ struct expected_entry_status
hbool_t deserialized;
hbool_t serialized;
hbool_t destroyed;
int flush_dep_par_type; /* Entry type of flush dependency parent */
int flush_dep_par_idx; /* Index of flush dependency parent */
uint64_t child_flush_dep_height_rc[H5C__NUM_FLUSH_DEP_HEIGHTS];
/* flush dependency heights of flush
* dependency children
*/
unsigned flush_dep_height; /* flush dependency height of entry */
int flush_dep_par_type[MAX_FLUSH_DEP_PARS]; /* Entry types of flush dependency parents */
int flush_dep_par_idx[MAX_FLUSH_DEP_PARS]; /* Indices of flush dependency parents */
unsigned flush_dep_npar; /* Number of flush dependency parents */
unsigned flush_dep_nchd; /* Number of flush dependency children */
unsigned flush_dep_ndirty_chd; /* Number of dirty flush dependency children */
int flush_order; /* flush order of entry */
unsigned char is_corked; /* cork status of entry */
};

View File

@ -666,7 +666,8 @@ test_userblock_offset(const char *env_h5_drvr, hid_t fapl)
f = HDopen(filename, O_RDONLY, 0);
HDlseek(f, (off_t)offset, SEEK_SET);
HDread(f, rdata, sizeof(int)*DSET_DIM1*DSET_DIM2);
if(HDread(f, rdata, sizeof(int)*DSET_DIM1*DSET_DIM2) < 0)
goto error;
/* Check that the values read are the same as the values written */
for(i = 0; i < DSET_DIM1; i++) {

View File

@ -88,7 +88,7 @@ void pause_proc(void)
}
printf("waiting(%ds) for file %s ...\n", time_int, greenlight);
fflush(stdout);
HDsleep(time_int);
HDsleep(time_int);
}
MPI_Barrier(MPI_COMM_WORLD);
}