summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/H5C.c232
-rw-r--r--src/H5Cprivate.h35
-rw-r--r--test/cache.c195
-rw-r--r--test/cache_common.c42
-rw-r--r--test/cache_common.h4
5 files changed, 363 insertions, 145 deletions
diff --git a/src/H5C.c b/src/H5C.c
index 27b98d0..b7d64f9 100644
--- a/src/H5C.c
+++ b/src/H5C.c
@@ -4881,6 +4881,7 @@ H5C_insert_entry(H5F_t * f,
entry_ptr->ro_ref_count = 0;
entry_ptr->is_pinned = insert_pinned;
+ entry_ptr->pinned_from_client = insert_pinned;
/* newly inserted entries are assumed to be dirty */
entry_ptr->is_dirty = TRUE;
@@ -5973,6 +5974,56 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5C_pin_entry_from_client()
+ *
+ * Purpose: Internal routine to pin a cache entry from a client action.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * 3/26/09
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NDEBUG
+static herr_t
+H5C_pin_entry_from_client(H5C_t * cache_ptr,
+ H5C_cache_entry_t * entry_ptr)
+#else
+static herr_t
+H5C_pin_entry_from_client(H5C_t UNUSED * cache_ptr,
+ H5C_cache_entry_t * entry_ptr)
+#endif
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5C_pin_entry_from_client)
+
+ /* Sanity checks */
+ HDassert( cache_ptr );
+ HDassert( entry_ptr );
+
+ /* Check if the entry is already pinned */
+ if(entry_ptr->is_pinned) {
+ /* Check if the entry was pinned through an explicit pin from a client */
+ if(entry_ptr->pinned_from_client)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTPIN, FAIL, "Entry is already pinned")
+ } /* end if */
+ else {
+ entry_ptr->is_pinned = TRUE;
+
+ H5C__UPDATE_STATS_FOR_PIN(cache_ptr, entry_ptr)
+ } /* end else */
+
+ /* Mark that the entry was pinned through an explicit pin from a client */
+ entry_ptr->pinned_from_client = TRUE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_pin_entry_from_client() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5C_pin_protected_entry()
*
* Purpose: Pin a protected cache entry. The entry must be protected
@@ -6000,47 +6051,32 @@ done:
*
*-------------------------------------------------------------------------
*/
-#ifndef NDEBUG
herr_t
H5C_pin_protected_entry(H5C_t * cache_ptr,
void * thing)
-#else
-herr_t
-H5C_pin_protected_entry(H5C_t UNUSED * cache_ptr,
- void * thing)
-#endif
{
+ H5C_cache_entry_t * entry_ptr; /* Pointer to entry to pin */
herr_t ret_value = SUCCEED; /* Return value */
- H5C_cache_entry_t * entry_ptr;
FUNC_ENTER_NOAPI(H5C_pin_protected_entry, FAIL)
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
HDassert( thing );
-
entry_ptr = (H5C_cache_entry_t *)thing;
-
+ HDassert( entry_ptr );
HDassert( H5F_addr_defined(entry_ptr->addr) );
- if ( ! ( entry_ptr->is_protected ) ) {
-
+ /* Only protected entries can be pinned */
+ if(!entry_ptr->is_protected)
HGOTO_ERROR(H5E_CACHE, H5E_CANTPIN, FAIL, "Entry isn't protected")
- }
-
- if ( entry_ptr->is_pinned ) {
-
- HGOTO_ERROR(H5E_CACHE, H5E_CANTPIN, FAIL, "Entry is already pinned")
- }
-
- entry_ptr->is_pinned = TRUE;
- H5C__UPDATE_STATS_FOR_PIN(cache_ptr, entry_ptr)
+ /* Pin the entry from a client */
+ if(H5C_pin_entry_from_client(cache_ptr, entry_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTPIN, FAIL, "Can't pin entry by client")
done:
-
FUNC_LEAVE_NOAPI(ret_value)
-
} /* H5C_pin_protected_entry() */
@@ -7671,6 +7707,58 @@ H5C_stats__reset(H5C_t UNUSED * cache_ptr)
/*-------------------------------------------------------------------------
+ * Function: H5C_unpin_entry_from_client()
+ *
+ * Purpose: Internal routine to unpin a cache entry from a client action.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * 3/24/09
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C_unpin_entry_from_client(H5C_t * cache_ptr,
+ H5C_cache_entry_t * entry_ptr,
+ hbool_t update_rp)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5C_unpin_entry_from_client)
+
+ /* Sanity checking */
+ HDassert( cache_ptr );
+ HDassert( entry_ptr );
+
+ /* Error checking (should be sanity checks?) */
+ if(!entry_ptr->is_pinned)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPIN, FAIL, "Entry isn't pinned")
+ if(!entry_ptr->pinned_from_client)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPIN, FAIL, "Entry wasn't pinned by cache client")
+
+ /* If requested, update the replacement policy if the entry is not protected */
+ if(update_rp && !entry_ptr->is_protected)
+ H5C__UPDATE_RP_FOR_UNPIN(cache_ptr, entry_ptr, FAIL)
+
+ /* Check if the entry is not pinned from a flush dependency */
+ if(!entry_ptr->pinned_from_cache) {
+ /* Unpin the entry now */
+ entry_ptr->is_pinned = FALSE;
+
+ /* Update the stats for an unpin operation */
+ H5C__UPDATE_STATS_FOR_UNPIN(cache_ptr, entry_ptr)
+ } /* end if */
+
+ /* Mark the entry as explicitly unpinned by the client */
+ entry_ptr->pinned_from_client = FALSE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_unpin_entry_from_client() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5C_unpin_entry()
*
* Purpose: Unpin a cache entry. The entry can be either protected or
@@ -7687,35 +7775,24 @@ herr_t
H5C_unpin_entry(H5C_t * cache_ptr,
void * thing)
{
+ H5C_cache_entry_t * entry_ptr; /* Pointer to entry to unpin */
herr_t ret_value = SUCCEED; /* Return value */
- H5C_cache_entry_t * entry_ptr;
FUNC_ENTER_NOAPI(H5C_unpin_entry, FAIL)
+ /* Sanity checking */
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
HDassert( thing );
-
entry_ptr = (H5C_cache_entry_t *)thing;
+ HDassert( entry_ptr );
- if ( ! ( entry_ptr->is_pinned ) ) {
-
- HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPIN, FAIL, "Entry isn't pinned")
- }
-
- if ( ! ( entry_ptr->is_protected ) ) {
-
- H5C__UPDATE_RP_FOR_UNPIN(cache_ptr, entry_ptr, FAIL)
- }
-
- entry_ptr->is_pinned = FALSE;
-
- H5C__UPDATE_STATS_FOR_UNPIN(cache_ptr, entry_ptr)
+ /* Unpin the entry */
+ if(H5C_unpin_entry_from_client(cache_ptr, entry_ptr, TRUE) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPIN, FAIL, "Can't unpin entry from client")
done:
-
FUNC_LEAVE_NOAPI(ret_value)
-
} /* H5C_unpin_entry() */
@@ -7846,7 +7923,6 @@ H5C_unprotect(H5F_t * f,
unsigned int flags,
size_t new_size)
{
- /* const char * fcn_name = "H5C_unprotect()"; */
hbool_t deleted;
hbool_t dirtied;
hbool_t set_flush_marker;
@@ -7938,23 +8014,15 @@ H5C_unprotect(H5F_t * f,
/* Pin or unpin the entry as requested. */
if ( pin_entry ) {
- if ( entry_ptr->is_pinned ) {
-
- HGOTO_ERROR(H5E_CACHE, H5E_CANTPIN, FAIL, \
- "Entry already pinned???")
- }
- entry_ptr->is_pinned = TRUE;
- H5C__UPDATE_STATS_FOR_PIN(cache_ptr, entry_ptr)
+ /* Pin the entry from a client */
+ if(H5C_pin_entry_from_client(cache_ptr, entry_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTPIN, FAIL, "Can't pin entry by client")
} else if ( unpin_entry ) {
- if ( ! ( entry_ptr->is_pinned ) ) {
-
- HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPIN, FAIL, \
- "Entry already unpinned???")
- }
- entry_ptr->is_pinned = FALSE;
- H5C__UPDATE_STATS_FOR_UNPIN(cache_ptr, entry_ptr)
+ /* Unpin the entry from a client */
+ if(H5C_unpin_entry_from_client(cache_ptr, entry_ptr, FALSE) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPIN, FAIL, "Can't unpin entry by client")
}
@@ -8071,23 +8139,15 @@ H5C_unprotect(H5F_t * f,
/* Pin or unpin the entry as requested. */
if ( pin_entry ) {
- if ( entry_ptr->is_pinned ) {
-
- HGOTO_ERROR(H5E_CACHE, H5E_CANTPIN, FAIL, \
- "Entry already pinned???")
- }
- entry_ptr->is_pinned = TRUE;
- H5C__UPDATE_STATS_FOR_PIN(cache_ptr, entry_ptr)
+ /* Pin the entry from a client */
+ if(H5C_pin_entry_from_client(cache_ptr, entry_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTPIN, FAIL, "Can't pin entry by client")
} else if ( unpin_entry ) {
- if ( ! ( entry_ptr->is_pinned ) ) {
-
- HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPIN, FAIL, \
- "Entry already unpinned???")
- }
- entry_ptr->is_pinned = FALSE;
- H5C__UPDATE_STATS_FOR_UNPIN(cache_ptr, entry_ptr)
+ /* Unpin the entry from a client */
+ if(H5C_unpin_entry_from_client(cache_ptr, entry_ptr, FALSE) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPIN, FAIL, "Can't unpin entry by client")
}
@@ -8675,21 +8735,21 @@ H5C_create_flush_dependency(H5C_t UNUSED * cache_ptr, void * parent_thing,
HGOTO_ERROR(H5E_CACHE, H5E_CANTDEPEND, FAIL, "Combined flush dependency height too large")
}
- /* Check for parent already pinned */
- if(parent_entry->is_pinned) {
- /* Verify that the parent entry was pinned through a flush dependency relationship */
- if(0 == parent_entry->flush_dep_height)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTDEPEND, FAIL, "Parent entry wasn't pinned through flush dependency")
- } /* end if */
- else {
+ /* Check for parent not pinned */
+ if(!parent_entry->is_pinned) {
/* Sanity check */
HDassert(parent_entry->flush_dep_height == 0);
+ HDassert(!parent_entry->pinned_from_client);
+ HDassert(!parent_entry->pinned_from_cache);
/* Pin the parent entry */
parent_entry->is_pinned = TRUE;
H5C__UPDATE_STATS_FOR_PIN(cache_ptr, parent_entry)
} /* end else */
+ /* Mark the entry as pinned from the cache's action (possibly redundantly) */
+ parent_entry->pinned_from_cache = TRUE;
+
/* Increment ref. count for parent's flush dependency children heights */
parent_entry->child_flush_dep_height_rc[child_entry->flush_dep_height]++;
@@ -8811,12 +8871,24 @@ H5C_destroy_flush_dependency(H5C_t * cache_ptr, void *parent_thing,
* parent of _any_ child flush dependencies).
*/
if(0 == parent_entry->flush_dep_height) {
- if(!parent_entry->is_protected)
- H5C__UPDATE_RP_FOR_UNPIN(cache_ptr, parent_entry, FAIL)
+ /* Sanity check */
+ HDassert(parent_entry->pinned_from_cache);
+
+ /* Check if we should unpin parent entry now */
+ if(!parent_entry->pinned_from_client) {
+ /* Update the replacement policy if the entry is not protected */
+ if(!parent_entry->is_protected)
+ H5C__UPDATE_RP_FOR_UNPIN(cache_ptr, parent_entry, FAIL)
+
+ /* Unpin the entry now */
+ parent_entry->is_pinned = FALSE;
+
+ /* Update the stats for an unpin operation */
+ H5C__UPDATE_STATS_FOR_UNPIN(cache_ptr, parent_entry)
+ } /* end if */
- /* Unpin parent entry */
- parent_entry->is_pinned = FALSE;
- H5C__UPDATE_STATS_FOR_UNPIN(cache_ptr, parent_entry)
+ /* Mark the entry as unpinned from the cache's action */
+ parent_entry->pinned_from_cache = FALSE;
} /* end if */
} /* end if */
diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h
index 855c861..5d89313 100644
--- a/src/H5Cprivate.h
+++ b/src/H5Cprivate.h
@@ -378,6 +378,37 @@ typedef herr_t (*H5C_log_flush_func_t)(H5C_t * cache_ptr,
* 'dest' callback routine.
*
*
+ * Fields supporting the 'flush dependency' feature:
+ *
+ * Entries in the cache may have a 'flush dependency' on another entry 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 parent entry for an entry in a flush
+ * dependency relationship.
+ *
+ * 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_height: The height of the entry, which is one greater than the
+ * maximum height of any of its child entries..
+ *
+ * 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.
+ *
+ *
* Fields supporting the hash table:
*
* Fields in the cache are indexed by a more or less conventional hash table.
@@ -504,11 +535,13 @@ typedef struct H5C_cache_entry_t
hbool_t destroy_in_progress;
hbool_t free_file_space_on_destroy;
- /* fields supporting the 'flush dependency height': */
+ /* 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;
+ hbool_t pinned_from_client;
+ hbool_t pinned_from_cache;
/* fields supporting the hash table: */
diff --git a/test/cache.c b/test/cache.c
index 65a6719..c3e5ee0 100644
--- a/test/cache.c
+++ b/test/cache.c
@@ -31214,6 +31214,145 @@ check_flush_deps(void)
if ( !pass ) CACHE_ERROR("verify_entry_status failed")
}
+/* Test Case #6a - Make certain that flush dependency relationship with parent
+ * already pinned works (unpin ater destroying flush dependency)
+ */
+
+ /* Create flush dependency between entries 0 (child) & 1 (parent) */
+ {
+ protect_entry(cache_ptr, entry_type, 1);
+ if ( !pass ) CACHE_ERROR("protect_entry failed")
+
+ pin_entry(cache_ptr, entry_type, 1);
+ if ( !pass ) CACHE_ERROR("pin_entry failed")
+
+ create_flush_dependency(cache_ptr, entry_type, 1, entry_type, 0);
+ if ( !pass ) CACHE_ERROR("create_flush_dependency failed")
+
+ /* Change expected values, and verify the status of the entries
+ * after creating flush dependency
+ */
+ expected[0].flush_dep_par_type = entry_type;
+ expected[0].flush_dep_par_idx = 1;
+ expected[1].is_protected = TRUE;
+ expected[1].is_pinned = TRUE;
+ expected[1].child_flush_dep_height_rc[0] = 1;
+ expected[1].flush_dep_height = 1;
+
+ /* Verify the status */
+ verify_entry_status(cache_ptr, /* H5C_t * cache_ptr */
+ (int)0, /* int tag */
+ (int)5, /* int num_entries */
+ expected); /* struct expected_entry_staus[] */
+ if ( !pass ) CACHE_ERROR("verify_entry_status failed")
+ }
+
+ /* Unpin entry & destroy flush dependency between entries 0 (child) & 1 (parent) */
+ {
+ destroy_flush_dependency(cache_ptr, entry_type, 1, entry_type, 0);
+ if ( !pass ) CACHE_ERROR("destroy_flush_dependency failed")
+
+ unpin_entry(cache_ptr, entry_type, 1);
+ if ( !pass ) CACHE_ERROR("unpin_entry failed")
+
+ unprotect_entry(cache_ptr, /* H5C_t * cache_ptr */
+ entry_type, /* int32_t type */
+ 1, /* int32_t idx */
+ FALSE, /* int32_t dirty */
+ H5C__NO_FLAGS_SET); /* unsigned int flags */
+ if ( !pass ) CACHE_ERROR("unprotect_entry failed")
+
+ /* Change expected values, and verify the status of the entries
+ * after destroy flush dependency
+ */
+ expected[0].flush_dep_par_type = -1;
+ expected[0].flush_dep_par_idx = -1;
+ expected[1].is_protected = FALSE;
+ expected[1].is_pinned = FALSE;
+ expected[1].child_flush_dep_height_rc[0] = 0;
+ expected[1].flush_dep_height = 0;
+
+ /* Verify the status */
+ verify_entry_status(cache_ptr, /* H5C_t * cache_ptr */
+ (int)0, /* int tag */
+ (int)5, /* int num_entries */
+ expected); /* struct expected_entry_staus[] */
+ if ( !pass ) CACHE_ERROR("verify_entry_status failed")
+ }
+
+/* Test Case #6b - Make certain that flush dependency relationship with parent
+ * already pinned works (unpin before destroying flush dependency)
+ */
+
+ /* Create flush dependency between entries 0 (child) & 1 (parent) */
+ {
+ protect_entry(cache_ptr, entry_type, 1);
+ if ( !pass ) CACHE_ERROR("protect_entry failed")
+
+ pin_entry(cache_ptr, entry_type, 1);
+ if ( !pass ) CACHE_ERROR("pin_entry failed")
+
+ create_flush_dependency(cache_ptr, entry_type, 1, entry_type, 0);
+ if ( !pass ) CACHE_ERROR("create_flush_dependency failed")
+
+ /* Change expected values, and verify the status of the entries
+ * after creating flush dependency
+ */
+ expected[0].flush_dep_par_type = entry_type;
+ expected[0].flush_dep_par_idx = 1;
+ expected[1].is_protected = TRUE;
+ expected[1].is_pinned = TRUE;
+ expected[1].child_flush_dep_height_rc[0] = 1;
+ expected[1].flush_dep_height = 1;
+
+ /* Verify the status */
+ verify_entry_status(cache_ptr, /* H5C_t * cache_ptr */
+ (int)0, /* int tag */
+ (int)5, /* int num_entries */
+ expected); /* struct expected_entry_staus[] */
+ if ( !pass ) CACHE_ERROR("verify_entry_status failed")
+ }
+
+ /* Unpin entry & destroy flush dependency between entries 0 (child) & 1 (parent) */
+ {
+ unpin_entry(cache_ptr, entry_type, 1);
+ if ( !pass ) CACHE_ERROR("unpin_entry failed")
+
+ /* Verify the status */
+ verify_entry_status(cache_ptr, /* H5C_t * cache_ptr */
+ (int)0, /* int tag */
+ (int)5, /* int num_entries */
+ expected); /* struct expected_entry_staus[] */
+ if ( !pass ) CACHE_ERROR("verify_entry_status failed")
+
+ destroy_flush_dependency(cache_ptr, entry_type, 1, entry_type, 0);
+ if ( !pass ) CACHE_ERROR("destroy_flush_dependency failed")
+
+ unprotect_entry(cache_ptr, /* H5C_t * cache_ptr */
+ entry_type, /* int32_t type */
+ 1, /* int32_t idx */
+ FALSE, /* int32_t dirty */
+ H5C__NO_FLAGS_SET); /* unsigned int flags */
+ if ( !pass ) CACHE_ERROR("unprotect_entry failed")
+
+ /* Change expected values, and verify the status of the entries
+ * after destroy flush dependency
+ */
+ expected[0].flush_dep_par_type = -1;
+ expected[0].flush_dep_par_idx = -1;
+ expected[1].is_protected = FALSE;
+ expected[1].is_pinned = FALSE;
+ expected[1].child_flush_dep_height_rc[0] = 0;
+ expected[1].flush_dep_height = 0;
+
+ /* Verify the status */
+ verify_entry_status(cache_ptr, /* H5C_t * cache_ptr */
+ (int)0, /* int tag */
+ (int)5, /* int num_entries */
+ expected); /* struct expected_entry_staus[] */
+ if ( !pass ) CACHE_ERROR("verify_entry_status failed")
+ }
+
done:
if(cache_ptr)
@@ -31257,7 +31396,7 @@ check_flush_deps_err(void)
/* Loop over test cases, check for various errors in configuring flush
* dependencies. Verify that all performs as expected.
*/
- for(test_count = 0; test_count < 11; test_count++) {
+ for(test_count = 0; test_count < 9; test_count++) {
unsigned u; /* Local index variable */
herr_t result; /* Generic return value */
@@ -31421,36 +31560,14 @@ check_flush_deps_err(void)
if ( !pass ) CACHE_ERROR("unprotect_entry failed")
break;
- /* Verify that parent entry isn't already pinned */
- case 4:
- protect_entry(cache_ptr, entry_type, 0);
- if ( !pass ) CACHE_ERROR("protect_entry failed")
-
- pin_entry(cache_ptr, entry_type, 0);
- if ( !pass ) CACHE_ERROR("pin_entry failed")
-
- result = H5C_create_flush_dependency(cache_ptr, &((entries[entry_type])[0]), &((entries[entry_type])[1]));
- if( result != FAIL ) CACHE_ERROR("Creating dependency when parent is pinned")
-
- unpin_entry(cache_ptr, entry_type, 0);
- if ( !pass ) CACHE_ERROR("unpin_entry failed")
-
- unprotect_entry(cache_ptr, /* H5C_t * cache_ptr */
- entry_type, /* int32_t type */
- 0, /* int32_t idx */
- FALSE, /* int32_t dirty */
- H5C__NO_FLAGS_SET); /* unsigned int flags */
- if ( !pass ) CACHE_ERROR("unprotect_entry failed")
- break;
-
/* Verify that parent entry must be protected */
- case 5:
+ case 4:
result = H5C_destroy_flush_dependency(cache_ptr, &((entries[entry_type])[0]), &((entries[entry_type])[1]));
if( result != FAIL ) CACHE_ERROR("Destroying [non-existant] dependency when parent isn't protected")
break;
/* Verify that parent entry has flush dependency */
- case 6:
+ case 5:
protect_entry(cache_ptr, entry_type, 0);
if ( !pass ) CACHE_ERROR("protect_entry failed")
@@ -31465,30 +31582,8 @@ check_flush_deps_err(void)
if ( !pass ) CACHE_ERROR("unprotect_entry failed")
break;
- /* Verify that parent entry is still pinned */
- case 7:
- protect_entry(cache_ptr, entry_type, 0);
- if ( !pass ) CACHE_ERROR("protect_entry failed")
-
- create_flush_dependency(cache_ptr, entry_type, 0, entry_type, 1);
- if ( !pass ) CACHE_ERROR("create_flush_dependency failed")
-
- unpin_entry(cache_ptr, entry_type, 0);
- if ( !pass ) CACHE_ERROR("unpin_entry failed")
-
- result = H5C_destroy_flush_dependency(cache_ptr, &((entries[entry_type])[0]), &((entries[entry_type])[1]));
- if( result != FAIL ) CACHE_ERROR("Destroying dependency when parent isn't in relationship")
-
- unprotect_entry(cache_ptr, /* H5C_t * cache_ptr */
- entry_type, /* int32_t type */
- 0, /* int32_t idx */
- FALSE, /* int32_t dirty */
- H5C__NO_FLAGS_SET); /* unsigned int flags */
- if ( !pass ) CACHE_ERROR("unprotect_entry failed")
- break;
-
/* Verify that child entry is in flush dependency relationship */
- case 8:
+ case 6:
protect_entry(cache_ptr, entry_type, 0);
if ( !pass ) CACHE_ERROR("protect_entry failed")
@@ -31510,7 +31605,7 @@ check_flush_deps_err(void)
break;
/* Verify that parent has child entries at this height */
- case 9:
+ case 7:
protect_entry(cache_ptr, entry_type, 0);
if ( !pass ) CACHE_ERROR("protect_entry failed")
@@ -31565,7 +31660,7 @@ check_flush_deps_err(void)
/* Verify that child entry is child of parent */
- case 10:
+ case 8:
protect_entry(cache_ptr, entry_type, 0);
if ( !pass ) CACHE_ERROR("protect_entry failed")
diff --git a/test/cache_common.c b/test/cache_common.c
index 7f8a458..c0ec7c8 100644
--- a/test/cache_common.c
+++ b/test/cache_common.c
@@ -1663,6 +1663,8 @@ reset_entries(void)
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].pinned_from_client = FALSE;
+ base_addr[j].pinned_from_cache = FALSE;
base_addr[j].flush_order = 0;
@@ -2279,8 +2281,6 @@ verify_entry_status(H5C_t * cache_ptr,
i++;
} /* while */
-if(!pass)
- HDfprintf(stderr, "failure_mssg = '%s'\n", failure_mssg);
return;
@@ -2680,14 +2680,15 @@ insert_entry(H5C_t * cache_ptr,
if ( insert_pinned ) {
HDassert( entry_ptr->header.is_pinned );
- entry_ptr->is_pinned = TRUE;
} else {
HDassert( ! ( entry_ptr->header.is_pinned ) );
- entry_ptr->is_pinned = FALSE;
}
+ entry_ptr->is_pinned = insert_pinned;
+ entry_ptr->pinned_from_client = insert_pinned;
+
HDassert( entry_ptr->header.is_dirty );
HDassert( ((entry_ptr->header).type)->id == type );
}
@@ -3201,7 +3202,7 @@ pin_entry(H5C_t * cache_ptr,
HDassert( entry_ptr->type == type );
HDassert( entry_ptr == entry_ptr->self );
HDassert( entry_ptr->is_protected );
- HDassert( !(entry_ptr->is_pinned) );
+ HDassert( !(entry_ptr->pinned_from_client) );
result = H5C_pin_protected_entry(cache_ptr, (void *)entry_ptr);
@@ -3217,7 +3218,9 @@ pin_entry(H5C_t * cache_ptr,
} else {
+ entry_ptr->pinned_from_client = TRUE;
entry_ptr->is_pinned = TRUE;
+
}
} /* end if */
@@ -3269,12 +3272,15 @@ unpin_entry(H5C_t * cache_ptr,
HDassert( entry_ptr == entry_ptr->self );
HDassert( entry_ptr->cache_ptr == cache_ptr );
HDassert( entry_ptr->header.is_pinned );
+ HDassert( entry_ptr->header.pinned_from_client );
HDassert( entry_ptr->is_pinned );
+ HDassert( entry_ptr->pinned_from_client );
result = H5C_unpin_entry(cache_ptr, (void *)entry_ptr);
if ( ( result < 0 ) ||
- ( entry_ptr->header.is_pinned ) ||
+ ( entry_ptr->header.pinned_from_client ) ||
+ ( entry_ptr->header.is_pinned && !entry_ptr->header.pinned_from_cache ) ||
( entry_ptr->header.type != &(types[type]) ) ||
( entry_ptr->size != entry_ptr->header.size ) ||
( entry_ptr->addr != entry_ptr->header.addr ) ) {
@@ -3284,7 +3290,9 @@ unpin_entry(H5C_t * cache_ptr,
}
- entry_ptr->is_pinned = FALSE;
+ entry_ptr->pinned_from_client = FALSE;
+
+ entry_ptr->is_pinned = entry_ptr->pinned_from_cache;
HDassert( ((entry_ptr->header).type)->id == type );
@@ -3430,12 +3438,14 @@ unprotect_entry(H5C_t * cache_ptr,
if ( pin_flag_set ) {
HDassert ( entry_ptr->header.is_pinned );
+ entry_ptr->pinned_from_client = TRUE;
entry_ptr->is_pinned = TRUE;
} else if ( unpin_flag_set ) {
- HDassert ( ! ( entry_ptr->header.is_pinned ) );
- entry_ptr->is_pinned = FALSE;
+ HDassert ( entry_ptr->header.is_pinned == entry_ptr->header.pinned_from_cache );
+ entry_ptr->pinned_from_client = FALSE;
+ entry_ptr->is_pinned = entry_ptr->pinned_from_cache;
}
}
@@ -3592,12 +3602,14 @@ unprotect_entry_with_size_change(H5C_t * cache_ptr,
if ( pin_flag_set ) {
HDassert ( entry_ptr->header.is_pinned );
+ entry_ptr->pinned_from_client = TRUE;
entry_ptr->is_pinned = TRUE;
} else if ( unpin_flag_set ) {
- HDassert ( ! ( entry_ptr->header.is_pinned ) );
- entry_ptr->is_pinned = FALSE;
+ HDassert ( entry_ptr->header.is_pinned == entry_ptr->header.pinned_from_cache );
+ entry_ptr->pinned_from_client = FALSE;
+ entry_ptr->is_pinned = entry_ptr->pinned_from_cache;
}
}
@@ -4979,6 +4991,7 @@ create_flush_dependency(H5C_t * cache_ptr,
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]++;
+ par_entry_ptr->pinned_from_cache = TRUE;
if( !par_is_pinned )
par_entry_ptr->is_pinned = TRUE;
@@ -5051,6 +5064,7 @@ destroy_flush_dependency(H5C_t * cache_ptr,
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 == par_entry_ptr->self );
@@ -5089,8 +5103,10 @@ destroy_flush_dependency(H5C_t * cache_ptr,
if((unsigned)(i + 1) < prev_par_flush_dep_height) {
par_entry_ptr->flush_dep_height = (unsigned)(i + 1);
- if(i < 0)
- par_entry_ptr->is_pinned = FALSE;
+ 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) {
diff --git a/test/cache_common.h b/test/cache_common.h
index 1284ea3..37e9e0c 100644
--- a/test/cache_common.h
+++ b/test/cache_common.h
@@ -35,7 +35,7 @@
#include "h5test.h"
/* Macro to make error reporting easier */
-#define CACHE_ERROR(s) {failure_mssg = "Line #" H5_TOSTRING(__LINE__) ": " s ; goto done;}
+#define CACHE_ERROR(s) {failure_mssg = "Line #" H5_TOSTRING(__LINE__) ": " s ; pass = FALSE; goto done;}
#define NO_CHANGE -1
@@ -306,6 +306,8 @@ typedef struct test_entry_t
* dependency children
*/
unsigned flush_dep_height; /* flush dependency height of entry */
+ 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 */
} test_entry_t;