From 33f35183cbfdde70ee8f803acb5b735ad4dfe086 Mon Sep 17 00:00:00 2001 From: mainzer Date: Wed, 5 Aug 2020 15:39:49 -0500 Subject: When flushing, the metadata cache attempts to flush entries in increasing address order. To facilitate this, the metadata cache needs a list of of dirty entries in increasing address order. This is implemented via a skip list of all dirty entries in the cache. To date this skip list has been maintained at all times. However, profiling indicates that we can avoid significant overhead by constructing the skip list of dirty entries just before a flush, taking it down afterwareds, and not maintaining it during normal operation. This commit implements this optimization for both serial and parallel. Tested serial and parallel, debug and production on charis and jelly. --- src/H5AC.c | 483 ++++++++---- src/H5ACmpio.c | 42 +- src/H5ACprivate.h | 2 + src/H5C.c | 1684 ++++++++++++++++++++++++++++++++-------- src/H5Cdbg.c | 41 +- src/H5Cimage.c | 13 +- src/H5Cmpio.c | 391 ++++++---- src/H5Cpkg.h | 471 +++++++---- src/H5Cprivate.h | 5 +- src/H5Fint.c | 10 + test/cache.c | 2099 ++++++++++++++++++++++++++------------------------ test/cache_common.c | 171 +++- test/cache_common.h | 59 ++ test/cache_tagging.c | 13 +- test/ohdr.c | 24 + 15 files changed, 3651 insertions(+), 1857 deletions(-) diff --git a/src/H5AC.c b/src/H5AC.c index f8805b3..59cabde 100644 --- a/src/H5AC.c +++ b/src/H5AC.c @@ -136,14 +136,14 @@ static const H5AC_class_t *const H5AC_class_s[] = { /*------------------------------------------------------------------------- - * Function: H5AC_init + * Function: H5AC_init * - * Purpose: Initialize the interface from some other layer. + * Purpose: Initialize the interface from some other layer. * - * Return: Success: non-negative - * Failure: negative + * Return: Success: non-negative + * Failure: negative * - * Programmer: Quincey Koziol + * Programmer: Quincey Koziol * Saturday, January 18, 2003 * *------------------------------------------------------------------------- @@ -162,13 +162,13 @@ done: /*------------------------------------------------------------------------- - * Function H5AC__init_package + * Function: H5AC__init_package * - * Purpose: Initialize interface-specific information + * Purpose: Initialize interface-specific information * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success/Negative on failure * - * Programmer: Quincey Koziol + * Programmer: Quincey Koziol * Thursday, July 18, 2002 * *------------------------------------------------------------------------- @@ -198,15 +198,15 @@ H5AC__init_package(void) /*------------------------------------------------------------------------- - * Function: H5AC_term_package + * Function: H5AC_term_package * - * Purpose: Terminate this interface. + * Purpose: Terminate this interface. * - * Return: Success: Positive if anything was done that might - * affect other interfaces; zero otherwise. - * Failure: Negative. + * Return: Success: Positive if anything was done that might + * affect other interfaces; zero otherwise. + * Failure: Negative. * - * Programmer: Quincey Koziol + * Programmer: Quincey Koziol * Thursday, July 18, 2002 * *------------------------------------------------------------------------- @@ -284,7 +284,7 @@ herr_t H5AC_create(const H5F_t *f, H5AC_cache_config_t *config_ptr, H5AC_cache_image_config_t * image_config_ptr) { #ifdef H5_HAVE_PARALLEL - char prefix[H5C__PREFIX_LEN] = ""; + char prefix[H5C__PREFIX_LEN] = ""; H5AC_aux_t * aux_ptr = NULL; #endif /* H5_HAVE_PARALLEL */ struct H5C_cache_image_ctl_t int_ci_config = H5C__DEFAULT_CACHE_IMAGE_CTL; @@ -309,9 +309,9 @@ H5AC_create(const H5F_t *f, H5AC_cache_config_t *config_ptr, H5AC_cache_image_co #ifdef H5_HAVE_PARALLEL if(H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI)) { - MPI_Comm mpi_comm; - int mpi_rank; - int mpi_size; + MPI_Comm mpi_comm; + int mpi_rank; + int mpi_size; if(MPI_COMM_NULL == (mpi_comm = H5F_mpi_get_comm(f))) HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get MPI communicator") @@ -400,7 +400,7 @@ H5AC_create(const H5F_t *f, H5AC_cache_config_t *config_ptr, H5AC_cache_image_co #endif /* H5_HAVE_PARALLEL */ if(NULL == f->shared->cache) - HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed") + HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed") #ifdef H5_HAVE_PARALLEL if(aux_ptr != NULL) @@ -472,6 +472,14 @@ done: * matzke@llnl.gov * Jul 9 1997 * + * Changes: + * + * In the parallel case, added code to setup the MDC slist + * before the call to H5AC__flush_entries() and take it down + * afterwards. + * + * JRM -- 7/29/20 + * *------------------------------------------------------------------------- */ herr_t @@ -497,58 +505,115 @@ H5AC_dest(H5F_t *f) #endif /* H5AC_DUMP_STATS_ON_CLOSE */ /* Check if log messages are being emitted */ - if(H5C_get_logging_status(f->shared->cache, &log_enabled, &curr_logging) < 0) + if(H5C_get_logging_status(f->shared->cache, + &log_enabled, &curr_logging) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to get logging status") - if(log_enabled && curr_logging) + if(log_enabled && curr_logging) { + if(H5C_log_write_destroy_cache_msg(f->shared->cache) < 0) - HDONE_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message") + + HDONE_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, \ + "unable to emit log message") + } + /* Tear down logging */ - if(log_enabled) + if(log_enabled) { + if(H5C_log_tear_down(f->shared->cache) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "mdc logging tear-down failed") + + HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, \ + "mdc logging tear-down failed") + } #ifdef H5_HAVE_PARALLEL + /* destroying the cache, so clear all collective entries */ if(H5C_clear_coll_entries(f->shared->cache, FALSE) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "H5C_clear_coll_entries() failed") + + HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, \ + "H5C_clear_coll_entries() failed") aux_ptr = (H5AC_aux_t *)H5C_get_aux_ptr(f->shared->cache); - if(aux_ptr) + + if(aux_ptr) { + /* Sanity check */ HDassert(aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC); + + + /* If the file was opened R/W, attempt to flush all entries + * from rank 0 & Bcast clean list to other ranks. + * + * Must not flush in the R/O case, as this will trigger the + * free space manager settle routines. + * + * Must also enable the skip list before the call to + * H5AC__flush_entries() and disable it afterwards, as the + * skip list will be disabled after the previous flush. + * + * Note that H5C_dest() does slist setup and take down as well. + * Unfortunately, we can't do the setup and take down just once, + * as H5C_dest() is called directly in the test code. + * + * Fortunately, the cache should be clean or close to it at this + * point, so the overhead should be minimal. + */ + if(H5F_ACC_RDWR & H5F_INTENT(f)) { - /* If the file was opened R/W, attempt to flush all entries - * from rank 0 & Bcast clean list to other ranks. - * - * Must not flush in the R/O case, as this will trigger the - * free space manager settle routines. - */ - if(H5F_ACC_RDWR & H5F_INTENT(f)) - if(H5AC__flush_entries(f) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush") + /* enable and load the slist */ + if ( H5C_set_slist_enabled(f->shared->cache, TRUE, FALSE) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "set slist enabled failed") + + if(H5AC__flush_entries(f) < 0) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush") + + /* disable the slist -- should be empty */ + if ( H5C_set_slist_enabled(f->shared->cache, FALSE, FALSE) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "disable slist failed") + } + } #endif /* H5_HAVE_PARALLEL */ /* Destroy the cache */ if(H5C_dest(f) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, "can't destroy cache") + f->shared->cache = NULL; #ifdef H5_HAVE_PARALLEL + if(aux_ptr != NULL) { + if(aux_ptr->d_slist_ptr != NULL) { + HDassert(H5SL_count(aux_ptr->d_slist_ptr) == 0); H5SL_close(aux_ptr->d_slist_ptr); + } /* end if */ + if(aux_ptr->c_slist_ptr != NULL) { + HDassert(H5SL_count(aux_ptr->c_slist_ptr) == 0); H5SL_close(aux_ptr->c_slist_ptr); + } /* end if */ + if(aux_ptr->candidate_slist_ptr != NULL) { + HDassert(H5SL_count(aux_ptr->candidate_slist_ptr) == 0); H5SL_close(aux_ptr->candidate_slist_ptr); + } /* end if */ + aux_ptr->magic = 0; aux_ptr = H5FL_FREE(H5AC_aux_t, aux_ptr); + } /* end if */ #endif /* H5_HAVE_PARALLEL */ @@ -561,12 +626,12 @@ done: * Function: H5AC_evict * * Purpose: Evict all entries except the pinned entries - * in the cache. + * in the cache. * * Return: Non-negative on success/Negative on failure * * Programmer: Vailin Choi - * Dec 2013 + * Dec 2013 * *------------------------------------------------------------------------- */ @@ -600,9 +665,9 @@ done: /*------------------------------------------------------------------------- * Function: H5AC_expunge_entry * - * Purpose: Expunge the target entry from the cache without writing it - * to disk even if it is dirty. The entry must not be either - * pinned or protected. + * Purpose: Expunge the target entry from the cache without writing it + * to disk even if it is dirty. The entry must not be either + * pinned or protected. * * Return: Non-negative on success/Negative on failure * @@ -643,13 +708,13 @@ done: /*------------------------------------------------------------------------- * Function: H5AC_flush * - * Purpose: Flush (and possibly destroy) the metadata cache associated - * with the specified file. + * Purpose: Flush (and possibly destroy) the metadata cache associated + * with the specified file. * - * If the cache contains protected entries, the function will - * fail, as protected entries cannot be flushed. However - * all unprotected entries should be flushed before the - * function returns failure. + * If the cache contains protected entries, the function will + * fail, as protected entries cannot be flushed. However + * all unprotected entries should be flushed before the + * function returns failure. * * Return: Non-negative on success/Negative on failure if there was a * request to flush all items and something was protected. @@ -701,15 +766,15 @@ done: * Function: H5AC_get_entry_status * * Purpose: Given a file address, determine whether the metadata - * cache contains an entry at that location. If it does, - * also determine whether the entry is dirty, protected, - * pinned, etc. and return that information to the caller - * in *status. + * cache contains an entry at that location. If it does, + * also determine whether the entry is dirty, protected, + * pinned, etc. and return that information to the caller + * in *status. * - * If the specified entry doesn't exist, set *status_ptr - * to zero. + * If the specified entry doesn't exist, set *status_ptr + * to zero. * - * On error, the value of *status is undefined. + * On error, the value of *status is undefined. * * Return: Non-negative on success/Negative on failure * @@ -721,14 +786,14 @@ done: herr_t H5AC_get_entry_status(const H5F_t *f, haddr_t addr, unsigned *status) { - hbool_t in_cache; /* Entry @ addr is in the cache */ - hbool_t is_dirty; /* Entry @ addr is in the cache and dirty */ - hbool_t is_protected; /* Entry @ addr is in the cache and protected */ - hbool_t is_pinned; /* Entry @ addr is in the cache and pinned */ - hbool_t is_corked; - hbool_t is_flush_dep_child; /* Entry @ addr is in the cache and is a flush dependency child */ - hbool_t is_flush_dep_parent; /* Entry @ addr is in the cache and is a flush dependency parent */ - hbool_t image_is_up_to_date; /* Entry @ addr is in the cache and has an up to date image */ + hbool_t in_cache; /* Entry @ addr is in the cache */ + hbool_t is_dirty; /* Entry @ addr is in the cache and dirty */ + hbool_t is_protected; /* Entry @ addr is in the cache and protected */ + hbool_t is_pinned; /* Entry @ addr is in the cache and pinned */ + hbool_t is_corked; + hbool_t is_flush_dep_child; /* Entry @ addr is in the cache and is a flush dependency child */ + hbool_t is_flush_dep_parent; /* Entry @ addr is in the cache and is a flush dependency parent */ + hbool_t image_is_up_to_date; /* Entry @ addr is in the cache and has an up to date image */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -741,21 +806,21 @@ H5AC_get_entry_status(const H5F_t *f, haddr_t addr, unsigned *status) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C_get_entry_status() failed") if(in_cache) { - *status |= H5AC_ES__IN_CACHE; - if(is_dirty) - *status |= H5AC_ES__IS_DIRTY; - if(is_protected) - *status |= H5AC_ES__IS_PROTECTED; - if(is_pinned) - *status |= H5AC_ES__IS_PINNED; - if(is_corked) - *status |= H5AC_ES__IS_CORKED; - if(is_flush_dep_parent) - *status |= H5AC_ES__IS_FLUSH_DEP_PARENT; - if(is_flush_dep_child) - *status |= H5AC_ES__IS_FLUSH_DEP_CHILD; - if(image_is_up_to_date) - *status |= H5AC_ES__IMAGE_IS_UP_TO_DATE; + *status |= H5AC_ES__IN_CACHE; + if(is_dirty) + *status |= H5AC_ES__IS_DIRTY; + if(is_protected) + *status |= H5AC_ES__IS_PROTECTED; + if(is_pinned) + *status |= H5AC_ES__IS_PINNED; + if(is_corked) + *status |= H5AC_ES__IS_CORKED; + if(is_flush_dep_parent) + *status |= H5AC_ES__IS_FLUSH_DEP_PARENT; + if(is_flush_dep_child) + *status |= H5AC_ES__IS_FLUSH_DEP_CHILD; + if(image_is_up_to_date) + *status |= H5AC_ES__IMAGE_IS_UP_TO_DATE; } /* end if */ else *status = 0; @@ -875,8 +940,8 @@ done: /*------------------------------------------------------------------------- * Function: H5AC_mark_entry_dirty * - * Purpose: Mark a pinned or protected entry as dirty. The target - * entry MUST be either pinned, protected, or both. + * Purpose: Mark a pinned or protected entry as dirty. The target + * entry MUST be either pinned, protected, or both. * * Return: Non-negative on success/Negative on failure * @@ -929,8 +994,8 @@ done: /*------------------------------------------------------------------------- * Function: H5AC_mark_entry_clean * - * Purpose: Mark a pinned entry as clean. The target - * entry MUST be pinned. + * Purpose: Mark a pinned entry as clean. The target + * entry MUST be pinned. * * Return: Non-negative on success/Negative on failure * @@ -982,8 +1047,8 @@ done: /*------------------------------------------------------------------------- * Function: H5AC_mark_entry_unserialized * - * Purpose: Mark a pinned or protected entry as unserialized. The target - * entry MUST be either pinned, protected, or both. + * Purpose: Mark a pinned or protected entry as unserialized. The target + * entry MUST be either pinned, protected, or both. * * Return: Non-negative on success/Negative on failure * @@ -1024,8 +1089,8 @@ done: /*------------------------------------------------------------------------- * Function: H5AC_mark_entry_serialized * - * Purpose: Mark a pinned entry as serialized. The target - * entry MUST be pinned. + * Purpose: Mark a pinned entry as serialized. The target + * entry MUST be pinned. * * Return: Non-negative on success/Negative on failure * @@ -1124,7 +1189,7 @@ done: /*------------------------------------------------------------------------- * Function: H5AC_pin_protected_entry() * - * Purpose: Pin a protected cache entry. The entry must be protected + * Purpose: Pin a protected cache entry. The entry must be protected * at the time of call, and must be unpinned. * * Return: Non-negative on success/Negative on failure @@ -1203,9 +1268,112 @@ done: /*------------------------------------------------------------------------- + * + * Function: H5AC_prep_for_file_flush + * + * Purpose: This function should be called just prior to the first + * call to H5AC_flush() during a file flush. + * + * Its purpose is to handly any setup required prior to + * metadata cache flush. + * + * Initially, this means setting up the slist prior to the + * flush. We do this in a seperate call because + * H5F__flush_phase2() make repeated calls to H5AC_flush(). + * Handling this detail in separate calls allows us to avoid + * the overhead of setting up and taking down the skip list + * repeatedly. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: John Mainzer + * 5/5/20 + * + * Changes: None. + * + *------------------------------------------------------------------------- + */ +herr_t +H5AC_prep_for_file_flush(H5F_t *f) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + HDassert(f); + HDassert(f->shared); + HDassert(f->shared->cache); + + if ( H5C_set_slist_enabled(f->shared->cache, TRUE, FALSE) < 0) + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "slist enabled failed") + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5AC_prep_for_file_flush() */ + + +/*------------------------------------------------------------------------- + * + * Function: H5AC_secure_from_file_flush + * + * Purpose: This function should be called just after the last + * call to H5AC_flush() during a file flush. + * + * Its purpose is to perform any necessary cleanup after the + * metadata cache flush. + * + * The objective of the call is to allow the metadata cache + * to do any necessary necessary cleanup work after a cache + * flush. + * + * Initially, this means taking down the slist after the + * flush. We do this in a seperate call because + * H5F__flush_phase2() make repeated calls to H5AC_flush(). + * Handling this detail in separate calls allows us to avoid + * the overhead of setting up and taking down the skip list + * repeatedly. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: John Mainzer + * 5/5/20 + * + * Changes: None. + * + *------------------------------------------------------------------------- + */ +herr_t +H5AC_secure_from_file_flush(H5F_t *f) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + HDassert(f); + HDassert(f->shared); + HDassert(f->shared->cache); + + if ( H5C_set_slist_enabled(f->shared->cache, FALSE, FALSE) < 0) + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "slist enabled failed") + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5AC_secure_from_file_flush() */ + + +/*------------------------------------------------------------------------- + * * Function: H5AC_create_flush_dependency() * - * Purpose: Create a flush dependency between two entries in the metadata + * Purpose: Create a flush dependency between two entries in the metadata * cache. * * Return: Non-negative on success/Negative on failure @@ -1250,16 +1418,16 @@ done: * Function: H5AC_protect * * Purpose: If the target entry is not in the cache, load it. If - * necessary, attempt to evict one or more entries to keep - * the cache within its maximum size. + * necessary, attempt to evict one or more entries to keep + * the cache within its maximum size. * - * Mark the target entry as protected, and return its address - * to the caller. The caller must call H5AC_unprotect() when - * finished with the entry. + * Mark the target entry as protected, and return its address + * to the caller. The caller must call H5AC_unprotect() when + * finished with the entry. * - * While it is protected, the entry may not be either evicted - * or flushed -- nor may it be accessed by another call to - * H5AC_protect. Any attempt to do so will result in a failure. + * While it is protected, the entry may not be either evicted + * or flushed -- nor may it be accessed by another call to + * H5AC_protect. Any attempt to do so will result in a failure. * * Return: Success: Ptr to the object. * Failure: NULL @@ -1301,7 +1469,7 @@ H5AC_protect(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *udata, /* Check for invalid access request */ if((0 == (H5F_INTENT(f) & H5F_ACC_RDWR)) && (0 == (flags & H5C__READ_ONLY_FLAG))) - HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, NULL, "no write intent on file") + HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, NULL, "no write intent on file") #if H5AC_DO_TAGGING_SANITY_CHECKS if(!H5C_get_ignore_tags(f->shared->cache) && H5AC__verify_tag(type) < 0) @@ -1331,7 +1499,7 @@ done: /*------------------------------------------------------------------------- * Function: H5AC_resize_entry * - * Purpose: Resize a pinned or protected entry. + * Purpose: Resize a pinned or protected entry. * * Return: Non-negative on success/Negative on failure * @@ -1384,8 +1552,8 @@ done: /*------------------------------------------------------------------------- * Function: H5AC_unpin_entry() * - * Purpose: Unpin a cache entry. The entry must be unprotected at - * the time of call, and must be pinned. + * Purpose: Unpin a cache entry. The entry must be unprotected at + * the time of call, and must be pinned. * * Return: Non-negative on success/Negative on failure * @@ -1427,7 +1595,7 @@ done: /*------------------------------------------------------------------------- * Function: H5AC_destroy_flush_dependency() * - * Purpose: Destroy a flush dependency between two entries. + * Purpose: Destroy a flush dependency between two entries. * * Return: Non-negative on success/Negative on failure * @@ -1470,27 +1638,27 @@ done: /*------------------------------------------------------------------------- * Function: H5AC_unprotect * - * Purpose: Undo an H5AC_protect() call -- specifically, mark the - * entry as unprotected, remove it from the protected list, - * and give it back to the replacement policy. + * Purpose: Undo an H5AC_protect() call -- specifically, mark the + * entry as unprotected, remove it from the protected list, + * and give it back to the replacement policy. * - * The TYPE and ADDR arguments must be the same as those in - * the corresponding call to H5AC_protect() and the THING - * argument must be the value returned by that call to - * H5AC_protect(). + * The TYPE and ADDR arguments must be the same as those in + * the corresponding call to H5AC_protect() and the THING + * argument must be the value returned by that call to + * H5AC_protect(). * - * If the deleted flag is TRUE, simply remove the target entry - * from the cache, clear it, and free it without writing it to - * disk. + * If the deleted flag is TRUE, simply remove the target entry + * from the cache, clear it, and free it without writing it to + * disk. * - * This version of the function is a complete re-write to - * use the new metadata cache. While there isn't all that - * much difference between the old and new Purpose sections, - * the original version is given below. + * This version of the function is a complete re-write to + * use the new metadata cache. While there isn't all that + * much difference between the old and new Purpose sections, + * the original version is given below. * - * Original purpose section: + * Original purpose section: * - * This function should be called to undo the effect of + * This function should be called to undo the effect of * H5AC_protect(). The TYPE and ADDR arguments should be the * same as the corresponding call to H5AC_protect() and the * THING argument should be the value returned by H5AC_protect(). @@ -1509,8 +1677,8 @@ herr_t H5AC_unprotect(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing, unsigned flags) { - hbool_t dirtied; - hbool_t deleted; + hbool_t dirtied; + hbool_t deleted; #ifdef H5_HAVE_PARALLEL H5AC_aux_t * aux_ptr = NULL; #endif /* H5_HAVE_PARALLEL */ @@ -1531,14 +1699,14 @@ H5AC_unprotect(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing, HDassert( ((H5AC_info_t *)thing)->type == type ); dirtied = (hbool_t)(((flags & H5AC__DIRTIED_FLAG) == H5AC__DIRTIED_FLAG) || - (((H5AC_info_t *)thing)->dirtied)); + (((H5AC_info_t *)thing)->dirtied)); deleted = (hbool_t)((flags & H5C__DELETED_FLAG) == H5C__DELETED_FLAG); /* Check if the size changed out from underneath us, if we're not deleting * the entry. */ if(dirtied && !deleted) { - size_t curr_size = 0; + size_t curr_size = 0; if((type->image_len)(thing, &curr_size) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTGETSIZE, FAIL, "Can't get size of thing") @@ -1625,7 +1793,7 @@ H5AC_get_cache_auto_resize_config(const H5AC_t *cache_ptr, if(internal_config.rpt_fcn == NULL) config_ptr->rpt_fcn_enabled = FALSE; else - config_ptr->rpt_fcn_enabled = TRUE; + config_ptr->rpt_fcn_enabled = TRUE; config_ptr->open_trace_file = FALSE; config_ptr->close_trace_file = FALSE; config_ptr->trace_file_name[0] = '\0'; @@ -1658,12 +1826,12 @@ H5AC_get_cache_auto_resize_config(const H5AC_t *cache_ptr, if(NULL != (aux_ptr = (H5AC_aux_t *)H5C_get_aux_ptr(cache_ptr))) { config_ptr->dirty_bytes_threshold = aux_ptr->dirty_bytes_threshold; - config_ptr->metadata_write_strategy = aux_ptr->metadata_write_strategy; + config_ptr->metadata_write_strategy = aux_ptr->metadata_write_strategy; } /* end if */ else { #endif /* H5_HAVE_PARALLEL */ config_ptr->dirty_bytes_threshold = H5AC__DEFAULT_DIRTY_BYTES_THRESHOLD; - config_ptr->metadata_write_strategy = H5AC__DEFAULT_METADATA_WRITE_STRATEGY; + config_ptr->metadata_write_strategy = H5AC__DEFAULT_METADATA_WRITE_STRATEGY; #ifdef H5_HAVE_PARALLEL } /* end else */ } @@ -1800,7 +1968,7 @@ herr_t H5AC_set_cache_auto_resize_config(H5AC_t *cache_ptr, H5AC_cache_config_t *config_ptr) { H5C_auto_size_ctl_t internal_config; - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -1880,16 +2048,16 @@ done: * Function: H5AC_validate_config() * * Purpose: Run a sanity check on the contents of the supplied - * instance of H5AC_cache_config_t. + * instance of H5AC_cache_config_t. * * Do nothing and return SUCCEED if no errors are detected, * and flag an error and return FAIL otherwise. * - * At present, this function operates by packing the data - * from the instance of H5AC_cache_config_t into an instance - * of H5C_auto_size_ctl_t, and then calling - * H5C_validate_resize_config(). As H5AC_cache_config_t and - * H5C_auto_size_ctl_t diverge, we may have to change this. + * At present, this function operates by packing the data + * from the instance of H5AC_cache_config_t into an instance + * of H5C_auto_size_ctl_t, and then calling + * H5C_validate_resize_config(). As H5AC_cache_config_t and + * H5C_auto_size_ctl_t diverge, we may have to change this. * * Return: Non-negative on success/Negative on failure * @@ -1914,7 +2082,7 @@ H5AC_validate_config(H5AC_cache_config_t *config_ptr) /* don't bother to test trace_file_name unless open_trace_file is TRUE */ if(config_ptr->open_trace_file) { - size_t name_len; + size_t name_len; /* Can't really test the trace_file_name field without trying to * open the file, so we will content ourselves with a couple of @@ -1957,17 +2125,17 @@ done: * Function: H5AC_validate_cache_image_config() * * Purpose: Run a sanity check on the contents of the supplied - * instance of H5AC_cache_image_config_t. + * instance of H5AC_cache_image_config_t. * * Do nothing and return SUCCEED if no errors are detected, * and flag an error and return FAIL otherwise. * - * At present, this function operates by packing the data - * from the instance of H5AC_cache_image_config_t into an - * instance of H5C_cache_image_ctl_t, and then calling - * H5C_validate_cache_image_config(). If and when + * At present, this function operates by packing the data + * from the instance of H5AC_cache_image_config_t into an + * instance of H5C_cache_image_ctl_t, and then calling + * H5C_validate_cache_image_config(). If and when * H5AC_cache_image_config_t and H5C_cache_image_ctl_t - * diverge, we may have to change this. + * diverge, we may have to change this. * * Return: Non-negative on success/Negative on failure * @@ -2013,13 +2181,13 @@ done: * Function: H5AC__check_if_write_permitted * * Purpose: Determine if a write is permitted under the current - * circumstances, and set *write_permitted_ptr accordingly. - * As a general rule it is, but when we are running in parallel - * mode with collective I/O, we must ensure that a read cannot - * cause a write. + * circumstances, and set *write_permitted_ptr accordingly. + * As a general rule it is, but when we are running in parallel + * mode with collective I/O, we must ensure that a read cannot + * cause a write. * - * In the event of failure, the value of *write_permitted_ptr - * is undefined. + * In the event of failure, the value of *write_permitted_ptr + * is undefined. * * Return: Non-negative on success/Negative on failure. * @@ -2035,9 +2203,9 @@ H5_ATTR_UNUSED *f, hbool_t *write_permitted_ptr) { #ifdef H5_HAVE_PARALLEL - H5AC_aux_t * aux_ptr = NULL; + H5AC_aux_t * aux_ptr = NULL; #endif /* H5_HAVE_PARALLEL */ - hbool_t write_permitted = TRUE; + hbool_t write_permitted = TRUE; FUNC_ENTER_STATIC_NOERR @@ -2051,9 +2219,9 @@ H5_ATTR_UNUSED HDassert(aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC); if((aux_ptr->mpi_rank == 0) || (aux_ptr->metadata_write_strategy == H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED)) - write_permitted = aux_ptr->write_permitted; + write_permitted = aux_ptr->write_permitted; else - write_permitted = FALSE; + write_permitted = FALSE; } /* end if */ #endif /* H5_HAVE_PARALLEL */ @@ -2067,12 +2235,12 @@ H5_ATTR_UNUSED * Function: H5AC__ext_config_2_int_config() * * Purpose: Utility function to translate an instance of - * H5AC_cache_config_t to an instance of H5C_auto_size_ctl_t. + * H5AC_cache_config_t to an instance of H5C_auto_size_ctl_t. * - * Places translation in *int_conf_ptr and returns SUCCEED - * if successful. Returns FAIL on failure. + * Places translation in *int_conf_ptr and returns SUCCEED + * if successful. Returns FAIL on failure. * - * Does only minimal sanity checking. + * Does only minimal sanity checking. * * Return: Non-negative on success/Negative on failure * @@ -2453,7 +2621,7 @@ done: * Purpose: Given a file address, retrieve the ring for an entry at that * address. * - * On error, the value of *ring is not modified. + * On error, the value of *ring is not modified. * * Return: Non-negative on success/Negative on failure * @@ -2531,11 +2699,11 @@ H5AC_set_ring(H5AC_ring_t ring, H5AC_ring_t *orig_ring) * are in the process of a file shutdown, post an error * message, and return FAIL. * - * Note that this function simply passes the call on to - * the metadata cache proper, and returns the result. + * Note that this function simply passes the call on to + * the metadata cache proper, and returns the result. * - * Return: Success: Non-negative - * Failure: Negative + * Return: Success: Non-negative + * Failure: Negative * * Programmer: Quincey Koziol * September 17, 2016 @@ -2608,7 +2776,7 @@ done: * Function: H5AC_remove_entry() * * Purpose: Remove an entry from the cache. Must be not protected, pinned, - * dirty, involved in flush dependencies, etc. + * dirty, involved in flush dependencies, etc. * * Return: Non-negative on success/Negative on failure * @@ -2669,4 +2837,3 @@ H5AC_get_mdc_image_info(H5AC_t *cache_ptr, haddr_t *image_addr, hsize_t *image_l done: FUNC_LEAVE_NOAPI(ret_value) } /* H5AC_get_mdc_image_info() */ - diff --git a/src/H5ACmpio.c b/src/H5ACmpio.c index f097e83..1c914b0 100644 --- a/src/H5ACmpio.c +++ b/src/H5ACmpio.c @@ -791,7 +791,7 @@ H5AC__log_dirtied_entry(const H5AC_info_t *entry_ptr) else { aux_ptr->dirty_bytes += entry_ptr->size; #if H5AC_DEBUG_DIRTY_BYTES_CREATION - aux_ptr->unprotect_dirty_bytes += entry_size; + aux_ptr->unprotect_dirty_bytes += entry_ptr->size; aux_ptr->unprotect_dirty_bytes_updates += 1; #endif /* H5AC_DEBUG_DIRTY_BYTES_CREATION */ } /* end else */ @@ -989,7 +989,7 @@ H5AC__log_inserted_entry(const H5AC_info_t *entry_ptr) aux_ptr->dirty_bytes += entry_ptr->size; #if H5AC_DEBUG_DIRTY_BYTES_CREATION - aux_ptr->insert_dirty_bytes += size; + aux_ptr->insert_dirty_bytes += entry_ptr->size; aux_ptr->insert_dirty_bytes_updates += 1; #endif /* H5AC_DEBUG_DIRTY_BYTES_CREATION */ @@ -1875,6 +1875,8 @@ done: * Programmer: John Mainzer * April 28, 2010 * + * Changes: None. + * *------------------------------------------------------------------------- */ static herr_t @@ -1894,7 +1896,8 @@ H5AC__rsp__p0_only__flush(H5F_t *f) aux_ptr = (H5AC_aux_t *)H5C_get_aux_ptr(cache_ptr); HDassert(aux_ptr != NULL); HDassert(aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC); - HDassert(aux_ptr->metadata_write_strategy == H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY); + HDassert(aux_ptr->metadata_write_strategy == \ + H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY); /* To prevent "messages from the future" we must * synchronize all processes before we start the flush. @@ -1903,9 +1906,12 @@ H5AC__rsp__p0_only__flush(H5F_t *f) * However, when flushing from within the close operation from a file, * it's possible to skip this barrier (on the second flush of the cache). */ - if(!H5CX_get_mpi_file_flushing()) - if(MPI_SUCCESS != (mpi_result = MPI_Barrier(aux_ptr->mpi_comm))) + if ( ! H5CX_get_mpi_file_flushing() ) { + + if ( MPI_SUCCESS != (mpi_result = MPI_Barrier(aux_ptr->mpi_comm)) ) + HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_result) + } /* Flush data to disk, from rank 0 process */ if(aux_ptr->mpi_rank == 0) { @@ -1921,23 +1927,30 @@ H5AC__rsp__p0_only__flush(H5F_t *f) aux_ptr->write_permitted = FALSE; /* Check for error on the write operation */ - if(result < 0) + if ( result < 0 ) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush.") /* this code exists primarily for the test bed -- it allows us to * enforce POSIX semantics on the server that pretends to be a * file system in our parallel tests. */ - if(aux_ptr->write_done) + if ( aux_ptr->write_done ) { + (aux_ptr->write_done)(); + } } /* end if */ /* Propagate cleaned entries to other ranks. */ - if(H5AC__propagate_flushed_and_still_clean_entries_list(f) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't propagate clean entries list.") + if ( H5AC__propagate_flushed_and_still_clean_entries_list(f) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "Can't propagate clean entries list.") done: + FUNC_LEAVE_NOAPI(ret_value) + } /* H5AC__rsp__p0_only__flush() */ @@ -2104,16 +2117,22 @@ H5AC__run_sync_point(H5F_t *f, int sync_point_op) /* Sanity checks */ HDassert(f != NULL); + cache_ptr = f->shared->cache; + HDassert(cache_ptr != NULL); + aux_ptr = (H5AC_aux_t *)H5C_get_aux_ptr(cache_ptr); + HDassert(aux_ptr != NULL); HDassert(aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC); HDassert((sync_point_op == H5AC_SYNC_POINT_OP__FLUSH_TO_MIN_CLEAN) || - (sync_point_op == H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED)); + (sync_point_op == H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED)); + #if H5AC_DEBUG_DIRTY_BYTES_CREATION -HDfprintf(stdout, "%d:H5AC_propagate...:%u: (u/uu/i/iu/r/ru) = %zu/%u/%zu/%u/%zu/%u\n", +HDfprintf(stdout, + "%d:H5AC_propagate...:%u: (u/uu/i/iu/r/ru) = %zu/%u/%zu/%u/%zu/%u\n", aux_ptr->mpi_rank, aux_ptr->dirty_bytes_propagations, aux_ptr->unprotect_dirty_bytes, @@ -2188,6 +2207,7 @@ HDfprintf(stdout, "%d:H5AC_propagate...:%u: (u/uu/i/iu/r/ru) = %zu/%u/%zu/%u/%zu #endif /* H5AC_DEBUG_DIRTY_BYTES_CREATION */ done: + FUNC_LEAVE_NOAPI(ret_value) } /* H5AC__run_sync_point() */ diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index b932e16..21e7396 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -387,6 +387,8 @@ H5_DLL herr_t H5AC_insert_entry(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing, unsigned int flags); H5_DLL herr_t H5AC_pin_protected_entry(void *thing); H5_DLL herr_t H5AC_prep_for_file_close(H5F_t *f); +H5_DLL herr_t H5AC_prep_for_file_flush(H5F_t *f); +H5_DLL herr_t H5AC_secure_from_file_flush(H5F_t *f); H5_DLL herr_t H5AC_create_flush_dependency(void *parent_thing, void *child_thing); H5_DLL void * H5AC_protect(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *udata, unsigned flags); diff --git a/src/H5C.c b/src/H5C.c index 91e4158..b70c6dc 100644 --- a/src/H5C.c +++ b/src/H5C.c @@ -237,6 +237,82 @@ H5FL_SEQ_DEFINE_STATIC(H5C_cache_entry_ptr_t); * Programmer: John Mainzer * 6/2/04 * + * Modifications: + * + * JRM -- 7/20/04 + * Updated for the addition of the hash table. + * + * JRM -- 10/5/04 + * Added call to H5C_reset_cache_hit_rate_stats(). Also + * added initialization for cache_is_full flag and for + * resize_ctl. + * + * JRM -- 11/12/04 + * Added initialization for the new size_decreased field. + * + * JRM -- 11/17/04 + * Added/updated initialization for the automatic cache + * size control data structures. + * + * JRM -- 6/24/05 + * Added support for the new write_permitted field of + * the H5C_t structure. + * + * JRM -- 7/5/05 + * Added the new log_flush parameter and supporting code. + * + * JRM -- 9/21/05 + * Added the new aux_ptr parameter and supporting code. + * + * JRM -- 1/20/06 + * Added initialization of the new prefix field in H5C_t. + * + * JRM -- 3/16/06 + * Added initialization for the pinned entry related fields. + * + * JRM -- 5/31/06 + * Added initialization for the trace_file_ptr field. + * + * JRM -- 8/19/06 + * Added initialization for the flush_in_progress field. + * + * JRM -- 8/25/06 + * Added initialization for the slist_len_increase and + * slist_size_increase fields. These fields are used + * for sanity checking in the flush process, and are not + * compiled in unless H5C_DO_SANITY_CHECKS is TRUE. + * + * JRM -- 3/28/07 + * Added initialization for the new is_read_only and + * ro_ref_count fields. + * + * JRM -- 7/27/07 + * Added initialization for the new evictions_enabled + * field of H5C_t. + * + * JRM -- 12/31/07 + * Added initialization for the new flash cache size increase + * related fields of H5C_t. + * + * JRM -- 11/5/08 + * Added initialization for the new clean_index_size and + * dirty_index_size fields of H5C_t. + * + * + * Missing entries? + * + * + * JRM -- 4/20/20 + * Added initialization for the slist_enabled field. Recall + * that the slist is used to flush metadata cache entries + * in (roughly) increasing address order. While this is + * needed at flush and close, it is not used elsewhere. + * The slist_enabled field exists to allow us to construct + * the slist when needed, and leave it empty otherwise -- thus + * avoiding the overhead of maintaining it. + * + * JRM -- 4/29/20 + * *------------------------------------------------------------------------- */ H5C_t * @@ -332,10 +408,16 @@ H5C_create(size_t max_cache_size, cache_ptr->ignore_tags = FALSE; cache_ptr->num_objs_corked = 0; + /* slist field initializations */ + cache_ptr->slist_enabled = ! H5C__SLIST_OPT_ENABLED; cache_ptr->slist_changed = FALSE; cache_ptr->slist_len = 0; cache_ptr->slist_size = (size_t)0; + /* slist_ring_len, slist_ring_size, and + * slist_ptr initializaed above. + */ + #if H5C_DO_SANITY_CHECKS cache_ptr->slist_len_increase = 0; cache_ptr->slist_size_increase = 0; @@ -828,6 +910,20 @@ done: * Programmer: John Mainzer * 6/2/04 * + * Modifications: + * + * JRM -- 5/15/20 + * + * Updated the function to enable the slist prior to the + * call to H5C__flush_invalidate_cache(). + * + * Arguably, it shouldn't be necessary to re-enable the + * slist after the call to H5C__flush_invalidate_cache(), as + * the metadata cache should be discarded. However, in the + * test code, we make multiple calls to H5C_dest(). Thus + * we re-enable the slist on failure if it and the cache + * still exist. + * *------------------------------------------------------------------------- */ herr_t @@ -848,33 +944,60 @@ H5C_dest(H5F_t * f) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't display cache image stats") #endif /* H5AC_DUMP_IMAGE_STATS_ON_CLOSE */ + /* Enable the slist, as it is needed in the flush */ + if ( H5C_set_slist_enabled(f->shared->cache, TRUE, FALSE) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "set slist enabled failed") + /* Flush and invalidate all cache entries */ - if(H5C__flush_invalidate_cache(f, H5C__NO_FLAGS_SET) < 0 ) + if ( H5C__flush_invalidate_cache(f, H5C__NO_FLAGS_SET) < 0 ) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache") /* Generate & write cache image if requested */ - if(cache_ptr->image_ctl.generate_image) - if(H5C__generate_cache_image(f, cache_ptr) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, FAIL, "Can't generate metadata cache image") + if ( cache_ptr->image_ctl.generate_image ) { + + if ( H5C__generate_cache_image(f, cache_ptr) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, FAIL, \ + "Can't generate metadata cache image") + } + + /* Question: Is it possible for cache_ptr->slist be non-null at this + * point? If no, shouldn't this if statement be an assert? + */ + if ( cache_ptr->slist_ptr != NULL ) { + + HDassert(cache_ptr->slist_len == 0); + HDassert(cache_ptr->slist_size == 0); - if(cache_ptr->slist_ptr != NULL) { H5SL_close(cache_ptr->slist_ptr); + cache_ptr->slist_ptr = NULL; + } /* end if */ if(cache_ptr->tag_list != NULL) { + H5SL_destroy(cache_ptr->tag_list, H5C_free_tag_list_cb, NULL); cache_ptr->tag_list = NULL; + } /* end if */ - if(cache_ptr->log_info != NULL) + if(cache_ptr->log_info != NULL) { + H5MM_xfree(cache_ptr->log_info); + } #ifndef NDEBUG #if H5C_DO_SANITY_CHECKS - if(cache_ptr->get_entry_ptr_from_addr_counter > 0) - HDfprintf(stdout, "*** %ld calls to H5C_get_entry_ptr_from_add(). ***\n", - cache_ptr->get_entry_ptr_from_addr_counter); + + if ( cache_ptr->get_entry_ptr_from_addr_counter > 0 ) { + + HDfprintf(stdout, + "*** %ld calls to H5C_get_entry_ptr_from_add(). ***\n", + cache_ptr->get_entry_ptr_from_addr_counter); + } #endif /* H5C_DO_SANITY_CHECKS */ cache_ptr->magic = 0; @@ -883,7 +1006,19 @@ H5C_dest(H5F_t * f) cache_ptr = H5FL_FREE(H5C_t, cache_ptr); done: + + if ( ( ret_value < 0 ) && ( cache_ptr ) && ( cache_ptr->slist_ptr ) ) { + + /* need this for test code -- see change note for details */ + + if ( H5C_set_slist_enabled(f->shared->cache, FALSE, FALSE) < 0 ) + + HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "disable slist on flush dest failure failed") + } + FUNC_LEAVE_NOAPI(ret_value) + } /* H5C_dest() */ @@ -897,6 +1032,14 @@ done: * Programmer: Vailin Choi * Dec 2013 * + * Modifications: + * + * JRM -- 5/5/20 + * + * Added code to enable the skip list prior to the call + * to H5C__flush_invalidate_cache(), and disable it + * afterwards. + * *------------------------------------------------------------------------- */ herr_t @@ -909,9 +1052,23 @@ H5C_evict(H5F_t * f) /* Sanity check */ HDassert(f); + /* Enable the slist, as it is needed in the flush */ + if ( H5C_set_slist_enabled(f->shared->cache, TRUE, FALSE) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "set slist enabled failed") + + /* Flush and invalidate all cache entries except the pinned entries */ - if(H5C__flush_invalidate_cache(f, H5C__EVICT_ALLOW_LAST_PINS_FLAG) < 0 ) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to evict entries in the cache") + if ( H5C__flush_invalidate_cache(f, H5C__EVICT_ALLOW_LAST_PINS_FLAG) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, + "unable to evict entries in the cache") + + /* Disable the slist, + */ + if ( H5C_set_slist_enabled(f->shared->cache, FALSE, TRUE) < 0) + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "set slist disabled failed") done: FUNC_LEAVE_NOAPI(ret_value) @@ -2879,6 +3036,179 @@ done: /*------------------------------------------------------------------------- + * + * Function: H5C_set_slist_enabled() + * + * Purpose: Enable or disable the slist as directed. + * + * The slist (skip list) is an address ordered list of + * dirty entries in the metadata cache. However, this + * list is only needed during flush and close, where we + * use it to write entries in more or less increasing + * address order. + * + * This function sets up and enables further operations + * on the slist, or disable the slist. This in turn + * allows us to avoid the overhead of maintaining the + * slist when it is not needed. + * + * + * If the slist_enabled parameter is TRUE, the function + * + * 1) Verifies that the slist is empty. + * + * 2) Scans the index list, and inserts all dirty entries + * into the slist. + * + * 3) Sets cache_ptr->slist_enabled = TRUE. + * + * Note that the clear_slist parameter is ignored if + * the slist_enabed parameter is TRUE. + * + * + * If the slist_enabled_parameter is FALSE, the function + * shuts down the slist. + * + * Normally the slist will be empty at this point, however + * that need not be the case if H5C_flush_cache() has been + * called with the H5C__FLUSH_MARKED_ENTRIES_FLAG. + * + * Thus shutdown proceeds as follows: + * + * 1) Test to see if the slist is empty. If it is, proceed + * to step 3. + * + * 2) Test to see if the clear_slist parameter is TRUE. + * + * If it is, remove all entries from the slist. + * + * If it isn't, throw an error. + * + * 3) set cache_ptr->slist_enabled = FALSE. + * + * Return: SUCCEED on success, and FAIL on failure. + * + * Programmer: John Mainzer + * 5/1/20 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ +herr_t +H5C_set_slist_enabled(H5C_t *cache_ptr, hbool_t slist_enabled, + hbool_t clear_slist) +{ + H5C_cache_entry_t * entry_ptr; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + if ( ( cache_ptr == NULL ) || ( cache_ptr->magic != H5C__H5C_T_MAGIC ) ) + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad cache_ptr on entry") + +#if H5C__SLIST_OPT_ENABLED + + if ( slist_enabled ) { + + if ( cache_ptr->slist_enabled ) { + + HDassert(FALSE); + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "slist already enabled?") + } + + if ( ( cache_ptr->slist_len != 0 ) || + ( cache_ptr->slist_size != 0 ) ) { + + HDassert(FALSE); + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "slist not empty (1)?") + } + + + /* set cache_ptr->slist_enabled to TRUE so that the slist + * mainenance macros will be enabled. + */ + cache_ptr->slist_enabled = TRUE; + + + /* scan the index list and insert all dirty entries in the slist */ + entry_ptr = cache_ptr->il_head; + + while ( entry_ptr != NULL ) { + + HDassert( entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC ); + + if ( entry_ptr->is_dirty ) { + + H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL) + } + + entry_ptr = entry_ptr->il_next; + } + + /* we don't maintain a dirty index len, so we can't do a cross + * check against it. Note that there is no point in cross checking + * against the dirty LRU size, as the dirty LRU may not be maintained, + * and in any case, there is no requirement that all dirty entries + * will reside on the dirty LRU. + */ + HDassert( cache_ptr->dirty_index_size == cache_ptr->slist_size ); + + } else { /* take down the skip list */ + + if ( ! cache_ptr->slist_enabled ) { + + HDassert(FALSE); + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "slist already disabled?") + } + + if ( ( cache_ptr->slist_len != 0 ) || + ( cache_ptr->slist_size != 0 ) ) { + + if ( clear_slist ) { + + H5SL_node_t *node_ptr; + + node_ptr = H5SL_first(cache_ptr->slist_ptr); + + while ( node_ptr != NULL ) { + + entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr); + + H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr, FALSE); + + node_ptr = H5SL_first(cache_ptr->slist_ptr); + } + } else { + + HDassert(FALSE); + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "slist not empty (2)?") + } + } + + cache_ptr->slist_enabled = FALSE; + + HDassert( 0 == cache_ptr->slist_len ); + HDassert( 0 == cache_ptr->slist_size ); + } + +#else /* H5C__SLIST_OPT_ENABLED is FALSE */ + + HDassert(cache_ptr->slist_enabled); + +#endif /* H5C__SLIST_OPT_ENABLED is FALSE */ + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5C_set_slist_enabled() */ + + +/*------------------------------------------------------------------------- * Function: H5C_unpin_entry() * * Purpose: Unpin a cache entry. The entry can be either protected or @@ -2890,7 +3220,7 @@ done: * 3/22/06 * * Changes: Added extreme sanity checks on entry and exit. - JRM -- 4/26/14 + * JRM -- 4/26/14 * *------------------------------------------------------------------------- */ @@ -2956,6 +3286,81 @@ done: * Programmer: John Mainzer * 6/2/04 * + * Modifications: + * + * JRM -- 7/21/04 + * Updated for the addition of the hash table. + * + * JRM -- 10/28/04 + * Added code to set cache_full to TRUE whenever we try to + * make space in the cache. + * + * JRM -- 11/12/04 + * Added code to call to H5C_make_space_in_cache() after the + * call to H5C__auto_adjust_cache_size() if that function + * sets the size_decreased flag is TRUE. + * + * JRM -- 4/25/05 + * The size_decreased flag can also be set to TRUE in + * H5C_set_cache_auto_resize_config() if a new configuration + * forces an immediate reduction in cache size. Modified + * the code to deal with this eventuallity. + * + * JRM -- 6/24/05 + * Added support for the new write_permitted field of H5C_t. + * + * JRM -- 10/22/05 + * Hand optimizations. + * + * JRM -- 5/3/06 + * Added code to set the new dirtied field in + * H5C_cache_entry_t to FALSE prior to return. + * + * JRM -- 6/23/06 + * Modified code to allow dirty entries to be loaded from + * disk. This is necessary as a bug fix in the object + * header code requires us to modify a header as it is read. + * + * JRM -- 3/28/07 + * Added the flags parameter and supporting code. At least + * for now, this parameter is used to allow the entry to + * be protected read only, thus allowing multiple protects. + * + * Also added code to allow multiple read only protects + * of cache entries. + * + * JRM -- 7/27/07 + * Added code supporting the new evictions_enabled field + * in H5C_t. + * + * JRM -- 1/3/08 + * Added to do a flash cache size increase if appropriate + * when a large entry is loaded. + * + * JRM -- 11/13/08 + * Modified function to call H5C_make_space_in_cache() when + * the min_clean_size is violated, not just when there isn't + * enough space for and entry that has just been loaded. + * + * The purpose of this modification is to avoid "metadata + * blizzards" in the write only case. In such instances, + * the cache was allowed to fill with dirty metadata. When + * we finally needed to evict an entry to make space, we had + * to flush out a whole cache full of metadata -- which has + * interesting performance effects. We hope to avoid (or + * perhaps more accurately hide) this effect by maintaining + * the min_clean_size, which should force us to start flushing + * entries long before we actually have to evict something + * to make space. + * + * + * Missing entries? + * + * + * JRM -- 5/8/20 + * Updated for the possibility that the slist will be + * disabled. + * *------------------------------------------------------------------------- */ herr_t @@ -2997,9 +3402,15 @@ H5C_unprotect(H5F_t *f, haddr_t addr, void *thing, unsigned flags) HDassert( H5F_addr_defined(addr) ); HDassert( thing ); HDassert( ! ( pin_entry && unpin_entry ) ); - HDassert( ( ! free_file_space ) || ( deleted ) ); /* deleted flag must accompany free_file_space */ - HDassert( ( ! take_ownership ) || ( deleted ) ); /* deleted flag must accompany take_ownership */ - HDassert( ! ( free_file_space && take_ownership ) ); /* can't have both free_file_space & take_ownership */ + + /* deleted flag must accompany free_file_space */ + HDassert( ( ! free_file_space ) || ( deleted ) ); + + /* deleted flag must accompany take_ownership */ + HDassert( ( ! take_ownership ) || ( deleted ) ); + + /* can't have both free_file_space & take_ownership */ + HDassert( ! ( free_file_space && take_ownership ) ); entry_ptr = (H5C_cache_entry_t *)thing; @@ -3012,47 +3423,65 @@ H5C_unprotect(H5F_t *f, haddr_t addr, void *thing, unsigned flags) was_clean = ! ( entry_ptr->is_dirty ); #if H5C_DO_EXTREME_SANITY_CHECKS - if((H5C_validate_protected_entry_list(cache_ptr) < 0) || - (H5C_validate_pinned_entry_list(cache_ptr) < 0) || - (H5C_validate_lru_list(cache_ptr) < 0)) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on entry") + if ( ( H5C_validate_protected_entry_list(cache_ptr) < 0 ) || + ( H5C_validate_pinned_entry_list(cache_ptr) < 0 ) || + ( H5C_validate_lru_list(cache_ptr) < 0 ) ) + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "an extreme sanity check failed on entry") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ /* if the entry has multiple read only protects, just decrement * the ro_ref_counter. Don't actually unprotect until the ref count * drops to zero. */ - if(entry_ptr->ro_ref_count > 1) { + if ( entry_ptr->ro_ref_count > 1 ) { + /* Sanity check */ HDassert(entry_ptr->is_protected); HDassert(entry_ptr->is_read_only); - if(dirtied) - HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "Read only entry modified??") + if ( dirtied ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \ + "Read only entry modified??") /* Reduce the RO ref count */ (entry_ptr->ro_ref_count)--; /* Pin or unpin the entry as requested. */ - if(pin_entry) { + if ( pin_entry ) { + /* 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 ( 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 ) { + /* 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") + 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") + } /* end if */ } else { - if(entry_ptr->is_read_only) { + + if ( entry_ptr->is_read_only ) { + /* Sanity check */ HDassert(entry_ptr->ro_ref_count == 1); - if(dirtied) - HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "Read only entry modified??") + if ( dirtied ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \ + "Read only entry modified??") entry_ptr->is_read_only = FALSE; entry_ptr->ro_ref_count = 0; + } /* end if */ #ifdef H5_HAVE_PARALLEL @@ -3081,63 +3510,102 @@ H5C_unprotect(H5F_t *f, haddr_t addr, void *thing, unsigned flags) } /* end if */ #endif /* H5_HAVE_PARALLEL */ - if(!entry_ptr->is_protected) - HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "Entry already unprotected??") + if ( ! entry_ptr->is_protected ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \ + "Entry already unprotected??") /* Mark the entry as dirty if appropriate */ entry_ptr->is_dirty = (entry_ptr->is_dirty || dirtied); - if(dirtied) - if(entry_ptr->image_up_to_date) { + if ( dirtied ) { + + if ( entry_ptr->image_up_to_date ) { + entry_ptr->image_up_to_date = FALSE; - if(entry_ptr->flush_dep_nparents > 0) - if(H5C__mark_flush_dep_unserialized(entry_ptr) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "Can't propagate serialization status to fd parents") + + if ( entry_ptr->flush_dep_nparents > 0 ) { + + if ( H5C__mark_flush_dep_unserialized(entry_ptr) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \ + "Can't propagate serialization status to fd parents") + + } /* end if */ } /* end if */ + } /* end if */ /* Check for newly dirtied entry */ - if(was_clean && entry_ptr->is_dirty) { + if ( was_clean && entry_ptr->is_dirty ) { + /* Update index for newly dirtied entry */ H5C__UPDATE_INDEX_FOR_ENTRY_DIRTY(cache_ptr, entry_ptr) - /* If the entry's type has a 'notify' callback send a 'entry dirtied' - * notice now that the entry is fully integrated into the cache. + /* If the entry's type has a 'notify' callback send a + * 'entry dirtied' notice now that the entry is fully + * integrated into the cache. */ - if(entry_ptr->type->notify && - (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_ENTRY_DIRTIED, entry_ptr) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client about entry dirty flag set") + if ( ( entry_ptr->type->notify ) && + ( (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_ENTRY_DIRTIED, + entry_ptr) < 0 ) ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \ + "can't notify client about entry dirty flag set") /* Propagate the flush dep dirty flag up the flush dependency chain - * if appropriate */ - if(entry_ptr->flush_dep_nparents > 0) - if(H5C__mark_flush_dep_dirty(entry_ptr) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, "Can't propagate flush dep dirty flag") + * if appropriate + */ + if ( entry_ptr->flush_dep_nparents > 0 ) { + + if ( H5C__mark_flush_dep_dirty(entry_ptr) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, \ + "Can't propagate flush dep dirty flag") + } } /* end if */ /* Check for newly clean entry */ - else if(!was_clean && !entry_ptr->is_dirty) { - /* If the entry's type has a 'notify' callback send a 'entry cleaned' - * notice now that the entry is fully integrated into the cache. + else if ( ! was_clean && ! entry_ptr->is_dirty ) { + + /* If the entry's type has a 'notify' callback send a + * 'entry cleaned' notice now that the entry is fully + * integrated into the cache. */ - if(entry_ptr->type->notify && - (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_ENTRY_CLEANED, entry_ptr) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client about entry dirty flag cleared") + if ( ( entry_ptr->type->notify ) && + ( (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_ENTRY_CLEANED, + entry_ptr) < 0 ) ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \ + "can't notify client about entry dirty flag cleared") /* Propagate the flush dep clean flag up the flush dependency chain - * if appropriate */ - if(entry_ptr->flush_dep_nparents > 0) - if(H5C__mark_flush_dep_clean(entry_ptr) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, "Can't propagate flush dep dirty flag") + * if appropriate + */ + if ( entry_ptr->flush_dep_nparents > 0 ) { + + if ( H5C__mark_flush_dep_clean(entry_ptr) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, \ + "Can't propagate flush dep dirty flag") + + } } /* end else-if */ /* Pin or unpin the entry as requested. */ - if(pin_entry) { + if ( pin_entry ) { + /* 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 ( 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 ) { + /* 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") + 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") } /* end if */ /* H5C__UPDATE_RP_FOR_UNPROTECT will place the unprotected entry on @@ -3150,10 +3618,15 @@ H5C_unprotect(H5F_t *f, haddr_t addr, void *thing, unsigned flags) /* if the entry is dirty, 'or' its flush_marker with the set flush flag, * and then add it to the skip list if it isn't there already. */ - if(entry_ptr->is_dirty) { + if ( entry_ptr->is_dirty ) { + entry_ptr->flush_marker |= set_flush_marker; - if(!entry_ptr->in_slist) + + if ( !entry_ptr->in_slist ) { + + /* this is a no-op if cache_ptr->slist_enabled is FALSE */ H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL) + } } /* end if */ /* this implementation of the "deleted" option is a bit inefficient, as @@ -3165,44 +3638,72 @@ H5C_unprotect(H5F_t *f, haddr_t addr, void *thing, unsigned flags) * makes good use of existing code. * JRM - 5/19/04 */ - if(deleted) { - unsigned flush_flags = (H5C__FLUSH_CLEAR_ONLY_FLAG | - H5C__FLUSH_INVALIDATE_FLAG); + if ( deleted ) { + + unsigned flush_flags = (H5C__FLUSH_CLEAR_ONLY_FLAG | + H5C__FLUSH_INVALIDATE_FLAG); /* verify that the target entry is in the cache. */ H5C__SEARCH_INDEX(cache_ptr, addr, test_entry_ptr, FAIL) - if(test_entry_ptr == NULL) - HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "entry not in hash table?!?") - else if(test_entry_ptr != entry_ptr) - HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "hash table contains multiple entries for addr?!?") + + if ( test_entry_ptr == NULL ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \ + "entry not in hash table?!?") + + else if ( test_entry_ptr != entry_ptr ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \ + "hash table contains multiple entries for addr?!?") /* Set the 'free file space' flag for the flush, if needed */ - if(free_file_space) + if ( free_file_space ) { + flush_flags |= H5C__FREE_FILE_SPACE_FLAG; + } /* Set the "take ownership" flag for the flush, if needed */ - if(take_ownership) + if ( take_ownership ) { + flush_flags |= H5C__TAKE_OWNERSHIP_FLAG; + } /* Delete the entry from the skip list on destroy */ flush_flags |= H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG; - HDassert(((!was_clean) || dirtied) == entry_ptr->in_slist); - if(H5C__flush_single_entry(f, entry_ptr, flush_flags) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "Can't flush entry") + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( ( ( ! was_clean ) || dirtied ) == \ + ( entry_ptr->in_slist ) ) ); + + if ( H5C__flush_single_entry(f, entry_ptr, flush_flags) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \ + "Can't flush entry") + } /* end if */ #ifdef H5_HAVE_PARALLEL - else if(clear_entry) { + else if ( clear_entry ) { /* verify that the target entry is in the cache. */ H5C__SEARCH_INDEX(cache_ptr, addr, test_entry_ptr, FAIL) - if(test_entry_ptr == NULL) - HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "entry not in hash table?!?") - else if(test_entry_ptr != entry_ptr) - HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "hash table contains multiple entries for addr?!?") - if(H5C__flush_single_entry(f, entry_ptr, H5C__FLUSH_CLEAR_ONLY_FLAG | H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "Can't clear entry") + if ( test_entry_ptr == NULL ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \ + "entry not in hash table?!?") + + else if ( test_entry_ptr != entry_ptr ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \ + "hash table contains multiple entries for addr?!?") + + if ( H5C__flush_single_entry(f, entry_ptr, + H5C__FLUSH_CLEAR_ONLY_FLAG | + H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \ + "Can't clear entry") + } /* end else if */ #endif /* H5_HAVE_PARALLEL */ } @@ -3210,14 +3711,18 @@ H5C_unprotect(H5F_t *f, haddr_t addr, void *thing, unsigned flags) H5C__UPDATE_STATS_FOR_UNPROTECT(cache_ptr) done: + #if H5C_DO_EXTREME_SANITY_CHECKS - if((H5C_validate_protected_entry_list(cache_ptr) < 0) || - (H5C_validate_pinned_entry_list(cache_ptr) < 0) || - (H5C_validate_lru_list(cache_ptr) < 0)) { - HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on exit") + if ( ( H5C_validate_protected_entry_list(cache_ptr) < 0 ) || + ( H5C_validate_pinned_entry_list(cache_ptr) < 0 ) || + ( H5C_validate_lru_list(cache_ptr) < 0 ) ) { + + HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "an extreme sanity check failed on exit") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ FUNC_LEAVE_NOAPI(ret_value) + } /* H5C_unprotect() */ @@ -5035,6 +5540,7 @@ done: /*------------------------------------------------------------------------- + * * Function: H5C__flush_invalidate_cache * * Purpose: Flush and destroy the entries contained in the target @@ -5064,6 +5570,51 @@ done: * Programmer: John Mainzer * 3/24/065 * + * Modifications: + * + * To support the fractal heap, the cache must now deal with + * entries being dirtied, resized, and/or renamed inside + * flush callbacks. Updated function to support this. + * + * -- JRM 8/27/06 + * + * Added code to detect and manage the case in which a + * flush callback changes the s-list out from under + * the function. The only way I can think of in which this + * can happen is if a flush function loads an entry + * into the cache that isn't there already. Quincey tells + * me that this will never happen, but I'm not sure I + * believe him. + * + * Note that this is a pretty bad scenario if it ever + * happens. The code I have added should allow us to + * handle the situation under all but the worst conditions, + * but one can argue that we should just scream and die if + * we ever detect the condidtion. + * + * -- JRM 10/13/07 + * + * Missing entries? + * + * + * Added support for the H5C__EVICT_ALLOW_LAST_PINS_FLAG. + * This flag is used to flush and evict all entries in + * the metadata cache that are not pinned -- typically, + * everything other than the superblock. + * + * ??? -- ??/??/?? + * + * Added sanity checks to verify that the skip list is + * enabled on entry. On the face of it, it would make + * sense to enable the slist on entry, and disable it + * on exit, as this function is not called repeatedly. + * However, since this function can be called from + * H5C_flush_cache(), this would create cases in the test + * code where we would have to check the flags to determine + * whether we must setup and take down the slist. + * + * JRM -- 5/5/20 + * *------------------------------------------------------------------------- */ static herr_t @@ -5081,6 +5632,7 @@ H5C__flush_invalidate_cache(H5F_t *f, unsigned flags) HDassert(cache_ptr); HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC); HDassert(cache_ptr->slist_ptr); + HDassert(cache_ptr->slist_enabled); #if H5C_DO_SANITY_CHECKS { @@ -5099,7 +5651,8 @@ H5C__flush_invalidate_cache(H5F_t *f, unsigned flags) HDassert(cache_ptr->slist_ring_len[H5C_RING_UNDEFINED] == 0); HDassert(cache_ptr->slist_ring_size[H5C_RING_UNDEFINED] == (size_t)0); - for(i = H5C_RING_USER; i < H5C_RING_NTYPES; i++) { + for ( i = H5C_RING_USER; i < H5C_RING_NTYPES; i++ ) { + index_len += cache_ptr->index_ring_len[i]; index_size += cache_ptr->index_ring_size[i]; clean_index_size += cache_ptr->clean_index_ring_size[i]; @@ -5107,6 +5660,7 @@ H5C__flush_invalidate_cache(H5F_t *f, unsigned flags) slist_len += cache_ptr->slist_ring_len[i]; slist_size += cache_ptr->slist_ring_size[i]; + } /* end for */ HDassert(cache_ptr->index_len == index_len); @@ -5119,49 +5673,68 @@ H5C__flush_invalidate_cache(H5F_t *f, unsigned flags) #endif /* H5C_DO_SANITY_CHECKS */ /* remove ageout markers if present */ - if(cache_ptr->epoch_markers_active > 0) - if(H5C__autoadjust__ageout__remove_all_markers(cache_ptr) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "error removing all epoch markers") + if ( cache_ptr->epoch_markers_active > 0 ) { + + if ( H5C__autoadjust__ageout__remove_all_markers(cache_ptr) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "error removing all epoch markers") + } /* flush invalidate each ring, starting from the outermost ring and * working inward. */ ring = H5C_RING_USER; - while(ring < H5C_RING_NTYPES) { + + while ( ring < H5C_RING_NTYPES) { + if(H5C_flush_invalidate_ring(f, ring, flags) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "flush invalidate ring failed") + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, + "flush invalidate ring failed") ring++; + } /* end while */ /* Invariants, after destroying all entries in the hash table */ - if(!(flags & H5C__EVICT_ALLOW_LAST_PINS_FLAG)) { + if( ! ( flags & H5C__EVICT_ALLOW_LAST_PINS_FLAG ) ) { + HDassert(cache_ptr->index_size == 0); HDassert(cache_ptr->clean_index_size == 0); HDassert(cache_ptr->pel_len == 0); HDassert(cache_ptr->pel_size == 0); + } /* end if */ else { + H5C_cache_entry_t *entry_ptr; /* Cache entry */ unsigned u; /* Local index variable */ /* All rings except ring 4 should be empty now */ /* (Ring 4 has the superblock) */ - for(u = H5C_RING_USER; u < H5C_RING_SB; u++) { + for ( u = H5C_RING_USER; u < H5C_RING_SB; u++ ) { + HDassert(cache_ptr->index_ring_len[u] == 0); HDassert(cache_ptr->index_ring_size[u] == 0); HDassert(cache_ptr->clean_index_ring_size[u] == 0); + } /* end for */ /* Check that any remaining pinned entries are in the superblock ring */ + entry_ptr = cache_ptr->pel_head_ptr; + while(entry_ptr) { + /* Check ring */ HDassert(entry_ptr->ring == H5C_RING_SB); /* Advance to next entry in pinned entry list */ entry_ptr = entry_ptr->next; + } /* end while */ } /* end else */ + HDassert(cache_ptr->dirty_index_size == 0); HDassert(cache_ptr->slist_len == 0); HDassert(cache_ptr->slist_size == 0); @@ -5171,7 +5744,9 @@ H5C__flush_invalidate_cache(H5F_t *f, unsigned flags) HDassert(cache_ptr->LRU_list_size == 0); done: + FUNC_LEAVE_NOAPI(ret_value) + } /* H5C__flush_invalidate_cache() */ @@ -5209,6 +5784,20 @@ done: * Programmer: John Mainzer * 9/1/15 * + * Changes: Added support for the H5C__EVICT_ALLOW_LAST_PINS_FLAG. + * This flag is used to flush and evict all entries in + * the metadata cache that are not pinned -- typically, + * everything other than the superblock. + * + * ??? -- ??/??/?? + * + * A recent optimization turns off the slist unless a flush + * is in progress. This should not effect this function, as + * it is only called during a flush. Added an assertion to + * verify this. + * + * JRM -- 5/6/20 + * *------------------------------------------------------------------------- */ static herr_t @@ -5235,9 +5824,12 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags) HDassert(f); HDassert(f->shared); + cache_ptr = f->shared->cache; + HDassert(cache_ptr); HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC); + HDassert(cache_ptr->slist_enabled); HDassert(cache_ptr->slist_ptr); HDassert(ring > H5C_RING_UNDEFINED); HDassert(ring < H5C_RING_NTYPES); @@ -5279,19 +5871,25 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags) */ /* compute the number of pinned entries in this ring */ + entry_ptr = cache_ptr->pel_head_ptr; cur_ring_pel_len = 0; - while(entry_ptr != NULL) { + + while ( entry_ptr != NULL ) { + HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); HDassert(entry_ptr->ring >= ring); if(entry_ptr->ring == ring) cur_ring_pel_len++; entry_ptr = entry_ptr->next; + } /* end while */ old_ring_pel_len = cur_ring_pel_len; + while(cache_ptr->index_ring_len[ring] > 0) { + /* first, try to flush-destroy any dirty entries. Do this by * making a scan through the slist. Note that new dirty entries * may be created by the flush call backs. Thus it is possible @@ -5334,25 +5932,33 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags) /* this done, start the scan of the slist */ restart_slist_scan = TRUE; - while(restart_slist_scan || (node_ptr != NULL)) { - if(restart_slist_scan) { + + while ( restart_slist_scan || ( node_ptr != NULL ) ) { + + if ( restart_slist_scan ) { + restart_slist_scan = FALSE; /* Start at beginning of skip list */ node_ptr = H5SL_first(cache_ptr->slist_ptr); - if(node_ptr == NULL) + + if ( node_ptr == NULL ) /* the slist is empty -- break out of inner loop */ break; /* Get cache entry for this node */ next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr); - if(NULL == next_entry_ptr) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "next_entry_ptr == NULL ?!?!") + + if ( NULL == next_entry_ptr ) + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "next_entry_ptr == NULL ?!?!") HDassert(next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); HDassert(next_entry_ptr->is_dirty); HDassert(next_entry_ptr->in_slist); HDassert(next_entry_ptr->ring >= ring); + } /* end if */ entry_ptr = next_entry_ptr; @@ -5378,18 +5984,26 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags) * from the slist. */ node_ptr = H5SL_next(node_ptr); + if(node_ptr != NULL) { + next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr); + if(NULL == next_entry_ptr) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "next_entry_ptr == NULL ?!?!") + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "next_entry_ptr == NULL ?!?!") + HDassert(next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); HDassert(next_entry_ptr->is_dirty); HDassert(next_entry_ptr->in_slist); HDassert(next_entry_ptr->ring >= ring); HDassert(entry_ptr != next_entry_ptr); } /* end if */ - else + else { + next_entry_ptr = NULL; + } /* Note that we now remove nodes from the slist as we flush * the associated entries, instead of leaving them there @@ -5401,22 +6015,31 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags) * flush, we must keep the slist in canonical form at all * times. */ - if(((!entry_ptr->flush_me_last) || - ((entry_ptr->flush_me_last) && - (cache_ptr->num_last_entries >= cache_ptr->slist_len))) && - (entry_ptr->flush_dep_nchildren == 0) && - (entry_ptr->ring == ring)) { - if(entry_ptr->is_protected) { + if ( ( ( !entry_ptr->flush_me_last ) || + ( ( entry_ptr->flush_me_last ) && + ( cache_ptr->num_last_entries >= cache_ptr->slist_len ) ) + ) && + ( entry_ptr->flush_dep_nchildren == 0 ) && + ( entry_ptr->ring == ring ) ) { + + if ( entry_ptr->is_protected ) { + /* we have major problems -- but lets flush * everything we can before we flag an error. */ protected_entries++; + } /* end if */ - else if(entry_ptr->is_pinned) { - if(H5C__flush_single_entry(f, entry_ptr, H5C__DURING_FLUSH_FLAG) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "dirty pinned entry flush failed") + else if ( entry_ptr->is_pinned ) { + + if ( H5C__flush_single_entry(f, entry_ptr, + H5C__DURING_FLUSH_FLAG) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "dirty pinned entry flush failed") + + if ( cache_ptr->slist_changed ) { - if(cache_ptr->slist_changed) { /* The slist has been modified by something * other than the simple removal of the * of the flushed entry after the flush. @@ -5427,13 +6050,22 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags) restart_slist_scan = TRUE; cache_ptr->slist_changed = FALSE; H5C__UPDATE_STATS_FOR_SLIST_SCAN_RESTART(cache_ptr); + } /* end if */ } /* end else-if */ else { - if(H5C__flush_single_entry(f, entry_ptr, (cooked_flags | H5C__DURING_FLUSH_FLAG | H5C__FLUSH_INVALIDATE_FLAG | H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG)) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "dirty entry flush destroy failed") - if(cache_ptr->slist_changed) { + if ( H5C__flush_single_entry(f, entry_ptr, + (cooked_flags | + H5C__DURING_FLUSH_FLAG | + H5C__FLUSH_INVALIDATE_FLAG | + H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG) ) < 0) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, + "dirty entry flush destroy failed") + + if ( cache_ptr->slist_changed ) { + /* The slist has been modified by something * other than the simple removal of the * of the flushed entry after the flush. @@ -5459,9 +6091,15 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags) * out from under us. */ - if(node_ptr == NULL) { - HDassert(cache_ptr->slist_len == (uint32_t)((int32_t)initial_slist_len + cache_ptr->slist_len_increase)); - HDassert(cache_ptr->slist_size == (size_t)((ssize_t)initial_slist_size + cache_ptr->slist_size_increase)); + if ( node_ptr == NULL ) { + + HDassert(cache_ptr->slist_len == + (uint32_t)((int32_t)initial_slist_len + + cache_ptr->slist_len_increase)); + + HDassert(cache_ptr->slist_size == + (size_t)((ssize_t)initial_slist_size + + cache_ptr->slist_size_increase)); } /* end if */ #endif /* H5C_DO_SANITY_CHECKS */ @@ -5485,7 +6123,9 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags) cache_ptr->entries_relocated_counter = 0; next_entry_ptr = cache_ptr->il_head; - while(next_entry_ptr != NULL) { + + while ( next_entry_ptr != NULL ) { + entry_ptr = next_entry_ptr; HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); HDassert(entry_ptr->ring >= ring); @@ -5494,18 +6134,28 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags) HDassert((next_entry_ptr == NULL) || (next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC)); - if((!entry_ptr->flush_me_last || (entry_ptr->flush_me_last && cache_ptr->num_last_entries >= cache_ptr->slist_len)) - && entry_ptr->flush_dep_nchildren == 0 && entry_ptr->ring == ring) { - if(entry_ptr->is_protected) { + if ( ( ( ! entry_ptr->flush_me_last ) || + ( entry_ptr->flush_me_last && + ( cache_ptr->num_last_entries >= cache_ptr->slist_len ) ) + ) && + ( entry_ptr->flush_dep_nchildren == 0 ) && + ( entry_ptr->ring == ring ) ) { + + if ( entry_ptr->is_protected ) { + /* we have major problems -- but lets flush and * destroy everything we can before we flag an * error. */ protected_entries++; - if(!entry_ptr->in_slist) + + if ( ! entry_ptr->in_slist ) { + HDassert(!(entry_ptr->is_dirty)); + } } /* end if */ - else if(!(entry_ptr->is_pinned)) { + else if ( ! ( entry_ptr->is_pinned ) ) { + /* if *entry_ptr is dirty, it is possible * that one or more other entries may be * either removed from the cache, loaded @@ -5534,8 +6184,14 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags) */ cache_ptr->entry_watched_for_removal = next_entry_ptr; - if(H5C__flush_single_entry(f, entry_ptr, (cooked_flags | H5C__DURING_FLUSH_FLAG | H5C__FLUSH_INVALIDATE_FLAG | H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG)) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Entry flush destroy failed") + if ( H5C__flush_single_entry(f, entry_ptr, + (cooked_flags | + H5C__DURING_FLUSH_FLAG | + H5C__FLUSH_INVALIDATE_FLAG | + H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG)) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "Entry flush destroy failed") /* Restart the index list scan if necessary. Must * do this if the next entry is evicted, and also if @@ -5545,10 +6201,12 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags) * if this results in the size of the pinned entry * failing to decline during the pass. */ - if((NULL != next_entry_ptr && NULL == cache_ptr->entry_watched_for_removal) - || (cache_ptr->entries_loaded_counter > 0) - || (cache_ptr->entries_inserted_counter > 0) - || (cache_ptr->entries_relocated_counter > 0)) { + if ( ( ( NULL != next_entry_ptr ) && + ( NULL == cache_ptr->entry_watched_for_removal ) + ) || + ( cache_ptr->entries_loaded_counter > 0 ) || + ( cache_ptr->entries_inserted_counter > 0 ) || + ( cache_ptr->entries_relocated_counter > 0 ) ) { next_entry_ptr = cache_ptr->il_head; @@ -5557,9 +6215,12 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags) cache_ptr->entries_relocated_counter = 0; H5C__UPDATE_STATS_FOR_INDEX_SCAN_RESTART(cache_ptr) + } /* end if */ - else + else { + cache_ptr->entry_watched_for_removal = NULL; + } } /* end if */ } /* end if */ } /* end for loop scanning hash table */ @@ -5575,35 +6236,53 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags) old_ring_pel_len = cur_ring_pel_len; entry_ptr = cache_ptr->pel_head_ptr; cur_ring_pel_len = 0; - while(entry_ptr != NULL) { + + while ( entry_ptr != NULL ) { + HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); HDassert(entry_ptr->ring >= ring); - if(entry_ptr->ring == ring) + if ( entry_ptr->ring == ring ) { + cur_ring_pel_len++; + } entry_ptr = entry_ptr->next; + } /* end while */ /* Check if the number of pinned entries in the ring is positive, and * it is not declining. Scream and die if so. */ - if(cur_ring_pel_len > 0 && cur_ring_pel_len >= old_ring_pel_len) { + if ( ( cur_ring_pel_len > 0 ) && + ( cur_ring_pel_len >= old_ring_pel_len ) ) { + /* Don't error if allowed to have pinned entries remaining */ - if(evict_flags) + if ( evict_flags ) { + HGOTO_DONE(TRUE) + } - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Pinned entry count not decreasing, cur_ring_pel_len = %d, old_ring_pel_len = %d, ring = %d", (int)cur_ring_pel_len, (int)old_ring_pel_len, (int)ring) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "Pinned entry count not decreasing, cur_ring_pel_len = %d, old_ring_pel_len = %d, ring = %d", \ + (int)cur_ring_pel_len, \ + (int)old_ring_pel_len, (int)ring) } /* end if */ HDassert(protected_entries == cache_ptr->pl_len); - if(protected_entries > 0 && protected_entries == cache_ptr->index_len) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Only protected entries left in cache, protected_entries = %d", (int)protected_entries) + if ( ( protected_entries > 0 ) && + ( protected_entries == cache_ptr->index_len ) ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "Only protected entries left in cache, protected_entries = %d",\ + (int)protected_entries) + } /* main while loop */ /* Invariants, after destroying all entries in the ring */ - for(i = (int)H5C_RING_UNDEFINED; i <= (int)ring; i++) { + for ( i = (int)H5C_RING_UNDEFINED; i <= (int)ring; i++ ) { + HDassert(cache_ptr->index_ring_len[i] == 0); HDassert(cache_ptr->index_ring_size[i] == (size_t)0); HDassert(cache_ptr->clean_index_ring_size[i] == (size_t)0); @@ -5611,21 +6290,31 @@ H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags) HDassert(cache_ptr->slist_ring_len[i] == 0); HDassert(cache_ptr->slist_ring_size[i] == (size_t)0); + } /* end for */ HDassert(protected_entries <= cache_ptr->pl_len); - if(protected_entries > 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Cache has protected entries") - else if(cur_ring_pel_len > 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't unpin all pinned entries in ring") + if ( protected_entries > 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "Cache has protected entries") + + } else if ( cur_ring_pel_len > 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "Can't unpin all pinned entries in ring") + } done: + FUNC_LEAVE_NOAPI(ret_value) + } /* H5C_flush_invalidate_ring() */ /*------------------------------------------------------------------------- + * * Function: H5C__flush_ring * * Purpose: Flush the entries contained in the specified cache and @@ -5647,6 +6336,14 @@ done: * Programmer: John Mainzer * 9/1/15 * + * Changes: A recent optimization turns off the slist unless a flush + * is in progress. This should not effect this function, as + * it is only called during a flush. Added an assertion to + * verify this. + * + * JRM -- 5/6/20 + * + * *------------------------------------------------------------------------- */ static herr_t @@ -5673,24 +6370,31 @@ H5C__flush_ring(H5F_t *f, H5C_ring_t ring, unsigned flags) HDassert(cache_ptr); HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC); + HDassert(cache_ptr->slist_enabled); HDassert(cache_ptr->slist_ptr); HDassert((flags & H5C__FLUSH_INVALIDATE_FLAG) == 0); HDassert(ring > H5C_RING_UNDEFINED); HDassert(ring < H5C_RING_NTYPES); #if H5C_DO_EXTREME_SANITY_CHECKS - if((H5C_validate_protected_entry_list(cache_ptr) < 0) || - (H5C_validate_pinned_entry_list(cache_ptr) < 0) || - (H5C_validate_lru_list(cache_ptr) < 0)) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on entry") + if ( ( H5C_validate_protected_entry_list(cache_ptr) < 0 ) || + ( H5C_validate_pinned_entry_list(cache_ptr ) < 0 ) || + ( H5C_validate_lru_list(cache_ptr) < 0 ) ) + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, + "an extreme sanity check failed on entry") #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ ignore_protected = ( (flags & H5C__FLUSH_IGNORE_PROTECTED_FLAG) != 0 ); flush_marked_entries = ( (flags & H5C__FLUSH_MARKED_ENTRIES_FLAG) != 0 ); - if(!flush_marked_entries) - for(i = (int)H5C_RING_UNDEFINED; i < (int)ring; i++) + if ( ! flush_marked_entries ) { + + for ( i = (int)H5C_RING_UNDEFINED; i < (int)ring; i++ ) { + HDassert(cache_ptr->slist_ring_len[i] == 0); + } + } HDassert(cache_ptr->flush_in_progress); @@ -5711,9 +6415,10 @@ H5C__flush_ring(H5F_t *f, H5C_ring_t ring, unsigned flags) */ cache_ptr->slist_changed = FALSE; - while((cache_ptr->slist_ring_len[ring] > 0) && - (protected_entries == 0) && - (flushed_entries_last_pass)) { + while ( ( cache_ptr->slist_ring_len[ring] > 0 ) && + ( protected_entries == 0 ) && + ( flushed_entries_last_pass ) ) { + flushed_entries_last_pass = FALSE; #if H5C_DO_SANITY_CHECKS @@ -5757,26 +6462,33 @@ H5C__flush_ring(H5F_t *f, H5C_ring_t ring, unsigned flags) restart_slist_scan = TRUE; - while((restart_slist_scan ) || (node_ptr != NULL)) { - if(restart_slist_scan) { + while ( ( restart_slist_scan ) || ( node_ptr != NULL ) ) { + + if ( restart_slist_scan ) { + restart_slist_scan = FALSE; /* Start at beginning of skip list */ node_ptr = H5SL_first(cache_ptr->slist_ptr); - if(node_ptr == NULL) + if ( node_ptr == NULL ) { + /* the slist is empty -- break out of inner loop */ break; + } /* Get cache entry for this node */ next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr); - if(NULL == next_entry_ptr) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "next_entry_ptr == NULL ?!?!") + if ( NULL == next_entry_ptr ) + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "next_entry_ptr == NULL ?!?!") HDassert(next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); HDassert(next_entry_ptr->is_dirty); HDassert(next_entry_ptr->in_slist); + } /* end if */ entry_ptr = next_entry_ptr; @@ -5801,54 +6513,76 @@ H5C__flush_ring(H5F_t *f, H5C_ring_t ring, unsigned flags) HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); HDassert(entry_ptr->in_slist); HDassert(entry_ptr->is_dirty); - if(!flush_marked_entries || entry_ptr->flush_marker) + + if ( ( ! flush_marked_entries ) || ( entry_ptr->flush_marker ) ) { + HDassert(entry_ptr->ring >= ring); + } /* Advance node pointer now, before we delete its target * from the slist. */ node_ptr = H5SL_next(node_ptr); - if(node_ptr != NULL) { + + if ( node_ptr != NULL ) { + next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr); - if(NULL == next_entry_ptr) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "next_entry_ptr == NULL ?!?!") + + if ( NULL == next_entry_ptr ) + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "next_entry_ptr == NULL ?!?!") HDassert(next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); HDassert(next_entry_ptr->is_dirty); HDassert(next_entry_ptr->in_slist); - if(!flush_marked_entries || next_entry_ptr->flush_marker) + if ( ! flush_marked_entries || next_entry_ptr->flush_marker ) { + HDassert(next_entry_ptr->ring >= ring); + } HDassert(entry_ptr != next_entry_ptr); + } /* end if */ - else + else { + next_entry_ptr = NULL; + } - if((!flush_marked_entries || entry_ptr->flush_marker) - && (!entry_ptr->flush_me_last || - (entry_ptr->flush_me_last - && (cache_ptr->num_last_entries >= cache_ptr->slist_len - || (flush_marked_entries && entry_ptr->flush_marker)))) - && (entry_ptr->flush_dep_nchildren == 0 - || entry_ptr->flush_dep_ndirty_children == 0) - && entry_ptr->ring == ring) { + if ( ( ! flush_marked_entries || entry_ptr->flush_marker ) && + ( ( ! entry_ptr->flush_me_last ) || + ( ( entry_ptr->flush_me_last ) && + ( ( cache_ptr->num_last_entries >= cache_ptr->slist_len )|| + ( flush_marked_entries && entry_ptr->flush_marker ) ) + ) + ) && + ( ( entry_ptr->flush_dep_nchildren == 0 ) || + ( entry_ptr->flush_dep_ndirty_children == 0 ) ) && + ( entry_ptr->ring == ring ) ) { HDassert(entry_ptr->flush_dep_nunser_children == 0); - if(entry_ptr->is_protected) { + if ( entry_ptr->is_protected ) { + /* we probably have major problems -- but lets * flush everything we can before we decide * whether to flag an error. */ tried_to_flush_protected_entry = TRUE; protected_entries++; + } /* end if */ else { - if(H5C__flush_single_entry(f, entry_ptr, (flags | H5C__DURING_FLUSH_FLAG)) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush entry") - if(cache_ptr->slist_changed) { + if ( H5C__flush_single_entry(f, entry_ptr, + (flags | H5C__DURING_FLUSH_FLAG)) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "Can't flush entry") + + if ( cache_ptr->slist_changed ) { + /* The slist has been modified by something * other than the simple removal of the * of the flushed entry after the flush. @@ -5859,34 +6593,46 @@ H5C__flush_ring(H5F_t *f, H5C_ring_t ring, unsigned flags) restart_slist_scan = TRUE; cache_ptr->slist_changed = FALSE; H5C__UPDATE_STATS_FOR_SLIST_SCAN_RESTART(cache_ptr) + } /* end if */ flushed_entries_last_pass = TRUE; + } /* end else */ } /* end if */ } /* while ( ( restart_slist_scan ) || ( node_ptr != NULL ) ) */ #if H5C_DO_SANITY_CHECKS /* Verify that the slist size and length are as expected. */ - HDassert((uint32_t)((int32_t)initial_slist_len + cache_ptr->slist_len_increase) == cache_ptr->slist_len); - HDassert((size_t)((ssize_t)initial_slist_size + cache_ptr->slist_size_increase) == cache_ptr->slist_size); + HDassert((uint32_t)((int32_t)initial_slist_len + \ + cache_ptr->slist_len_increase) == cache_ptr->slist_len); + HDassert((size_t)((ssize_t)initial_slist_size + \ + cache_ptr->slist_size_increase) == cache_ptr->slist_size); #endif /* H5C_DO_SANITY_CHECKS */ + } /* while */ HDassert(protected_entries <= cache_ptr->pl_len); - if(((cache_ptr->pl_len > 0) && (!ignore_protected)) || (tried_to_flush_protected_entry)) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "cache has protected items") + if ( ( ( cache_ptr->pl_len > 0 ) && ( ! ignore_protected ) ) || + ( tried_to_flush_protected_entry ) ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "cache has protected items") #if H5C_DO_SANITY_CHECKS - if(!flush_marked_entries) { + if ( ! flush_marked_entries ) { + HDassert(cache_ptr->slist_ring_len[ring] == 0); HDassert(cache_ptr->slist_ring_size[ring] == 0); + } /* end if */ #endif /* H5C_DO_SANITY_CHECKS */ done: + FUNC_LEAVE_NOAPI(ret_value) + } /* H5C__flush_ring() */ @@ -5906,12 +6652,6 @@ done: * be cleared and not flushed, and the call can't be part of a * sequence of flushes. * - * If the caller knows the address of the skip list node at - * which the target entry resides, it can avoid a lookup - * by supplying that address in the tgt_node_ptr parameter. - * If this parameter is NULL, the function will do a skip list - * search for the entry instead. - * * The function does nothing silently if there is no entry * at the supplied address, or if the entry found has the * wrong type. @@ -5921,6 +6661,69 @@ done: * * Programmer: John Mainzer, 5/5/04 * + * Modifications: + * + * JRM -- 7/21/04 + * Updated function for the addition of the hash table. + * + * QAK -- 11/26/04 + * Updated function for the switch from TBBTs to skip lists. + * + * JRM -- 1/6/05 + * Updated function to reset the flush_marker field. + * Also replace references to H5F_FLUSH_INVALIDATE and + * H5F_FLUSH_CLEAR_ONLY with references to + * H5C__FLUSH_INVALIDATE_FLAG and H5C__FLUSH_CLEAR_ONLY_FLAG + * respectively. + * + * JRM -- 6/24/05 + * Added code to remove dirty entries from the slist after + * they have been flushed. Also added a sanity check that + * will scream if we attempt a write when writes are + * completely disabled. + * + * JRM -- 7/5/05 + * Added code to call the new log_flush callback whenever + * a dirty entry is written to disk. Note that the callback + * is not called if the H5C__FLUSH_CLEAR_ONLY_FLAG is set, + * as there is no write to file in this case. + * + * JRM -- 8/21/06 + * Added code maintaining the flush_in_progress and + * destroy_in_progress fields in H5C_cache_entry_t. + * + * Also added flush_flags parameter to the call to + * type_ptr->flush() so that the flush routine can report + * whether the entry has been resized or renamed. Added + * code using the flush_flags variable to detect the case + * in which the target entry is resized during flush, and + * update the caches data structures accordingly. + * + * JRM -- 3/29/07 + * Added sanity checks on the new is_read_only and + * ro_ref_count fields. + * + * QAK -- 2/07/08 + * Separated "destroy entry" concept from "remove entry from + * cache" concept, by adding the 'take_ownership' flag and + * the "destroy_entry" variable. + * + * JRM -- 11/5/08 + * Added call to H5C__UPDATE_INDEX_FOR_ENTRY_CLEAN() to + * maintain the new clean_index_size and clean_index_size + * fields of H5C_t. + * + * + * Missing entries?? + * + * + * JRM -- 5/8/20 + * Updated sanity checks for the possibility that the slist + * is disabled. + * + * Also updated main comment to conform more closely with + * the current state of the code. + * *------------------------------------------------------------------------- */ herr_t @@ -5955,30 +6758,39 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags) HDassert(entry_ptr->type); /* setup external flags from the flags parameter */ - destroy = ((flags & H5C__FLUSH_INVALIDATE_FLAG) != 0); - clear_only = ((flags & H5C__FLUSH_CLEAR_ONLY_FLAG) != 0); - free_file_space = ((flags & H5C__FREE_FILE_SPACE_FLAG) != 0); - take_ownership = ((flags & H5C__TAKE_OWNERSHIP_FLAG) != 0); - del_from_slist_on_destroy = ((flags & H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG) != 0); - during_flush = ((flags & H5C__DURING_FLUSH_FLAG) != 0); - generate_image = ((flags & H5C__GENERATE_IMAGE_FLAG) != 0); - update_page_buffer = ((flags & H5C__UPDATE_PAGE_BUFFER_FLAG) != 0); + destroy = ((flags & H5C__FLUSH_INVALIDATE_FLAG) != 0); + clear_only = ((flags & H5C__FLUSH_CLEAR_ONLY_FLAG) != 0); + free_file_space = ((flags & H5C__FREE_FILE_SPACE_FLAG) != 0); + take_ownership = ((flags & H5C__TAKE_OWNERSHIP_FLAG) != 0); + del_from_slist_on_destroy = + ((flags & H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG) != 0); + during_flush = ((flags & H5C__DURING_FLUSH_FLAG) != 0); + generate_image = ((flags & H5C__GENERATE_IMAGE_FLAG) != 0); + update_page_buffer = ((flags & H5C__UPDATE_PAGE_BUFFER_FLAG) != 0); /* Set the flag for destroying the entry, based on the 'take ownership' * and 'destroy' flags */ - if(take_ownership) + if ( take_ownership ) { + destroy_entry = FALSE; - else + + } else { + destroy_entry = destroy; + } /* we will write the entry to disk if it exists, is dirty, and if the * clear only flag is not set. */ - if(entry_ptr->is_dirty && !clear_only) + if ( entry_ptr->is_dirty && !clear_only ) { + write_entry = TRUE; - else + + } else { + write_entry = FALSE; + } /* if we have received close warning, and we have been instructed to * generate a metadata cache image, and we have actually constructed @@ -5987,8 +6799,11 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags) * Set suppress_image_entry_writes to TRUE if indicated by the * image_ctl flags. */ - if(cache_ptr->close_warning_received && cache_ptr->image_ctl.generate_image - && cache_ptr->num_entries_in_image > 0 && cache_ptr->image_entries) { + if ( ( cache_ptr->close_warning_received ) && + ( cache_ptr->image_ctl.generate_image ) && + ( cache_ptr->num_entries_in_image > 0 ) && + ( cache_ptr->image_entries != NULL ) ) { + /* Sanity checks */ HDassert(entry_ptr->image_up_to_date || !(entry_ptr->include_in_image)); HDassert(entry_ptr->image_ptr || !(entry_ptr->include_in_image)); @@ -5998,32 +6813,60 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags) suppress_image_entry_frees = TRUE; - if(cache_ptr->image_ctl.flags & H5C_CI__SUPRESS_ENTRY_WRITES) + if ( cache_ptr->image_ctl.flags & H5C_CI__SUPRESS_ENTRY_WRITES ) { + suppress_image_entry_writes = TRUE; + + } /* end if */ } /* end if */ - /* run initial sanity checks */ -#if H5C_DO_SANITY_CHECKS - if(entry_ptr->in_slist) { - HDassert(entry_ptr->is_dirty); + /* run initial sanity checks */ +#if H5C_DO_SANITY_CHECKS + if ( cache_ptr->slist_enabled ) { - if((entry_ptr->flush_marker) && (!entry_ptr->is_dirty)) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "entry in slist failed sanity checks") - } /* end if */ - else { - HDassert(!entry_ptr->is_dirty); - HDassert(!entry_ptr->flush_marker); + if ( entry_ptr->in_slist ) { - if((entry_ptr->is_dirty) || (entry_ptr->flush_marker)) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "entry failed sanity checks") - } /* end else */ + HDassert(entry_ptr->is_dirty); + + if ( ( entry_ptr->flush_marker ) && ( ! entry_ptr->is_dirty ) ) + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "entry in slist failed sanity checks") + } /* end if */ + else { + + HDassert(!entry_ptr->is_dirty); + HDassert(!entry_ptr->flush_marker); + + if ( ( entry_ptr->is_dirty ) || ( entry_ptr->flush_marker ) ) + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "entry failed sanity checks") + + } /* end else */ + } else { /* slist is disabled */ + + HDassert( ! entry_ptr->in_slist ); + + if ( ! entry_ptr->is_dirty ) { + + if ( entry_ptr->flush_marker ) + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "flush marked clean entry?") + + } + } #endif /* H5C_DO_SANITY_CHECKS */ - if(entry_ptr->is_protected) { + if ( entry_ptr->is_protected ) { + HDassert(!entry_ptr->is_protected); /* Attempt to flush a protected entry -- scream and die. */ - HGOTO_ERROR(H5E_CACHE, H5E_PROTECT, FAIL, "Attempt to flush a protected entry") + HGOTO_ERROR(H5E_CACHE, H5E_PROTECT, FAIL, \ + "Attempt to flush a protected entry") + } /* end if */ /* Set entry_ptr->flush_in_progress = TRUE and set @@ -6042,24 +6885,36 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags) * been requested to generate an image. In those cases, serialize the * entry. */ - if(write_entry || generate_image) { + if ( write_entry || generate_image ) { + HDassert(entry_ptr->is_dirty); - if(NULL == entry_ptr->image_ptr) { - if(NULL == (entry_ptr->image_ptr = H5MM_malloc(entry_ptr->size + H5C_IMAGE_EXTRA_SPACE))) - HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for on disk image buffer") + if ( NULL == entry_ptr->image_ptr ) { + + if ( NULL == (entry_ptr->image_ptr = + H5MM_malloc(entry_ptr->size + H5C_IMAGE_EXTRA_SPACE)) ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, \ + "memory allocation failed for on disk image buffer") + #if H5C_DO_MEMORY_SANITY_CHECKS - H5MM_memcpy(((uint8_t *)entry_ptr->image_ptr) + entry_ptr->size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE); + H5MM_memcpy(((uint8_t *)entry_ptr->image_ptr) + entry_ptr->size, + H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE); #endif /* H5C_DO_MEMORY_SANITY_CHECKS */ + } /* end if */ - if(!(entry_ptr->image_up_to_date)) { + if ( ! ( entry_ptr->image_up_to_date ) ) { + /* Sanity check */ HDassert(!entry_ptr->prefetched); /* Generate the entry's image */ - if(H5C__generate_image(f, cache_ptr, entry_ptr) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "can't generate entry's image") + if ( H5C__generate_image(f, cache_ptr, entry_ptr) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, \ + "can't generate entry's image") + } /* end if ( ! (entry_ptr->image_up_to_date) ) */ } /* end if */ @@ -6069,12 +6924,16 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags) * in the entry's type, we silently skip the write. This * flag should only be used in test code. */ - if(write_entry) { + if ( write_entry ) { + HDassert(entry_ptr->is_dirty); #if H5C_DO_SANITY_CHECKS - if(cache_ptr->check_write_permitted && !(cache_ptr->write_permitted)) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Write when writes are always forbidden!?!?!") + if ( ( cache_ptr->check_write_permitted ) && + ( ! ( cache_ptr->write_permitted ) ) ) + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "Write when writes are always forbidden!?!?!") #endif /* H5C_DO_SANITY_CHECKS */ /* Write the image to disk unless the write is suppressed. @@ -6084,41 +6943,60 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags) * H5AC__CLASS_SKIP_WRITES is set in the entry's type. This * flag should only be used in test code */ - if((!suppress_image_entry_writes || !entry_ptr->include_in_image) - && (((entry_ptr->type->flags) & H5C__CLASS_SKIP_WRITES) == 0)) { + if ( ( ( ! suppress_image_entry_writes ) || + ( ! entry_ptr->include_in_image ) ) && + ( ( (entry_ptr->type->flags) & H5C__CLASS_SKIP_WRITES) == 0 ) ) { + H5FD_mem_t mem_type = H5FD_MEM_DEFAULT; #ifdef H5_HAVE_PARALLEL - if(cache_ptr->coll_write_list) { - if(H5SL_insert(cache_ptr->coll_write_list, entry_ptr, &entry_ptr->addr) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTINSERT, FAIL, "unable to insert skip list item") + if ( cache_ptr->coll_write_list ) { + + if ( H5SL_insert(cache_ptr->coll_write_list, entry_ptr, + &entry_ptr->addr) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTINSERT, FAIL, \ + "unable to insert skip list item") } /* end if */ else { #endif /* H5_HAVE_PARALLEL */ - if(entry_ptr->prefetched) { + if ( entry_ptr->prefetched ) { + HDassert(entry_ptr->type->id == H5AC_PREFETCHED_ENTRY_ID); + mem_type = cache_ptr-> class_table_ptr[entry_ptr->prefetch_type_id]-> mem_type; } /* end if */ - else + else { + mem_type = entry_ptr->type->mem_type; + } + + if ( H5F_block_write(f, mem_type, entry_ptr->addr, + entry_ptr->size, entry_ptr->image_ptr) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "Can't write image to file") - if(H5F_block_write(f, mem_type, entry_ptr->addr, entry_ptr->size, entry_ptr->image_ptr) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't write image to file") #ifdef H5_HAVE_PARALLEL } #endif /* H5_HAVE_PARALLEL */ + } /* end if */ /* if the entry has a notify callback, notify it that we have * just flushed the entry. */ - if(entry_ptr->type->notify && - (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_AFTER_FLUSH, entry_ptr) < 0 ) - HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client of entry flush") + if ( ( entry_ptr->type->notify ) && + ( (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_AFTER_FLUSH, + entry_ptr) < 0 ) ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \ + "can't notify client of entry flush") + } /* if ( write_entry ) */ /* At this point, all pre-serialize and serialize calls have been @@ -6130,16 +7008,21 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags) */ /* start by updating the statistics */ - if(clear_only) { + if ( clear_only ) { + /* only log a clear if the entry was dirty */ - if(was_dirty) { + if ( was_dirty ) { + H5C__UPDATE_STATS_FOR_CLEAR(cache_ptr, entry_ptr) + } /* end if */ } else if(write_entry) { + HDassert(was_dirty); /* only log a flush if we actually wrote to disk */ H5C__UPDATE_STATS_FOR_FLUSH(cache_ptr, entry_ptr) + } /* end else if */ /* Note that the algorithm below is (very) similar to the set of operations @@ -6148,12 +7031,18 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags) */ /* Update the cache internal data structures. */ - if(destroy) { + if ( destroy ) { + /* Sanity checks */ - if(take_ownership) + if ( take_ownership ) { + HDassert(!destroy_entry); - else + + } else { + HDassert(destroy_entry); + } + HDassert(!entry_ptr->is_pinned); /* Update stats, while entry is still in the cache */ @@ -6163,8 +7052,12 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags) * to be removed from the cache, send a 'before eviction' notice while * the entry is still fully integrated in the cache. */ - if(entry_ptr->type->notify && (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_BEFORE_EVICT, entry_ptr) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client about entry to evict") + if ( ( entry_ptr->type->notify ) && + ( (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_BEFORE_EVICT, + entry_ptr) < 0 ) ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \ + "can't notify client about entry to evict") /* Update the cache internal data structures as appropriate * for a destroy. Specifically: @@ -6184,31 +7077,40 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags) */ H5C__DELETE_FROM_INDEX(cache_ptr, entry_ptr, FAIL) - if(entry_ptr->in_slist && del_from_slist_on_destroy) + if ( ( entry_ptr->in_slist ) && ( del_from_slist_on_destroy ) ) { + H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr, during_flush) + } #ifdef H5_HAVE_PARALLEL /* Check for collective read access flag */ - if(entry_ptr->coll_access) { + if ( entry_ptr->coll_access ) { + entry_ptr->coll_access = FALSE; + H5C__REMOVE_FROM_COLL_LIST(cache_ptr, entry_ptr, FAIL) + } /* end if */ #endif /* H5_HAVE_PARALLEL */ H5C__UPDATE_RP_FOR_EVICTION(cache_ptr, entry_ptr, FAIL) /* Remove entry from tag list */ - if(H5C__untag_entry(cache_ptr, entry_ptr) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTREMOVE, FAIL, "can't remove entry from tag list") + if ( H5C__untag_entry(cache_ptr, entry_ptr) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTREMOVE, FAIL, \ + "can't remove entry from tag list") /* verify that the entry is no longer part of any flush dependencies */ HDassert(entry_ptr->flush_dep_nparents == 0); HDassert(entry_ptr->flush_dep_nchildren == 0); + } /* end if */ else { + HDassert(clear_only || write_entry); HDassert(entry_ptr->is_dirty); - HDassert(entry_ptr->in_slist); + HDassert((!cache_ptr->slist_enabled) || (entry_ptr->in_slist)); /* We are either doing a flush or a clear. * @@ -6232,20 +7134,34 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags) H5C__UPDATE_INDEX_FOR_ENTRY_CLEAN(cache_ptr, entry_ptr); /* Check for entry changing status and do notifications, etc. */ - if(was_dirty) { - /* If the entry's type has a 'notify' callback send a 'entry cleaned' - * notice now that the entry is fully integrated into the cache. + if ( was_dirty ) { + + /* If the entry's type has a 'notify' callback send a + * 'entry cleaned' notice now that the entry is fully + * integrated into the cache. */ - if(entry_ptr->type->notify && - (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_ENTRY_CLEANED, entry_ptr) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client about entry dirty flag cleared") + if ( ( entry_ptr->type->notify ) && + ( (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_ENTRY_CLEANED, + entry_ptr) < 0 ) ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \ + "can't notify client about entry dirty flag cleared") + + /* Propagate the clean flag up the flush dependency chain + * if appropriate + */ + if ( entry_ptr->flush_dep_ndirty_children != 0 ) { - /* Propagate the clean flag up the flush dependency chain if appropriate */ - if(entry_ptr->flush_dep_ndirty_children != 0) HDassert(entry_ptr->flush_dep_ndirty_children == 0); - if(entry_ptr->flush_dep_nparents > 0) - if(H5C__mark_flush_dep_clean(entry_ptr) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKCLEAN, FAIL, "Can't propagate flush dep clean flag") + } + + if ( entry_ptr->flush_dep_nparents > 0 ) { + + if ( H5C__mark_flush_dep_clean(entry_ptr) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKCLEAN, FAIL, \ + "Can't propagate flush dep clean flag") + } } /* end if */ } /* end else */ @@ -6253,7 +7169,8 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags) entry_ptr->flush_in_progress = FALSE; /* capture the cache entry address for the log_flush call at the - end before the entry_ptr gets freed */ + * end before the entry_ptr gets freed + */ entry_addr = entry_ptr->addr; /* Internal cache data structures should now be up to date, and @@ -6261,7 +7178,8 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags) * * Now discard the entry if appropriate. */ - if(destroy) { + if ( destroy ) { + /* Sanity check */ HDassert(0 == entry_ptr->flush_dep_nparents); @@ -6272,10 +7190,14 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags) * * Otherwise, free the buffer if it exists. */ - if(suppress_image_entry_frees && entry_ptr->include_in_image) + if ( suppress_image_entry_frees && entry_ptr->include_in_image ) { + entry_ptr->image_ptr = NULL; - else if(entry_ptr->image_ptr != NULL) + + } else if ( entry_ptr->image_ptr != NULL ) { + entry_ptr->image_ptr = H5MM_xfree(entry_ptr->image_ptr); + } /* If the entry is not a prefetched entry, verify that the flush * dependency parents addresses array has been transferred. @@ -6283,15 +7205,18 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags) * If the entry is prefetched, the free_isr routine will dispose of * the flush dependency parents addresses array if necessary. */ - if(!entry_ptr->prefetched) { + if ( ! entry_ptr->prefetched ) { + HDassert(0 == entry_ptr->fd_parent_count); HDassert(NULL == entry_ptr->fd_parent_addrs); + } /* end if */ /* Check whether we should free the space in the file that * the entry occupies */ - if(free_file_space) { + if ( free_file_space ) { + hsize_t fsf_size; /* Sanity checks */ @@ -6311,16 +7236,27 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags) * it to get the size of the block of file space to free. * Otherwise use entry_ptr->size. */ - if(entry_ptr->type->fsf_size) { - if((entry_ptr->type->fsf_size)((void *)entry_ptr, &fsf_size) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, "unable to get file space free size") + if ( entry_ptr->type->fsf_size ) { + + if ( (entry_ptr->type->fsf_size)((void *)entry_ptr, &fsf_size) + < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, \ + "unable to get file space free size") + } /* end if */ - else /* no file space free size callback -- use entry size */ + else { /* no file space free size callback -- use entry size */ + fsf_size = entry_ptr->size; + } /* Release the space on disk */ - if(H5MF_xfree(f, entry_ptr->type->mem_type, entry_ptr->addr, fsf_size) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, "unable to free file space for cache entry") + if ( H5MF_xfree(f, entry_ptr->type->mem_type, + entry_ptr->addr, fsf_size) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, \ + "unable to free file space for cache entry") + } /* end if ( free_file_space ) */ /* Reset the pointer to the cache the entry is within. -QAK */ @@ -6343,22 +7279,32 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags) */ cache_ptr->entries_removed_counter++; cache_ptr->last_entry_removed_ptr = entry_ptr; - if(entry_ptr == cache_ptr->entry_watched_for_removal) + + if ( entry_ptr == cache_ptr->entry_watched_for_removal ) { + cache_ptr->entry_watched_for_removal = NULL; + } /* Check for actually destroying the entry in memory */ /* (As opposed to taking ownership of it) */ - if(destroy_entry) { - if(entry_ptr->is_dirty) { + if ( destroy_entry ) { + + if ( entry_ptr->is_dirty ) { + /* Reset dirty flag */ entry_ptr->is_dirty = FALSE; - /* If the entry's type has a 'notify' callback send a 'entry cleaned' - * notice now that the entry is fully integrated into the cache. + /* If the entry's type has a 'notify' callback send a + * 'entry cleaned' notice now that the entry is fully + * integrated into the cache. */ - if(entry_ptr->type->notify && - (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_ENTRY_CLEANED, entry_ptr) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client about entry dirty flag cleared") + if ( ( entry_ptr->type->notify ) && + ( (entry_ptr->type->notify) + (H5C_NOTIFY_ACTION_ENTRY_CLEANED, entry_ptr) < 0 ) ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \ + "can't notify client about entry dirty flag cleared") + } /* end if */ /* we are about to discard the in core representation -- @@ -6370,10 +7316,14 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags) /* verify that the image has been freed */ HDassert(entry_ptr->image_ptr == NULL); - if(entry_ptr->type->free_icr((void *)entry_ptr) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "free_icr callback failed") + if ( entry_ptr->type->free_icr((void *)entry_ptr) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "free_icr callback failed") + } /* end if */ else { + HDassert(take_ownership); /* client is taking ownership of the entry. @@ -6381,33 +7331,50 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags) * unless the entry is re-inserted properly */ entry_ptr->magic = H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC; + } /* end else */ } /* if (destroy) */ /* Check if we have to update the page buffer with cleared entries * so it doesn't go out of date */ - if(update_page_buffer) { + if ( update_page_buffer ) { + /* Sanity check */ HDassert(!destroy); HDassert(entry_ptr->image_ptr); - if(f->shared->page_buf && f->shared->page_buf->page_size >= entry_ptr->size) - if(H5PB_update_entry(f->shared->page_buf, entry_ptr->addr, entry_ptr->size, entry_ptr->image_ptr) > 0) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Failed to update PB with metadata cache") + if ( ( f->shared->page_buf ) && + ( f->shared->page_buf->page_size >= entry_ptr->size ) ) { + + if ( H5PB_update_entry(f->shared->page_buf, entry_ptr->addr, + entry_ptr->size, entry_ptr->image_ptr) > 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "Failed to update PB with metadata cache") + } /* end if */ } /* end if */ - if(cache_ptr->log_flush) - if((cache_ptr->log_flush)(cache_ptr, entry_addr, was_dirty, flags) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "log_flush callback failed") + if ( cache_ptr->log_flush ) { + + if ( (cache_ptr->log_flush)(cache_ptr, entry_addr, + was_dirty, flags) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "log_flush callback failed") + + } /* end if */ done: + HDassert( ( ret_value != SUCCEED ) || ( destroy_entry ) || ( ! entry_ptr->flush_in_progress ) ); + HDassert( ( ret_value != SUCCEED ) || ( destroy_entry ) || ( take_ownership ) || ( ! entry_ptr->is_dirty ) ); FUNC_LEAVE_NOAPI(ret_value) + } /* H5C__flush_single_entry() */ @@ -7613,8 +8580,18 @@ H5C_entry_in_skip_list(H5C_t * cache_ptr, H5C_cache_entry_t *target_ptr) * Programmer: Mike McGreevy * November 3, 2010 * + * Changes: Modified function to setup the slist before calling + * H%C_flush_cache(), and take it down afterwards. Note + * that the slist need not be empty after the call to + * H5C_flush_cache() since we are only flushing marked + * entries. Thus must set the clear_slist parameter + * of H5C_set_slist_enabled to TRUE. + * + * JRM -- 5/6/20 + * *------------------------------------------------------------------------- */ + herr_t H5C__flush_marked_entries(H5F_t * f) { @@ -7625,12 +8602,31 @@ H5C__flush_marked_entries(H5F_t * f) /* Assertions */ HDassert(f != NULL); + + /* Enable the slist, as it is needed in the flush */ + if ( H5C_set_slist_enabled(f->shared->cache, TRUE, FALSE) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "set slist enabled failed") + + /* Flush all marked entries */ - if(H5C_flush_cache(f, H5C__FLUSH_MARKED_ENTRIES_FLAG | H5C__FLUSH_IGNORE_PROTECTED_FLAG) < 0) + if ( H5C_flush_cache(f, H5C__FLUSH_MARKED_ENTRIES_FLAG | + H5C__FLUSH_IGNORE_PROTECTED_FLAG) < 0 ) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush cache") + /* Disable the slist. Set the clear_slist parameter to TRUE + * since we called H5C_flush_cache() with the + * H5C__FLUSH_MARKED_ENTRIES_FLAG. + */ + if ( H5C_set_slist_enabled(f->shared->cache, FALSE, TRUE) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "disable slist failed") + done: + FUNC_LEAVE_NOAPI(ret_value) + } /* H5C__flush_marked_entries */ @@ -8500,6 +9496,10 @@ done: * Programmer: Mohamad Chaarawi * 2/10/16 * + * Changes: Updated sanity checks for the possibility that the skip + * list is disabled. + * JRM 5/16/20 + * *------------------------------------------------------------------------- */ herr_t @@ -8528,16 +9528,24 @@ H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr) old_addr = entry_ptr->addr; /* Call client's pre-serialize callback, if there's one */ - if(entry_ptr->type->pre_serialize && - (entry_ptr->type->pre_serialize)(f, (void *)entry_ptr, - entry_ptr->addr, entry_ptr->size, &new_addr, &new_len, &serialize_flags) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to pre-serialize entry") + if ( ( entry_ptr->type->pre_serialize ) && + ( (entry_ptr->type->pre_serialize)(f, (void *)entry_ptr, + entry_ptr->addr, entry_ptr->size, + &new_addr, &new_len, + &serialize_flags) < 0 ) ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "unable to pre-serialize entry") /* Check for any flags set in the pre-serialize callback */ - if(serialize_flags != H5C__SERIALIZE_NO_FLAGS_SET) { + if ( serialize_flags != H5C__SERIALIZE_NO_FLAGS_SET ) { + /* Check for unexpected flags from serialize callback */ - if(serialize_flags & ~(H5C__SERIALIZE_RESIZED_FLAG | H5C__SERIALIZE_MOVED_FLAG)) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unknown serialize flag(s)") + if ( serialize_flags & ~(H5C__SERIALIZE_RESIZED_FLAG | + H5C__SERIALIZE_MOVED_FLAG) ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "unknown serialize flag(s)") #ifdef H5_HAVE_PARALLEL /* In the parallel case, resizes and moves in @@ -8566,28 +9574,40 @@ H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr) * If that ceases to be the case, further * tests will be necessary. */ - if(cache_ptr->aux_ptr != NULL) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "resize/move in serialize occurred in parallel case") + if ( cache_ptr->aux_ptr != NULL ) + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "resize/move in serialize occurred in parallel case") #endif /* If required, resize the buffer and update the entry and the cache - * data structures */ - if(serialize_flags & H5C__SERIALIZE_RESIZED_FLAG) { + * data structures + */ + if ( serialize_flags & H5C__SERIALIZE_RESIZED_FLAG ) { + /* Sanity check */ HDassert(new_len > 0); /* Allocate a new image buffer */ - if(NULL == (entry_ptr->image_ptr = H5MM_realloc(entry_ptr->image_ptr, new_len + H5C_IMAGE_EXTRA_SPACE))) - HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for on disk image buffer") + if ( NULL == (entry_ptr->image_ptr = + H5MM_realloc(entry_ptr->image_ptr, + new_len + H5C_IMAGE_EXTRA_SPACE)) ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, \ + "memory allocation failed for on disk image buffer") + #if H5C_DO_MEMORY_SANITY_CHECKS - H5MM_memcpy(((uint8_t *)entry_ptr->image_ptr) + new_len, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE); + H5MM_memcpy(((uint8_t *)entry_ptr->image_ptr) + new_len, + H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE); #endif /* H5C_DO_MEMORY_SANITY_CHECKS */ /* Update statistics for resizing the entry */ - H5C__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE(cache_ptr, entry_ptr, new_len); + H5C__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE(cache_ptr, entry_ptr, \ + new_len); /* Update the hash table for the size change */ - H5C__UPDATE_INDEX_FOR_SIZE_CHANGE(cache_ptr, entry_ptr->size, new_len, entry_ptr, !(entry_ptr->is_dirty)); + H5C__UPDATE_INDEX_FOR_SIZE_CHANGE(cache_ptr, entry_ptr->size, \ + new_len, entry_ptr, !(entry_ptr->is_dirty)); /* The entry can't be protected since we are in the process of * flushing it. Thus we must update the replacement policy data @@ -8598,25 +9618,32 @@ H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr) /* As we haven't updated the cache data structures for * for the flush or flush destroy yet, the entry should - * be in the slist. Thus update it for the size change. + * be in the slist if the slist is enabled. Since + * H5C__UPDATE_SLIST_FOR_SIZE_CHANGE() is a no-op if the + * slist is enabled, call it un-conditionally. */ HDassert(entry_ptr->is_dirty); - HDassert(entry_ptr->in_slist); - H5C__UPDATE_SLIST_FOR_SIZE_CHANGE(cache_ptr, entry_ptr->size, new_len); + HDassert((entry_ptr->in_slist) || (!cache_ptr->slist_enabled)); + + H5C__UPDATE_SLIST_FOR_SIZE_CHANGE(cache_ptr, entry_ptr->size, \ + new_len); /* Finally, update the entry for its new size */ entry_ptr->size = new_len; + } /* end if */ /* If required, udate the entry and the cache data structures * for a move */ - if(serialize_flags & H5C__SERIALIZE_MOVED_FLAG) { + if ( serialize_flags & H5C__SERIALIZE_MOVED_FLAG ) { + /* Update stats and entries relocated counter */ H5C__UPDATE_STATS_FOR_MOVE(cache_ptr, entry_ptr) /* We must update cache data structures for the change in address */ - if(entry_ptr->addr == old_addr) { + if ( entry_ptr->addr == old_addr ) { + /* Delete the entry from the hash table and the slist */ H5C__DELETE_FROM_INDEX(cache_ptr, entry_ptr, FAIL); H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr, FALSE); @@ -8627,18 +9654,26 @@ H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr) /* And then reinsert in the index and slist */ H5C__INSERT_IN_INDEX(cache_ptr, entry_ptr, FAIL); H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL); + } /* end if */ - else /* move is already done for us -- just do sanity checks */ + else { /* move is already done for us -- just do sanity checks */ + HDassert(entry_ptr->addr == new_addr); + } } /* end if */ } /* end if(serialize_flags != H5C__SERIALIZE_NO_FLAGS_SET) */ /* Serialize object into buffer */ - if(entry_ptr->type->serialize(f, entry_ptr->image_ptr, entry_ptr->size, (void *)entry_ptr) < 0) + if ( entry_ptr->type->serialize(f, entry_ptr->image_ptr, entry_ptr->size, + (void *)entry_ptr) < 0 ) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to serialize entry") + #if H5C_DO_MEMORY_SANITY_CHECKS - HDassert(0 == HDmemcmp(((uint8_t *)entry_ptr->image_ptr) + entry_ptr->size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE)); + HDassert(0 == HDmemcmp(((uint8_t *)entry_ptr->image_ptr) + entry_ptr->size,\ + H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE)); #endif /* H5C_DO_MEMORY_SANITY_CHECKS */ + entry_ptr->image_up_to_date = TRUE; /* Propagate the fact that the entry is serialized up the @@ -8648,9 +9683,14 @@ H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr) * for flush dependency parents. */ HDassert(entry_ptr->flush_dep_nunser_children == 0); - if(entry_ptr->flush_dep_nparents > 0) - if(H5C__mark_flush_dep_serialized(entry_ptr) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "Can't propagate serialization status to fd parents") + + if ( entry_ptr->flush_dep_nparents > 0 ) { + + if ( H5C__mark_flush_dep_serialized(entry_ptr) < 0 ) + + HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \ + "Can't propagate serialization status to fd parents") + } done: FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5Cdbg.c b/src/H5Cdbg.c index d5599f2..085ac77 100644 --- a/src/H5Cdbg.c +++ b/src/H5Cdbg.c @@ -260,6 +260,7 @@ H5C_dump_cache_LRU(H5C_t *cache_ptr, const char *cache_name) /*------------------------------------------------------------------------- + * * Function: H5C_dump_cache_skip_list * * Purpose: Debugging routine that prints a summary of the contents of @@ -271,6 +272,12 @@ H5C_dump_cache_LRU(H5C_t *cache_ptr, const char *cache_name) * Programmer: John Mainzer * 11/15/14 * + * Changes: Updated function for the slist_enabled field in H6C_t. + * Recall that to minimize slist overhead, the slist is + * empty and not maintained if cache_ptr->slist_enabled is + * false. + * JRM -- 5/6/20 + * *------------------------------------------------------------------------- */ #ifndef NDEBUG @@ -288,11 +295,16 @@ H5C_dump_cache_skip_list(H5C_t * cache_ptr, char * calling_fcn) HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC); HDassert(calling_fcn != NULL); - HDfprintf(stdout, "\n\nDumping metadata cache skip list from %s.\n", calling_fcn); + HDfprintf(stdout, "\n\nDumping metadata cache skip list from %s.\n", + calling_fcn); + HDfprintf(stdout, " slist enabled = %d.\n", + (int)(cache_ptr->slist_enabled)); HDfprintf(stdout, " slist len = %u.\n", cache_ptr->slist_len); - HDfprintf(stdout, " slist size = %lld.\n", (long long)(cache_ptr->slist_size)); + HDfprintf(stdout, " slist size = %lld.\n", + (long long)(cache_ptr->slist_size)); if(cache_ptr->slist_len > 0) { + /* If we get this far, all entries in the cache are listed in the * skip list -- scan the skip list generating the desired output. */ @@ -300,13 +312,20 @@ H5C_dump_cache_skip_list(H5C_t * cache_ptr, char * calling_fcn) "Num: Addr: Len: Prot/Pind: Dirty: Type:\n"); i = 0; + node_ptr = H5SL_first(cache_ptr->slist_ptr); - if(node_ptr != NULL) + + if ( node_ptr != NULL ) { + entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr); - else + + } else { + entry_ptr = NULL; + } + + while ( entry_ptr != NULL ) { - while(entry_ptr != NULL) { HDassert( entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC ); HDfprintf(stdout, @@ -323,19 +342,27 @@ H5C_dump_cache_skip_list(H5C_t * cache_ptr, char * calling_fcn) node_ptr, H5SL_item(node_ptr)); /* increment node_ptr before we delete its target */ + node_ptr = H5SL_next(node_ptr); - if(node_ptr != NULL) + + if ( node_ptr != NULL ) { + entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr); - else + + } else { + entry_ptr = NULL; + } i++; + } /* end while */ } /* end if */ HDfprintf(stdout, "\n\n"); FUNC_LEAVE_NOAPI(ret_value) + } /* H5C_dump_cache_skip_list() */ #endif /* NDEBUG */ diff --git a/src/H5Cimage.c b/src/H5Cimage.c index ee286d9..9dd2ac6 100644 --- a/src/H5Cimage.c +++ b/src/H5Cimage.c @@ -461,6 +461,10 @@ done: * * Programmer: John Mainzer, 8/10/15 * + * Changes: Updated sanity checks for possibility that the slist + * is disabled. + * JRM -- 5/17/20 + * *------------------------------------------------------------------------- */ herr_t @@ -700,9 +704,14 @@ H5C__deserialize_prefetched_entry(H5F_t *f, H5C_t *cache_ptr, * and H5C__FLUSH_CLEAR_ONLY_FLAG flags set. */ pf_entry_ptr->image_ptr = NULL; - if(pf_entry_ptr->is_dirty) { - HDassert(pf_entry_ptr->in_slist); + + if ( pf_entry_ptr->is_dirty ) { + + HDassert(((cache_ptr->slist_enabled) && (pf_entry_ptr->in_slist)) || \ + ((!cache_ptr->slist_enabled) && (!pf_entry_ptr->in_slist))); + flush_flags |= H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG; + } /* end if */ if(H5C__flush_single_entry(f, pf_entry_ptr, flush_flags) < 0) diff --git a/src/H5Cmpio.c b/src/H5Cmpio.c index 199c494..31dc647 100644 --- a/src/H5Cmpio.c +++ b/src/H5Cmpio.c @@ -18,7 +18,7 @@ * Quincey Koziol * * Purpose: Functions in this file implement support for parallel I/O for - * generic cache code. + * generic cache code. * *------------------------------------------------------------------------- */ @@ -28,20 +28,20 @@ /****************/ #include "H5Cmodule.h" /* This source code file is part of the H5C module */ -#define H5F_FRIEND /*suppress error about including H5Fpkg */ +#define H5F_FRIEND /*suppress error about including H5Fpkg */ /***********/ /* Headers */ /***********/ -#include "H5private.h" /* Generic Functions */ +#include "H5private.h" /* Generic Functions */ #include "H5ACprivate.h" /* Metadata cache */ -#include "H5Cpkg.h" /* Cache */ +#include "H5Cpkg.h" /* Cache */ #include "H5CXprivate.h" /* API Contexts */ -#include "H5Eprivate.h" /* Error handling */ -#include "H5Fpkg.h" /* Files */ -#include "H5FDprivate.h" /* File drivers */ -#include "H5MMprivate.h" /* Memory management */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fpkg.h" /* Files */ +#include "H5FDprivate.h" /* File drivers */ +#include "H5MMprivate.h" /* Memory management */ #ifdef H5_HAVE_PARALLEL @@ -87,74 +87,74 @@ static herr_t H5C__flush_candidates_in_ring(H5F_t *f, H5C_ring_t ring, * * Purpose: Apply the supplied candidate list. * - * We used to do this by simply having each process write - * every mpi_size-th entry in the candidate list, starting - * at index mpi_rank, and mark all the others clean. + * We used to do this by simply having each process write + * every mpi_size-th entry in the candidate list, starting + * at index mpi_rank, and mark all the others clean. * - * However, this can cause unnecessary contention in a file - * system by increasing the number of processes writing to - * adjacent locations in the HDF5 file. + * However, this can cause unnecessary contention in a file + * system by increasing the number of processes writing to + * adjacent locations in the HDF5 file. * - * To attempt to minimize this, we now arange matters such - * that each process writes n adjacent entries in the - * candidate list, and marks all others clean. We must do - * this in such a fashion as to guarantee that each entry - * on the candidate list is written by exactly one process, - * and marked clean by all others. + * To attempt to minimize this, we now arange matters such + * that each process writes n adjacent entries in the + * candidate list, and marks all others clean. We must do + * this in such a fashion as to guarantee that each entry + * on the candidate list is written by exactly one process, + * and marked clean by all others. * - * To do this, first construct a table mapping mpi_rank - * to the index of the first entry in the candidate list to - * be written by the process of that mpi_rank, and then use - * the table to control which entries are written and which - * are marked as clean as a function of the mpi_rank. + * To do this, first construct a table mapping mpi_rank + * to the index of the first entry in the candidate list to + * be written by the process of that mpi_rank, and then use + * the table to control which entries are written and which + * are marked as clean as a function of the mpi_rank. * - * Note that the table must be identical on all processes, as - * all see the same candidate list, mpi_size, and mpi_rank -- - * the inputs used to construct the table. + * Note that the table must be identical on all processes, as + * all see the same candidate list, mpi_size, and mpi_rank -- + * the inputs used to construct the table. * - * We construct the table as follows. Let: + * We construct the table as follows. Let: * - * n = num_candidates / mpi_size; + * n = num_candidates / mpi_size; * - * m = num_candidates % mpi_size; + * m = num_candidates % mpi_size; * - * Now allocate an array of integers of length mpi_size + 1, - * and call this array candidate_assignment_table. + * Now allocate an array of integers of length mpi_size + 1, + * and call this array candidate_assignment_table. * - * Conceptually, if the number of candidates is a multiple - * of the mpi_size, we simply pass through the candidate list - * and assign n entries to each process to flush, with the - * index of the first entry to flush in the location in - * the candidate_assignment_table indicated by the mpi_rank - * of the process. + * Conceptually, if the number of candidates is a multiple + * of the mpi_size, we simply pass through the candidate list + * and assign n entries to each process to flush, with the + * index of the first entry to flush in the location in + * the candidate_assignment_table indicated by the mpi_rank + * of the process. * - * In the more common case in which the candidate list isn't - * isn't a multiple of the mpi_size, we pretend it is, and - * give num_candidates % mpi_size processes one extra entry - * each to make things work out. + * In the more common case in which the candidate list isn't + * isn't a multiple of the mpi_size, we pretend it is, and + * give num_candidates % mpi_size processes one extra entry + * each to make things work out. * - * Once the table is constructed, we determine the first and - * last entry this process is to flush as follows: + * Once the table is constructed, we determine the first and + * last entry this process is to flush as follows: * - * first_entry_to_flush = candidate_assignment_table[mpi_rank] + * first_entry_to_flush = candidate_assignment_table[mpi_rank] * - * last_entry_to_flush = - * candidate_assignment_table[mpi_rank + 1] - 1; + * last_entry_to_flush = + * candidate_assignment_table[mpi_rank + 1] - 1; * - * With these values determined, we simply scan through the - * candidate list, marking all entries in the range - * [first_entry_to_flush, last_entry_to_flush] for flush, - * and all others to be cleaned. + * With these values determined, we simply scan through the + * candidate list, marking all entries in the range + * [first_entry_to_flush, last_entry_to_flush] for flush, + * and all others to be cleaned. * - * Finally, we scan the LRU from tail to head, flushing - * or marking clean the candidate entries as indicated. - * If necessary, we scan the pinned list as well. + * Finally, we scan the LRU from tail to head, flushing + * or marking clean the candidate entries as indicated. + * If necessary, we scan the pinned list as well. * - * Note that this function will fail if any protected or - * clean entries appear on the candidate list. + * Note that this function will fail if any protected or + * clean entries appear on the candidate list. * - * This function is used in managing sync points, and - * shouldn't be used elsewhere. + * This function is used in managing sync points, and + * shouldn't be used elsewhere. * * Return: Success: SUCCEED * @@ -163,6 +163,10 @@ static herr_t H5C__flush_candidates_in_ring(H5F_t *f, H5C_ring_t ring, * Programmer: John Mainzer * 3/17/10 * + * Changes: Updated sanity checks to allow for the possibility that + * the slist is disabled. + * JRM -- 8/3/20 + * *------------------------------------------------------------------------- */ herr_t @@ -183,14 +187,17 @@ H5C_apply_candidate_list(H5F_t * f, unsigned * candidate_assignment_table = NULL; unsigned entries_to_flush[H5C_RING_NTYPES]; unsigned entries_to_clear[H5C_RING_NTYPES]; - haddr_t addr; - H5C_cache_entry_t * entry_ptr = NULL; + haddr_t addr; + H5C_cache_entry_t * entry_ptr = NULL; + #if H5C_DO_SANITY_CHECKS - haddr_t last_addr; + haddr_t last_addr; #endif /* H5C_DO_SANITY_CHECKS */ + #if H5C_APPLY_CANDIDATE_LIST__DEBUG - char tbl_buf[1024]; + char tbl_buf[1024]; #endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ + unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ @@ -200,7 +207,8 @@ H5C_apply_candidate_list(H5F_t * f, HDassert(cache_ptr != NULL); HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC); HDassert(num_candidates > 0); - HDassert(num_candidates <= cache_ptr->slist_len); + HDassert( ( ! cache_ptr->slist_enabled ) || + ( num_candidates <= cache_ptr->slist_len )); HDassert(candidates_list_ptr != NULL); HDassert(0 <= mpi_rank); HDassert(mpi_rank < mpi_size); @@ -410,13 +418,14 @@ done: /*------------------------------------------------------------------------- + * * Function: H5C_construct_candidate_list__clean_cache * * Purpose: Construct the list of entries that should be flushed to - * clean all entries in the cache. + * clean all entries in the cache. * - * This function is used in managing sync points, and - * shouldn't be used elsewhere. + * This function is used in managing sync points, and + * shouldn't be used elsewhere. * * Return: Success: SUCCEED * @@ -425,6 +434,16 @@ done: * Programmer: John Mainzer * 3/17/10 * + * Changes: With the slist optimization, the slist is not maintained + * unless a flush is in progress. Thus we can not longer use + * cache_ptr->slist_size to determine the total size of + * the entries we must insert in the candidate list. + * + * To address this, we now use cache_ptr->dirty_index_size + * instead. + * + * JRM -- 7/27/20 + * *------------------------------------------------------------------------- */ herr_t @@ -438,60 +457,82 @@ H5C_construct_candidate_list__clean_cache(H5C_t * cache_ptr) HDassert( cache_ptr != NULL ); HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); - /* As a sanity check, set space needed to the size of the skip list. - * This should be the sum total of the sizes of all the dirty entries - * in the metadata cache. + /* As a sanity check, set space needed to the dirty_index_size. This + * should be the sum total of the sizes of all the dirty entries in + * in the metadata cache. Note that if the slist is enabled, + * cache_ptr->slist_size should equal cache_ptr->dirty_index_size. */ - space_needed = cache_ptr->slist_size; + space_needed = cache_ptr->dirty_index_size; + + HDassert( ( ! cache_ptr->slist_enabled ) || + ( space_needed == cache_ptr->slist_size ) ); + /* Recall that while we shouldn't have any protected entries at this * point, it is possible that some dirty entries may reside on the * pinned list at this point. */ - HDassert( cache_ptr->slist_size <= + HDassert( cache_ptr->dirty_index_size <= (cache_ptr->dLRU_list_size + cache_ptr->pel_size) ); - HDassert( cache_ptr->slist_len <= - (cache_ptr->dLRU_list_len + cache_ptr->pel_len) ); + HDassert( ( ! cache_ptr->slist_enabled ) || + ( cache_ptr->slist_len <= + (cache_ptr->dLRU_list_len + cache_ptr->pel_len) ) ); + if(space_needed > 0) { /* we have work to do */ + H5C_cache_entry_t *entry_ptr; unsigned nominated_entries_count = 0; size_t nominated_entries_size = 0; - haddr_t nominated_addr; + haddr_t nominated_addr; - HDassert( cache_ptr->slist_len > 0 ); + HDassert( ( ! cache_ptr->slist_enabled ) || + ( cache_ptr->slist_len > 0 ) ); /* Scan the dirty LRU list from tail forward and nominate sufficient * entries to free up the necessary space. */ entry_ptr = cache_ptr->dLRU_tail_ptr; - while((nominated_entries_size < space_needed) && - (nominated_entries_count < cache_ptr->slist_len) && - (entry_ptr != NULL)) { + + while ( ( nominated_entries_size < space_needed ) && + ( ( ! cache_ptr->slist_enabled ) || + ( nominated_entries_count < cache_ptr->slist_len ) ) && + ( entry_ptr != NULL ) ) { + HDassert( ! (entry_ptr->is_protected) ); HDassert( ! (entry_ptr->is_read_only) ); HDassert( entry_ptr->ro_ref_count == 0 ); HDassert( entry_ptr->is_dirty ); - HDassert( entry_ptr->in_slist ); + HDassert( ( ! cache_ptr->slist_enabled ) || + ( entry_ptr->in_slist ) ); nominated_addr = entry_ptr->addr; + if(H5AC_add_candidate((H5AC_t *)cache_ptr, nominated_addr) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5AC_add_candidate() failed") + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "H5AC_add_candidate() failed") nominated_entries_size += entry_ptr->size; nominated_entries_count++; entry_ptr = entry_ptr->aux_prev; + } /* end while */ + HDassert( entry_ptr == NULL ); /* it is possible that there are some dirty entries on the * protected entry list as well -- scan it too if necessary */ entry_ptr = cache_ptr->pel_head_ptr; - while((nominated_entries_size < space_needed) && - (nominated_entries_count < cache_ptr->slist_len) && - (entry_ptr != NULL)) { + + while ( ( nominated_entries_size < space_needed ) && + ( ( ! cache_ptr->slist_enabled ) || + ( nominated_entries_count < cache_ptr->slist_len ) ) && + ( entry_ptr != NULL ) ) { + if(entry_ptr->is_dirty) { + HDassert( ! (entry_ptr->is_protected) ); HDassert( ! (entry_ptr->is_read_only) ); HDassert( entry_ptr->ro_ref_count == 0 ); @@ -499,22 +540,31 @@ H5C_construct_candidate_list__clean_cache(H5C_t * cache_ptr) HDassert( entry_ptr->in_slist ); nominated_addr = entry_ptr->addr; + if(H5AC_add_candidate((H5AC_t *)cache_ptr, nominated_addr) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5AC_add_candidate() failed") + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "H5AC_add_candidate() failed") nominated_entries_size += entry_ptr->size; nominated_entries_count++; + } /* end if */ entry_ptr = entry_ptr->next; + } /* end while */ - HDassert( nominated_entries_count == cache_ptr->slist_len ); + HDassert( ( ! cache_ptr->slist_enabled ) || + ( nominated_entries_count == cache_ptr->slist_len ) ); HDassert( nominated_entries_size == space_needed ); + } /* end if */ done: + FUNC_LEAVE_NOAPI(ret_value) + } /* H5C_construct_candidate_list__clean_cache() */ @@ -522,10 +572,10 @@ done: * Function: H5C_construct_candidate_list__min_clean * * Purpose: Construct the list of entries that should be flushed to - * get the cache back within its min clean constraints. + * get the cache back within its min clean constraints. * - * This function is used in managing sync points, and - * shouldn't be used elsewhere. + * This function is used in managing sync points, and + * shouldn't be used elsewhere. * * Return: Success: SUCCEED * @@ -534,6 +584,12 @@ done: * Programmer: John Mainzer * 3/17/10 * + * Changes: With the slist optimization, the slist is not maintained + * unless a flush is in progress. Updated sanity checks to + * reflect this. + * + * JRM -- 7/27/20 + * *------------------------------------------------------------------------- */ herr_t @@ -551,54 +607,77 @@ H5C_construct_candidate_list__min_clean(H5C_t * cache_ptr) * cache back within its min clean constraints. */ if(cache_ptr->max_cache_size > cache_ptr->index_size) { - if(((cache_ptr->max_cache_size - cache_ptr->index_size) + - cache_ptr->cLRU_list_size) >= cache_ptr->min_clean_size) + + if ( ( (cache_ptr->max_cache_size - cache_ptr->index_size) + + cache_ptr->cLRU_list_size) >= cache_ptr->min_clean_size ) { + space_needed = 0; - else + + } else { + space_needed = cache_ptr->min_clean_size - ((cache_ptr->max_cache_size - cache_ptr->index_size) + cache_ptr->cLRU_list_size); + } } /* end if */ else { - if(cache_ptr->min_clean_size <= cache_ptr->cLRU_list_size) + + if(cache_ptr->min_clean_size <= cache_ptr->cLRU_list_size) { + space_needed = 0; - else + + } else { + space_needed = cache_ptr->min_clean_size - cache_ptr->cLRU_list_size; + } } /* end else */ if(space_needed > 0) { /* we have work to do */ + H5C_cache_entry_t *entry_ptr; unsigned nominated_entries_count = 0; size_t nominated_entries_size = 0; - HDassert( cache_ptr->slist_len > 0 ); + HDassert( ( ! cache_ptr->slist_enabled ) || + ( cache_ptr->slist_len > 0 ) ); /* Scan the dirty LRU list from tail forward and nominate sufficient * entries to free up the necessary space. */ entry_ptr = cache_ptr->dLRU_tail_ptr; - while((nominated_entries_size < space_needed) && - (nominated_entries_count < cache_ptr->slist_len) && - (entry_ptr != NULL) && - (!entry_ptr->flush_me_last)) { - haddr_t nominated_addr; + + while ( ( nominated_entries_size < space_needed ) && + ( ( ! cache_ptr->slist_enabled ) || + ( nominated_entries_count < cache_ptr->slist_len ) ) && + ( entry_ptr != NULL ) && + ( ! entry_ptr->flush_me_last ) ) { + + haddr_t nominated_addr; HDassert( ! (entry_ptr->is_protected) ); HDassert( ! (entry_ptr->is_read_only) ); HDassert( entry_ptr->ro_ref_count == 0 ); HDassert( entry_ptr->is_dirty ); - HDassert( entry_ptr->in_slist ); + HDassert( ( ! cache_ptr->slist_enabled ) || + ( entry_ptr->in_slist ) ); nominated_addr = entry_ptr->addr; + if(H5AC_add_candidate((H5AC_t *)cache_ptr, nominated_addr) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5AC_add_candidate() failed") + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "H5AC_add_candidate() failed") nominated_entries_size += entry_ptr->size; nominated_entries_count++; entry_ptr = entry_ptr->aux_prev; + } /* end while */ - HDassert( nominated_entries_count <= cache_ptr->slist_len ); + + HDassert( ( ! cache_ptr->slist_enabled ) || + ( nominated_entries_count <= cache_ptr->slist_len ) ); + HDassert( nominated_entries_size <= cache_ptr->dirty_index_size ); HDassert( nominated_entries_size >= space_needed ); } /* end if */ @@ -612,24 +691,24 @@ done: * Function: H5C_mark_entries_as_clean * * Purpose: When the H5C code is used to implement the metadata caches - * in PHDF5, only the cache with MPI_rank 0 is allowed to - * actually write entries to disk -- all other caches must - * retain dirty entries until they are advised that the - * entries are clean. + * in PHDF5, only the cache with MPI_rank 0 is allowed to + * actually write entries to disk -- all other caches must + * retain dirty entries until they are advised that the + * entries are clean. * - * This function exists to allow the H5C code to receive these - * notifications. + * This function exists to allow the H5C code to receive these + * notifications. * - * The function receives a list of entry base addresses - * which must refer to dirty entries in the cache. If any - * of the entries are either clean or don't exist, the - * function flags an error. + * The function receives a list of entry base addresses + * which must refer to dirty entries in the cache. If any + * of the entries are either clean or don't exist, the + * function flags an error. * - * The function scans the list of entries and flushes all - * those that are currently unprotected with the - * H5C__FLUSH_CLEAR_ONLY_FLAG. Those that are currently - * protected are flagged for clearing when they are - * unprotected. + * The function scans the list of entries and flushes all + * those that are currently unprotected with the + * H5C__FLUSH_CLEAR_ONLY_FLAG. Those that are currently + * protected are flagged for clearing when they are + * unprotected. * * Return: Non-negative on success/Negative on failure * @@ -644,22 +723,22 @@ H5C_mark_entries_as_clean(H5F_t * f, haddr_t * ce_array_ptr) { H5C_t * cache_ptr; - unsigned entries_cleared; + unsigned entries_cleared; unsigned pinned_entries_cleared; hbool_t progress; - unsigned entries_examined; - unsigned initial_list_len; - haddr_t addr; - unsigned pinned_entries_marked = 0; + unsigned entries_examined; + unsigned initial_list_len; + haddr_t addr; + unsigned pinned_entries_marked = 0; #if H5C_DO_SANITY_CHECKS - unsigned protected_entries_marked = 0; - unsigned other_entries_marked = 0; - haddr_t last_addr; + unsigned protected_entries_marked = 0; + unsigned other_entries_marked = 0; + haddr_t last_addr; #endif /* H5C_DO_SANITY_CHECKS */ - H5C_cache_entry_t * clear_ptr = NULL; - H5C_cache_entry_t * entry_ptr = NULL; + H5C_cache_entry_t * clear_ptr = NULL; + H5C_cache_entry_t * entry_ptr = NULL; unsigned u; - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -706,7 +785,7 @@ H5C_mark_entries_as_clean(H5F_t * f, if(entry_ptr == NULL) { #if H5C_DO_SANITY_CHECKS - HDfprintf(stdout, + HDfprintf(stdout, "H5C_mark_entries_as_clean: entry[%u] = %a not in cache.\n", u, addr); @@ -715,7 +794,7 @@ H5C_mark_entries_as_clean(H5F_t * f, } /* end if */ else if(!entry_ptr->is_dirty) { #if H5C_DO_SANITY_CHECKS - HDfprintf(stdout, + HDfprintf(stdout, "H5C_mark_entries_as_clean: entry %a is not dirty!?!\n", addr); #endif /* H5C_DO_SANITY_CHECKS */ @@ -735,13 +814,13 @@ H5C_mark_entries_as_clean(H5F_t * f, } /* end if */ entry_ptr->clear_on_unprotect = TRUE; - if(entry_ptr->is_pinned) - pinned_entries_marked++; + if(entry_ptr->is_pinned) + pinned_entries_marked++; #if H5C_DO_SANITY_CHECKS - else if(entry_ptr->is_protected) - protected_entries_marked++; - else - other_entries_marked++; + else if(entry_ptr->is_protected) + protected_entries_marked++; + else + other_entries_marked++; #endif /* H5C_DO_SANITY_CHECKS */ } } @@ -769,7 +848,7 @@ H5C_mark_entries_as_clean(H5F_t * f, * of the pre_serialize / serialize routines, this may * cease to be the case -- requiring a review of this * point. - * JRM -- 4/7/15 + * JRM -- 4/7/15 */ entries_cleared = 0; entries_examined = 0; @@ -873,9 +952,9 @@ done: herr_t H5C_clear_coll_entries(H5C_t *cache_ptr, hbool_t partial) { - uint32_t clear_cnt; - H5C_cache_entry_t * entry_ptr = NULL; - herr_t ret_value = SUCCEED; + uint32_t clear_cnt; + H5C_cache_entry_t * entry_ptr = NULL; + herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI_NOINIT @@ -1084,7 +1163,7 @@ done: /*------------------------------------------------------------------------- * Function: H5C__flush_candidate_entries * - * Purpose: Flush or clear (as indicated) the candidate entries that + * Purpose: Flush or clear (as indicated) the candidate entries that * have been marked in the metadata cache. In so doing, * observe rings and flush dependencies. * @@ -1113,9 +1192,9 @@ done: * Return: Non-negative on success/Negative on failure. * * Programmer: John Mainzer - * 2/10/17 + * 2/10/17 * - * Changes: None. + * Changes: None. * *------------------------------------------------------------------------- */ @@ -1124,17 +1203,17 @@ H5C__flush_candidate_entries(H5F_t *f, unsigned entries_to_flush[H5C_RING_NTYPES unsigned entries_to_clear[H5C_RING_NTYPES]) { #if H5C_DO_SANITY_CHECKS - int i; - uint32_t index_len = 0; - size_t index_size = (size_t)0; - size_t clean_index_size = (size_t)0; - size_t dirty_index_size = (size_t)0; - size_t slist_size = (size_t)0; - uint32_t slist_len = 0; + int i; + uint32_t index_len = 0; + size_t index_size = (size_t)0; + size_t clean_index_size = (size_t)0; + size_t dirty_index_size = (size_t)0; + size_t slist_size = (size_t)0; + uint32_t slist_len = 0; #endif /* H5C_DO_SANITY_CHECKS */ - H5C_ring_t ring; + H5C_ring_t ring; H5C_t * cache_ptr; - herr_t ret_value = SUCCEED; + herr_t ret_value = SUCCEED; FUNC_ENTER_STATIC @@ -1164,7 +1243,7 @@ H5C__flush_candidate_entries(H5F_t *f, unsigned entries_to_flush[H5C_RING_NTYPES clean_index_size += cache_ptr->clean_index_ring_size[i]; dirty_index_size += cache_ptr->dirty_index_ring_size[i]; - slist_len += cache_ptr->slist_ring_len[i]; + slist_len += cache_ptr->slist_ring_len[i]; slist_size += cache_ptr->slist_ring_size[i]; } /* end for */ @@ -1206,7 +1285,7 @@ done: /*------------------------------------------------------------------------- * Function: H5C__flush_candidates_in_ring * - * Purpose: Flush or clear (as indicated) the candidate entries + * Purpose: Flush or clear (as indicated) the candidate entries * contained in the specified cache and ring. All candidate * entries in rings outside the specified ring must have been * flushed (or cleared) on entry. @@ -1235,7 +1314,7 @@ done: * Return: Non-negative on success/Negative on failure. * * Programmer: John Mainzer - * 2/10/17 + * 2/10/17 * *------------------------------------------------------------------------- */ diff --git a/src/H5Cpkg.h b/src/H5Cpkg.h index 8712af5..ac761f6 100644 --- a/src/H5Cpkg.h +++ b/src/H5Cpkg.h @@ -47,13 +47,22 @@ /* Number of epoch markers active */ #define H5C__MAX_EPOCH_MARKERS 10 + /* 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 + +/* Set to TRUE to enable the slist optimization. If this field is TRUE, + * the slist is disabled whenever a flush is not in progress. + */ +#define H5C__SLIST_OPT_ENABLED TRUE + + /**************************************************************************** * * We maintain doubly linked lists of instances of H5C_cache_entry_t for a @@ -1568,49 +1577,82 @@ if ( ( (cache_ptr)->index_size != \ * Added code to maintain the cache_ptr->slist_ring_len * and cache_ptr->slist_ring_size arrays. * + * JRM -- 4/29/20 + * Reworked macro to support the slist_enabled field + * of H5C_t. If slist_enabled == TRUE, the macro + * functions as before. Otherwise, the macro is a no-op, + * and the slist must be empty. + * *------------------------------------------------------------------------- */ +/* NOTE: The H5C__INSERT_ENTRY_IN_SLIST() macro is set up so that + * + * H5C_DO_SANITY_CHECKS + * + * and + * + * H5C_DO_SLIST_SANITY_CHECKS + * + * can be selected independantly. This is easy to miss as the + * two #defines are easy to confuse. + */ + #if H5C_DO_SLIST_SANITY_CHECKS + #define ENTRY_IN_SLIST(cache_ptr, entry_ptr) \ H5C_entry_in_skip_list((cache_ptr), (entry_ptr)) + #else /* H5C_DO_SLIST_SANITY_CHECKS */ + #define ENTRY_IN_SLIST(cache_ptr, entry_ptr) FALSE + #endif /* H5C_DO_SLIST_SANITY_CHECKS */ + #if H5C_DO_SANITY_CHECKS #define H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, fail_val) \ { \ HDassert( (cache_ptr) ); \ HDassert( (cache_ptr)->magic == H5C__H5C_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( (entry_ptr)->size > 0 ); \ - HDassert( H5F_addr_defined((entry_ptr)->addr) ); \ - HDassert( !((entry_ptr)->in_slist) ); \ - HDassert( !ENTRY_IN_SLIST((cache_ptr), (entry_ptr)) ); \ - HDassert( (entry_ptr)->ring > H5C_RING_UNDEFINED ); \ - HDassert( (entry_ptr)->ring < H5C_RING_NTYPES ); \ - HDassert( (cache_ptr)->slist_ring_len[(entry_ptr)->ring] <= \ - (cache_ptr)->slist_len ); \ - HDassert( (cache_ptr)->slist_ring_size[(entry_ptr)->ring] <= \ - (cache_ptr)->slist_size ); \ \ - if(H5SL_insert((cache_ptr)->slist_ptr, entry_ptr, &(entry_ptr)->addr) < 0) \ - HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, (fail_val), "can't insert entry in skip list") \ + if ( (cache_ptr)->slist_enabled ) { \ + \ + HDassert( (entry_ptr) ); \ + HDassert( (entry_ptr)->size > 0 ); \ + HDassert( H5F_addr_defined((entry_ptr)->addr) ); \ + HDassert( !((entry_ptr)->in_slist) ); \ + HDassert( ! ENTRY_IN_SLIST((cache_ptr), (entry_ptr)) ); \ + HDassert( (entry_ptr)->ring > H5C_RING_UNDEFINED ); \ + HDassert( (entry_ptr)->ring < H5C_RING_NTYPES ); \ + HDassert( (cache_ptr)->slist_ring_len[(entry_ptr)->ring] <= \ + (cache_ptr)->slist_len ); \ + HDassert( (cache_ptr)->slist_ring_size[(entry_ptr)->ring] <= \ + (cache_ptr)->slist_size ); \ \ - (entry_ptr)->in_slist = TRUE; \ - (cache_ptr)->slist_changed = TRUE; \ - (cache_ptr)->slist_len++; \ - (cache_ptr)->slist_size += (entry_ptr)->size; \ - ((cache_ptr)->slist_ring_len[(entry_ptr)->ring])++; \ - ((cache_ptr)->slist_ring_size[(entry_ptr)->ring]) += (entry_ptr)->size; \ - (cache_ptr)->slist_len_increase++; \ - (cache_ptr)->slist_size_increase += (int64_t)((entry_ptr)->size); \ + if ( H5SL_insert((cache_ptr)->slist_ptr, entry_ptr, \ + &((entry_ptr)->addr)) < 0) \ + HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, (fail_val), \ + "can't insert entry in skip list") \ \ - HDassert( (cache_ptr)->slist_len > 0 ); \ - HDassert( (cache_ptr)->slist_size > 0 ); \ + (entry_ptr)->in_slist = TRUE; \ + (cache_ptr)->slist_changed = TRUE; \ + (cache_ptr)->slist_len++; \ + (cache_ptr)->slist_size += (entry_ptr)->size; \ + ((cache_ptr)->slist_ring_len[(entry_ptr)->ring])++; \ + ((cache_ptr)->slist_ring_size[(entry_ptr)->ring]) += (entry_ptr)->size;\ + (cache_ptr)->slist_len_increase++; \ + (cache_ptr)->slist_size_increase += (int64_t)((entry_ptr)->size); \ \ + HDassert( (cache_ptr)->slist_len > 0 ); \ + HDassert( (cache_ptr)->slist_size > 0 ); \ + \ + } else { /* slist disabled */ \ + \ + HDassert( (cache_ptr)->slist_len == 0 ); \ + HDassert( (cache_ptr)->slist_size == 0 ); \ + } \ } /* H5C__INSERT_ENTRY_IN_SLIST */ #else /* H5C_DO_SANITY_CHECKS */ @@ -1619,31 +1661,42 @@ if ( ( (cache_ptr)->index_size != \ { \ HDassert( (cache_ptr) ); \ HDassert( (cache_ptr)->magic == H5C__H5C_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( (entry_ptr)->size > 0 ); \ - HDassert( H5F_addr_defined((entry_ptr)->addr) ); \ - HDassert( !((entry_ptr)->in_slist) ); \ - HDassert( !ENTRY_IN_SLIST((cache_ptr), (entry_ptr)) ); \ - HDassert( (entry_ptr)->ring > H5C_RING_UNDEFINED ); \ - HDassert( (entry_ptr)->ring < H5C_RING_NTYPES ); \ - HDassert( (cache_ptr)->slist_ring_len[(entry_ptr)->ring] <= \ - (cache_ptr)->slist_len ); \ - HDassert( (cache_ptr)->slist_ring_size[(entry_ptr)->ring] <= \ - (cache_ptr)->slist_size ); \ \ - if(H5SL_insert((cache_ptr)->slist_ptr, entry_ptr, &(entry_ptr)->addr) < 0) \ - HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, (fail_val), "can't insert entry in skip list") \ + if ( (cache_ptr)->slist_enabled ) { \ + \ + HDassert( (entry_ptr) ); \ + HDassert( (entry_ptr)->size > 0 ); \ + HDassert( ! ENTRY_IN_SLIST((cache_ptr), (entry_ptr)) ); \ + HDassert( H5F_addr_defined((entry_ptr)->addr) ); \ + HDassert( !((entry_ptr)->in_slist) ); \ + HDassert( (entry_ptr)->ring > H5C_RING_UNDEFINED ); \ + HDassert( (entry_ptr)->ring < H5C_RING_NTYPES ); \ + HDassert( (cache_ptr)->slist_ring_len[(entry_ptr)->ring] <= \ + (cache_ptr)->slist_len ); \ + HDassert( (cache_ptr)->slist_ring_size[(entry_ptr)->ring] <= \ + (cache_ptr)->slist_size ); \ + HDassert( (cache_ptr)->slist_ptr ); \ + \ + if ( H5SL_insert((cache_ptr)->slist_ptr, entry_ptr, \ + &((entry_ptr)->addr)) < 0) \ + HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, (fail_val), \ + "can't insert entry in skip list") \ \ - (entry_ptr)->in_slist = TRUE; \ - (cache_ptr)->slist_changed = TRUE; \ - (cache_ptr)->slist_len++; \ - (cache_ptr)->slist_size += (entry_ptr)->size; \ - ((cache_ptr)->slist_ring_len[(entry_ptr)->ring])++; \ - ((cache_ptr)->slist_ring_size[(entry_ptr)->ring]) += (entry_ptr)->size; \ + (entry_ptr)->in_slist = TRUE; \ + (cache_ptr)->slist_changed = TRUE; \ + (cache_ptr)->slist_len++; \ + (cache_ptr)->slist_size += (entry_ptr)->size; \ + ((cache_ptr)->slist_ring_len[(entry_ptr)->ring])++; \ + ((cache_ptr)->slist_ring_size[(entry_ptr)->ring]) += (entry_ptr)->size;\ \ - HDassert( (cache_ptr)->slist_len > 0 ); \ - HDassert( (cache_ptr)->slist_size > 0 ); \ + HDassert( (cache_ptr)->slist_len > 0 ); \ + HDassert( (cache_ptr)->slist_size > 0 ); \ \ + } else { /* slist disabled */ \ + \ + HDassert( (cache_ptr)->slist_len == 0 ); \ + HDassert( (cache_ptr)->slist_size == 0 ); \ + } \ } /* H5C__INSERT_ENTRY_IN_SLIST */ #endif /* H5C_DO_SANITY_CHECKS */ @@ -1661,80 +1714,129 @@ if ( ( (cache_ptr)->index_size != \ * * Programmer: John Mainzer, 5/10/04 * + * Modifications: + * + * JRM -- 7/21/04 + * Updated function for the addition of the hash table. + * + * JRM - 7/27/04 + * Converted from the function H5C_remove_entry_from_tree() + * to the macro H5C__REMOVE_ENTRY_FROM_TREE in the hopes of + * wringing a little more performance out of the cache. + * + * QAK -- 11/27/04 + * Switched over to using skip list routines. + * + * JRM -- 3/28/07 + * Updated sanity checks for the new is_read_only and + * ro_ref_count fields in H5C_cache_entry_t. + * + * JRM -- 12/13/14 + * Added code to set cache_ptr->slist_changed to TRUE + * when an entry is removed from the slist. + * + * JRM -- 4/29/20 + * Reworked macro to support the slist_enabled field + * of H5C_t. If slist_enabled == TRUE, the macro + * functions as before. Otherwise, the macro is a no-op, + * and the slist must be empty. + * *------------------------------------------------------------------------- */ #if H5C_DO_SANITY_CHECKS -#define H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr, during_flush) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C__H5C_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( !((entry_ptr)->is_read_only) ); \ - HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ - HDassert( (entry_ptr)->size > 0 ); \ - HDassert( (entry_ptr)->in_slist ); \ - HDassert( (cache_ptr)->slist_ptr ); \ - HDassert( (entry_ptr)->ring > H5C_RING_UNDEFINED ); \ - HDassert( (entry_ptr)->ring < H5C_RING_NTYPES ); \ - HDassert( (cache_ptr)->slist_ring_len[(entry_ptr)->ring] <= \ - (cache_ptr)->slist_len ); \ - HDassert( (cache_ptr)->slist_ring_size[(entry_ptr)->ring] <= \ - (cache_ptr)->slist_size ); \ - \ - if ( H5SL_remove((cache_ptr)->slist_ptr, &(entry_ptr)->addr) \ - != (entry_ptr) ) \ - HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "can't delete entry from skip list") \ - \ - HDassert( (cache_ptr)->slist_len > 0 ); \ - if(!(during_flush)) \ - (cache_ptr)->slist_changed = TRUE; \ - (cache_ptr)->slist_len--; \ - HDassert( (cache_ptr)->slist_size >= (entry_ptr)->size ); \ - (cache_ptr)->slist_size -= (entry_ptr)->size; \ - ((cache_ptr)->slist_ring_len[(entry_ptr)->ring])--; \ - HDassert( (cache_ptr)->slist_ring_size[(entry_ptr->ring)] >= \ - (entry_ptr)->size ); \ - ((cache_ptr)->slist_ring_size[(entry_ptr)->ring]) -= (entry_ptr)->size; \ - (cache_ptr)->slist_len_increase--; \ - (cache_ptr)->slist_size_increase -= (int64_t)((entry_ptr)->size); \ - (entry_ptr)->in_slist = FALSE; \ +#define H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr, during_flush) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C__H5C_T_MAGIC ); \ + \ + if ( (cache_ptr)->slist_enabled ) { \ + \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( (entry_ptr)->size > 0 ); \ + HDassert( (entry_ptr)->in_slist ); \ + HDassert( (cache_ptr)->slist_ptr ); \ + HDassert( (entry_ptr)->ring > H5C_RING_UNDEFINED ); \ + HDassert( (entry_ptr)->ring < H5C_RING_NTYPES ); \ + HDassert( (cache_ptr)->slist_ring_len[(entry_ptr)->ring] <= \ + (cache_ptr)->slist_len ); \ + HDassert( (cache_ptr)->slist_ring_size[(entry_ptr)->ring] <= \ + (cache_ptr)->slist_size ); \ + HDassert( (cache_ptr)->slist_size >= (entry_ptr)->size ); \ + \ + if ( H5SL_remove((cache_ptr)->slist_ptr, &(entry_ptr)->addr) \ + != (entry_ptr) ) \ + HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, \ + "can't delete entry from skip list") \ + \ + HDassert( (cache_ptr)->slist_len > 0 ); \ + if(!(during_flush)) \ + (cache_ptr)->slist_changed = TRUE; \ + (cache_ptr)->slist_len--; \ + HDassert( (cache_ptr)->slist_size >= (entry_ptr)->size ); \ + (cache_ptr)->slist_size -= (entry_ptr)->size; \ + ((cache_ptr)->slist_ring_len[(entry_ptr)->ring])--; \ + HDassert( (cache_ptr)->slist_ring_size[(entry_ptr->ring)] >= \ + (entry_ptr)->size ); \ + ((cache_ptr)->slist_ring_size[(entry_ptr)->ring]) -= (entry_ptr)->size;\ + (cache_ptr)->slist_len_increase--; \ + (cache_ptr)->slist_size_increase -= (int64_t)((entry_ptr)->size); \ + (entry_ptr)->in_slist = FALSE; \ + \ + } else { /* slist disabled */ \ + \ + HDassert( (cache_ptr)->slist_len == 0 ); \ + HDassert( (cache_ptr)->slist_size == 0 ); \ + } \ } /* H5C__REMOVE_ENTRY_FROM_SLIST */ #else /* H5C_DO_SANITY_CHECKS */ -#define H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr, during_flush) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C__H5C_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( !((entry_ptr)->is_read_only) ); \ - HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ - HDassert( (entry_ptr)->in_slist ); \ - HDassert( (cache_ptr)->slist_ptr ); \ - HDassert( (entry_ptr)->ring > H5C_RING_UNDEFINED ); \ - HDassert( (entry_ptr)->ring < H5C_RING_NTYPES ); \ - HDassert( (cache_ptr)->slist_ring_len[(entry_ptr)->ring] <= \ - (cache_ptr)->slist_len ); \ - HDassert( (cache_ptr)->slist_ring_size[(entry_ptr)->ring] <= \ - (cache_ptr)->slist_size ); \ - \ - if ( H5SL_remove((cache_ptr)->slist_ptr, &(entry_ptr)->addr) \ - != (entry_ptr) ) \ - HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "can't delete entry from skip list") \ - \ - HDassert( (cache_ptr)->slist_len > 0 ); \ - if(!(during_flush)) \ - (cache_ptr)->slist_changed = TRUE; \ - (cache_ptr)->slist_len--; \ - HDassert( (cache_ptr)->slist_size >= (entry_ptr)->size ); \ - (cache_ptr)->slist_size -= (entry_ptr)->size; \ - ((cache_ptr)->slist_ring_len[(entry_ptr)->ring])--; \ - HDassert( (cache_ptr)->slist_ring_size[(entry_ptr->ring)] >= \ - (entry_ptr)->size ); \ - ((cache_ptr)->slist_ring_size[(entry_ptr)->ring]) -= (entry_ptr)->size; \ - (entry_ptr)->in_slist = FALSE; \ +#define H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr, during_flush) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C__H5C_T_MAGIC ); \ + \ + if ( (cache_ptr)->slist_enabled ) { \ + \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( (entry_ptr)->in_slist ); \ + HDassert( (cache_ptr)->slist_ptr ); \ + HDassert( (entry_ptr)->ring > H5C_RING_UNDEFINED ); \ + HDassert( (entry_ptr)->ring < H5C_RING_NTYPES ); \ + HDassert( (cache_ptr)->slist_ring_len[(entry_ptr)->ring] <= \ + (cache_ptr)->slist_len ); \ + HDassert( (cache_ptr)->slist_ring_size[(entry_ptr)->ring] <= \ + (cache_ptr)->slist_size ); \ + \ + if ( H5SL_remove((cache_ptr)->slist_ptr, &(entry_ptr)->addr) \ + != (entry_ptr) ) \ + HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, \ + "can't delete entry from skip list") \ + \ + HDassert( (cache_ptr)->slist_len > 0 ); \ + if(!(during_flush)) \ + (cache_ptr)->slist_changed = TRUE; \ + (cache_ptr)->slist_len--; \ + HDassert( (cache_ptr)->slist_size >= (entry_ptr)->size ); \ + (cache_ptr)->slist_size -= (entry_ptr)->size; \ + ((cache_ptr)->slist_ring_len[(entry_ptr)->ring])--; \ + HDassert( (cache_ptr)->slist_ring_size[(entry_ptr->ring)] >= \ + (entry_ptr)->size ); \ + ((cache_ptr)->slist_ring_size[(entry_ptr)->ring]) -= (entry_ptr)->size;\ + (entry_ptr)->in_slist = FALSE; \ + \ + } else { /* slist disabled */ \ + \ + HDassert( (cache_ptr)->slist_len == 0 ); \ + HDassert( (cache_ptr)->slist_size == 0 ); \ + } \ } /* H5C__REMOVE_ENTRY_FROM_SLIST */ + #endif /* H5C_DO_SANITY_CHECKS */ @@ -1770,6 +1872,12 @@ if ( ( (cache_ptr)->index_size != \ * Added code to maintain the cache_ptr->slist_ring_len * and cache_ptr->slist_ring_size arrays. * + * JRM -- 4/29/20 + * Reworked macro to support the slist_enabled field + * of H5C_t. If slist_enabled == TRUE, the macro + * functions as before. Otherwise, the macro is a no-op, + * and the slist must be empty. + * *------------------------------------------------------------------------- */ @@ -1779,32 +1887,43 @@ if ( ( (cache_ptr)->index_size != \ { \ HDassert( (cache_ptr) ); \ HDassert( (cache_ptr)->magic == H5C__H5C_T_MAGIC ); \ - HDassert( (old_size) > 0 ); \ - HDassert( (new_size) > 0 ); \ - HDassert( (old_size) <= (cache_ptr)->slist_size ); \ - HDassert( (cache_ptr)->slist_len > 0 ); \ - HDassert( ((cache_ptr)->slist_len > 1) || \ - ( (cache_ptr)->slist_size == (old_size) ) ); \ - HDassert( (entry_ptr)->ring > H5C_RING_UNDEFINED ); \ - HDassert( (entry_ptr)->ring < H5C_RING_NTYPES ); \ - HDassert( (cache_ptr)->slist_ring_len[(entry_ptr)->ring] <= \ - (cache_ptr)->slist_len ); \ - HDassert( (cache_ptr)->slist_ring_size[(entry_ptr)->ring] <= \ - (cache_ptr)->slist_size ); \ \ - (cache_ptr)->slist_size -= (old_size); \ - (cache_ptr)->slist_size += (new_size); \ + if ( (cache_ptr)->slist_enabled ) { \ + \ + HDassert( (old_size) > 0 ); \ + HDassert( (new_size) > 0 ); \ + HDassert( (old_size) <= (cache_ptr)->slist_size ); \ + HDassert( (cache_ptr)->slist_len > 0 ); \ + HDassert( ((cache_ptr)->slist_len > 1) || \ + ( (cache_ptr)->slist_size == (old_size) ) ); \ + HDassert( (entry_ptr)->ring > H5C_RING_UNDEFINED ); \ + HDassert( (entry_ptr)->ring < H5C_RING_NTYPES ); \ + HDassert( (cache_ptr)->slist_ring_len[(entry_ptr)->ring] <= \ + (cache_ptr)->slist_len ); \ + HDassert( (cache_ptr)->slist_ring_size[(entry_ptr)->ring] <= \ + (cache_ptr)->slist_size ); \ + \ + (cache_ptr)->slist_size -= (old_size); \ + (cache_ptr)->slist_size += (new_size); \ + \ + HDassert( (cache_ptr)->slist_ring_size[(entry_ptr->ring)] \ + >= (old_size) ); \ \ - HDassert( (cache_ptr)->slist_ring_size[(entry_ptr->ring)] >=(old_size) ); \ - ((cache_ptr)->slist_ring_size[(entry_ptr)->ring]) -= (old_size); \ - ((cache_ptr)->slist_ring_size[(entry_ptr)->ring]) += (new_size); \ + ((cache_ptr)->slist_ring_size[(entry_ptr)->ring]) -= (old_size); \ + ((cache_ptr)->slist_ring_size[(entry_ptr)->ring]) += (new_size); \ \ - (cache_ptr)->slist_size_increase -= (int64_t)(old_size); \ - (cache_ptr)->slist_size_increase += (int64_t)(new_size); \ + (cache_ptr)->slist_size_increase -= (int64_t)(old_size); \ + (cache_ptr)->slist_size_increase += (int64_t)(new_size); \ \ - HDassert( (new_size) <= (cache_ptr)->slist_size ); \ - HDassert( ( (cache_ptr)->slist_len > 1 ) || \ - ( (cache_ptr)->slist_size == (new_size) ) ); \ + HDassert( (new_size) <= (cache_ptr)->slist_size ); \ + HDassert( ( (cache_ptr)->slist_len > 1 ) || \ + ( (cache_ptr)->slist_size == (new_size) ) ); \ + \ + } else { /* slist disabled */ \ + \ + HDassert( (cache_ptr)->slist_len == 0 ); \ + HDassert( (cache_ptr)->slist_size == 0 ); \ + } \ } /* H5C__UPDATE_SLIST_FOR_SIZE_CHANGE */ #else /* H5C_DO_SANITY_CHECKS */ @@ -1813,29 +1932,39 @@ if ( ( (cache_ptr)->index_size != \ { \ HDassert( (cache_ptr) ); \ HDassert( (cache_ptr)->magic == H5C__H5C_T_MAGIC ); \ - HDassert( (old_size) > 0 ); \ - HDassert( (new_size) > 0 ); \ - HDassert( (old_size) <= (cache_ptr)->slist_size ); \ - HDassert( (cache_ptr)->slist_len > 0 ); \ - HDassert( ((cache_ptr)->slist_len > 1) || \ - ( (cache_ptr)->slist_size == (old_size) ) ); \ - HDassert( (entry_ptr)->ring > H5C_RING_UNDEFINED ); \ - HDassert( (entry_ptr)->ring < H5C_RING_NTYPES ); \ - HDassert( (cache_ptr)->slist_ring_len[(entry_ptr)->ring] <= \ - (cache_ptr)->slist_len ); \ - HDassert( (cache_ptr)->slist_ring_size[(entry_ptr)->ring] <= \ - (cache_ptr)->slist_size ); \ \ - (cache_ptr)->slist_size -= (old_size); \ - (cache_ptr)->slist_size += (new_size); \ + if ( (cache_ptr)->slist_enabled ) { \ + \ + HDassert( (old_size) > 0 ); \ + HDassert( (new_size) > 0 ); \ + HDassert( (old_size) <= (cache_ptr)->slist_size ); \ + HDassert( (cache_ptr)->slist_len > 0 ); \ + HDassert( ((cache_ptr)->slist_len > 1) || \ + ( (cache_ptr)->slist_size == (old_size) ) ); \ + HDassert( (entry_ptr)->ring > H5C_RING_UNDEFINED ); \ + HDassert( (entry_ptr)->ring < H5C_RING_NTYPES ); \ + HDassert( (cache_ptr)->slist_ring_len[(entry_ptr)->ring] <= \ + (cache_ptr)->slist_len ); \ + HDassert( (cache_ptr)->slist_ring_size[(entry_ptr)->ring] <= \ + (cache_ptr)->slist_size ); \ + \ + (cache_ptr)->slist_size -= (old_size); \ + (cache_ptr)->slist_size += (new_size); \ + \ + HDassert( (cache_ptr)->slist_ring_size[(entry_ptr->ring)] >= \ + (old_size) ); \ + ((cache_ptr)->slist_ring_size[(entry_ptr)->ring]) -= (old_size); \ + ((cache_ptr)->slist_ring_size[(entry_ptr)->ring]) += (new_size); \ \ - HDassert( (cache_ptr)->slist_ring_size[(entry_ptr->ring)] >=(old_size) ); \ - ((cache_ptr)->slist_ring_size[(entry_ptr)->ring]) -= (old_size); \ - ((cache_ptr)->slist_ring_size[(entry_ptr)->ring]) += (new_size); \ + HDassert( (new_size) <= (cache_ptr)->slist_size ); \ + HDassert( ( (cache_ptr)->slist_len > 1 ) || \ + ( (cache_ptr)->slist_size == (new_size) ) ); \ \ - HDassert( (new_size) <= (cache_ptr)->slist_size ); \ - HDassert( ( (cache_ptr)->slist_len > 1 ) || \ - ( (cache_ptr)->slist_size == (new_size) ) ); \ + } else { /* slist disabled */ \ + \ + HDassert( (cache_ptr)->slist_len == 0 ); \ + HDassert( (cache_ptr)->slist_size == 0 ); \ + } \ } /* H5C__UPDATE_SLIST_FOR_SIZE_CHANGE */ #endif /* H5C_DO_SANITY_CHECKS */ @@ -3726,7 +3855,8 @@ typedef struct H5C_tag_info_t { * which contains the 'next' entry for an iteration. Removing * this entry must trigger a rescan of the iteration, so each * entry removed from the cache is compared against this pointer - * and the pointer is reset to NULL if the watched entry is removed. + * and the pointer is reset to NULL if the watched entry is + * removed. * (This functions similarly to a "dead man's switch") * * @@ -3740,6 +3870,36 @@ typedef struct H5C_tag_info_t { * are flushed. (this has been changed -- dirty entries are now removed from * the skip list as they are flushed. JRM - 10/25/05) * + * Update 4/21/20: + * + * Profiling indicates that the cost of maintaining the skip list is + * significant. As it is only used on flush and close, maintaining it + * only when needed is an obvious optimization. + * + * To do this, we add a flag to control maintenanace of the skip list. + * This flag is initially set to FALSE, which disables all operations + * on the skip list. + * + * At the beginning of either flush or close, we scan the index list, + * insert all dirtly entries in the skip list, and enable operations + * on skip list by setting above control flag to true. + * + * At the end of a complete flush, we verify that the skip list is empty, + * and set the control flag back to false, so as to avoid skip list + * maintenance overhead until the next flush or close. + * + * In the case of a partial flush (i.e. flush marked entries), we remove + * all remaining entries from the skip list, and then set the control flag + * back to false -- again avoiding skip list maintenance overhead until + * the next flush or close. + * + * slist_enabled: Boolean flag used to control operation of the skip + * list. If this filed is FALSE, operations on the + * slist are no-ops, and the slist must be empty. If + * it is TRUE, operations on the slist proceed as usual, + * and all dirty entries in the metadata cache must be + * listed in the slist. + * * slist_changed: Boolean flag used to indicate whether the contents of * the slist has changed since the last time this flag was * reset. This is used in the cache flush code to detect @@ -4649,6 +4809,7 @@ typedef struct H5C_tag_info_t { * NDEBUG is not #defined. * ****************************************************************************/ + struct H5C_t { uint32_t magic; hbool_t flush_in_progress; @@ -4664,7 +4825,7 @@ struct H5C_t { hbool_t evictions_enabled; hbool_t close_warning_received; - /* Fields for maintaining [hash table] index of entries */ + /* Fields for maintaining the [hash table] index of entries */ uint32_t index_len; size_t index_size; uint32_t index_ring_len[H5C_RING_NTYPES]; @@ -4685,6 +4846,7 @@ struct H5C_t { H5C_cache_entry_t * entry_watched_for_removal; /* Fields for maintaining list of in-order entries, for flushing */ + hbool_t slist_enabled; hbool_t slist_changed; uint32_t slist_len; size_t slist_size; @@ -4882,7 +5044,8 @@ struct H5C_t { #ifndef NDEBUG int64_t get_entry_ptr_from_addr_counter; #endif /* NDEBUG */ -}; + +}; /* H5C_t */ /* Define typedef for tagged cache entry iteration callbacks */ typedef int (*H5C_tag_iter_cb_t)(H5C_cache_entry_t *entry, void *ctx); diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h index 0ba0234..cdccb4f 100644 --- a/src/H5Cprivate.h +++ b/src/H5Cprivate.h @@ -2288,7 +2288,10 @@ H5_DLL herr_t H5C_resize_entry(void *thing, size_t new_size); H5_DLL herr_t H5C_set_cache_auto_resize_config(H5C_t *cache_ptr, H5C_auto_size_ctl_t *config_ptr); H5_DLL herr_t H5C_set_cache_image_config(const H5F_t *f, H5C_t *cache_ptr, H5C_cache_image_ctl_t *config_ptr); -H5_DLL herr_t H5C_set_evictions_enabled(H5C_t *cache_ptr, hbool_t evictions_enabled); +H5_DLL herr_t H5C_set_evictions_enabled(H5C_t *cache_ptr, + hbool_t evictions_enabled); +H5_DLL herr_t H5C_set_slist_enabled(H5C_t *cache_ptr, hbool_t slist_enabled, + hbool_t clear_slist); H5_DLL herr_t H5C_set_prefix(H5C_t *cache_ptr, char *prefix); H5_DLL herr_t H5C_stats(H5C_t *cache_ptr, const char *cache_name, hbool_t display_detailed_stats); diff --git a/src/H5Fint.c b/src/H5Fint.c index 0bda894..4a4b8b6 100644 --- a/src/H5Fint.c +++ b/src/H5Fint.c @@ -1914,6 +1914,11 @@ H5F__flush_phase2(H5F_t *f, hbool_t closing) /* Sanity check arguments */ HDassert(f); + /* Inform the metadata cache that we are about to flush */ + if(H5AC_prep_for_file_flush(f) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "prep for MDC flush failed") + /* Flush the entire metadata cache */ if(H5AC_flush(f) < 0) /* Push error, but keep going*/ @@ -1946,6 +1951,11 @@ H5F__flush_phase2(H5F_t *f, hbool_t closing) H5CX_set_mpi_file_flushing(FALSE); #endif /* H5_HAVE_PARALLEL */ + /* Inform the metadata cache that we are done with the flush */ + if(H5AC_secure_from_file_flush(f) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "secure from MDC flush failed") + /* Flush out the metadata accumulator */ if(H5F__accum_flush(f->shared) < 0) /* Push error, but keep going*/ diff --git a/test/cache.c b/test/cache.c index bb18728..8eda0a2 100644 --- a/test/cache.c +++ b/test/cache.c @@ -2933,21 +2933,25 @@ express_test, unsigned paged) /*------------------------------------------------------------------------- * Function: check_insert_entry() * - * Purpose: Verify that H5C_insert_entry behaves as expected. - * Test the behaviour with different flags. + * Purpose: Verify that H5C_insert_entry behaves as expected. + * Test the behaviour with different flags. * - * This test was added primarily to test basic insert - * pinned entry functionallity, but I through in explicit - * tests for other functionallity that is tested implicitly - * elsewhere. + * This test was added primarily to test basic insert + * pinned entry functionallity, but I through in explicit + * tests for other functionallity that is tested implicitly + * elsewhere. * - * Return: void + * Return: void * - * Programmer: John Mainzer + * Programmer: John Mainzer * 8/10/06 * * Modifications: * + * Updated tests to accommodate the case in which the + * slist is disabled. + * JRM -- 5/14/20 + * *------------------------------------------------------------------------- */ @@ -3154,52 +3158,59 @@ check_insert_entry(unsigned paged) if(pass) { - if((cache_ptr->index_len != 4) || - (cache_ptr->index_size != 4 * entry_sizes[entry_type]) || - (cache_ptr->slist_len != 4) || - (cache_ptr->slist_size != 4 * entry_sizes[entry_type]) || - (cache_ptr->pl_len != 0) || - (cache_ptr->pl_size != (size_t)0) || - (cache_ptr->pel_len != 2) || - (cache_ptr->pel_size != 2 * entry_sizes[entry_type]) || - (cache_ptr->LRU_list_len != 2) || - (cache_ptr->LRU_list_size != 2 * entry_sizes[entry_type]) + if ( ( cache_ptr->index_len != 4 ) || + ( cache_ptr->index_size != 4 * entry_sizes[entry_type] ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 4 ) || + ( cache_ptr->slist_size != 4 * entry_sizes[entry_type] ) + ) + ) || + ( cache_ptr->pl_len != 0 ) || + ( cache_ptr->pl_size != (size_t)0 ) || + ( cache_ptr->pel_len != 2 ) || + ( cache_ptr->pel_size != 2 * entry_sizes[entry_type] ) || + ( cache_ptr->LRU_list_len != 2 ) || + ( cache_ptr->LRU_list_size != 2 * entry_sizes[entry_type] ) #if H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS - || (cache_ptr->dLRU_list_len != 2) || - (cache_ptr->dLRU_list_size != 2 * entry_sizes[entry_type]) || - (cache_ptr->cLRU_list_len != 0) || - (cache_ptr->cLRU_list_size != (size_t)0) + || + ( cache_ptr->dLRU_list_len != 2 ) || + ( cache_ptr->dLRU_list_size != 2 * entry_sizes[entry_type] ) || + ( cache_ptr->cLRU_list_len != 0 ) || + ( cache_ptr->cLRU_list_size != (size_t)0 ) #endif /* H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ - ) { + ) { - pass = FALSE; - failure_mssg = "Unexpected insert results 10."; - } + pass = FALSE; + failure_mssg = "Unexpected insert results 10."; + } } /* Finally, if stats collection is enabled, verify that the expected * stats are collected. */ #if H5C_COLLECT_CACHE_STATS - if(pass) { - - if((cache_ptr->insertions[entry_type] != 4) || - (cache_ptr->pinned_insertions[entry_type] != 2) || - (cache_ptr->pins[entry_type] != 2) || - (cache_ptr->unpins[entry_type] != 0) || - (cache_ptr->dirty_pins[entry_type] != 0) || - (cache_ptr->max_index_len != 4) || - (cache_ptr->max_index_size != 4 * entry_sizes[entry_type]) || - (cache_ptr->max_slist_len != 4) || - (cache_ptr->max_slist_size != 4 * entry_sizes[entry_type]) || - (cache_ptr->max_pl_len != 0) || - (cache_ptr->max_pl_size != (size_t)0) || - (cache_ptr->max_pel_len != 2) || - (cache_ptr->max_pel_size != 2 * entry_sizes[entry_type])) { - - pass = FALSE; - failure_mssg = "Unexpected insert results 11."; - } + if ( pass ) { + + if ( ( cache_ptr->insertions[entry_type] != 4 ) || + ( cache_ptr->pinned_insertions[entry_type] != 2 ) || + ( cache_ptr->pins[entry_type] != 2 ) || + ( cache_ptr->unpins[entry_type] != 0 ) || + ( cache_ptr->dirty_pins[entry_type] != 0 ) || + ( cache_ptr->max_index_len != 4 ) || + ( cache_ptr->max_index_size != 4 * entry_sizes[entry_type] ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 4 ) || + ( cache_ptr->slist_size != 4 * entry_sizes[entry_type] ) + ) + ) || + ( cache_ptr->max_pl_len != 0 ) || + ( cache_ptr->max_pl_size != (size_t)0 ) || + ( cache_ptr->max_pel_len != 2 ) || + ( cache_ptr->max_pel_size != 2 * entry_sizes[entry_type] ) ) { + + pass = FALSE; + failure_mssg = "Unexpected insert results 11."; + } } #endif /* H5C_COLLECT_CACHE_STATS */ @@ -3208,7 +3219,7 @@ check_insert_entry(unsigned paged) if(pass) { unpin_entry(entry_type, 2); - unpin_entry(entry_type, 3); + unpin_entry(entry_type, 3); } if(pass) { @@ -3316,18 +3327,25 @@ check_flush_cache(unsigned paged) /*------------------------------------------------------------------------- + * * Function: check_flush_cache__empty_cache() * - * Purpose: Verify that flush_cache behaves as expected with an empty + * Purpose : Verify that flush_cache behaves as expected with an empty * cache. * - * Return: void + * Return: void * - * Programmer: John Mainzer + * Programmer: John Mainzer * 1/12/05 * * Modifications: * + * Added code to setup and take down the skip list before + * and after calls to H5C_flush_cache(). Do this via the + * H5C_FLUSH_CACHE macro. + * + * JRM -- 5/14/20 + * *------------------------------------------------------------------------- */ @@ -3335,7 +3353,6 @@ static void check_flush_cache__empty_cache(H5F_t * file_ptr) { H5C_t * cache_ptr = file_ptr->shared->cache; - herr_t result; if(cache_ptr == NULL) { @@ -3352,53 +3369,37 @@ check_flush_cache__empty_cache(H5F_t * file_ptr) /* Test behaviour on an empty cache. Can't do much sanity * checking in this case, so simply check the return values. + * + * Check of return values is done in the H5C_FLUSH_CACHE() macro. */ - if(pass) { + if ( pass ) { - result = H5C_flush_cache(file_ptr, H5C__NO_FLAGS_SET); - - if(result < 0) { - - pass = FALSE; - failure_mssg = "flush with flags = 0x00 failed on empty cache.\n"; - } + H5C_FLUSH_CACHE(file_ptr, H5C__NO_FLAGS_SET, \ + "flush with flags = 0x00 failed on empty cache.\n") } - if(pass) { - - result = H5C_flush_cache(file_ptr, H5C__FLUSH_INVALIDATE_FLAG); - - if(result < 0) { + if ( pass ) { - pass = FALSE; - failure_mssg = "flush with flags = 0x04 failed on empty cache.\n"; - } + H5C_FLUSH_CACHE(file_ptr, H5C__FLUSH_INVALIDATE_FLAG, \ + "flush with flags = 0x04 failed on empty cache.\n") } - if(pass) { - - result = H5C_flush_cache(file_ptr, H5C__FLUSH_CLEAR_ONLY_FLAG); + if ( pass ) { - if(result < 0) { - - pass = FALSE; - failure_mssg = "flush with flags = 0x08 failed on empty cache.\n"; - } + H5C_FLUSH_CACHE(file_ptr, H5C__FLUSH_CLEAR_ONLY_FLAG, \ + "flush with flags = 0x08 failed on empty cache.\n") } - if(pass) { - - result = H5C_flush_cache(file_ptr, H5C__FLUSH_MARKED_ENTRIES_FLAG); + if ( pass ) { - if(result < 0) { - - pass = FALSE; - failure_mssg = "flush with flags = 0x10 failed on empty cache.\n"; - } + H5C_FLUSH_CACHE(file_ptr, H5C__FLUSH_MARKED_ENTRIES_FLAG, \ + "flush with flags = 0x10 failed on empty cache.\n") } + return; + } /* check_flush_cache__empty_cache() */ @@ -4959,15 +4960,21 @@ check_flush_cache__multi_entry(H5F_t * file_ptr) /*------------------------------------------------------------------------- * Function: check_flush_cache__multi_entry_test() * - * Purpose: Run a multi entry flush cache test. + * Purpose : Run a multi entry flush cache test. * - * Return: void - * - * Programmer: John Mainzer + * Return: void + * + * Programmer: John Mainzer * 1/13/05 * * Modifications: * + * Added code to setup and take down the skip list before + * and after calls to H5C_flush_cache(). Do this via the + * H5C_FLUSH_CACHE macro. + * + * JRM -- 5/14/20 + * *------------------------------------------------------------------------- */ @@ -4980,7 +4987,6 @@ check_flush_cache__multi_entry_test(H5F_t * file_ptr, { H5C_t * cache_ptr = file_ptr->shared->cache; static char msg[128]; - herr_t result; unsigned u; size_t total_entry_size = 0; test_entry_t * base_addr; @@ -4989,8 +4995,8 @@ check_flush_cache__multi_entry_test(H5F_t * file_ptr, #if 0 /* JRM */ /* This gets used a lot, so lets leave it in. */ - HDfprintf(stdout, "check_flush_cache__multi_entry_test: test %d\n", - test_num); + HDfprintf(stdout, "check_flush_cache__multi_entry_test: test %d\n", + test_num); #endif /* JRM */ if(cache_ptr == NULL) { @@ -5001,8 +5007,8 @@ check_flush_cache__multi_entry_test(H5F_t * file_ptr, test_num); failure_mssg = msg; } - else if((cache_ptr->index_len != 0) || - (cache_ptr->index_size != 0)) { + else if ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) ) { pass = FALSE; @@ -5021,13 +5027,13 @@ check_flush_cache__multi_entry_test(H5F_t * file_ptr, } u = 0; - while(pass && (u < spec_size)) - { - if(((unsigned)spec[u].entry_num != u) || - (spec[u].entry_type < 0) || - (spec[u].entry_type >= NUMBER_OF_ENTRY_TYPES) || - (spec[u].entry_index < 0) || - (spec[u].entry_index > max_indices[spec[u].entry_type])) { + while ( pass && ( u < spec_size ) ) { + + if ( ( (unsigned)spec[u].entry_num != u ) || + ( spec[u].entry_type < 0 ) || + ( spec[u].entry_type >= NUMBER_OF_ENTRY_TYPES ) || + ( spec[u].entry_index < 0 ) || + ( spec[u].entry_index > max_indices[spec[u].entry_type] ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, @@ -5039,8 +5045,8 @@ check_flush_cache__multi_entry_test(H5F_t * file_ptr, } u = 0; - while(pass && (u < spec_size)) - { + while ( pass && (u < spec_size) ) { + if(spec[u].insert_flag) { insert_entry(file_ptr, spec[u].entry_type, spec[u].entry_index, @@ -5061,11 +5067,10 @@ check_flush_cache__multi_entry_test(H5F_t * file_ptr, if(pass) { - result = H5C_flush_cache(file_ptr, flush_flags); + H5C_FLUSH_CACHE(file_ptr, flush_flags, "dummy failure message.\n") - if(result < 0) { + if ( ! pass ) { - pass = FALSE; HDsnprintf(msg, (size_t)128, "flush with flags 0x%x failed in multi entry test #%d.", flush_flags, test_num); @@ -5107,22 +5112,22 @@ check_flush_cache__multi_entry_test(H5F_t * file_ptr, if(pass) { - if((((flush_flags & H5C__FLUSH_INVALIDATE_FLAG) == 0) + if ( ( ( (flush_flags & H5C__FLUSH_INVALIDATE_FLAG) == 0) && - ((cache_ptr->index_len != spec_size) + ( ( cache_ptr->index_len != spec_size ) || - (cache_ptr->index_size != total_entry_size) - ) - ) + ( cache_ptr->index_size != total_entry_size ) + ) + ) || - (((flush_flags & H5C__FLUSH_INVALIDATE_FLAG) != 0) + ( ( (flush_flags & H5C__FLUSH_INVALIDATE_FLAG) != 0) && - ((cache_ptr->index_len != 0) + ( ( cache_ptr->index_len != 0 ) || - (cache_ptr->index_size != 0) - ) - ) - ) { + ( cache_ptr->index_size != 0 ) + ) + ) + ) { pass = FALSE; HDsnprintf(msg, (size_t)128, @@ -5135,9 +5140,9 @@ check_flush_cache__multi_entry_test(H5F_t * file_ptr, /* clean up the cache to prep for the next test */ if(pass) { - result = H5C_flush_cache(file_ptr, H5C__FLUSH_INVALIDATE_FLAG); + H5C_FLUSH_CACHE(file_ptr, H5C__FLUSH_INVALIDATE_FLAG, "dummy mssg.\n") - if(result < 0) { + if ( ! pass ) { pass = FALSE; HDsnprintf(msg, (size_t)128, @@ -5145,8 +5150,8 @@ check_flush_cache__multi_entry_test(H5F_t * file_ptr, test_num); failure_mssg = msg; } - else if((cache_ptr->index_len != 0) || - (cache_ptr->index_size != 0)) { + else if ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, @@ -5158,8 +5163,8 @@ check_flush_cache__multi_entry_test(H5F_t * file_ptr, } u = 0; - while(pass && (u < spec_size)) - { + while ( pass && ( u < spec_size ) ) { + base_addr = entries[spec[u].entry_type]; entry_ptr = &(base_addr[spec[u].entry_index]); @@ -5176,17 +5181,24 @@ check_flush_cache__multi_entry_test(H5F_t * file_ptr, /*------------------------------------------------------------------------- + * * Function: check_flush_cache__pe_multi_entry_test() * - * Purpose: Run a multi entry flush cache test. + * Purpose: Run a multi entry flush cache test. * - * Return: void + * Return: void * - * Programmer: John Mainzer + * Programmer: John Mainzer * 4/5/06 * * Modifications: * + * Added code to setup and take down the skip list before + * and after calls to H5C_flush_cache(). Do this via the + * H5C_FLUSH_CACHE macro. + * + * JRM -- 5/16/20 + * *------------------------------------------------------------------------- */ @@ -5199,7 +5211,6 @@ check_flush_cache__pe_multi_entry_test(H5F_t * file_ptr, { H5C_t *cache_ptr = file_ptr->shared->cache; static char msg[128]; - herr_t result; unsigned u; int j; size_t total_entry_size = 0; @@ -5221,8 +5232,8 @@ check_flush_cache__pe_multi_entry_test(H5F_t * file_ptr, test_num); failure_mssg = msg; } - else if((cache_ptr->index_len != 0) || - (cache_ptr->index_size != 0)) { + else if ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) ) { pass = FALSE; @@ -5241,15 +5252,15 @@ check_flush_cache__pe_multi_entry_test(H5F_t * file_ptr, } u = 0; - while(pass && (u < spec_size)) - { - if(((unsigned)spec[u].entry_num != u) || - (spec[u].entry_type < 0) || - (spec[u].entry_type >= NUMBER_OF_ENTRY_TYPES) || - (spec[u].entry_index < 0) || - (spec[u].entry_index > max_indices[spec[u].entry_type]) || - (spec[u].num_pins < 0) || - (spec[u].num_pins > MAX_PINS)) { + while ( pass && ( u < spec_size ) ) { + + if ( ( (unsigned)spec[u].entry_num != u ) || + ( spec[u].entry_type < 0 ) || + ( spec[u].entry_type >= NUMBER_OF_ENTRY_TYPES ) || + ( spec[u].entry_index < 0 ) || + ( spec[u].entry_index > max_indices[spec[u].entry_type] ) || + ( spec[u].num_pins < 0 ) || + ( spec[u].num_pins > MAX_PINS ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, @@ -5278,25 +5289,24 @@ check_flush_cache__pe_multi_entry_test(H5F_t * file_ptr, total_entry_size += entry_sizes[spec[u].entry_type]; - for (j = 0; j < spec[u].num_pins; j++) - { + for (j = 0; j < spec[u].num_pins; j++) { + create_pinned_entry_dependency(file_ptr, - spec[u].entry_type, - spec[u].entry_index, - spec[u].pin_type[j], - spec[u].pin_idx[j]); - } + spec[u].entry_type, + spec[u].entry_index, + spec[u].pin_type[j], + spec[u].pin_idx[j]); + } u++; } if(pass) { - result = H5C_flush_cache(file_ptr, flush_flags); + H5C_FLUSH_CACHE(file_ptr, flush_flags, "dummy failure message.\n") - if(result < 0) { + if ( ! pass ) { - pass = FALSE; HDsnprintf(msg, (size_t)128, "flush with flags 0x%x failed in pe multi entry test #%d.", flush_flags, test_num); @@ -5305,14 +5315,14 @@ check_flush_cache__pe_multi_entry_test(H5F_t * file_ptr, } u = 0; - while(pass && (u < spec_size)) - { + while ( pass && ( u < spec_size ) ) { + base_addr = entries[spec[u].entry_type]; entry_ptr = &(base_addr[spec[u].entry_index]); - if((entry_ptr->deserialized != spec[u].expected_deserialized) || - (entry_ptr->serialized != spec[u].expected_serialized) || - (entry_ptr->destroyed != spec[u].expected_destroyed)) { + if ( ( entry_ptr->deserialized != spec[u].expected_deserialized ) || + ( entry_ptr->serialized != spec[u].expected_serialized ) || + ( entry_ptr->destroyed != spec[u].expected_destroyed ) ) { #if 0 /* This is useful debugging code. Lets keep it around. */ @@ -5338,22 +5348,22 @@ check_flush_cache__pe_multi_entry_test(H5F_t * file_ptr, if(pass) { - if((((flush_flags & H5C__FLUSH_INVALIDATE_FLAG) == 0) + if ( ( ( (flush_flags & H5C__FLUSH_INVALIDATE_FLAG) == 0) && - ((cache_ptr->index_len != spec_size) + ( ( cache_ptr->index_len != spec_size ) || - (cache_ptr->index_size != total_entry_size) - ) - ) + ( cache_ptr->index_size != total_entry_size ) + ) + ) || - (((flush_flags & H5C__FLUSH_INVALIDATE_FLAG) != 0) + ( ( (flush_flags & H5C__FLUSH_INVALIDATE_FLAG) != 0 ) && - ((cache_ptr->index_len != 0) + ( ( cache_ptr->index_len != 0 ) || - (cache_ptr->index_size != 0) - ) - ) - ) { + ( cache_ptr->index_size != 0 ) + ) + ) + ) { pass = FALSE; HDsnprintf(msg, (size_t)128, @@ -5364,11 +5374,11 @@ check_flush_cache__pe_multi_entry_test(H5F_t * file_ptr, } /* clean up the cache to prep for the next test */ - if(pass) { + if ( pass ) { - result = H5C_flush_cache(file_ptr, H5C__FLUSH_INVALIDATE_FLAG); + H5C_FLUSH_CACHE(file_ptr, H5C__FLUSH_INVALIDATE_FLAG, "dummy mssg.\n") - if(result < 0) { + if ( ! pass ) { pass = FALSE; HDsnprintf(msg, (size_t)128, @@ -5376,8 +5386,8 @@ check_flush_cache__pe_multi_entry_test(H5F_t * file_ptr, test_num); failure_mssg = msg; } - else if((cache_ptr->index_len != 0) || - (cache_ptr->index_size != 0)) { + else if ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, @@ -5389,8 +5399,8 @@ check_flush_cache__pe_multi_entry_test(H5F_t * file_ptr, } u = 0; - while(pass && (u < spec_size)) - { + while ( pass && ( u < spec_size ) ) { + base_addr = entries[spec[u].entry_type]; entry_ptr = &(base_addr[spec[u].entry_index]); @@ -9181,16 +9191,22 @@ check_flush_cache__flush_ops(H5F_t * file_ptr) /*------------------------------------------------------------------------- * Function: check_flush_cache__flush_op_test() * - * Purpose: Run a flush op flush cache test. Of the nature of - * flush operations, this is a multi-entry test. + * Purpose: Run a flush op flush cache test. Of the nature of + * flush operations, this is a multi-entry test. * - * Return: void + * Return: void * - * Programmer: John Mainzer + * Programmer: John Mainzer * 9/3/06 * * Modifications: * + * Added code to setup and take down the skip list before + * and after calls to H5C_flush_cache(). Do this via the + * H5C_FLUSH_CACHE macro. + * + * JRM -- 5/16/20 + * *------------------------------------------------------------------------- */ @@ -9200,16 +9216,15 @@ check_flush_cache__flush_op_test(H5F_t * file_ptr, unsigned int flush_flags, int spec_size, const struct fo_flush_cache_test_spec spec[], - unsigned init_expected_index_len, - size_t init_expected_index_size, - unsigned expected_index_len, - size_t expected_index_size, - int check_size, - struct fo_flush_entry_check check[]) + unsigned init_expected_index_len, + size_t init_expected_index_size, + unsigned expected_index_len, + size_t expected_index_size, + int check_size, + struct fo_flush_entry_check check[]) { H5C_t * cache_ptr = file_ptr->shared->cache; static char msg[128]; - herr_t result; int i; int j; test_entry_t * base_addr; @@ -9228,8 +9243,8 @@ check_flush_cache__flush_op_test(H5F_t * file_ptr, test_num); failure_mssg = msg; } - else if((cache_ptr->index_len != 0) || - (cache_ptr->index_size != 0)) { + else if ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) ) { pass = FALSE; @@ -9248,17 +9263,17 @@ check_flush_cache__flush_op_test(H5F_t * file_ptr, } i = 0; - while(pass && (i < spec_size)) - { - if((spec[i].entry_num != i) || - (spec[i].entry_type < 0) || - (spec[i].entry_type >= NUMBER_OF_ENTRY_TYPES) || - (spec[i].entry_index < 0) || - (spec[i].entry_index > max_indices[spec[i].entry_type]) || - (spec[i].num_pins < 0) || - (spec[i].num_pins > MAX_PINS) || - (spec[i].num_flush_ops < 0) || - (spec[i].num_flush_ops > MAX_FLUSH_OPS)) { + while ( pass && ( i < spec_size ) ) { + + if ( ( spec[i].entry_num != i ) || + ( spec[i].entry_type < 0 ) || + ( spec[i].entry_type >= NUMBER_OF_ENTRY_TYPES ) || + ( spec[i].entry_index < 0 ) || + ( spec[i].entry_index > max_indices[spec[i].entry_type] ) || + ( spec[i].num_pins < 0 ) || + ( spec[i].num_pins > MAX_PINS ) || + ( spec[i].num_flush_ops < 0 ) || + ( spec[i].num_flush_ops > MAX_FLUSH_OPS ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, @@ -9270,36 +9285,36 @@ check_flush_cache__flush_op_test(H5F_t * file_ptr, } i = 0; - while(pass && (i < check_size)) - { - if((check[i].entry_num != i) || - (check[i].entry_type < 0) || - (check[i].entry_type >= NUMBER_OF_ENTRY_TYPES) || - (check[i].entry_index < 0) || - (check[i].entry_index > max_indices[check[i].entry_type]) || + while ( pass && ( i < check_size ) ) { + + if ( ( check[i].entry_num != i) || + ( check[i].entry_type < 0) || + ( check[i].entry_type >= NUMBER_OF_ENTRY_TYPES) || + ( check[i].entry_index < 0) || + ( check[i].entry_index > max_indices[check[i].entry_type]) || #ifndef H5_HAVE_STDBOOL_H /* Check for nonsense values if hbool_t is an integral * type instead of a real Boolean. */ - ((check[i].in_cache != TRUE) && - (check[i].in_cache != FALSE)) || - ((check[i].at_main_addr != TRUE) && - (check[i].at_main_addr != FALSE)) || - ((check[i].is_dirty != TRUE) && - (check[i].is_dirty != FALSE)) || - ((check[i].is_protected != TRUE) && - (check[i].is_protected != FALSE)) || - ((check[i].is_pinned != TRUE) && - (check[i].is_pinned != FALSE)) || - ((check[i].expected_deserialized != TRUE) && - (check[i].expected_deserialized != FALSE)) || - ((check[i].expected_serialized != TRUE) && - (check[i].expected_serialized != FALSE)) || - ((check[i].expected_destroyed != TRUE) && - (check[i].expected_destroyed != FALSE)) || + ( ( check[i].in_cache != TRUE ) && + ( check[i].in_cache != FALSE ) ) || + ( ( check[i].at_main_addr != TRUE ) && + ( check[i].at_main_addr != FALSE ) ) || + ( ( check[i].is_dirty != TRUE ) && + ( check[i].is_dirty != FALSE ) ) || + ( ( check[i].is_protected != TRUE ) && + ( check[i].is_protected != FALSE ) ) || + ( ( check[i].is_pinned != TRUE ) && + ( check[i].is_pinned != FALSE ) ) || + ( ( check[i].expected_deserialized != TRUE ) && + ( check[i].expected_deserialized != FALSE ) ) || + ( ( check[i].expected_serialized != TRUE ) && + ( check[i].expected_serialized != FALSE ) ) || + ( ( check[i].expected_destroyed != TRUE ) && + ( check[i].expected_destroyed != FALSE ) ) || #endif /* H5_HAVE_STDBOOL_H */ - (check[i].expected_size <= (size_t)0) - ) { + ( check[i].expected_size <= (size_t)0 ) + ) { pass = FALSE; HDsnprintf(msg, (size_t)128, @@ -9311,8 +9326,8 @@ check_flush_cache__flush_op_test(H5F_t * file_ptr, } i = 0; - while(pass && (i < spec_size)) - { + while ( pass && ( i < spec_size ) ) { + if(spec[i].insert_flag) { insert_entry(file_ptr, spec[i].entry_type, spec[i].entry_index, @@ -9330,34 +9345,34 @@ check_flush_cache__flush_op_test(H5F_t * file_ptr, spec[i].flags); } - for (j = 0; j < spec[i].num_pins; j++) - { + for (j = 0; j < spec[i].num_pins; j++) + { create_pinned_entry_dependency(file_ptr, spec[i].entry_type, spec[i].entry_index, spec[i].pin_type[j], spec[i].pin_idx[j]); - } + } - for (j = 0; j < spec[i].num_flush_ops; j++) - { - add_flush_op(spec[i].entry_type, - spec[i].entry_index, - spec[i].flush_ops[j].op_code, - spec[i].flush_ops[j].type, - spec[i].flush_ops[j].idx, - spec[i].flush_ops[j].flag, - spec[i].flush_ops[j].size, + for (j = 0; j < spec[i].num_flush_ops; j++) { + + add_flush_op(spec[i].entry_type, + spec[i].entry_index, + spec[i].flush_ops[j].op_code, + spec[i].flush_ops[j].type, + spec[i].flush_ops[j].idx, + spec[i].flush_ops[j].flag, + spec[i].flush_ops[j].size, spec[i].flush_ops[j].order_ptr); - } + } i++; } - if(pass) { + if ( pass ) { - if((cache_ptr->index_len != init_expected_index_len) || - (cache_ptr->index_size != init_expected_index_size)) { + if ( ( cache_ptr->index_len != init_expected_index_len ) || + ( cache_ptr->index_size != init_expected_index_size ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, @@ -9369,9 +9384,9 @@ check_flush_cache__flush_op_test(H5F_t * file_ptr, if(pass) { - result = H5C_flush_cache(file_ptr, flush_flags); + H5C_FLUSH_CACHE(file_ptr, flush_flags, "dummy failure message") - if(result < 0) { + if ( ! pass ) { pass = FALSE; HDsnprintf(msg, (size_t)128, @@ -9383,14 +9398,14 @@ check_flush_cache__flush_op_test(H5F_t * file_ptr, i = 0; - while(pass && (i < spec_size)) - { + while ( pass && ( i < spec_size ) ) { + base_addr = entries[spec[i].entry_type]; entry_ptr = &(base_addr[spec[i].entry_index]); - if((entry_ptr->deserialized != spec[i].expected_deserialized) || - (entry_ptr->serialized != spec[i].expected_serialized) || - (entry_ptr->destroyed != spec[i].expected_destroyed)) { + if ( ( entry_ptr->deserialized != spec[i].expected_deserialized ) || + ( entry_ptr->serialized != spec[i].expected_serialized ) || + ( entry_ptr->destroyed != spec[i].expected_destroyed ) ) { #if 0 /* This is useful debugging code. Lets keep it around. */ @@ -9419,136 +9434,166 @@ check_flush_cache__flush_op_test(H5F_t * file_ptr, if(pass) { i = 0; - while(pass && (i < check_size)) - { - if(check[i].in_cache != entry_in_cache(cache_ptr, - check[i].entry_type, - check[i].entry_index)) { + while ( pass && (i < check_size ) ) { + + if ( check[i].in_cache != entry_in_cache(cache_ptr, + check[i].entry_type, + check[i].entry_index) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Check1 failed on entry %d after flush op test #%d.", i, test_num); failure_mssg = msg; - } + } base_addr = entries[check[i].entry_type]; entry_ptr = &(base_addr[check[i].entry_index]); - if((entry_ptr->size != check[i].expected_size) || - ((!entry_ptr->header.destroy_in_progress) && - (check[i].in_cache) && - (entry_ptr->header.size != check[i].expected_size)) || - (entry_ptr->at_main_addr != check[i].at_main_addr) || - (entry_ptr->is_dirty != check[i].is_dirty) || - (entry_ptr->header.is_dirty != check[i].is_dirty) || - (entry_ptr->is_protected != check[i].is_protected) || - (entry_ptr->header.is_protected != check[i].is_protected) || - (entry_ptr->is_pinned != check[i].is_pinned) || - (entry_ptr->header.is_pinned != check[i].is_pinned) || - (entry_ptr->deserialized != check[i].expected_deserialized) || - (entry_ptr->serialized != check[i].expected_serialized) || - (entry_ptr->destroyed != check[i].expected_destroyed)) { + if ( ( entry_ptr->size != check[i].expected_size) || + ( ( !entry_ptr->header.destroy_in_progress) && + ( check[i].in_cache ) && + ( entry_ptr->header.size != check[i].expected_size ) ) || + ( entry_ptr->at_main_addr != check[i].at_main_addr ) || + ( entry_ptr->is_dirty != check[i].is_dirty ) || + ( entry_ptr->header.is_dirty != check[i].is_dirty ) || + ( entry_ptr->is_protected != check[i].is_protected ) || + ( entry_ptr->header.is_protected != check[i].is_protected ) || + ( entry_ptr->is_pinned != check[i].is_pinned ) || + ( entry_ptr->header.is_pinned != check[i].is_pinned ) || + ( entry_ptr->deserialized != check[i].expected_deserialized ) || + ( entry_ptr->serialized != check[i].expected_serialized ) || + ( entry_ptr->destroyed != check[i].expected_destroyed ) ) { #if 0 /* This is useful debugging code. Lets keep it around for a while. */ - if(entry_ptr->size != check[i].expected_size) { - HDfprintf(stdout, "entry_ptr->size (expected) = %d (%d).\n", - (int)(entry_ptr->size), - (int)(check[i].expected_size)); - } - if((!entry_ptr->header.destroy_in_progress) && - (check[i].in_cache) && - (entry_ptr->header.size != check[i].expected_size)) { - HDfprintf(stdout, + if ( entry_ptr->size != check[i].expected_size ) { + + HDfprintf(stdout, "entry_ptr->size (expected) = %d (%d).\n", + (int)(entry_ptr->size), + (int)(check[i].expected_size)); + } + + if ( ( ! entry_ptr->header.destroy_in_progress ) && + ( check[i].in_cache ) && + ( entry_ptr->header.size != check[i].expected_size ) ) { + + HDfprintf(stdout, "(!destroy in progress and in cache and size (expected) = %d (%d).\n", (int)(entry_ptr->header.size), - (int)(check[i].expected_size)); - } - if(entry_ptr->at_main_addr != check[i].at_main_addr) { - HDfprintf(stdout, "(%d,%d) at main addr (expected) = %d (%d).\n", - (int)(check[i].entry_type), - (int)(check[i].entry_index), + (int)(check[i].expected_size)); + } + + if ( entry_ptr->at_main_addr != check[i].at_main_addr ) { + + HDfprintf(stdout, + "(%d,%d) at main addr (expected) = %d (%d).\n", + (int)(check[i].entry_type), + (int)(check[i].entry_index), (int)(entry_ptr->at_main_addr), - (int)(check[i].at_main_addr)); + (int)(check[i].at_main_addr)); + } + + if ( entry_ptr->is_dirty != check[i].is_dirty ) { + + HDfprintf(stdout, + "entry_ptr->is_dirty (expected) = %d (%d).\n", + (int)(entry_ptr->is_dirty), + (int)(check[i].is_dirty)); + } + + if ( entry_ptr->header.is_dirty != check[i].is_dirty ) { + + HDfprintf(stdout, + "entry_ptr->header.is_dirty (expected) = %d (%d).\n", + (int)(entry_ptr->header.is_dirty), + (int)(check[i].is_dirty)); + } + + if ( entry_ptr->is_protected != check[i].is_protected ) { + + HDfprintf(stdout, + "entry_ptr->is_protected (expected) = %d (%d).\n", + (int)(entry_ptr->is_protected), + (int)(check[i].is_protected)); + } + + if ( entry_ptr->header.is_protected != check[i].is_protected ) { + + HDfprintf(stdout, + "entry_ptr->header.is_protected (expected) = %d (%d).\n", + (int)(entry_ptr->is_protected), + (int)(check[i].is_protected)); + } + + if ( entry_ptr->is_pinned != check[i].is_pinned ) { + + HDfprintf(stdout, + "entry_ptr->is_pinned (expected) = %d (%d).\n", + (int)(entry_ptr->is_pinned), + (int)(check[i].is_pinned)); + } + + if ( entry_ptr->header.is_pinned != check[i].is_pinned ) { + + HDfprintf(stdout, + "entry_ptr->header.is_pinned (expected) = %d (%d).\n", + (int)(entry_ptr->header.is_pinned), + (int)(check[i].is_pinned)); + } + + if ( entry_ptr->deserialized != check[i].expected_deserialized ) { + + HDfprintf(stdout, + "entry_ptr->deserialized (expected) = %d (%d).\n", + (int)(entry_ptr->deserialized), + (int)(check[i].expected_deserialized)); + } + + if ( entry_ptr->serialized != check[i].expected_serialized ) { + + HDfprintf(stdout, + "entry_ptr->serialized (expected) = %d (%d).\n", + (int)(entry_ptr->serialized), + (int)(check[i].expected_serialized)); + } + + if ( entry_ptr->destroyed != check[i].expected_destroyed ) { + + HDfprintf(stdout, \ + "entry_ptr->destroyed (expected) = %d (%d).\n", + (int)(entry_ptr->destroyed), + (int)(check[i].expected_destroyed)); } - if(entry_ptr->is_dirty != check[i].is_dirty) { - HDfprintf(stdout, "entry_ptr->is_dirty (expected) = %d (%d).\n", - (int)(entry_ptr->is_dirty), - (int)(check[i].is_dirty)); - } - if(entry_ptr->header.is_dirty != check[i].is_dirty) { - HDfprintf(stdout, "entry_ptr->header.is_dirty (expected) = %d (%d).\n", - (int)(entry_ptr->header.is_dirty), - (int)(check[i].is_dirty)); - } - if(entry_ptr->is_protected != check[i].is_protected) { - HDfprintf(stdout, "entry_ptr->is_protected (expected) = %d (%d).\n", - (int)(entry_ptr->is_protected), - (int)(check[i].is_protected)); - } - if(entry_ptr->header.is_protected != check[i].is_protected) { - HDfprintf(stdout, "entry_ptr->header.is_protected (expected) = %d (%d).\n", - (int)(entry_ptr->is_protected), - (int)(check[i].is_protected)); - } - if(entry_ptr->is_pinned != check[i].is_pinned) { - HDfprintf(stdout, "entry_ptr->is_pinned (expected) = %d (%d).\n", - (int)(entry_ptr->is_pinned), - (int)(check[i].is_pinned)); - } - if(entry_ptr->header.is_pinned != check[i].is_pinned) { - HDfprintf(stdout, "entry_ptr->header.is_pinned (expected) = %d (%d).\n", - (int)(entry_ptr->header.is_pinned), - (int)(check[i].is_pinned)); - } - if(entry_ptr->deserialized != - check[i].expected_deserialized) { - HDfprintf(stdout, - "entry_ptr->deserialized (expected) = %d (%d).\n", - (int)(entry_ptr->deserialized), - (int)(check[i].expected_deserialized)); - } - if(entry_ptr->serialized != check[i].expected_serialized) { - HDfprintf(stdout, - "entry_ptr->serialized (expected) = %d (%d).\n", - (int)(entry_ptr->serialized), - (int)(check[i].expected_serialized)); - } - if(entry_ptr->destroyed != check[i].expected_destroyed) { - HDfprintf(stdout, "entry_ptr->destroyed (expected) = %d (%d).\n", - (int)(entry_ptr->destroyed), - (int)(check[i].expected_destroyed)); - } #endif pass = FALSE; HDsnprintf(msg, (size_t)128, "Check2 failed on entry %d after flush op test #%d.", i, test_num); failure_mssg = msg; - } - i++; + } + i++; } } - if(pass) { + if ( pass ) { - if((((flush_flags & H5C__FLUSH_INVALIDATE_FLAG) == 0) + if ( ( ( (flush_flags & H5C__FLUSH_INVALIDATE_FLAG) == 0 ) && - ((cache_ptr->index_len != expected_index_len) + ( ( cache_ptr->index_len != expected_index_len ) || - (cache_ptr->index_size != expected_index_size) - ) - ) + ( cache_ptr->index_size != expected_index_size ) + ) + ) || - (((flush_flags & H5C__FLUSH_INVALIDATE_FLAG) != 0) + ( ( (flush_flags & H5C__FLUSH_INVALIDATE_FLAG) != 0 ) && - ((cache_ptr->index_len != 0) + ( ( cache_ptr->index_len != 0 ) || - (cache_ptr->index_size != 0) - ) - ) - ) { + ( cache_ptr->index_size != 0 ) + ) + ) + ) { pass = FALSE; HDsnprintf(msg, (size_t)128, @@ -9561,20 +9606,19 @@ check_flush_cache__flush_op_test(H5F_t * file_ptr, /* clean up the cache to prep for the next test */ if(pass) { - result = H5C_flush_cache(file_ptr, H5C__FLUSH_INVALIDATE_FLAG); + H5C_FLUSH_CACHE(file_ptr, H5C__FLUSH_INVALIDATE_FLAG, "dummy mssg.") - if(result < 0) { + if ( ! pass ) { - pass = FALSE; HDsnprintf(msg, (size_t)128, "Flush failed on cleanup in flush op test #%d.", test_num); failure_mssg = msg; } - else if((cache_ptr->index_len != 0) || - (cache_ptr->index_size != 0) || - (cache_ptr->clean_index_size != 0) || - (cache_ptr->dirty_index_size != 0)) { + else if ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) || + ( cache_ptr->clean_index_size != 0 ) || + ( cache_ptr->dirty_index_size != 0 ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, @@ -9586,12 +9630,12 @@ check_flush_cache__flush_op_test(H5F_t * file_ptr, } i = 0; - while(pass && (i < spec_size)) - { - base_addr = entries[spec[i].entry_type]; - entry_ptr = &(base_addr[spec[i].entry_index]); + while ( pass && ( i < spec_size ) ) { - entry_ptr->size = entry_sizes[spec[i].entry_type]; + base_addr = entries[spec[i].entry_type]; + entry_ptr = &(base_addr[spec[i].entry_index]); + + entry_ptr->size = entry_sizes[spec[i].entry_type]; entry_ptr->deserialized = FALSE; entry_ptr->serialized = FALSE; @@ -9601,12 +9645,12 @@ check_flush_cache__flush_op_test(H5F_t * file_ptr, } i = 0; - while(pass && (i < check_size)) - { - base_addr = entries[check[i].entry_type]; - entry_ptr = &(base_addr[check[i].entry_index]); + while ( pass && ( i < check_size ) ) { - entry_ptr->size = entry_sizes[check[i].entry_type]; + base_addr = entries[check[i].entry_type]; + entry_ptr = &(base_addr[check[i].entry_index]); + + entry_ptr->size = entry_sizes[check[i].entry_type]; entry_ptr->deserialized = FALSE; entry_ptr->serialized = FALSE; @@ -9623,22 +9667,28 @@ check_flush_cache__flush_op_test(H5F_t * file_ptr, /*------------------------------------------------------------------------- * Function: check_flush_cache__flush_op_eviction_test() * - * Purpose: Verify that flush operations work as expected when an + * Purpose: Verify that flush operations work as expected when an * entry is evicted. * * Do nothing if pass is FALSE on entry. * - * Return: void + * Return: void * - * Programmer: John Mainzer + * Programmer: John Mainzer * 10/3/06 * * Modifications: * - * Updated test for minor changes in the behaviour - * of H5C__flush_single_entry(). + * Updated test for minor changes in the behaviour + * of H5C__flush_single_entry(). + * + * JRM -- 2/16/15 * - * JRM -- 2/16/15 + * Added code to setup and take down the skip list before + * and after calls to H5C_flush_cache(). Do this via the + * H5C_FLUSH_CACHE macro. + * + * JRM -- 5/16/20 * *------------------------------------------------------------------------- */ @@ -9651,7 +9701,6 @@ check_flush_cache__flush_op_eviction_test(H5F_t * file_ptr) int num_variable_entries = 10; int num_monster_entries = 31; int num_large_entries = 0; - herr_t result; test_entry_t * entry_ptr; test_entry_t * base_addr; struct expected_entry_status expected[10 + 31 + 14] = @@ -10840,15 +10889,12 @@ check_flush_cache__flush_op_eviction_test(H5F_t * file_ptr) if(pass) { - result = H5C_flush_cache(file_ptr, H5C__FLUSH_INVALIDATE_FLAG); + H5C_FLUSH_CACHE(file_ptr, H5C__FLUSH_INVALIDATE_FLAG, \ + "Cache flush invalidate failed after flush op eviction test") - if(result < 0) { - - pass = FALSE; - failure_mssg = "Cache flush invalidate failed after flush op eviction test"; - } - else if((cache_ptr->index_len != 0) || - (cache_ptr->index_size != 0)) { + if ( ( pass ) && + ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) ) ) { pass = FALSE; failure_mssg = "Unexpected cache len/size after cleanup of flush op eviction test"; @@ -12493,15 +12539,21 @@ check_flush_cache__single_entry(H5F_t * file_ptr) /*------------------------------------------------------------------------- * Function: check_flush_cache__single_entry_test() * - * Purpose: Run a single entry flush cache test. + * Purpose: Run a single entry flush cache test. * - * Return: void + * Return: void * - * Programmer: John Mainzer + * Programmer: John Mainzer * 1/12/05 * * Modifications: * + * Added code to setup and take down the skip list before + * and after calls to H5C_flush_cache(). Do this via the + * H5C_FLUSH_CACHE macro. + * + * JRM -- 5/14/20 + * *------------------------------------------------------------------------- */ @@ -12519,7 +12571,6 @@ check_flush_cache__single_entry_test(H5F_t * file_ptr, { H5C_t * cache_ptr = file_ptr->shared->cache; static char msg[128]; - herr_t result; test_entry_t * base_addr; test_entry_t * entry_ptr = NULL; @@ -12531,8 +12582,8 @@ check_flush_cache__single_entry_test(H5F_t * file_ptr, test_num); failure_mssg = msg; } - else if((cache_ptr->index_len != 0) || - (cache_ptr->index_size != 0)) { + else if ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, @@ -12540,8 +12591,10 @@ check_flush_cache__single_entry_test(H5F_t * file_ptr, test_num); failure_mssg = msg; } - else if((entry_type < 0) || (entry_type >= NUMBER_OF_ENTRY_TYPES) || - (entry_idx < 0) || (entry_idx > max_indices[entry_type])) { + else if ( ( entry_type < 0 ) || + ( entry_type >= NUMBER_OF_ENTRY_TYPES ) || + ( entry_idx < 0 ) || + ( entry_idx > max_indices[entry_type] ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, @@ -12569,19 +12622,20 @@ check_flush_cache__single_entry_test(H5F_t * file_ptr, if(pass) { - result = H5C_flush_cache(file_ptr, flush_flags); + H5C_FLUSH_CACHE(file_ptr, flush_flags, "dummy failure mssg.") - if(result < 0) { + if ( ! pass ) { /* construct and set actual failure message */ - pass = FALSE; HDsnprintf(msg, (size_t)128, "flush with flags 0x%x failed in single entry test #%d.", flush_flags, test_num); + failure_mssg = msg; } - else if((entry_ptr->deserialized != expected_deserialized) || - (entry_ptr->serialized != expected_serialized) || - (entry_ptr->destroyed != expected_destroyed)) { + else if ( ( entry_ptr->deserialized != expected_deserialized ) || + ( entry_ptr->serialized != expected_serialized ) || + ( entry_ptr->destroyed != expected_destroyed ) ) { + #if 0 /* This is useful debugging code -- lets keep it for a while */ HDfprintf(stdout, @@ -12599,22 +12653,22 @@ check_flush_cache__single_entry_test(H5F_t * file_ptr, test_num); failure_mssg = msg; } - else if((((flush_flags & H5C__FLUSH_INVALIDATE_FLAG) == 0) + else if ( ( ( (flush_flags & H5C__FLUSH_INVALIDATE_FLAG) == 0) && - ((cache_ptr->index_len != 1) + ( ( cache_ptr->index_len != 1 ) || - (cache_ptr->index_size != entry_sizes[entry_type]) - ) - ) + ( cache_ptr->index_size != entry_sizes[entry_type] ) + ) + ) || - (((flush_flags & H5C__FLUSH_INVALIDATE_FLAG) != 0) + ( ( (flush_flags & H5C__FLUSH_INVALIDATE_FLAG) != 0) && - ((cache_ptr->index_len != 0) + ( ( cache_ptr->index_len != 0 ) || - (cache_ptr->index_size != 0) - ) - ) - ) { + ( cache_ptr->index_size != 0 ) + ) + ) + ) { pass = FALSE; HDsnprintf(msg, (size_t)128, @@ -12628,18 +12682,18 @@ check_flush_cache__single_entry_test(H5F_t * file_ptr, /* clean up the cache to prep for the next test */ if(pass) { - result = H5C_flush_cache(file_ptr, H5C__FLUSH_INVALIDATE_FLAG); + H5C_FLUSH_CACHE(file_ptr, H5C__FLUSH_INVALIDATE_FLAG, \ + "dummy failure mssg.") - if(result < 0) { + if ( ! pass ) { /* construct and set actual failure message */ - pass = FALSE; HDsnprintf(msg, (size_t)128, "Flush failed on cleanup in single entry test #%d.", test_num); failure_mssg = msg; } - else if((cache_ptr->index_len != 0) || - (cache_ptr->index_size != 0)) { + else if ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, @@ -12663,22 +12717,27 @@ check_flush_cache__single_entry_test(H5F_t * file_ptr, /*------------------------------------------------------------------------- * Function: check_flush_cache__pinned_single_entry_test() * - * Purpose: Run a pinned single entry flush cache test. + * Purpose: Run a pinned single entry flush cache test. * - * Return: void + * Return: void * - * Programmer: John Mainzer + * Programmer: John Mainzer * 3/28/06 * * Modifications: * - * JRM -- 5/17/06 - * Added the pop_mark_dirty_prot and pop_mark_dirty_pinned - * flags and supporting code to allow us to test the - * H5C_mark_entry_dirty() call. Use the - * call to mark the entry dirty while the entry is protected - * if pop_mark_dirty_prot is TRUE, and to mark the entry - * dirty while it is pinned if pop_mark_dirty_pinned is TRUE. + * JRM -- 5/17/06 + * Added the pop_mark_dirty_prot and pop_mark_dirty_pinned + * flags and supporting code to allow us to test the + * H5C_mark_entry_dirty() call. Use the + * call to mark the entry dirty while the entry is protected + * if pop_mark_dirty_prot is TRUE, and to mark the entry + * dirty while it is pinned if pop_mark_dirty_pinned is TRUE. + * + * JRM -- 5/14/20 + * Added code to setup and take down the skip list before + * and after calls to H5C_flush_cache(). Do this via the + * H5C_FLUSH_CACHE macro. * *------------------------------------------------------------------------- */ @@ -12689,10 +12748,10 @@ check_flush_cache__pinned_single_entry_test(H5F_t * file_ptr, int entry_type, int entry_idx, hbool_t unprot_dirty_flag, - hbool_t mark_dirty, - hbool_t pop_mark_dirty_prot, - hbool_t pop_mark_dirty_pinned, - hbool_t unprotect_unpin, + hbool_t mark_dirty, + hbool_t pop_mark_dirty_prot, + hbool_t pop_mark_dirty_pinned, + hbool_t unprotect_unpin, unsigned int flags, unsigned int flush_flags, hbool_t expected_serialized, @@ -12701,7 +12760,6 @@ check_flush_cache__pinned_single_entry_test(H5F_t * file_ptr, H5C_t * cache_ptr = file_ptr->shared->cache; static char msg[128]; hbool_t expected_deserialized = TRUE; - herr_t result; test_entry_t * base_addr; test_entry_t * entry_ptr = NULL; @@ -12713,8 +12771,8 @@ check_flush_cache__pinned_single_entry_test(H5F_t * file_ptr, test_num); failure_mssg = msg; } - else if((cache_ptr->index_len != 0) || - (cache_ptr->index_size != 0)) { + else if ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, @@ -12722,7 +12780,7 @@ check_flush_cache__pinned_single_entry_test(H5F_t * file_ptr, test_num); failure_mssg = msg; } - else if((entry_type < 0) || (entry_type >= NUMBER_OF_ENTRY_TYPES) || + else if ( (entry_type < 0) || (entry_type >= NUMBER_OF_ENTRY_TYPES) || (entry_idx < 0) || (entry_idx > max_indices[entry_type])) { pass = FALSE; @@ -12739,41 +12797,41 @@ check_flush_cache__pinned_single_entry_test(H5F_t * file_ptr, protect_entry(file_ptr, entry_type, entry_idx); - if(pop_mark_dirty_prot) { + if(pop_mark_dirty_prot) { - mark_entry_dirty(entry_type, entry_idx); - } + mark_entry_dirty(entry_type, entry_idx); + } unprotect_entry(file_ptr, entry_type, entry_idx, (unprot_dirty_flag ? H5C__DIRTIED_FLAG : H5C__NO_FLAGS_SET) | (flags | H5C__PIN_ENTRY_FLAG)); - if(mark_dirty) { + if(mark_dirty) { mark_entry_dirty(entry_type, entry_idx); - } + } - if(pop_mark_dirty_pinned) { + if(pop_mark_dirty_pinned) { - mark_entry_dirty(entry_type, entry_idx); - } + mark_entry_dirty(entry_type, entry_idx); + } } if(pass) { - result = H5C_flush_cache(file_ptr, flush_flags); + H5C_FLUSH_CACHE(file_ptr, flush_flags, "dummy failure message\n") - if(result < 0) { + if ( ! pass ) { /* construct and set the correct failure message */ - pass = FALSE; HDsnprintf(msg, (size_t)128, "flush with flags 0x%x failed in pinned single entry test #%d.", - flush_flags, test_num); + flush_flags, test_num); failure_mssg = msg; } - else if((entry_ptr->deserialized != expected_deserialized) || - (entry_ptr->serialized != expected_serialized) || - (entry_ptr->destroyed != expected_destroyed)) { + else if ( ( entry_ptr->deserialized != expected_deserialized ) || + ( entry_ptr->serialized != expected_serialized ) || + ( entry_ptr->destroyed != expected_destroyed ) ) { + #if 0 /* this is useful debugging code -- keep it around */ HDfprintf(stdout, "desrlzd = %d(%d), srlzd = %d(%d), dest = %d(%d)\n", @@ -12790,22 +12848,22 @@ check_flush_cache__pinned_single_entry_test(H5F_t * file_ptr, test_num); failure_mssg = msg; } - else if((((flush_flags & H5C__FLUSH_INVALIDATE_FLAG) == 0) + else if ( ( ( ( flush_flags & H5C__FLUSH_INVALIDATE_FLAG) == 0 ) && - ((cache_ptr->index_len != 1) + ( ( cache_ptr->index_len != 1 ) || - (cache_ptr->index_size != entry_sizes[entry_type]) - ) - ) + ( cache_ptr->index_size != entry_sizes[entry_type] ) + ) + ) || - (((flush_flags & H5C__FLUSH_INVALIDATE_FLAG) != 0) + ( ( ( flush_flags & H5C__FLUSH_INVALIDATE_FLAG) != 0 ) && - ((cache_ptr->index_len != 0) + ( ( cache_ptr->index_len != 0 ) || - (cache_ptr->index_size != 0) - ) - ) - ) { + ( cache_ptr->index_size != 0 ) + ) + ) + ) { pass = FALSE; HDsnprintf(msg, (size_t)128, @@ -12836,18 +12894,17 @@ check_flush_cache__pinned_single_entry_test(H5F_t * file_ptr, if(pass) { - result = H5C_flush_cache(file_ptr, H5C__FLUSH_INVALIDATE_FLAG); + H5C_FLUSH_CACHE(file_ptr, H5C__FLUSH_INVALIDATE_FLAG, "dummy mssg\n") - if(result < 0) { + if ( ! pass ) { - pass = FALSE; HDsnprintf(msg, (size_t)128, "Flush failed on cleanup in pinned single entry test #%d.", test_num); failure_mssg = msg; } - else if((cache_ptr->index_len != 0) || - (cache_ptr->index_size != 0)) { + else if ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, @@ -14233,14 +14290,20 @@ check_pin_protected_entry(unsigned paged) /*------------------------------------------------------------------------- * Function: check_resize_entry() * - * Purpose: Verify that H5C_resize_entry() and H5C_unprotect() resize - * entries as expected. - * - * Return: void + * Purpose: Verify that H5C_resize_entry() and H5C_unprotect() resize + * entries as expected. + * + * Return: void * - * Programmer: John Mainzer + * Programmer: John Mainzer * 7/7/06 * + * Modifications: + * + * Updated function to allow for disabling of the slist. + * + * JRM -- 5/18/20 + * *------------------------------------------------------------------------- */ @@ -14421,16 +14484,16 @@ check_resize_entry(unsigned paged) if(pass) { - if((cache_ptr->index_len != 1) || - (cache_ptr->index_size != (LARGE_ENTRY_SIZE / 2)) || - (cache_ptr->slist_len != 1) || - (cache_ptr->slist_size != (LARGE_ENTRY_SIZE / 2))) { + if ( ( cache_ptr->index_len != 1 ) || + ( cache_ptr->index_size != (LARGE_ENTRY_SIZE / 2) ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 1 ) || + ( cache_ptr->slist_size != (LARGE_ENTRY_SIZE / 2) ) ) ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 3."); failure_mssg = msg; - - } + } } if(pass) { @@ -14506,16 +14569,16 @@ check_resize_entry(unsigned paged) if(pass) { - if((cache_ptr->index_len != 1) || - (cache_ptr->index_size != LARGE_ENTRY_SIZE) || - (cache_ptr->slist_len != 1) || - (cache_ptr->slist_size != LARGE_ENTRY_SIZE)) { + if ( ( cache_ptr->index_len != 1 ) || + ( cache_ptr->index_size != LARGE_ENTRY_SIZE ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 1 ) || + ( cache_ptr->slist_size != LARGE_ENTRY_SIZE ) ) ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 4."); failure_mssg = msg; - - } + } } if(pass) { @@ -14574,16 +14637,17 @@ check_resize_entry(unsigned paged) if(pass) { - if((cache_ptr->index_len != 1) || - (cache_ptr->index_size != (LARGE_ENTRY_SIZE / 4)) || - (cache_ptr->slist_len != 1) || - (cache_ptr->slist_size != (LARGE_ENTRY_SIZE / 4))) { + if ( ( cache_ptr->index_len != 1 ) || + ( cache_ptr->index_size != (LARGE_ENTRY_SIZE / 4) ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 1 ) || + ( cache_ptr->slist_size != (LARGE_ENTRY_SIZE / 4) ) ) ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 5."); failure_mssg = msg; - } + } } if(pass) { @@ -14634,16 +14698,17 @@ check_resize_entry(unsigned paged) if(pass) { - if((cache_ptr->index_len != 1) || - (cache_ptr->index_size != LARGE_ENTRY_SIZE) || - (cache_ptr->slist_len != 1) || - (cache_ptr->slist_size != LARGE_ENTRY_SIZE)) { + if ( ( cache_ptr->index_len != 1 ) || + ( cache_ptr->index_size != LARGE_ENTRY_SIZE ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 1 ) || + ( cache_ptr->slist_size != LARGE_ENTRY_SIZE) ) ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 6."); failure_mssg = msg; - } + } } if(pass) { @@ -14719,16 +14784,16 @@ check_resize_entry(unsigned paged) if(pass) { - if((cache_ptr->index_len != 0) || - (cache_ptr->index_size != 0) || - (cache_ptr->slist_len != 0) || - (cache_ptr->slist_size != 0)) { + if ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 0 ) || + ( cache_ptr->slist_size != 0) ) ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 7."); failure_mssg = msg; - - } + } } @@ -14736,19 +14801,20 @@ check_resize_entry(unsigned paged) if(pass) { - if((cache_ptr->index_len != 0) || - (cache_ptr->index_size != 0) || - (cache_ptr->slist_len != 0) || - (cache_ptr->slist_size != 0)) { + if ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 0 ) || + ( cache_ptr->slist_size != 0) ) ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 8."); failure_mssg = msg; + } - } base_addr = entries[LARGE_ENTRY_TYPE]; entry_ptr = &(base_addr[3]); - entry_size = LARGE_ENTRY_SIZE; + entry_size = LARGE_ENTRY_SIZE; } if(pass) { @@ -14766,17 +14832,17 @@ check_resize_entry(unsigned paged) if(pass) { - if((cache_ptr->index_len != 3) || - (cache_ptr->index_size != 3 * LARGE_ENTRY_SIZE) || - (cache_ptr->slist_len != 1) || - (cache_ptr->slist_size != LARGE_ENTRY_SIZE)) { - + if ( ( cache_ptr->index_len != 3 ) || + ( cache_ptr->index_size != 3 * LARGE_ENTRY_SIZE ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 1 ) || + ( cache_ptr->slist_size != LARGE_ENTRY_SIZE) ) ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 9."); failure_mssg = msg; - } + } } if(pass) { @@ -14787,10 +14853,11 @@ check_resize_entry(unsigned paged) if(pass) { - if((cache_ptr->index_len != 4) || - (cache_ptr->index_size != 4 * LARGE_ENTRY_SIZE) || - (cache_ptr->slist_len != 1) || - (cache_ptr->slist_size != LARGE_ENTRY_SIZE)) { + if ( ( cache_ptr->index_len != 4 ) || + ( cache_ptr->index_size != 4 * LARGE_ENTRY_SIZE ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 1) || + ( cache_ptr->slist_size != LARGE_ENTRY_SIZE) ) ) ) { pass = FALSE; @@ -14866,18 +14933,18 @@ check_resize_entry(unsigned paged) if(pass) { - if((cache_ptr->index_len != 4) || - (cache_ptr->index_size != - ((3 * LARGE_ENTRY_SIZE) + (LARGE_ENTRY_SIZE / 2))) || - (cache_ptr->slist_len != 2) || - (cache_ptr->slist_size != - (LARGE_ENTRY_SIZE + (LARGE_ENTRY_SIZE / 2)))) { + if ( ( cache_ptr->index_len != 4 ) || + ( cache_ptr->index_size != + ((3 * LARGE_ENTRY_SIZE) + (LARGE_ENTRY_SIZE / 2)) ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 2 ) || + ( cache_ptr->slist_size != + (LARGE_ENTRY_SIZE + (LARGE_ENTRY_SIZE / 2)) ) ) ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 11."); failure_mssg = msg; - - } + } } if(pass) { @@ -14953,16 +15020,16 @@ check_resize_entry(unsigned paged) if(pass) { - if((cache_ptr->index_len != 4) || - (cache_ptr->index_size != 4 * LARGE_ENTRY_SIZE) || - (cache_ptr->slist_len != 2) || - (cache_ptr->slist_size != 2 * LARGE_ENTRY_SIZE)) { + if ( ( cache_ptr->index_len != 4 ) || + ( cache_ptr->index_size != 4 * LARGE_ENTRY_SIZE ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 2 ) || + ( cache_ptr->slist_size != 2 * LARGE_ENTRY_SIZE ) ) ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 12."); failure_mssg = msg; - - } + } } if(pass) { @@ -15021,18 +15088,18 @@ check_resize_entry(unsigned paged) if(pass) { - if((cache_ptr->index_len != 4) || - (cache_ptr->index_size != - ((3 * LARGE_ENTRY_SIZE) + (LARGE_ENTRY_SIZE / 4))) || - (cache_ptr->slist_len != 2) || - (cache_ptr->slist_size != - (LARGE_ENTRY_SIZE + (LARGE_ENTRY_SIZE / 4)))) { + if ( ( cache_ptr->index_len != 4 ) || + ( cache_ptr->index_size != + ((3 * LARGE_ENTRY_SIZE) + (LARGE_ENTRY_SIZE / 4)) ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 2 ) || + ( cache_ptr->slist_size != + (LARGE_ENTRY_SIZE + (LARGE_ENTRY_SIZE / 4)) ) ) ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 13."); failure_mssg = msg; - - } + } } if(pass) { @@ -15083,16 +15150,16 @@ check_resize_entry(unsigned paged) if(pass) { - if((cache_ptr->index_len != 4) || - (cache_ptr->index_size != (4 * LARGE_ENTRY_SIZE)) || - (cache_ptr->slist_len != 2) || - (cache_ptr->slist_size != (2 * LARGE_ENTRY_SIZE))) { + if ( ( cache_ptr->index_len != 4 ) || + ( cache_ptr->index_size != (4 * LARGE_ENTRY_SIZE) ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 2 ) || + ( cache_ptr->slist_size != (2 * LARGE_ENTRY_SIZE)) ) ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 14."); failure_mssg = msg; - - } + } } if(pass) { @@ -15168,16 +15235,16 @@ check_resize_entry(unsigned paged) if(pass) { - if((cache_ptr->index_len != 3) || - (cache_ptr->index_size != (3 * LARGE_ENTRY_SIZE)) || - (cache_ptr->slist_len != 1) || - (cache_ptr->slist_size != LARGE_ENTRY_SIZE)) { + if ( ( cache_ptr->index_len != 3 ) || + ( cache_ptr->index_size != (3 * LARGE_ENTRY_SIZE) ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 1 ) || + ( cache_ptr->slist_size != LARGE_ENTRY_SIZE) ) ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 15."); failure_mssg = msg; - - } + } } if(pass) { @@ -15195,16 +15262,16 @@ check_resize_entry(unsigned paged) if(pass) { - if((cache_ptr->index_len != 0) || - (cache_ptr->index_size != 0) || - (cache_ptr->slist_len != 0) || - (cache_ptr->slist_size != 0)) { + if ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 0 ) || + ( cache_ptr->slist_size != 0 ) ) ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 16."); failure_mssg = msg; - - } + } } if(pass) { @@ -15228,16 +15295,19 @@ check_resize_entry(unsigned paged) /*------------------------------------------------------------------------- * Function: check_evictions_enabled() * - * Purpose: Verify that H5C_get_evictions_enabled() and - * H5C_set_evictions_enabled() functions perform as expected. + * Purpose: Verify that H5C_get_evictions_enabled() and + * H5C_set_evictions_enabled() functions perform as expected. * - * Return: void + * Return: void * - * Programmer: John Mainzer + * Programmer: John Mainzer * 8/2/07 * * Modifications: * + * Updated function to allow for disabling of the slist. + * + * JRM -- 5/18/20 * *------------------------------------------------------------------------- */ @@ -15331,17 +15401,17 @@ check_evictions_enabled(unsigned paged) /* verify that it is empty */ if(pass) { - if((cache_ptr->index_len != 0) || - (cache_ptr->index_size != 0) || - (cache_ptr->slist_len != 0) || - (cache_ptr->slist_size != 0) || - (cache_ptr->evictions_enabled != TRUE)) { + if ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 0 ) || + ( cache_ptr->slist_size != 0 ) ) ) || + ( cache_ptr->evictions_enabled != TRUE ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 1."); failure_mssg = msg; - - } + } } if(show_progress) /* 3 */ @@ -15383,18 +15453,17 @@ check_evictions_enabled(unsigned paged) /* verify that the cache is full */ if(pass) { - if((cache_ptr->index_len != 16) || - (cache_ptr->index_size != 16 * MONSTER_ENTRY_SIZE) || - (cache_ptr->slist_len != 0) || - (cache_ptr->slist_size != 0) || - (cache_ptr->evictions_enabled != TRUE)) { - + if ( ( cache_ptr->index_len != 16 ) || + ( cache_ptr->index_size != 16 * MONSTER_ENTRY_SIZE ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 0 ) || + ( cache_ptr->slist_size != 0 ) ) ) || + ( cache_ptr->evictions_enabled != TRUE ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 2."); failure_mssg = msg; - - } + } } if(show_progress) /* 6 */ @@ -15416,17 +15485,17 @@ check_evictions_enabled(unsigned paged) /* verify that an entry has been evicted */ if(pass) { - if((cache_ptr->index_len != 16) || - (cache_ptr->index_size != 16 * MONSTER_ENTRY_SIZE) || - (cache_ptr->slist_len != 0) || - (cache_ptr->slist_size != 0) || - (cache_ptr->evictions_enabled != TRUE)) { + if ( ( cache_ptr->index_len != 16 ) || + ( cache_ptr->index_size != 16 * MONSTER_ENTRY_SIZE ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 0 ) || + ( cache_ptr->slist_size != 0 ) ) ) || + ( cache_ptr->evictions_enabled != TRUE ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 3."); failure_mssg = msg; - - } + } } if(show_progress) /* 8 */ @@ -15483,17 +15552,17 @@ check_evictions_enabled(unsigned paged) /* verify that another entry has been evicted */ if(pass) { - if((cache_ptr->index_len != 16) || - (cache_ptr->index_size != 16 * MONSTER_ENTRY_SIZE) || - (cache_ptr->slist_len != 1) || - (cache_ptr->slist_size != MONSTER_ENTRY_SIZE) || - (cache_ptr->evictions_enabled != TRUE)) { + if ( ( cache_ptr->index_len != 16 ) || + ( cache_ptr->index_size != 16 * MONSTER_ENTRY_SIZE ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 1 ) || + ( cache_ptr->slist_size != MONSTER_ENTRY_SIZE ) ) ) || + ( cache_ptr->evictions_enabled != TRUE ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 4."); failure_mssg = msg; - - } + } } if(show_progress) /* 11 */ @@ -15555,17 +15624,17 @@ check_evictions_enabled(unsigned paged) /* verify that evictions are disabled */ if(pass) { - if((cache_ptr->index_len != 16) || - (cache_ptr->index_size != 16 * MONSTER_ENTRY_SIZE) || - (cache_ptr->slist_len != 1) || - (cache_ptr->slist_size != MONSTER_ENTRY_SIZE) || - (cache_ptr->evictions_enabled != FALSE)) { + if ( ( cache_ptr->index_len != 16 ) || + ( cache_ptr->index_size != 16 * MONSTER_ENTRY_SIZE ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 1 ) || + ( cache_ptr->slist_size != MONSTER_ENTRY_SIZE ) ) ) || + ( cache_ptr->evictions_enabled != FALSE ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 5."); failure_mssg = msg; - - } + } } if(show_progress) /* 14 */ @@ -15587,17 +15656,17 @@ check_evictions_enabled(unsigned paged) /* verify that no entry has been evicted */ if(pass) { - if((cache_ptr->index_len != 17) || - (cache_ptr->index_size != 17 * MONSTER_ENTRY_SIZE) || - (cache_ptr->slist_len != 1) || - (cache_ptr->slist_size != MONSTER_ENTRY_SIZE) || - (cache_ptr->evictions_enabled != FALSE)) { + if ( ( cache_ptr->index_len != 17 ) || + ( cache_ptr->index_size != 17 * MONSTER_ENTRY_SIZE ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 1 ) || + ( cache_ptr->slist_size != MONSTER_ENTRY_SIZE ) ) ) || + ( cache_ptr->evictions_enabled != FALSE ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 6."); failure_mssg = msg; - - } + } } if(show_progress) /* 16 */ @@ -15618,17 +15687,17 @@ check_evictions_enabled(unsigned paged) /* verify that no entry has been evicted */ if(pass) { - if((cache_ptr->index_len != 18) || - (cache_ptr->index_size != 18 * MONSTER_ENTRY_SIZE) || - (cache_ptr->slist_len != 2) || - (cache_ptr->slist_size != 2 * MONSTER_ENTRY_SIZE) || - (cache_ptr->evictions_enabled != FALSE)) { + if ( ( cache_ptr->index_len != 18 ) || + ( cache_ptr->index_size != 18 * MONSTER_ENTRY_SIZE ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 2 ) || + ( cache_ptr->slist_size != 2 * MONSTER_ENTRY_SIZE ) ) ) || + ( cache_ptr->evictions_enabled != FALSE ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 7."); failure_mssg = msg; - - } + } } if(show_progress) /* 18 */ @@ -15667,17 +15736,17 @@ check_evictions_enabled(unsigned paged) /* verify that no entries have been evicted */ if(pass) { - if((cache_ptr->index_len != 18) || - (cache_ptr->index_size != 18 * MONSTER_ENTRY_SIZE) || - (cache_ptr->slist_len != 2) || - (cache_ptr->slist_size != 2 * MONSTER_ENTRY_SIZE) || - (cache_ptr->evictions_enabled != TRUE)) { + if ( ( cache_ptr->index_len != 18 ) || + ( cache_ptr->index_size != 18 * MONSTER_ENTRY_SIZE ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 2 ) || + ( cache_ptr->slist_size != 2 * MONSTER_ENTRY_SIZE ) ) ) || + ( cache_ptr->evictions_enabled != TRUE ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 8."); failure_mssg = msg; - - } + } } if(show_progress) /* 21 */ @@ -15702,17 +15771,17 @@ check_evictions_enabled(unsigned paged) if(pass) { - if((cache_ptr->index_len != 16) || - (cache_ptr->index_size != 16 * MONSTER_ENTRY_SIZE) || - (cache_ptr->slist_len != 2) || - (cache_ptr->slist_size != 2 * MONSTER_ENTRY_SIZE) || - (cache_ptr->evictions_enabled != TRUE)) { + if ( ( cache_ptr->index_len != 16 ) || + ( cache_ptr->index_size != 16 * MONSTER_ENTRY_SIZE ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 2 ) || + ( cache_ptr->slist_size != 2 * MONSTER_ENTRY_SIZE ) ) ) || + ( cache_ptr->evictions_enabled != TRUE ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 9."); failure_mssg = msg; - - } + } } if(show_progress) /* 23 */ @@ -15823,17 +15892,17 @@ check_evictions_enabled(unsigned paged) /* verify that the cache has grown */ if(pass) { - if((cache_ptr->index_len != 17) || - (cache_ptr->index_size != 17 * MONSTER_ENTRY_SIZE) || - (cache_ptr->slist_len != 2) || - (cache_ptr->slist_size != 2 * MONSTER_ENTRY_SIZE) || - (cache_ptr->evictions_enabled != FALSE)) { + if ( ( cache_ptr->index_len != 17 ) || + ( cache_ptr->index_size != 17 * MONSTER_ENTRY_SIZE ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 2 ) || + ( cache_ptr->slist_size != 2 * MONSTER_ENTRY_SIZE ) ) ) || + ( cache_ptr->evictions_enabled != FALSE ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 10."); failure_mssg = msg; - - } + } } if(show_progress) /* 28 */ @@ -15871,17 +15940,17 @@ check_evictions_enabled(unsigned paged) /* verify that the cache has returned to its maximum size */ if(pass) { - if((cache_ptr->index_len != 16) || - (cache_ptr->index_size != 16 * MONSTER_ENTRY_SIZE) || - (cache_ptr->slist_len != 3) || - (cache_ptr->slist_size != 3 * MONSTER_ENTRY_SIZE) || - (cache_ptr->evictions_enabled != TRUE)) { + if ( ( cache_ptr->index_len != 16 ) || + ( cache_ptr->index_size != 16 * MONSTER_ENTRY_SIZE ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->slist_len != 3 ) || + ( cache_ptr->slist_size != 3 * MONSTER_ENTRY_SIZE ) ) ) || + ( cache_ptr->evictions_enabled != TRUE ) ) { pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected cache status 11."); failure_mssg = msg; - - } + } } if(show_progress) /* 31 */ @@ -15964,17 +16033,22 @@ check_evictions_enabled(unsigned paged) /*------------------------------------------------------------------------- * Function: check_flush_protected_err() + * + * Purpose: Verify that an attempt to flush the cache when it contains + * a protected entry will generate an error. * - * Purpose: Verify that an attempt to flush the cache when it contains - * a protected entry will generate an error. - * - * Return: void + * Return: void * - * Programmer: John Mainzer + * Programmer: John Mainzer * 6/24/04 * * Modifications: * + * Added code to setup and take down the skip list before + * and after calls to H5C_flush_cache(). + * + * JRM -- 5/14/20 + * *------------------------------------------------------------------------- */ @@ -15982,6 +16056,7 @@ static unsigned check_flush_protected_err(unsigned paged) { H5F_t * file_ptr = NULL; + H5C_t * cache_ptr = NULL; if(paged) TESTING("flush cache with protected entry error (paged aggregation)") @@ -16001,27 +16076,45 @@ check_flush_protected_err(unsigned paged) file_ptr = setup_cache((size_t)(2 * 1024), (size_t)(1 * 1024), paged); + if ( pass ) { + + cache_ptr = file_ptr->shared->cache; + } + protect_entry(file_ptr, 0, 0); - if(H5C_flush_cache(file_ptr, H5C__NO_FLAGS_SET) >= 0) { + /* enable slist prior to flush */ + if ( ( pass ) && + ( H5C_set_slist_enabled(cache_ptr, TRUE, FALSE) < 0 ) ) { pass = FALSE; - failure_mssg = "flush succeeded on cache with protected entry.\n"; + failure_mssg = "unable to enable slist prior to flush.\n"; + } - } else { + if ( ( pass ) && + ( H5C_flush_cache(file_ptr, H5C__NO_FLAGS_SET) >= 0 ) ) { - unprotect_entry(file_ptr, 0, 0, H5C__DIRTIED_FLAG); + pass = FALSE; + failure_mssg = "flush succeeded on cache with protected entry.\n"; + } - if(H5C_flush_cache(file_ptr, H5C__NO_FLAGS_SET) < 0) { + /* disable the slist after the flush */ + if ( ( pass ) && + ( H5C_set_slist_enabled(cache_ptr, FALSE, FALSE) < 0 ) ) { - pass = FALSE; - failure_mssg = "flush failed after unprotect.\n"; + pass = FALSE; + failure_mssg = "unable to disable slist after flush.\n"; + } - } else { + unprotect_entry(file_ptr, 0, 0, H5C__DIRTIED_FLAG); - takedown_cache(file_ptr, FALSE, FALSE); - } + if ( pass ) { + + H5C_FLUSH_CACHE(file_ptr, H5C__NO_FLAGS_SET, \ + "flush failed after unprotect.\n") } + + takedown_cache(file_ptr, FALSE, FALSE); } if(pass) { PASSED(); } else { H5_FAILED(); } @@ -17075,12 +17168,12 @@ check_move_entry_errs(unsigned paged) /*------------------------------------------------------------------------- * Function: check_resize_entry_errs() * - * Purpose: Verify that invalid calls to H5C_resize_entry() - * generates errors as expected. + * Purpose: Verify that invalid calls to H5C_resize_entry() + * generates errors as expected. * - * Return: void + * Return: void * - * Programmer: John Mainzer + * Programmer: John Mainzer * 7/7/06 * *------------------------------------------------------------------------- @@ -17135,9 +17228,9 @@ check_resize_entry_errs(unsigned paged) } else { - unprotect_entry(file_ptr, 0, 0, H5C__PIN_ENTRY_FLAG); + unprotect_entry(file_ptr, 0, 0, H5C__PIN_ENTRY_FLAG); - } + } } if(pass) { @@ -17152,9 +17245,9 @@ check_resize_entry_errs(unsigned paged) } else { - unpin_entry(0, 0); + unpin_entry(0, 0); - } + } } if(pass) { @@ -30952,13 +31045,21 @@ done: /*------------------------------------------------------------------------- * Function: check_flush_deps_order() * - * Purpose: Verify that the order that entries with flush dependencies + * Purpose: Verify that the order that entries with flush dependencies * is correct * - * Return: 0 on success, non-zero on failure + * Return: 0 on success, non-zero on failure + * + * Programmer: Quincey Koziol + * 3/17/09 * - * Programmer: Quincey Koziol - * 3/17/09 + * Modifications: + * + * Added code to setup and take down the skip list before + * and after calls to H5C_flush_cache(). Do this via the + * H5C_FLUSH_CACHE macro. + * + * JRM -- 5/14/20 * *------------------------------------------------------------------------- */ @@ -31049,8 +31150,6 @@ check_flush_deps_order(unsigned paged) /* Flush the cache and verify that the entries were flushed in correct order */ { - herr_t result; /* Generic return value */ - add_flush_op(entry_type, 0, FLUSH_OP__ORDER, entry_type, 0, FALSE, (size_t)0, &flush_order); add_flush_op(entry_type, 1, FLUSH_OP__ORDER, @@ -31065,8 +31164,8 @@ check_flush_deps_order(unsigned paged) /* Reset index for tracking flush order */ flush_order = 0; - result = H5C_flush_cache(file_ptr, H5C__NO_FLAGS_SET); - if(result < 0) CACHE_ERROR("flushing entries with flush dependendices") + H5C_FLUSH_CACHE(file_ptr, H5C__NO_FLAGS_SET, "dummy mssg") + if(!pass) CACHE_ERROR("flushing entries with flush dependendices") /* Change expected values, and verify the status of the entries * after destroy flush dependency @@ -31144,8 +31243,6 @@ check_flush_deps_order(unsigned paged) /* Flush the cache and verify that the entries were flushed in correct order */ { - herr_t result; /* Generic return value */ - add_flush_op(entry_type, 0, FLUSH_OP__ORDER, entry_type, 0, FALSE, (size_t)0, &flush_order); add_flush_op(entry_type, 1, FLUSH_OP__ORDER, @@ -31171,8 +31268,8 @@ check_flush_deps_order(unsigned paged) /* Reset index for tracking flush order */ flush_order = 0; - result = H5C_flush_cache(file_ptr, H5C__NO_FLAGS_SET); - if(result < 0) CACHE_ERROR("flushing entries with flush dependendices") + H5C_FLUSH_CACHE(file_ptr, H5C__NO_FLAGS_SET, "dummy mssg") + if(!pass) CACHE_ERROR("flushing entries with flush dependendices") /* Change expected values, and verify the status of the entries * after destroy flush dependency @@ -31251,8 +31348,6 @@ check_flush_deps_order(unsigned paged) /* Flush the cache and verify that the entries were flushed in correct order */ { - herr_t result; /* Generic return value */ - add_flush_op(entry_type, 0, FLUSH_OP__ORDER, entry_type, 0, FALSE, (size_t)0, &flush_order); add_flush_op(entry_type, 1, FLUSH_OP__ORDER, @@ -31283,8 +31378,8 @@ check_flush_deps_order(unsigned paged) /* Reset index for tracking flush order */ flush_order = 0; - result = H5C_flush_cache(file_ptr, H5C__NO_FLAGS_SET); - if(result < 0) CACHE_ERROR("flushing entries with flush dependendices") + H5C_FLUSH_CACHE(file_ptr, H5C__NO_FLAGS_SET, "dummy mssg") + if(!pass) CACHE_ERROR("flushing entries with flush dependendices") /* Change expected values, and verify the status of the entries * after destroy flush dependency @@ -31370,8 +31465,6 @@ check_flush_deps_order(unsigned paged) /* Flush the cache and verify that the entries were flushed in correct order */ { - herr_t result; /* Generic return value */ - add_flush_op(entry_type, 0, FLUSH_OP__ORDER, entry_type, 0, FALSE, (size_t)0, &flush_order); add_flush_op(entry_type, 1, FLUSH_OP__ORDER, @@ -31402,8 +31495,8 @@ check_flush_deps_order(unsigned paged) /* Reset index for tracking flush order */ flush_order = 0; - result = H5C_flush_cache(file_ptr, H5C__NO_FLAGS_SET); - if(result < 0) CACHE_ERROR("flushing entries with flush dependendices") + H5C_FLUSH_CACHE(file_ptr, H5C__NO_FLAGS_SET, "dummy mssg") + if(!pass) CACHE_ERROR("flushing entries with flush dependendices") /* Change expected values, and verify the status of the entries * after destroy flush dependency @@ -31529,8 +31622,6 @@ check_flush_deps_order(unsigned paged) /* Flush the cache and verify that the entries were flushed in correct order */ { - herr_t result; /* Generic return value */ - add_flush_op(entry_type, 0, FLUSH_OP__ORDER, entry_type, 0, FALSE, (size_t)0, &flush_order); add_flush_op(entry_type, 1, FLUSH_OP__ORDER, @@ -31578,8 +31669,8 @@ check_flush_deps_order(unsigned paged) /* Reset index for tracking flush order */ flush_order = 0; - result = H5C_flush_cache(file_ptr, H5C__NO_FLAGS_SET); - if(result < 0) CACHE_ERROR("flushing entries with flush dependendices") + H5C_FLUSH_CACHE(file_ptr, H5C__NO_FLAGS_SET, "dummy mssg") + if(!pass) CACHE_ERROR("flushing entries with flush dependendices") /* Change expected values, and verify the status of the entries * after destroy flush dependency @@ -31739,8 +31830,6 @@ check_flush_deps_order(unsigned paged) /* Flush the cache and verify that the entries were flushed in correct order */ { - herr_t result; /* Generic return value */ - add_flush_op(entry_type, 0, FLUSH_OP__ORDER, entry_type, 0, FALSE, (size_t)0, &flush_order); add_flush_op(entry_type, 1, FLUSH_OP__ORDER, @@ -31788,8 +31877,8 @@ check_flush_deps_order(unsigned paged) /* Reset index for tracking flush order */ flush_order = 0; - result = H5C_flush_cache(file_ptr, H5C__NO_FLAGS_SET); - if(result < 0) CACHE_ERROR("flushing entries with flush dependendices") + H5C_FLUSH_CACHE(file_ptr, H5C__NO_FLAGS_SET, "dummy mssg") + if(!pass) CACHE_ERROR("flushing entries with flush dependendices") /* Change expected values, and verify the status of the entries * after destroy flush dependency @@ -31904,8 +31993,6 @@ check_flush_deps_order(unsigned paged) /* Flush the cache and verify that the entries were flushed in correct order */ { - herr_t result; /* Generic return value */ - add_flush_op(entry_type, 0, FLUSH_OP__ORDER, entry_type, 0, FALSE, (size_t)0, &flush_order); add_flush_op(entry_type, 1, FLUSH_OP__ORDER, @@ -31946,8 +32033,8 @@ check_flush_deps_order(unsigned paged) /* Reset index for tracking flush order */ flush_order = 0; - result = H5C_flush_cache(file_ptr, H5C__NO_FLAGS_SET); - if(result < 0) CACHE_ERROR("flushing entries with flush dependendices") + H5C_FLUSH_CACHE(file_ptr, H5C__NO_FLAGS_SET, "dummy mssg") + if(!pass) CACHE_ERROR("flushing entries with flush dependendices") /* Change expected values, and verify the status of the entries * after destroy flush dependency @@ -32038,8 +32125,6 @@ check_flush_deps_order(unsigned paged) /* Flush the cache and verify that the entries were flushed in correct order */ { - herr_t result; /* Generic return value */ - add_flush_op(entry_type, 0, FLUSH_OP__ORDER, entry_type, 0, FALSE, (size_t)0, &flush_order); add_flush_op(entry_type, 1, FLUSH_OP__ORDER, @@ -32080,8 +32165,8 @@ check_flush_deps_order(unsigned paged) /* Reset index for tracking flush order */ flush_order = 0; - result = H5C_flush_cache(file_ptr, H5C__NO_FLAGS_SET); - if(result < 0) CACHE_ERROR("flushing entries with flush dependendices") + H5C_FLUSH_CACHE(file_ptr, H5C__NO_FLAGS_SET, "dummy mssg") + if(!pass) CACHE_ERROR("flushing entries with flush dependendices") /* Change expected values, and verify the status of the entries * after destroy flush dependency @@ -32221,8 +32306,6 @@ check_flush_deps_order(unsigned paged) /* Flush the cache and verify that the entries were flushed in correct order */ { - herr_t result; /* Generic return value */ - add_flush_op(entry_type, 0, FLUSH_OP__ORDER, entry_type, 0, FALSE, (size_t)0, &flush_order); add_flush_op(entry_type, 1, FLUSH_OP__ORDER, @@ -32273,8 +32356,8 @@ check_flush_deps_order(unsigned paged) /* Reset index for tracking flush order */ flush_order = 0; - result = H5C_flush_cache(file_ptr, H5C__NO_FLAGS_SET); - if(result < 0) CACHE_ERROR("flushing entries with flush dependendices") + H5C_FLUSH_CACHE(file_ptr, H5C__NO_FLAGS_SET, "dummy mssg") + if(!pass) CACHE_ERROR("flushing entries with flush dependendices") /* Change expected values, and verify the status of the entries * after destroy flush dependency @@ -32458,8 +32541,6 @@ check_flush_deps_order(unsigned paged) /* Flush the cache and verify that the entries were flushed in correct order */ { - herr_t result; /* Generic return value */ - add_flush_op(entry_type, 0, FLUSH_OP__ORDER, entry_type, 0, FALSE, (size_t)0, &flush_order); add_flush_op(entry_type, 1, FLUSH_OP__ORDER, @@ -32512,8 +32593,8 @@ check_flush_deps_order(unsigned paged) /* Reset index for tracking flush order */ flush_order = 0; - result = H5C_flush_cache(file_ptr, H5C__NO_FLAGS_SET); - if(result < 0) CACHE_ERROR("flushing entries with flush dependendices") + H5C_FLUSH_CACHE(file_ptr, H5C__NO_FLAGS_SET, "dummy mssg") + if(!pass) CACHE_ERROR("flushing entries with flush dependendices") /* Change expected values, and verify the status of the entries * after destroy flush dependency @@ -32715,8 +32796,6 @@ check_flush_deps_order(unsigned paged) /* Flush the cache and verify that the entries were flushed in correct order */ { - herr_t result; /* Generic return value */ - add_flush_op(entry_type, 0, FLUSH_OP__ORDER, entry_type, 0, FALSE, (size_t)0, &flush_order); add_flush_op(entry_type, 1, FLUSH_OP__ORDER, @@ -32769,8 +32848,8 @@ check_flush_deps_order(unsigned paged) /* Reset index for tracking flush order */ flush_order = 0; - result = H5C_flush_cache(file_ptr, H5C__NO_FLAGS_SET); - if(result < 0) CACHE_ERROR("flushing entries with flush dependendices") + H5C_FLUSH_CACHE(file_ptr, H5C__NO_FLAGS_SET, "dummy mssg") + if(!pass) CACHE_ERROR("flushing entries with flush dependendices") /* Change expected values, and verify the status of the entries * after destroy flush dependency @@ -33007,8 +33086,6 @@ check_flush_deps_order(unsigned paged) /* Flush the cache and verify that the entries were flushed in correct order */ { - herr_t result; /* Generic return value */ - add_flush_op(entry_type, 0, FLUSH_OP__ORDER, entry_type, 0, FALSE, (size_t)0, &flush_order); add_flush_op(entry_type, 1, FLUSH_OP__ORDER, @@ -33056,8 +33133,8 @@ check_flush_deps_order(unsigned paged) /* Reset index for tracking flush order */ flush_order = 0; - result = H5C_flush_cache(file_ptr, H5C__NO_FLAGS_SET); - if(result < 0) CACHE_ERROR("flushing entries with flush dependendices") + H5C_FLUSH_CACHE(file_ptr, H5C__NO_FLAGS_SET, "dummy mssg") + if(!pass) CACHE_ERROR("flushing entries with flush dependendices") /* Change expected values, and verify the status of the entries * after destroy flush dependency @@ -33323,8 +33400,6 @@ check_flush_deps_order(unsigned paged) /* Flush the cache and verify that the entries were flushed in correct order */ { - herr_t result; /* Generic return value */ - add_flush_op(entry_type, 0, FLUSH_OP__ORDER, entry_type, 0, FALSE, (size_t)0, &flush_order); add_flush_op(entry_type, 1, FLUSH_OP__ORDER, @@ -33372,8 +33447,8 @@ check_flush_deps_order(unsigned paged) /* Reset index for tracking flush order */ flush_order = 0; - result = H5C_flush_cache(file_ptr, H5C__NO_FLAGS_SET); - if(result < 0) CACHE_ERROR("flushing entries with flush dependendices") + H5C_FLUSH_CACHE(file_ptr, H5C__NO_FLAGS_SET, "dummy mssg") + if(!pass) CACHE_ERROR("flushing entries with flush dependendices") /* Change expected values, and verify the status of the entries * after destroy flush dependency @@ -34551,30 +34626,35 @@ check_entry_deletions_during_scans(unsigned paged) /*------------------------------------------------------------------------- + * * Function: cedds__expunge_dirty_entry_in_flush_test() * - * Purpose: Verify that H5C_flush_cache() can handle the removal of - * a dirty entry from the cache during its scan of the - * skip list. + * Purpose: Verify that H5C_flush_cache() can handle the removal of + * a dirty entry from the cache during its scan of the + * skip list. * - * Do this by setting up a full cache, with the last entry - * on the LRU being both dirty and having a flush operation - * that deletes the second to last entry on the LRU. Then - * flush the cache, triggering the flush of the last - * item, and thereby the deletion of the second to last item. + * Do this by setting up a full cache, with the last entry + * on the LRU being both dirty and having a flush operation + * that deletes the second to last entry on the LRU. Then + * flush the cache, triggering the flush of the last + * item, and thereby the deletion of the second to last item. * - * H5C_flush_cache() should handle this deletion gracefully. + * H5C_flush_cache() should handle this deletion gracefully. * * Do nothing if pass is FALSE on entry. * - * Return: void + * Return: void * - * Programmer: John Mainzer + * Programmer: John Mainzer * 4/4/15 * * Modifications: * - * None. + * Added code to setup and take down the skip list before + * and after calls to H5C_flush_cache(). Do this via the + * H5C_FLUSH_CACHE macro. + * + * JRM -- 5/14/20 * *------------------------------------------------------------------------- */ @@ -34584,7 +34664,6 @@ cedds__expunge_dirty_entry_in_flush_test(H5F_t * file_ptr) { H5C_t * cache_ptr = file_ptr->shared->cache; int i; - herr_t result; struct expected_entry_status expected[36] = { /* the expected array is used to maintain a table of the expected status of every @@ -34681,44 +34760,41 @@ cedds__expunge_dirty_entry_in_flush_test(H5F_t * file_ptr) } - if(pass) { + if ( pass ) { - /* to summarize, at present the following entries - * are in cache with the following characteristics: - * - * in - * entry: cache? size: dirty? pinned? pins: flush operations: - * - * (HET, 0) Y 16 KB Y N - expunge (HET 1) - * - * (HET, 1) Y 16 KB Y N - - + /* to summarize, at present the following entries + * are in cache with the following characteristics: * - * (HET, 2) Y 16 KB Y N - - + * in + * entry: cache? size: dirty? pinned? pins: flush operations: * - * (HET, 3) Y 16 KB Y N - - - * - * Recall that in this test bed, flush operations are excuted the - * first time the associated entry is flushed, and are then - * deleted. - */ + * (HET, 0) Y 16 KB Y N - expunge (HET 1) + * + * (HET, 1) Y 16 KB Y N - - + * + * (HET, 2) Y 16 KB Y N - - + * + * (HET, 3) Y 16 KB Y N - - + * + * Recall that in this test bed, flush operations are excuted the + * first time the associated entry is flushed, and are then + * deleted. + */ - /* verify the expected status of all entries we have loaded to date: */ - verify_entry_status(cache_ptr, 0, 4, expected); + /* verify the expected status of all entries we have loaded to date: */ + verify_entry_status(cache_ptr, 0, 4, expected); } /* flush the cache to run the test. In the process, clean up after test. */ - if(pass) { - - result = H5C_flush_cache(file_ptr, H5C__FLUSH_INVALIDATE_FLAG); + if ( pass ) { - if(result < 0) { + H5C_FLUSH_CACHE(file_ptr, H5C__FLUSH_INVALIDATE_FLAG, \ + "Cache flush inval failed in cedds expunge dirty entry in flush test") - pass = FALSE; - failure_mssg = "Cache flush invalidate failed in cedds expunge dirty entry in flush test"; - } - else if((cache_ptr->index_len != 0) || - (cache_ptr->index_size != 0)) { + if ( ( pass ) && + ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) ) ) { pass = FALSE; failure_mssg = "Unexpected cache len/size after cedds expunge dirty entry in flush test"; @@ -34730,7 +34806,7 @@ cedds__expunge_dirty_entry_in_flush_test(H5F_t * file_ptr) /* If we are collecting stats, check to see if we get the expected * values. */ - if(pass) + if(pass) if((cache_ptr->insertions[HUGE_ENTRY_TYPE] != 0) || (cache_ptr->pinned_insertions[HUGE_ENTRY_TYPE] != 0) || (cache_ptr->clears[HUGE_ENTRY_TYPE] != 1) || @@ -34778,30 +34854,34 @@ cedds__expunge_dirty_entry_in_flush_test(H5F_t * file_ptr) /*------------------------------------------------------------------------- * Function: cedds__H5C_make_space_in_cache() * - * Purpose: Verify that H5C__make_space_in_cache() can handle the - * removal from the cache of the next item in its reverse scan - * of the LRU list. + * Purpose: Verify that H5C__make_space_in_cache() can handle the + * removal from the cache of the next item in its reverse scan + * of the LRU list. * - * Do this by setting up a full cache, with the last entry - * on the LRU being both dirty and having a flush operation - * that deleted the second to last entry on the LRU. Then - * load an additional entry, triggering the flush of the last - * item, and thereby the deletion of the second to last item. + * Do this by setting up a full cache, with the last entry + * on the LRU being both dirty and having a flush operation + * that deleted the second to last entry on the LRU. Then + * load an additional entry, triggering the flush of the last + * item, and thereby the deletion of the second to last item. * - * H5C__make_space_in_cache() should detect this deletion, and - * restart its scan of the LRU from the tail, instead of - * examining the now deleted next item up on the LRU. + * H5C__make_space_in_cache() should detect this deletion, and + * restart its scan of the LRU from the tail, instead of + * examining the now deleted next item up on the LRU. * * Do nothing if pass is FALSE on entry. * - * Return: void + * Return: void * - * Programmer: John Mainzer + * Programmer: John Mainzer * 4/4/15 * * Modifications: * - * None. + * Added code to setup and take down the skip list before + * and after calls to H5C_flush_cache(). Do this via the + * H5C_FLUSH_CACHE macro. + * + * JRM -- 5/14/20 * *------------------------------------------------------------------------- */ @@ -34813,7 +34893,6 @@ cedds__H5C_make_space_in_cache(H5F_t * file_ptr) int i; const int num_huge_entries = 4; const int num_monster_entries = 32; - herr_t result; struct expected_entry_status expected[36] = { /* the expected array is used to maintain a table of the expected status of every @@ -35060,17 +35139,14 @@ cedds__H5C_make_space_in_cache(H5F_t * file_ptr) /* flush the cache and end the test. */ - if(pass) { - - result = H5C_flush_cache(file_ptr, H5C__FLUSH_INVALIDATE_FLAG); + if ( pass ) { - if(result < 0) { + H5C_FLUSH_CACHE(file_ptr, H5C__FLUSH_INVALIDATE_FLAG, \ + "Cache flush invalidate failed after flush op eviction test") - pass = FALSE; - failure_mssg = "Cache flush invalidate failed after flush op eviction test"; - } - else if((cache_ptr->index_len != 0) || - (cache_ptr->index_size != 0)) { + if ( ( pass ) && + ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) ) ) { pass = FALSE; failure_mssg = "Unexpected cache len/size after cleanup of flush op eviction test"; @@ -35159,30 +35235,34 @@ cedds__H5C_make_space_in_cache(H5F_t * file_ptr) /*------------------------------------------------------------------------- * Function: cedds__H5C__autoadjust__ageout__evict_aged_out_entries() * - * Purpose: Verify that H5C__autoadjust__ageout__evict_aged_out_entries() - * can handle the removal from the cache of the next item in - * its reverse scan of the LRU list. + * Purpose: Verify that H5C__autoadjust__ageout__evict_aged_out_entries() + * can handle the removal from the cache of the next item in + * its reverse scan of the LRU list. * - * Do this by setting up a full cache, with the last entry - * on the LRU being both dirty and having a flush operation - * that deletes the second to last entry on the LRU. Then - * access the first item in the LRU repeatedly until the - * item, and thereby the deletion of the second to last item. + * Do this by setting up a full cache, with the last entry + * on the LRU being both dirty and having a flush operation + * that deletes the second to last entry on the LRU. Then + * access the first item in the LRU repeatedly until the + * item, and thereby the deletion of the second to last item. * - * H5C__make_space_in_cache() should detect this deletion, and - * restart its scan of the LRU from the tail, instead of - * examining the now deleted next item up on the LRU. + * H5C__make_space_in_cache() should detect this deletion, and + * restart its scan of the LRU from the tail, instead of + * examining the now deleted next item up on the LRU. * * Do nothing if pass is FALSE on entry. * - * Return: void + * Return: void * - * Programmer: John Mainzer + * Programmer: John Mainzer * 4/4/15 * * Modifications: * - * None. + * Added code to setup and take down the skip list before + * and after calls to H5C_flush_cache(). Do this via the + * H5C_FLUSH_CACHE macro. + * + * JRM -- 5/14/20 * *------------------------------------------------------------------------- */ @@ -35496,17 +35576,14 @@ cedds__H5C__autoadjust__ageout__evict_aged_out_entries(H5F_t * file_ptr) /* flush the cache and end the test. */ - if(pass) { - - result = H5C_flush_cache(file_ptr, H5C__FLUSH_INVALIDATE_FLAG); + if ( pass ) { - if(result < 0) { + H5C_FLUSH_CACHE(file_ptr, H5C__FLUSH_INVALIDATE_FLAG, \ + "Cache flush invalidate failed after flush op eviction test") - pass = FALSE; - failure_mssg = "Cache flush invalidate failed after flush op eviction test"; - } - else if((cache_ptr->index_len != 0) || - (cache_ptr->index_size != 0)) { + if ( ( pass ) && + ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) ) ) { pass = FALSE; failure_mssg = "Unexpected cache len/size after cleanup of flush op eviction test"; @@ -35569,91 +35646,95 @@ cedds__H5C__autoadjust__ageout__evict_aged_out_entries(H5F_t * file_ptr) /*------------------------------------------------------------------------- * Function: cedds__H5C_flush_invalidate_cache__bucket_scan() * - * Purpose: Note: We now use the index list when we scan the - * contents of the metadata cache, so in principal, - * this test is obsolete. However, even using the - * index list, restarts are possible, and must be - * handled gracefully. - * - * As it turns out, this test triggers index list - * scan restarts, and thus with minor changes is - * still a useful test. - * - * For this reason, with the exception of changing - * to check the index_scan_restart stat instead of - * hash bucket restarts, I'm leaving the test - * alone. If and when it starts to fail due to - * other changes, we can re-work it to test - * index list scan restarts explicitly. - * - * JRM -- 11/2/16 - * - * Verify that H5C_flush_invalidate_cache() can handle - * the removal from the cache of the next item in - * its scans of hash buckets. - * - * !!!!!!!!!!WARNING !!!!!!!!!! - * - * This test may fail to function correctly if the hash - * table size or hash function is altered. - * - * To setup the test, this function depends on the fact that - * H5C_flush_invalidate_cache() does alternating scans of the - * slist and the index. If this changes, the test will likely - * also cease to function correctly. - * - * The test relies on a known hash function and hash table - * size to select a set of test entries that will all hash - * to the same hash bucket -- call it the test hash bucket. - * It also relies on known behavior of the cache to place - * the entries in the test bucket in a known order. - * - * To avoid pre-mature flushes of the entries in the - * test hash bucket, all entries are initially clean, - * with the exception of the first entry which is dirty. - * It avoids premature flushing by being the parent in - * a flush dependency. The first entry in the test bucket - * also has a flush op which expunges the second entry -- - * setting up the failure. - * - * An additional dirty entry is added (which must hash - * to a different bucket, and must have a higher address - * than at least the first entry in the test hash bucket. - * This entry is the child in a flush dependency with the - * first entry in the above hash bucket, and contains - * a flush op to destroy this flush dependency. - * - * Since the first entry in the test hash bucket has a lower - * address that the other dirty entry, the scan of the - * slist encounters it first, and passes over it because - * it has a flush dependency height of 1. - * - * The scan then encounters the second dirty entry and flushes - * it -- causing it to destroy the flush dependency and thus - * reducing the flush dependency height of the first entry in - * the test hash bucket to zero. - * - * After completing a scan of the slist, - * H5C_flush_invalidate_cache() then scans the index, - * flushing all entries of flush dependency height zero. - * - * This sets up the potential error when the first entry - * in the test hash bucket is flushed -- expunging the - * second entry as a side effect. If - * H5C_flush_invalidate_cache() fails to detect this, - * it will attempt to continue its scan of the bucket with - * an entry that has been deleted from the cache. + * Purpose: Note: We now use the index list when we scan the + * contents of the metadata cache, so in principal, + * this test is obsolete. However, even using the + * index list, restarts are possible, and must be + * handled gracefully. + * + * As it turns out, this test triggers index list + * scan restarts, and thus with minor changes is + * still a useful test. + * + * For this reason, with the exception of changing + * to check the index_scan_restart stat instead of + * hash bucket restarts, I'm leaving the test + * alone. If and when it starts to fail due to + * other changes, we can re-work it to test + * index list scan restarts explicitly. + * + * JRM -- 11/2/16 + * + * Verify that H5C_flush_invalidate_cache() can handle + * the removal from the cache of the next item in + * its scans of hash buckets. + * + * !!!!!!!!!!WARNING !!!!!!!!!! + * + * This test may fail to function correctly if the hash + * table size or hash function is altered. + * + * To setup the test, this function depends on the fact that + * H5C_flush_invalidate_cache() does alternating scans of the + * slist and the index. If this changes, the test will likely + * also cease to function correctly. + * + * The test relies on a known hash function and hash table + * size to select a set of test entries that will all hash + * to the same hash bucket -- call it the test hash bucket. + * It also relies on known behavior of the cache to place + * the entries in the test bucket in a known order. + * + * To avoid pre-mature flushes of the entries in the + * test hash bucket, all entries are initially clean, + * with the exception of the first entry which is dirty. + * It avoids premature flushing by being the parent in + * a flush dependency. The first entry in the test bucket + * also has a flush op which expunges the second entry -- + * setting up the failure. + * + * An additional dirty entry is added (which must hash + * to a different bucket, and must have a higher address + * than at least the first entry in the test hash bucket. + * This entry is the child in a flush dependency with the + * first entry in the above hash bucket, and contains + * a flush op to destroy this flush dependency. + * + * Since the first entry in the test hash bucket has a lower + * address that the other dirty entry, the scan of the + * slist encounters it first, and passes over it because + * it has a flush dependency height of 1. + * + * The scan then encounters the second dirty entry and flushes + * it -- causing it to destroy the flush dependency and thus + * reducing the flush dependency height of the first entry in + * the test hash bucket to zero. + * + * After completing a scan of the slist, + * H5C_flush_invalidate_cache() then scans the index, + * flushing all entries of flush dependency height zero. + * + * This sets up the potential error when the first entry + * in the test hash bucket is flushed -- expunging the + * second entry as a side effect. If + * H5C_flush_invalidate_cache() fails to detect this, + * it will attempt to continue its scan of the bucket with + * an entry that has been deleted from the cache. * * Do nothing if pass is FALSE on entry. * - * Return: void + * Return: void * - * Programmer: John Mainzer + * Programmer: John Mainzer * 4/9/15 * * Modifications: * - * None. + * Added code to setup and take down the skip list before + * and after calls to H5C_flush_cache(). Do this via the + * H5C_FLUSH_CACHE macro. + * + * JRM -- 5/14/20 * *------------------------------------------------------------------------- */ @@ -35664,7 +35745,6 @@ cedds__H5C_flush_invalidate_cache__bucket_scan(H5F_t * file_ptr) H5C_t * cache_ptr = file_ptr->shared->cache; int i; int expected_hash_bucket = 0; - herr_t result; haddr_t entry_addr; test_entry_t * entry_ptr; test_entry_t * base_addr = NULL; @@ -35883,17 +35963,14 @@ cedds__H5C_flush_invalidate_cache__bucket_scan(H5F_t * file_ptr) /* test setup complete -- flush the cache to run and end the test. */ - if(pass) { - - result = H5C_flush_cache(file_ptr, H5C__FLUSH_INVALIDATE_FLAG); + if ( pass ) { - if(result < 0) { + H5C_FLUSH_CACHE(file_ptr, H5C__FLUSH_INVALIDATE_FLAG, \ + "Cache flush invalidate failed after flush op eviction test") - pass = FALSE; - failure_mssg = "Cache flush invalidate failed after flush op eviction test"; - } - else if((cache_ptr->index_len != 0) || - (cache_ptr->index_size != 0)) { + if ( ( pass ) && + ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) ) ) { pass = FALSE; failure_mssg = "Unexpected cache len/size after cleanup of flush op eviction test"; @@ -36036,26 +36113,34 @@ check_stats(unsigned paged) /*------------------------------------------------------------------------- * Function: check_stats__smoke_check_1() * - * Purpose: Test to see if the statistics collection code is working - * more or less as expected. Do this by performing a number - * of operations in the cache, and checking to verify that - * they result in the expected statistics. + * Purpose: Test to see if the statistics collection code is working + * more or less as expected. Do this by performing a number + * of operations in the cache, and checking to verify that + * they result in the expected statistics. * - * Note that this function is not intended to be a full test - * of the statistics collection facility -- only a cursory - * check that will serve as a place holder until more complete - * tests are implemented. + * Note that this function is not intended to be a full test + * of the statistics collection facility -- only a cursory + * check that will serve as a place holder until more complete + * tests are implemented. * * Do nothing if pass is FALSE on entry. * - * Return: void + * Return: void * - * Programmer: John Mainzer + * Programmer: John Mainzer * 4/22/15 * * Modifications: * - * None. + * Modified slist stats checks to allow for the case that + * the slist is disabled. + * + * Also added code to setup and take down the skip list before + * and after calls to H5C_flush_cache(). Do this via the + * H5C_FLUSH_CACHE macro. + * + * JRM -- 5/14/20 + * * *------------------------------------------------------------------------- */ @@ -36063,9 +36148,8 @@ check_stats(unsigned paged) static void check_stats__smoke_check_1(H5F_t * file_ptr) { - H5C_t * cache_ptr = file_ptr->shared->cache; + H5C_t * cache_ptr = file_ptr->shared->cache; int i; - herr_t result; if(pass) { if(cache_ptr == NULL) { @@ -36129,36 +36213,39 @@ check_stats__smoke_check_1(H5F_t * file_ptr) failure_mssg = "Unexpected monster size entry stats in check_stats__smoke_check_1(1)."; } /* end if */ - if(pass) - if((cache_ptr->total_ht_insertions != 32) || - (cache_ptr->total_ht_deletions != 0) || - (cache_ptr->successful_ht_searches != 0) || - (cache_ptr->total_successful_ht_search_depth != 0) || - (cache_ptr->failed_ht_searches != 32) || - (cache_ptr->total_failed_ht_search_depth != 48) || - (cache_ptr->max_index_len != 32) || - (cache_ptr->max_index_size != 2 * 1024 * 1024) || - (cache_ptr->max_clean_index_size != 0) || - (cache_ptr->max_dirty_index_size != 2 * 1024 * 1024) || - (cache_ptr->max_slist_len != 32) || - (cache_ptr->max_slist_size != 2 * 1024 * 1024) || - (cache_ptr->max_pl_len != 0) || - (cache_ptr->max_pl_size != 0) || - (cache_ptr->max_pel_len != 0) || - (cache_ptr->max_pel_size != 0) || - (cache_ptr->calls_to_msic != 0) || - (cache_ptr->total_entries_skipped_in_msic != 0) || - (cache_ptr->total_entries_scanned_in_msic != 0) || - (cache_ptr->max_entries_skipped_in_msic != 0) || - (cache_ptr->max_entries_scanned_in_msic != 0) || - (cache_ptr->entries_scanned_to_make_space != 0) || - (cache_ptr->slist_scan_restarts != 0) || - (cache_ptr->LRU_scan_restarts != 0) || - (cache_ptr->index_scan_restarts != 0)) { + if ( pass ) { + + if ( ( cache_ptr->total_ht_insertions != 32 ) || + ( cache_ptr->total_ht_deletions != 0 ) || + ( cache_ptr->successful_ht_searches != 0 ) || + ( cache_ptr->total_successful_ht_search_depth != 0 ) || + ( cache_ptr->failed_ht_searches != 32 ) || + ( cache_ptr->total_failed_ht_search_depth != 48 ) || + ( cache_ptr->max_index_len != 32 ) || + ( cache_ptr->max_index_size != 2 * 1024 * 1024 ) || + ( cache_ptr->max_clean_index_size != 0 ) || + ( cache_ptr->max_dirty_index_size != 2 * 1024 * 1024 ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->max_slist_len != 32 ) || + ( cache_ptr->max_slist_size != 2 * 1024 * 1024 ) ) ) || + ( cache_ptr->max_pl_len != 0 ) || + ( cache_ptr->max_pl_size != 0 ) || + ( cache_ptr->max_pel_len != 0 ) || + ( cache_ptr->max_pel_size != 0 ) || + ( cache_ptr->calls_to_msic != 0 ) || + ( cache_ptr->total_entries_skipped_in_msic != 0 ) || + ( cache_ptr->total_entries_scanned_in_msic != 0 ) || + ( cache_ptr->max_entries_skipped_in_msic != 0 ) || + ( cache_ptr->max_entries_scanned_in_msic != 0 ) || + ( cache_ptr->entries_scanned_to_make_space != 0 ) || + ( cache_ptr->slist_scan_restarts != 0 ) || + ( cache_ptr->LRU_scan_restarts != 0 ) || + ( cache_ptr->index_scan_restarts != 0 ) ) { pass = FALSE; failure_mssg = "Unexpected cache stats in check_stats__smoke_check_1(1)."; } /* end if */ + } #if H5C_COLLECT_CACHE_ENTRY_STATS if(pass) @@ -36214,36 +36301,39 @@ check_stats__smoke_check_1(H5F_t * file_ptr) failure_mssg = "Unexpected monster size entry stats in check_stats__smoke_check_1(2)."; } /* end if */ - if(pass) - if((cache_ptr->total_ht_insertions != 32) || - (cache_ptr->total_ht_deletions != 0) || - (cache_ptr->successful_ht_searches != 32) || - (cache_ptr->total_successful_ht_search_depth != 96) || - (cache_ptr->failed_ht_searches != 32) || - (cache_ptr->total_failed_ht_search_depth != 48) || - (cache_ptr->max_index_len != 32) || - (cache_ptr->max_index_size != 2 * 1024 * 1024) || - (cache_ptr->max_clean_index_size != 0) || - (cache_ptr->max_dirty_index_size != 2 * 1024 * 1024) || - (cache_ptr->max_slist_len != 32) || - (cache_ptr->max_slist_size != 2 * 1024 * 1024) || - (cache_ptr->max_pl_len != 1) || - (cache_ptr->max_pl_size != 64 * 1024) || - (cache_ptr->max_pel_len != 0) || - (cache_ptr->max_pel_size != 0) || - (cache_ptr->calls_to_msic != 0) || - (cache_ptr->total_entries_skipped_in_msic != 0) || - (cache_ptr->total_entries_scanned_in_msic != 0) || - (cache_ptr->max_entries_skipped_in_msic != 0) || - (cache_ptr->max_entries_scanned_in_msic != 0) || - (cache_ptr->entries_scanned_to_make_space != 0) || - (cache_ptr->slist_scan_restarts != 0) || - (cache_ptr->LRU_scan_restarts != 0) || - (cache_ptr->index_scan_restarts != 0)) { + if ( pass ) { + + if ( ( cache_ptr->total_ht_insertions != 32 ) || + ( cache_ptr->total_ht_deletions != 0 ) || + ( cache_ptr->successful_ht_searches != 32 ) || + ( cache_ptr->total_successful_ht_search_depth != 96 ) || + ( cache_ptr->failed_ht_searches != 32 ) || + ( cache_ptr->total_failed_ht_search_depth != 48 ) || + ( cache_ptr->max_index_len != 32 ) || + ( cache_ptr->max_index_size != 2 * 1024 * 1024 ) || + ( cache_ptr->max_clean_index_size != 0 ) || + ( cache_ptr->max_dirty_index_size != 2 * 1024 * 1024 ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->max_slist_len != 32 ) || + ( cache_ptr->max_slist_size != 2 * 1024 * 1024 ) ) ) || + ( cache_ptr->max_pl_len != 1 ) || + ( cache_ptr->max_pl_size != 64 * 1024 ) || + ( cache_ptr->max_pel_len != 0 ) || + ( cache_ptr->max_pel_size != 0 ) || + ( cache_ptr->calls_to_msic != 0 ) || + ( cache_ptr->total_entries_skipped_in_msic != 0 ) || + ( cache_ptr->total_entries_scanned_in_msic != 0 ) || + ( cache_ptr->max_entries_skipped_in_msic != 0 ) || + ( cache_ptr->max_entries_scanned_in_msic != 0 ) || + ( cache_ptr->entries_scanned_to_make_space != 0 ) || + ( cache_ptr->slist_scan_restarts != 0 ) || + ( cache_ptr->LRU_scan_restarts != 0 ) || + ( cache_ptr->index_scan_restarts != 0 ) ) { pass = FALSE; failure_mssg = "Unexpected cache stats in check_stats__smoke_check_1(2)."; } /* end if */ + } #if H5C_COLLECT_CACHE_ENTRY_STATS if(pass) @@ -36299,36 +36389,39 @@ check_stats__smoke_check_1(H5F_t * file_ptr) failure_mssg = "Unexpected monster size entry stats in check_stats__smoke_check_1(3)."; } /* end if */ - if(pass) - if((cache_ptr->total_ht_insertions != 33) || - (cache_ptr->total_ht_deletions != 1) || - (cache_ptr->successful_ht_searches != 32) || - (cache_ptr->total_successful_ht_search_depth != 96) || - (cache_ptr->failed_ht_searches != 33) || - (cache_ptr->total_failed_ht_search_depth != 52) || - (cache_ptr->max_index_len != 32) || - (cache_ptr->max_index_size != 2 * 1024 * 1024) || - (cache_ptr->max_clean_index_size != 2 * 1024 * 1024) || - (cache_ptr->max_dirty_index_size != 2 * 1024 * 1024) || - (cache_ptr->max_slist_len != 32) || - (cache_ptr->max_slist_size != 2 * 1024 * 1024) || - (cache_ptr->max_pl_len != 1) || - (cache_ptr->max_pl_size != 64 * 1024) || - (cache_ptr->max_pel_len != 0) || - (cache_ptr->max_pel_size != 0) || - (cache_ptr->calls_to_msic != 1) || - (cache_ptr->total_entries_skipped_in_msic != 0) || - (cache_ptr->total_entries_scanned_in_msic != 33) || - (cache_ptr->max_entries_skipped_in_msic != 0) || - (cache_ptr->max_entries_scanned_in_msic != 33) || - (cache_ptr->entries_scanned_to_make_space != 33) || - (cache_ptr->slist_scan_restarts != 0) || - (cache_ptr->LRU_scan_restarts != 0) || - (cache_ptr->index_scan_restarts != 0)) { + if ( pass ) { + + if ( ( cache_ptr->total_ht_insertions != 33 ) || + ( cache_ptr->total_ht_deletions != 1 ) || + ( cache_ptr->successful_ht_searches != 32 ) || + ( cache_ptr->total_successful_ht_search_depth != 96 ) || + ( cache_ptr->failed_ht_searches != 33 ) || + ( cache_ptr->total_failed_ht_search_depth != 52 ) || + ( cache_ptr->max_index_len != 32 ) || + ( cache_ptr->max_index_size != 2 * 1024 * 1024 ) || + ( cache_ptr->max_clean_index_size != 2 * 1024 * 1024 ) || + ( cache_ptr->max_dirty_index_size != 2 * 1024 * 1024 ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->max_slist_len != 32 ) || + ( cache_ptr->max_slist_size != 2 * 1024 * 1024 ) ) ) || + ( cache_ptr->max_pl_len != 1 ) || + ( cache_ptr->max_pl_size != 64 * 1024 ) || + ( cache_ptr->max_pel_len != 0 ) || + ( cache_ptr->max_pel_size != 0 ) || + ( cache_ptr->calls_to_msic != 1 ) || + ( cache_ptr->total_entries_skipped_in_msic != 0 ) || + ( cache_ptr->total_entries_scanned_in_msic != 33 ) || + ( cache_ptr->max_entries_skipped_in_msic != 0 ) || + ( cache_ptr->max_entries_scanned_in_msic != 33 ) || + ( cache_ptr->entries_scanned_to_make_space != 33 ) || + ( cache_ptr->slist_scan_restarts != 0 ) || + ( cache_ptr->LRU_scan_restarts != 0 ) || + ( cache_ptr->index_scan_restarts != 0 ) ) { pass = FALSE; failure_mssg = "Unexpected cache stats in check_stats__smoke_check_1(3)."; } /* end if */ + } #if H5C_COLLECT_CACHE_ENTRY_STATS if(pass) @@ -36356,17 +36449,14 @@ check_stats__smoke_check_1(H5F_t * file_ptr) /* flush the cache to end the test and collect all entry stats */ - if(pass) { - - result = H5C_flush_cache(file_ptr, H5C__FLUSH_INVALIDATE_FLAG); + if ( pass ) { - if(result < 0) { + H5C_FLUSH_CACHE(file_ptr, H5C__FLUSH_INVALIDATE_FLAG, \ + "Cache flush invalidate failed in check_stats__smoke_check_1()") - pass = FALSE; - failure_mssg = "Cache flush invalidate failed in check_stats__smoke_check_1()"; - } /* end if */ - else if((cache_ptr->index_len != 0) || - (cache_ptr->index_size != 0)) { + if ( ( pass ) && + ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) ) ) { pass = FALSE; failure_mssg = "Unexpected cache len/size after check_stats__smoke_check_1()"; @@ -36403,36 +36493,39 @@ check_stats__smoke_check_1(H5F_t * file_ptr) failure_mssg = "Unexpected monster size entry stats in check_stats__smoke_check_1(4)."; } /* end if */ - if(pass) - if((cache_ptr->total_ht_insertions != 33) || - (cache_ptr->total_ht_deletions != 33) || - (cache_ptr->successful_ht_searches != 33) || - (cache_ptr->total_successful_ht_search_depth != 99) || - (cache_ptr->failed_ht_searches != 33) || - (cache_ptr->total_failed_ht_search_depth != 52) || - (cache_ptr->max_index_len != 32) || - (cache_ptr->max_index_size != 2 * 1024 * 1024) || - (cache_ptr->max_clean_index_size != 2 * 1024 * 1024) || - (cache_ptr->max_dirty_index_size != 2 * 1024 * 1024) || - (cache_ptr->max_slist_len != 32) || - (cache_ptr->max_slist_size != 2 * 1024 * 1024) || - (cache_ptr->max_pl_len != 1) || - (cache_ptr->max_pl_size != 64 * 1024) || - (cache_ptr->max_pel_len != 0) || - (cache_ptr->max_pel_size != 0) || - (cache_ptr->calls_to_msic != 1) || - (cache_ptr->total_entries_skipped_in_msic != 0) || - (cache_ptr->total_entries_scanned_in_msic != 33) || - (cache_ptr->max_entries_skipped_in_msic != 0) || - (cache_ptr->max_entries_scanned_in_msic != 33) || - (cache_ptr->entries_scanned_to_make_space != 33) || - (cache_ptr->slist_scan_restarts != 0) || - (cache_ptr->LRU_scan_restarts != 0) || - (cache_ptr->index_scan_restarts != 0)) { + if ( pass ) { + + if ( ( cache_ptr->total_ht_insertions != 33 ) || + ( cache_ptr->total_ht_deletions != 33 ) || + ( cache_ptr->successful_ht_searches != 33 ) || + ( cache_ptr->total_successful_ht_search_depth != 99 ) || + ( cache_ptr->failed_ht_searches != 33 ) || + ( cache_ptr->total_failed_ht_search_depth != 52 ) || + ( cache_ptr->max_index_len != 32 ) || + ( cache_ptr->max_index_size != 2 * 1024 * 1024 ) || + ( cache_ptr->max_clean_index_size != 2 * 1024 * 1024 ) || + ( cache_ptr->max_dirty_index_size != 2 * 1024 * 1024 ) || + ( ( cache_ptr->slist_enabled ) && + ( ( cache_ptr->max_slist_len != 32 ) || + ( cache_ptr->max_slist_size != 2 * 1024 * 1024 ) ) ) || + ( cache_ptr->max_pl_len != 1 ) || + ( cache_ptr->max_pl_size != 64 * 1024 ) || + ( cache_ptr->max_pel_len != 0 ) || + ( cache_ptr->max_pel_size != 0 ) || + ( cache_ptr->calls_to_msic != 1 ) || + ( cache_ptr->total_entries_skipped_in_msic != 0 ) || + ( cache_ptr->total_entries_scanned_in_msic != 33 ) || + ( cache_ptr->max_entries_skipped_in_msic != 0 ) || + ( cache_ptr->max_entries_scanned_in_msic != 33 ) || + ( cache_ptr->entries_scanned_to_make_space != 33 ) || + ( cache_ptr->slist_scan_restarts != 0 ) || + ( cache_ptr->LRU_scan_restarts != 0 ) || + ( cache_ptr->index_scan_restarts != 0 ) ) { pass = FALSE; failure_mssg = "Unexpected cache stats in check_stats__smoke_check_1(4)."; } /* end if */ + } #if H5C_COLLECT_CACHE_ENTRY_STATS if(pass) diff --git a/test/cache_common.c b/test/cache_common.c index 1dc13a1..52ff33e 100644 --- a/test/cache_common.c +++ b/test/cache_common.c @@ -3111,12 +3111,25 @@ expunge_entry(H5F_t * file_ptr, * Function: flush_cache() * * Purpose: Flush the specified cache, destroying all entries if - requested. If requested, dump stats first. + * requested. If requested, dump stats first. * * Return: void * * Programmer: John Mainzer - * 6/23/04 + * 6/23/04 + * + * Changes: Added code to setup and take down the skip list before + * and after calls to H5C_flush_cache(). Do this via calls + * to the H5C_FLUSH_CACHE macro. + * + * This is necessary, as H5C_flush() is called repeatedly + * during file flush. If we setup and took down the + * skip list on H5C_flush_cache(), we would find ourselves + * doing this repeatedly -- which is contrary to the + * objective of the exercise (avoiding as many skip list + * operations as possible). + * + * JRM -- 5/14/20 * *------------------------------------------------------------------------- */ @@ -3139,25 +3152,30 @@ flush_cache(H5F_t * file_ptr, cache_ptr = file_ptr->shared->cache; - if(destroy_entries) - result = H5C_flush_cache(file_ptr, H5C__FLUSH_INVALIDATE_FLAG); + if ( destroy_entries ) { - else - result = H5C_flush_cache(file_ptr, H5C__NO_FLAGS_SET); + H5C_FLUSH_CACHE(file_ptr, H5C__FLUSH_INVALIDATE_FLAG, \ + "error in H5C_flush_cache().") - if(dump_stats) - H5C_stats(cache_ptr, "test cache", dump_detailed_stats); + } else { - if(result < 0) { - pass = FALSE; - failure_mssg = "error in H5C_flush_cache()."; + H5C_FLUSH_CACHE(file_ptr, H5C__NO_FLAGS_SET, \ + "error in H5C_flush_cache().") + } + + if ( dump_stats ) { + + H5C_stats(cache_ptr, "test cache", dump_detailed_stats); } - else if((destroy_entries) && ((cache_ptr->index_len != 0) - || (cache_ptr->index_size != 0) - || (cache_ptr->clean_index_size != 0) - || (cache_ptr->dirty_index_size != 0))) { - if(verbose) { + if ( ( pass ) && ( destroy_entries ) && + ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) || + ( cache_ptr->clean_index_size != 0 ) || + ( cache_ptr->dirty_index_size != 0 ) ) ) { + + if ( verbose ) { + HDfprintf(stdout, "%s: unexpected il/is/cis/dis = %lld/%lld/%lld/%lld.\n", FUNC, @@ -3961,14 +3979,19 @@ unprotect_entry(H5F_t * file_ptr, * Function: row_major_scan_forward() * * Purpose: Do a sequence of inserts, protects, unprotects, moves, - * destroys while scanning through the set of entries. If - * pass is false on entry, do nothing. + * destroys while scanning through the set of entries. If + * pass is false on entry, do nothing. * * Return: void * * Programmer: John Mainzer * 6/12/04 * + * Changes: Updated slist size == dirty index size checks to + * bypass the test if cache_ptr->slist_enabled is FALSE. + * + * JRM -- 5/8/20 + * *------------------------------------------------------------------------- */ void @@ -3983,7 +4006,7 @@ row_major_scan_forward(H5F_t * file_ptr, hbool_t do_moves, hbool_t move_to_main_addr, hbool_t do_destroys, - hbool_t do_mult_ro_protects, + hbool_t do_mult_ro_protects, int dirty_destroys, int dirty_unprotects) { @@ -4022,7 +4045,10 @@ row_major_scan_forward(H5F_t * file_ptr, HDfprintf(stdout, "1(i, %d, %d) ", type, tmp_idx); insert_entry(file_ptr, type, tmp_idx, H5C__NO_FLAGS_SET); - HDassert(cache_ptr->slist_size == cache_ptr->dirty_index_size); + + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( cache_ptr->slist_size == \ + cache_ptr->dirty_index_size ) ); } /* end if */ tmp_idx--; @@ -4033,7 +4059,10 @@ row_major_scan_forward(H5F_t * file_ptr, HDfprintf(stdout, "2(p, %d, %d) ", type, tmp_idx); protect_entry(file_ptr, type, tmp_idx); - HDassert(cache_ptr->slist_size == cache_ptr->dirty_index_size); + + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( cache_ptr->slist_size == \ + cache_ptr->dirty_index_size ) ); } /* end if */ tmp_idx--; @@ -4044,7 +4073,10 @@ row_major_scan_forward(H5F_t * file_ptr, HDfprintf(stdout, "3(u, %d, %d) ", type, tmp_idx); unprotect_entry(file_ptr, type, tmp_idx, H5C__NO_FLAGS_SET); - HDassert(cache_ptr->slist_size == cache_ptr->dirty_index_size); + + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( cache_ptr->slist_size == \ + cache_ptr->dirty_index_size ) ); } /* end if */ /* (don't decrement tmp_idx) */ @@ -4055,7 +4087,10 @@ row_major_scan_forward(H5F_t * file_ptr, HDfprintf(stdout, "4(r, %d, %d, %d) ", type, tmp_idx, (int)move_to_main_addr); move_entry(cache_ptr, type, tmp_idx, move_to_main_addr); - HDassert(cache_ptr->slist_size == cache_ptr->dirty_index_size); + + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( cache_ptr->slist_size == \ + cache_ptr->dirty_index_size ) ); } /* end if */ tmp_idx--; @@ -4066,7 +4101,10 @@ row_major_scan_forward(H5F_t * file_ptr, HDfprintf(stdout, "5(p, %d, %d) ", type, tmp_idx); protect_entry(file_ptr, type, tmp_idx); - HDassert(cache_ptr->slist_size == cache_ptr->dirty_index_size); + + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( cache_ptr->slist_size == \ + cache_ptr->dirty_index_size ) ); } /* end if */ tmp_idx -= 2; @@ -4077,7 +4115,10 @@ row_major_scan_forward(H5F_t * file_ptr, HDfprintf(stdout, "6(u, %d, %d) ", type, tmp_idx); unprotect_entry(file_ptr, type, tmp_idx, H5C__NO_FLAGS_SET); - HDassert(cache_ptr->slist_size == cache_ptr->dirty_index_size); + + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( cache_ptr->slist_size == \ + cache_ptr->dirty_index_size ) ); } /* end if */ if(do_mult_ro_protects) { @@ -4089,7 +4130,10 @@ row_major_scan_forward(H5F_t * file_ptr, HDfprintf(stdout, "7(p-ro, %d, %d) ", type, tmp_idx); protect_entry_ro(file_ptr, type, tmp_idx); - HDassert(cache_ptr->slist_size == cache_ptr->dirty_index_size); + + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( cache_ptr->slist_size == \ + cache_ptr->dirty_index_size ) ); } /* end if */ tmp_idx--; @@ -4100,7 +4144,10 @@ row_major_scan_forward(H5F_t * file_ptr, HDfprintf(stdout, "8(p-ro, %d, %d) ", type, tmp_idx); protect_entry_ro(file_ptr, type, tmp_idx); - HDassert(cache_ptr->slist_size == cache_ptr->dirty_index_size); + + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( cache_ptr->slist_size == \ + cache_ptr->dirty_index_size ) ); } /* end if */ tmp_idx--; @@ -4111,7 +4158,10 @@ row_major_scan_forward(H5F_t * file_ptr, HDfprintf(stdout, "9(p-ro, %d, %d) ", type, tmp_idx); protect_entry_ro(file_ptr, type, tmp_idx); - HDassert(cache_ptr->slist_size == cache_ptr->dirty_index_size); + + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( cache_ptr->slist_size == \ + cache_ptr->dirty_index_size ) ); } /* end if */ /* (don't decrement tmp_idx) */ @@ -4122,7 +4172,10 @@ row_major_scan_forward(H5F_t * file_ptr, HDfprintf(stdout, "10(u-ro, %d, %d) ", type, tmp_idx); unprotect_entry(file_ptr, type, tmp_idx, H5C__NO_FLAGS_SET); - HDassert(cache_ptr->slist_size == cache_ptr->dirty_index_size); + + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( cache_ptr->slist_size == \ + cache_ptr->dirty_index_size ) ); } /* end if */ tmp_idx--; @@ -4133,7 +4186,10 @@ row_major_scan_forward(H5F_t * file_ptr, HDfprintf(stdout, "11(u-ro, %d, %d) ", type, tmp_idx); unprotect_entry(file_ptr, type, tmp_idx, H5C__NO_FLAGS_SET); - HDassert(cache_ptr->slist_size == cache_ptr->dirty_index_size); + + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( cache_ptr->slist_size == \ + cache_ptr->dirty_index_size ) ); } /* end if */ tmp_idx--; @@ -4144,7 +4200,10 @@ row_major_scan_forward(H5F_t * file_ptr, HDfprintf(stdout, "12(u-ro, %d, %d) ", type, tmp_idx); unprotect_entry(file_ptr, type, tmp_idx, H5C__NO_FLAGS_SET); - HDassert(cache_ptr->slist_size == cache_ptr->dirty_index_size); + + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( cache_ptr->slist_size == \ + cache_ptr->dirty_index_size ) ); } /* end if */ } /* if ( do_mult_ro_protects ) */ @@ -4153,7 +4212,10 @@ row_major_scan_forward(H5F_t * file_ptr, HDfprintf(stdout, "13(p, %d, %d) ", type, idx); protect_entry(file_ptr, type, idx); - HDassert(cache_ptr->slist_size == cache_ptr->dirty_index_size); + + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( cache_ptr->slist_size == \ + cache_ptr->dirty_index_size ) ); } /* end if */ tmp_idx = idx - lag + 2; @@ -4164,7 +4226,10 @@ row_major_scan_forward(H5F_t * file_ptr, HDfprintf(stdout, "14(u, %d, %d) ", type, tmp_idx); unprotect_entry(file_ptr, type, tmp_idx, H5C__NO_FLAGS_SET); - HDassert(cache_ptr->slist_size == cache_ptr->dirty_index_size); + + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( cache_ptr->slist_size == \ + cache_ptr->dirty_index_size ) ); } /* end if */ tmp_idx--; @@ -4175,7 +4240,10 @@ row_major_scan_forward(H5F_t * file_ptr, HDfprintf(stdout, "15(p, %d, %d) ", type, tmp_idx); protect_entry(file_ptr, type, tmp_idx); - HDassert(cache_ptr->slist_size == cache_ptr->dirty_index_size); + + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( cache_ptr->slist_size == \ + cache_ptr->dirty_index_size ) ); } /* end if */ if(do_destroys) { @@ -4187,7 +4255,10 @@ row_major_scan_forward(H5F_t * file_ptr, HDfprintf(stdout, "16(u, %d, %d) ", type, tmp_idx); unprotect_entry(file_ptr, type, tmp_idx, H5C__NO_FLAGS_SET); - HDassert(cache_ptr->slist_size == cache_ptr->dirty_index_size); + + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( cache_ptr->slist_size == \ + cache_ptr->dirty_index_size ) ); break; case 1: @@ -4196,14 +4267,20 @@ row_major_scan_forward(H5F_t * file_ptr, HDfprintf(stdout, "17(u, %d, %d) ", type, tmp_idx); unprotect_entry(file_ptr, type, tmp_idx, H5C__NO_FLAGS_SET); - HDassert(cache_ptr->slist_size == cache_ptr->dirty_index_size); + + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( cache_ptr->slist_size == \ + cache_ptr->dirty_index_size ) ); } /* end if */ else { if(verbose) HDfprintf(stdout, "18(u, %d, %d) ", type, tmp_idx); unprotect_entry(file_ptr, type, tmp_idx, (dirty_unprotects ? H5C__DIRTIED_FLAG : H5C__NO_FLAGS_SET)); - HDassert(cache_ptr->slist_size == cache_ptr->dirty_index_size); + + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( cache_ptr->slist_size == \ + cache_ptr->dirty_index_size ) ); } /* end else */ break; @@ -4212,7 +4289,10 @@ row_major_scan_forward(H5F_t * file_ptr, HDfprintf(stdout, "19(u-del, %d, %d) ", type, tmp_idx); unprotect_entry(file_ptr, type, tmp_idx, H5C__DELETED_FLAG); - HDassert(cache_ptr->slist_size == cache_ptr->dirty_index_size); + + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( cache_ptr->slist_size == \ + cache_ptr->dirty_index_size ) ); break; case 3: @@ -4221,14 +4301,20 @@ row_major_scan_forward(H5F_t * file_ptr, HDfprintf(stdout, "20(u-del, %d, %d) ", type, tmp_idx); unprotect_entry(file_ptr, type, tmp_idx, H5C__DELETED_FLAG); - HDassert(cache_ptr->slist_size == cache_ptr->dirty_index_size); + + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( cache_ptr->slist_size == \ + cache_ptr->dirty_index_size ) ); } /* end if */ else { if(verbose) HDfprintf(stdout, "21(u-del, %d, %d) ", type, tmp_idx); unprotect_entry(file_ptr, type, tmp_idx, (dirty_destroys ? H5C__DIRTIED_FLAG : H5C__NO_FLAGS_SET) | H5C__DELETED_FLAG); - HDassert(cache_ptr->slist_size == cache_ptr->dirty_index_size); + + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( cache_ptr->slist_size == \ + cache_ptr->dirty_index_size ) ); } /* end else */ break; @@ -4245,7 +4331,10 @@ row_major_scan_forward(H5F_t * file_ptr, HDfprintf(stdout, "22(u, %d, %d) ", type, tmp_idx); unprotect_entry(file_ptr, type, tmp_idx, (dirty_unprotects ? H5C__DIRTIED_FLAG : H5C__NO_FLAGS_SET)); - HDassert(cache_ptr->slist_size == cache_ptr->dirty_index_size); + + HDassert( ( ! cache_ptr->slist_enabled ) || \ + ( cache_ptr->slist_size == \ + cache_ptr->dirty_index_size ) ); } /* end if */ } /* end elsef */ diff --git a/test/cache_common.h b/test/cache_common.h index 785dc21..807ba35 100644 --- a/test/cache_common.h +++ b/test/cache_common.h @@ -134,6 +134,65 @@ (NOTIFY_ENTRY_SIZE * NUM_NOTIFY_ENTRIES)) #define ADDR_SPACE_SIZE (haddr_t)(MAX_ADDR - BASE_ADDR) + +/*********************************************************************** + * + * Macro: H5C_FLUSH_CACHE + * + * Purpose: Wrap a call to H5C_flush_cache() in calls to + * H5C_set_slist_enabled() to setup and take down the slist. + * + * This is necessary, as H5C_flush_cache() needs the + * slist to be active. Further, since it is called + * repeatedly during file flush, it would be inefficient + * for it to setup the slist on entry, and take it down + * on exit. + * + * Note that the slist need not be empty if the flags + * indicate a partial flush (i.e. + * H5C__FLUSH_MARKED_ENTRIES_FLAG). Compute clear_slist + * and pass it into H5C_set_slist_enabled as appropriate. + * + * On error, set pass to FALSE, and set failure_mssg + * to the supplied error message. + * + * Return: N/A + * + * Programmer: John Mainzer + * 5/14/20 + * + * Changes: None. + * + ***********************************************************************/ + +#define H5C_FLUSH_CACHE(file, flags, fail_mssg) \ +{ \ + hbool_t clear_slist; \ + herr_t rslt; \ + \ + clear_slist = ( (flags & H5C__FLUSH_MARKED_ENTRIES_FLAG) != 0 ); \ + \ + rslt = H5C_set_slist_enabled((file)->shared->cache, TRUE, FALSE); \ + \ + if ( rslt >= 0 ) { \ + \ + rslt = H5C_flush_cache((file), (flags)); \ + } \ + \ + if ( rslt >= 0 ) { \ + \ + rslt = H5C_set_slist_enabled((file)->shared->cache, FALSE, \ + clear_slist); \ + } \ + \ + if( rslt < 0 ) { \ + \ + pass = FALSE; \ + failure_mssg = (fail_mssg); \ + } \ +} /* H5C_FLUSH_CACHE */ + + #define MAX_PINS 8 /* Maximum number of entries that can be * directly pinned by a single entry. */ diff --git a/test/cache_tagging.c b/test/cache_tagging.c index cf0cd8d..499f23b 100644 --- a/test/cache_tagging.c +++ b/test/cache_tagging.c @@ -348,11 +348,20 @@ evict_entries(hid_t fid) /* Mark all entries investigated */ mark_all_entries_investigated(fid); + /* setup the skip list prior to calling H5C_flush_cache() */ + if ( H5C_set_slist_enabled(f->shared->cache, TRUE, FALSE) < 0 ) + TEST_ERROR; + /* Evict all we can from the cache to examine full tag creation tree */ - /* This function will likely return failure since the root group - * is still protected. Thus, don't check its return value. */ + /* This function will likely return failure since the root group + * is still protected. Thus, don't check its return value. + */ H5C_flush_cache(f, H5C__FLUSH_INVALIDATE_FLAG); + /* shutdown the slist -- allow it to be non-empty */ + if ( H5C_set_slist_enabled(f->shared->cache, FALSE, TRUE) < 0 ) + TEST_ERROR; + return 0; error: diff --git a/test/ohdr.c b/test/ohdr.c index ad76576..709f67f 100644 --- a/test/ohdr.c +++ b/test/ohdr.c @@ -126,8 +126,12 @@ test_cont(char *filename, hid_t fapl) FAIL_STACK_ERROR if(1 != H5O_link(&oh_locB, 1)) FAIL_STACK_ERROR + if(H5AC_prep_for_file_flush(f) < 0) + FAIL_STACK_ERROR if(H5AC_flush(f) < 0) FAIL_STACK_ERROR + if(H5AC_secure_from_file_flush(f) < 0) + FAIL_STACK_ERROR if(H5O__expunge_chunks_test(&oh_locA) < 0) FAIL_STACK_ERROR @@ -1681,8 +1685,12 @@ main(void) FAIL_STACK_ERROR if(1 != H5O_link(&oh_loc, 1)) FAIL_STACK_ERROR + if(H5AC_prep_for_file_flush(f) < 0) + FAIL_STACK_ERROR if(H5AC_flush(f) < 0) FAIL_STACK_ERROR + if(H5AC_secure_from_file_flush(f) < 0) + FAIL_STACK_ERROR if(H5AC_expunge_entry(f, H5AC_OHDR, oh_loc.addr, H5AC__NO_FLAGS_SET) < 0) FAIL_STACK_ERROR if(NULL == H5O_msg_read(&oh_loc, H5O_MTIME_NEW_ID, &ro)) @@ -1698,8 +1706,12 @@ main(void) time_new = 33333333; if(H5O_msg_write(&oh_loc, H5O_MTIME_NEW_ID, 0, 0, &time_new) < 0) FAIL_STACK_ERROR + if(H5AC_prep_for_file_flush(f) < 0) + FAIL_STACK_ERROR if(H5AC_flush(f) < 0) FAIL_STACK_ERROR + if(H5AC_secure_from_file_flush(f) < 0) + FAIL_STACK_ERROR if(H5AC_expunge_entry(f, H5AC_OHDR, oh_loc.addr, H5AC__NO_FLAGS_SET) < 0) FAIL_STACK_ERROR if(NULL == H5O_msg_read(&oh_loc, H5O_MTIME_NEW_ID, &ro)) @@ -1729,8 +1741,12 @@ main(void) if(H5O_msg_create(&oh_loc, H5O_MTIME_ID, 0, 0, &time_new) < 0) FAIL_STACK_ERROR } /* end for */ + if(H5AC_prep_for_file_flush(f) < 0) + FAIL_STACK_ERROR if(H5AC_flush(f) < 0) FAIL_STACK_ERROR + if(H5AC_secure_from_file_flush(f) < 0) + FAIL_STACK_ERROR if(H5AC_expunge_entry(f, H5AC_OHDR, oh_loc.addr, H5AC__NO_FLAGS_SET) < 0) FAIL_STACK_ERROR @@ -1772,8 +1788,12 @@ main(void) time_new = (i + 1) * 1000 + 10; if(H5O_msg_create(&oh_loc, H5O_MTIME_NEW_ID, 0, 0, &time_new) < 0) FAIL_STACK_ERROR + if(H5AC_prep_for_file_flush(f) < 0) + FAIL_STACK_ERROR if(H5AC_flush(f) < 0) FAIL_STACK_ERROR + if(H5AC_secure_from_file_flush(f) < 0) + FAIL_STACK_ERROR if(H5AC_expunge_entry(f, H5AC_OHDR, oh_loc.addr, H5AC__NO_FLAGS_SET) < 0) FAIL_STACK_ERROR } /* end for */ @@ -1802,8 +1822,12 @@ main(void) time_new = 22222222; if(H5O_msg_create(&oh_loc, H5O_MTIME_NEW_ID, H5O_MSG_FLAG_CONSTANT, 0, &time_new) < 0) FAIL_STACK_ERROR + if(H5AC_prep_for_file_flush(f) < 0) + FAIL_STACK_ERROR if(H5AC_flush(f) < 0) FAIL_STACK_ERROR + if(H5AC_secure_from_file_flush(f) < 0) + FAIL_STACK_ERROR if(H5AC_expunge_entry(f, H5AC_OHDR, oh_loc.addr, H5AC__NO_FLAGS_SET) < 0) FAIL_STACK_ERROR if(NULL == H5O_msg_read(&oh_loc, H5O_MTIME_NEW_ID, &ro)) -- cgit v0.12