From bbe430429dd0f922578a566a6873160ac3dfa518 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Thu, 26 Mar 2009 13:16:54 -0500 Subject: [svn-r16618] Description: Modify metadata cache flush dependency feature to allow it to work with entries that are pinned through the cache API calls. Tested on: FreeBSD/32 6.3 (duty) in debug mode FreeBSD/64 6.3 (liberty) w/C++ & FORTRAN, in debug mode Linux/32 2.6 (jam) w/PGI compilers, w/C++ & FORTRAN, w/threadsafe, in debug mode Linux/64-amd64 2.6 (smirom) w/Intel compilers w/default API=1.6.x, w/C++ & FORTRAN, in production mode Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN, w/szip filter, in production mode Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN, in production mode Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in production mode Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in production mode Mac OS X/32 10.5.6 (amazon) in debug mode Mac OS X/32 10.5.6 (amazon) w/C++ & FORTRAN, w/threadsafe, in production mode --- src/H5C.c | 232 ++++++++++++++++++++++++++++++++++------------------ src/H5Cprivate.h | 35 +++++++- test/cache.c | 195 ++++++++++++++++++++++++++++++++----------- test/cache_common.c | 42 +++++++--- test/cache_common.h | 4 +- 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; -- cgit v0.12