diff options
-rw-r--r-- | src/H5AC.c | 483 | ||||
-rw-r--r-- | src/H5ACmpio.c | 42 | ||||
-rw-r--r-- | src/H5ACprivate.h | 2 | ||||
-rw-r--r-- | src/H5C.c | 1684 | ||||
-rw-r--r-- | src/H5Cdbg.c | 41 | ||||
-rw-r--r-- | src/H5Cimage.c | 13 | ||||
-rw-r--r-- | src/H5Cmpio.c | 391 | ||||
-rw-r--r-- | src/H5Cpkg.h | 471 | ||||
-rw-r--r-- | src/H5Cprivate.h | 5 | ||||
-rw-r--r-- | src/H5Fint.c | 10 | ||||
-rw-r--r-- | test/cache.c | 2099 | ||||
-rw-r--r-- | test/cache_common.c | 171 | ||||
-rw-r--r-- | test/cache_common.h | 59 | ||||
-rw-r--r-- | test/cache_tagging.c | 13 | ||||
-rw-r--r-- | test/ohdr.c | 24 |
15 files changed, 3651 insertions, 1857 deletions
@@ -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); @@ -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) { - - result = H5C_flush_cache(file_ptr, H5C__NO_FLAGS_SET); - - if(result < 0) { + if ( pass ) { - 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 ( pass ) { - if(result < 0) { - - 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) { + if ( pass ) { - result = H5C_flush_cache(file_ptr, H5C__FLUSH_CLEAR_ONLY_FLAG); - - 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(result < 0) { + if ( pass ) { - 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. - * - * Return: void + * Purpose : Run a multi entry flush cache test. * - * 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 ) ) { + + 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->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 ) ) { + + 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->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) { + 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"; @@ -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) { + 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"; @@ -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)) |