diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/H5AC.c | 289 | ||||
-rw-r--r-- | src/H5ACprivate.h | 8 | ||||
-rw-r--r-- | src/H5ACpublic.h | 47 | ||||
-rw-r--r-- | src/H5C.c | 657 | ||||
-rw-r--r-- | src/H5Cpkg.h | 12 | ||||
-rw-r--r-- | src/H5Cprivate.h | 25 |
6 files changed, 873 insertions, 165 deletions
@@ -71,6 +71,19 @@ #define H5AC_DEBUG_DIRTY_BYTES_CREATION 0 +/*------------------------------------------------------------------------- + * It is a bit difficult to set ranges of allowable values on the + * dirty_bytes_threshold field of H5AC_aux_t. The following are + * probably broader than they should be. + *------------------------------------------------------------------------- + */ + +#define H5AC__MIN_DIRTY_BYTES_THRESHOLD (int32_t) \ + (H5C__MIN_MAX_CACHE_SIZE / 2) +#define H5AC__DEFAULT_DIRTY_BYTES_THRESHOLD (256 * 1024) +#define H5AC__MAX_DIRTY_BYTES_THRESHOLD (int32_t) \ + (H5C__MAX_MAX_CACHE_SIZE / 4) + /**************************************************************************** * * structure H5AC_aux_t @@ -392,7 +405,12 @@ static herr_t H5AC_check_if_write_permitted(const H5F_t *f, #ifdef H5_HAVE_PARALLEL static herr_t H5AC_broadcast_clean_list(H5AC_t * cache_ptr); +#endif /* JRM */ +static herr_t H5AC_ext_config_2_int_config(H5AC_cache_config_t * ext_conf_ptr, + H5C_auto_size_ctl_t * int_conf_ptr); + +#ifdef H5_HAVE_PARALLEL static herr_t H5AC_log_deleted_entry(H5AC_t * cache_ptr, H5AC_info_t * entry_ptr, haddr_t addr, @@ -707,6 +725,10 @@ H5AC_term_interface(void) * * JRM - 6/28/05 * + * Added code to set the prefix if required. + * + * JRM - 1/20/06 + * *------------------------------------------------------------------------- */ @@ -723,7 +745,8 @@ static const char * H5AC_entry_type_names[H5AC_NTYPES] = "block tracker nodes", "segmented heaps", "B+ tree headers", - "B+ tree leaves" + "B+ tree leaves", + "test entry" /* for testing only -- not used for actual files */ }; herr_t @@ -733,6 +756,7 @@ H5AC_create(const H5F_t *f, herr_t ret_value = SUCCEED; /* Return value */ herr_t result; #ifdef H5_HAVE_PARALLEL + char prefix[H5C__PREFIX_LEN] = ""; MPI_Comm mpi_comm = MPI_COMM_NULL; int mpi_rank = -1; int mpi_size = -1; @@ -789,7 +813,8 @@ H5AC_create(const H5F_t *f, aux_ptr->mpi_rank = mpi_rank; aux_ptr->mpi_size = mpi_size; aux_ptr->write_permitted = FALSE; - aux_ptr->dirty_bytes_threshold = 256 * 1024; + aux_ptr->dirty_bytes_threshold = + H5AC__DEFAULT_DIRTY_BYTES_THRESHOLD; aux_ptr->dirty_bytes = 0; #if H5AC_DEBUG_DIRTY_BYTES_CREATION aux_ptr->dirty_bytes_propagations = 0; @@ -804,6 +829,8 @@ H5AC_create(const H5F_t *f, aux_ptr->d_slist_len = 0; aux_ptr->c_slist_ptr = NULL; aux_ptr->c_slist_len = 0; + + sprintf(prefix, "%d:", mpi_rank); } if ( mpi_rank == 0 ) { @@ -856,6 +883,7 @@ H5AC_create(const H5F_t *f, #endif /* JRM */ (void *)aux_ptr); } + } else { f->shared->cache = H5C_create(H5AC__DEFAULT_MAX_CACHE_SIZE, @@ -889,7 +917,19 @@ H5AC_create(const H5F_t *f, HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + } +#ifdef H5_HAVE_PARALLEL + else if ( aux_ptr != NULL ) { + + result = H5C_set_prefix(f->shared->cache, prefix); + + if ( result != SUCCEED ) { + + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ + "H5C_set_prefix() failed") + } } +#endif /* H5_HAVE_PARALLEL */ result = H5AC_set_cache_auto_resize_config(f->shared->cache, config_ptr); @@ -1133,7 +1173,7 @@ H5AC_flush(H5F_t *f, hid_t dxpl_id, unsigned flags) * flush first. */ if ( ( aux_ptr->mpi_rank == 0 ) && - ( (flags & H5AC__FLUSH_CLEAR_ONLY_FLAG) != 0 ) ) { + ( (flags & H5AC__FLUSH_CLEAR_ONLY_FLAG) == 0 ) ) { unsigned init_flush_flags = H5AC__NO_FLAGS_SET; @@ -2058,7 +2098,8 @@ H5AC_stats(const H5F_t *f) HDassert(f); HDassert(f->shared->cache); - (void)H5C_stats(f->shared->cache, f->name, FALSE); /* at present, this can't fail */ + /* at present, this can't fail */ + (void)H5C_stats(f->shared->cache, f->name, FALSE); done: FUNC_LEAVE_NOAPI(ret_value) @@ -2081,6 +2122,10 @@ done: * JRM - 4/6/05 * Reworked for the addition of struct H5AC_cache_config_t. * + * JRM - 10/25/05 + * Added support for the new dirty_bytes_threshold field of + * both H5AC_cache_config_t and H5AC_aux_t. + * *------------------------------------------------------------------------- */ @@ -2094,9 +2139,22 @@ H5AC_get_cache_auto_resize_config(H5AC_t * cache_ptr, FUNC_ENTER_NOAPI(H5AC_get_cache_auto_resize_config, FAIL) - if ( ( cache_ptr == NULL ) || - ( config_ptr == NULL ) || - ( config_ptr->version != H5AC__CURR_CACHE_CONFIG_VERSION ) ) + if ( ( cache_ptr == NULL ) + || +#ifdef H5_HAVE_PARALLEL + ( ( cache_ptr->aux_ptr != NULL ) + && + ( ((H5AC_aux_t *)(cache_ptr->aux_ptr))->magic + != + H5AC__H5AC_AUX_T_MAGIC + ) + ) + || +#endif /* H5_HAVE_PARALLEL */ + ( config_ptr == NULL ) + || + ( config_ptr->version != H5AC__CURR_CACHE_CONFIG_VERSION ) + ) { HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ "Bad cache_ptr or config_ptr on entry.") @@ -2142,6 +2200,21 @@ H5AC_get_cache_auto_resize_config(H5AC_t * cache_ptr, config_ptr->apply_empty_reserve = internal_config.apply_empty_reserve; config_ptr->empty_reserve = internal_config.empty_reserve; +#ifdef H5_HAVE_PARALLEL + if ( cache_ptr->aux_ptr != NULL ) { + + config_ptr->dirty_bytes_threshold = + ((H5AC_aux_t *)(cache_ptr->aux_ptr))->dirty_bytes_threshold; + + } else { +#endif /* H5_HAVE_PARALLEL */ + + config_ptr->dirty_bytes_threshold = H5AC__DEFAULT_DIRTY_BYTES_THRESHOLD; + +#ifdef H5_HAVE_PARALLEL + } +#endif /* H5_HAVE_PARALLEL */ + done: FUNC_LEAVE_NOAPI(ret_value) @@ -2294,6 +2367,10 @@ done: * John Mainzer -- 4/6/05 * Updated for the addition of H5AC_cache_config_t. * + * John Mainzer -- 1025/05 + * Added support for the new dirty_bytes_threshold field of + * both H5AC_cache_config_t and H5AC_aux_t. + * *------------------------------------------------------------------------- */ @@ -2307,9 +2384,21 @@ H5AC_set_cache_auto_resize_config(H5AC_t * cache_ptr, FUNC_ENTER_NOAPI(H5AC_set_cache_auto_resize_config, FAIL) - if ( cache_ptr == NULL ) { + if ( ( cache_ptr == NULL ) +#ifdef H5_HAVE_PARALLEL + || + ( ( cache_ptr->aux_ptr != NULL ) + && + ( + ((H5AC_aux_t *)(cache_ptr->aux_ptr))->magic + != + H5AC__H5AC_AUX_T_MAGIC + ) + ) +#endif /* H5_HAVE_PARALLEL */ + ) { - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "NULL cache_ptr on entry.") + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "bad cache_ptr on entry.") } if ( config_ptr == NULL ) { @@ -2329,40 +2418,30 @@ H5AC_set_cache_auto_resize_config(H5AC_t * cache_ptr, "config_ptr->rpt_fcn_enabled must be either TRUE or FALSE.") } - internal_config.version = H5C__CURR_AUTO_SIZE_CTL_VER; - - if ( config_ptr->rpt_fcn_enabled ) { + if ( + ( + config_ptr->dirty_bytes_threshold + < + H5AC__MIN_DIRTY_BYTES_THRESHOLD + ) + || + ( + config_ptr->dirty_bytes_threshold + > + H5AC__MAX_DIRTY_BYTES_THRESHOLD + ) + ) { - internal_config.rpt_fcn = H5C_def_auto_resize_rpt_fcn; + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, + "config_ptr->dirty_bytes_threshold out of range.") + } - } else { + if ( H5AC_ext_config_2_int_config(config_ptr, &internal_config) != + SUCCEED ) { - internal_config.rpt_fcn = NULL; - } - - internal_config.set_initial_size = config_ptr->set_initial_size; - internal_config.initial_size = config_ptr->initial_size; - internal_config.min_clean_fraction = config_ptr->min_clean_fraction; - internal_config.max_size = config_ptr->max_size; - internal_config.min_size = config_ptr->min_size; - internal_config.epoch_length = - (int64_t)(config_ptr->epoch_length); - - internal_config.incr_mode = config_ptr->incr_mode; - internal_config.lower_hr_threshold = config_ptr->lower_hr_threshold; - internal_config.increment = config_ptr->increment; - internal_config.apply_max_increment = config_ptr->apply_max_increment; - internal_config.max_increment = config_ptr->max_increment; - - internal_config.decr_mode = config_ptr->decr_mode; - internal_config.upper_hr_threshold = config_ptr->upper_hr_threshold; - internal_config.decrement = config_ptr->decrement; - internal_config.apply_max_decrement = config_ptr->apply_max_decrement; - internal_config.max_decrement = config_ptr->max_decrement; - internal_config.epochs_before_eviction = - (int32_t)(config_ptr->epochs_before_eviction); - internal_config.apply_empty_reserve = config_ptr->apply_empty_reserve; - internal_config.empty_reserve = config_ptr->empty_reserve; + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "H5AC_ext_config_2_int_config() failed.") + } result = H5C_set_cache_auto_resize_config((H5C_t *)cache_ptr, &internal_config); @@ -2372,6 +2451,14 @@ H5AC_set_cache_auto_resize_config(H5AC_t * cache_ptr, "H5C_set_cache_auto_resize_config() failed.") } +#ifdef H5_HAVE_PARALLEL + if ( cache_ptr->aux_ptr != NULL ) { + + ((H5AC_aux_t *)(cache_ptr->aux_ptr))->dirty_bytes_threshold = + config_ptr->dirty_bytes_threshold; + } +#endif /* H5_HAVE_PARALLEL */ + done: FUNC_LEAVE_NOAPI(ret_value) @@ -2433,40 +2520,23 @@ H5AC_validate_config(H5AC_cache_config_t * config_ptr) "config_ptr->rpt_fcn_enabled must be either TRUE or FALSE.") } - internal_config.version = H5C__CURR_AUTO_SIZE_CTL_VER; + if ( config_ptr->dirty_bytes_threshold < H5AC__MIN_DIRTY_BYTES_THRESHOLD ) { - if ( config_ptr->rpt_fcn_enabled ) { + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, + "dirty_bytes_threshold too small.") + } else + if ( config_ptr->dirty_bytes_threshold > H5AC__MAX_DIRTY_BYTES_THRESHOLD ) { - internal_config.rpt_fcn = H5C_def_auto_resize_rpt_fcn; + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, + "dirty_bytes_threshold too big.") + } - } else { + if ( H5AC_ext_config_2_int_config(config_ptr, &internal_config) != + SUCCEED ) { - internal_config.rpt_fcn = NULL; - } - - internal_config.set_initial_size = config_ptr->set_initial_size; - internal_config.initial_size = config_ptr->initial_size; - internal_config.min_clean_fraction = config_ptr->min_clean_fraction; - internal_config.max_size = config_ptr->max_size; - internal_config.min_size = config_ptr->min_size; - internal_config.epoch_length = - (int64_t)(config_ptr->epoch_length); - - internal_config.incr_mode = config_ptr->incr_mode; - internal_config.lower_hr_threshold = config_ptr->lower_hr_threshold; - internal_config.increment = config_ptr->increment; - internal_config.apply_max_increment = config_ptr->apply_max_increment; - internal_config.max_increment = config_ptr->max_increment; - - internal_config.decr_mode = config_ptr->decr_mode; - internal_config.upper_hr_threshold = config_ptr->upper_hr_threshold; - internal_config.decrement = config_ptr->decrement; - internal_config.apply_max_decrement = config_ptr->apply_max_decrement; - internal_config.max_decrement = config_ptr->max_decrement; - internal_config.epochs_before_eviction = - (int32_t)(config_ptr->epochs_before_eviction); - internal_config.apply_empty_reserve = config_ptr->apply_empty_reserve; - internal_config.empty_reserve = config_ptr->empty_reserve; + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "H5AC_ext_config_2_int_config() failed.") + } result = H5C_validate_resize_config(&internal_config, H5C_RESIZE_CFG__VALIDATE_ALL); @@ -2750,6 +2820,85 @@ done: /*------------------------------------------------------------------------- + * 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. + * + * Places translation in *int_conf_ptr and returns SUCCEED + * if successful. Returns FAIL on failure. + * + * Does only minimal sanity checking. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: John Mainzer + * 1/26/06 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +herr_t +H5AC_ext_config_2_int_config(H5AC_cache_config_t * ext_conf_ptr, + H5C_auto_size_ctl_t * int_conf_ptr) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5AC_ext_config_2_int_config, FAIL) + + if ( ( ext_conf_ptr == NULL ) || + ( ext_conf_ptr->version != H5AC__CURR_CACHE_CONFIG_VERSION ) || + ( int_conf_ptr == NULL ) ) { + + } + + int_conf_ptr->version = H5C__CURR_AUTO_SIZE_CTL_VER; + + if ( ext_conf_ptr->rpt_fcn_enabled ) { + + int_conf_ptr->rpt_fcn = H5C_def_auto_resize_rpt_fcn; + + } else { + + int_conf_ptr->rpt_fcn = NULL; + } + + int_conf_ptr->set_initial_size = ext_conf_ptr->set_initial_size; + int_conf_ptr->initial_size = ext_conf_ptr->initial_size; + int_conf_ptr->min_clean_fraction = ext_conf_ptr->min_clean_fraction; + int_conf_ptr->max_size = ext_conf_ptr->max_size; + int_conf_ptr->min_size = ext_conf_ptr->min_size; + int_conf_ptr->epoch_length = + (int64_t)(ext_conf_ptr->epoch_length); + + int_conf_ptr->incr_mode = ext_conf_ptr->incr_mode; + int_conf_ptr->lower_hr_threshold = ext_conf_ptr->lower_hr_threshold; + int_conf_ptr->increment = ext_conf_ptr->increment; + int_conf_ptr->apply_max_increment = ext_conf_ptr->apply_max_increment; + int_conf_ptr->max_increment = ext_conf_ptr->max_increment; + + int_conf_ptr->decr_mode = ext_conf_ptr->decr_mode; + int_conf_ptr->upper_hr_threshold = ext_conf_ptr->upper_hr_threshold; + int_conf_ptr->decrement = ext_conf_ptr->decrement; + int_conf_ptr->apply_max_decrement = ext_conf_ptr->apply_max_decrement; + int_conf_ptr->max_decrement = ext_conf_ptr->max_decrement; + int_conf_ptr->epochs_before_eviction = + (int32_t)(ext_conf_ptr->epochs_before_eviction); + int_conf_ptr->apply_empty_reserve = ext_conf_ptr->apply_empty_reserve; + int_conf_ptr->empty_reserve = ext_conf_ptr->empty_reserve; + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5AC_ext_config_2_int_config() */ + + +/*------------------------------------------------------------------------- * * Function: H5AC_log_deleted_entry() * diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index 3cbe62e..f492556 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -51,7 +51,8 @@ #define H5AC_SHEAP_ID 9 /*segmented heap */ #define H5AC_BPT_HDR_ID 10 /*B+ tree header */ #define H5AC_BPT_LEAF_ID 11 /*B+ tree leaf */ -#define H5AC_NTYPES 12 +#define H5AC_TEST_ID 12 /*test entry -- not used for actual files */ +#define H5AC_NTYPES 13 /* H5AC_DUMP_STATS_ON_CLOSE should always be FALSE when * H5C_COLLECT_CACHE_STATS is FALSE. @@ -183,7 +184,7 @@ extern hid_t H5AC_ind_dxpl_id; /* hbool_t rpt_fcn_enabled = */ FALSE, \ /* hbool_t set_initial_size = */ TRUE, \ /* size_t initial_size = */ ( 1 * 1024 * 1024), \ - /* double min_clean_fraction = */ 0.25, \ + /* double min_clean_fraction = */ 0.5, \ /* size_t max_size = */ (16 * 1024 * 1024), \ /* size_t min_size = */ ( 1 * 1024 * 1024), \ /* long int epoch_length = */ 50000, \ @@ -199,7 +200,8 @@ extern hid_t H5AC_ind_dxpl_id; /* size_t max_decrement = */ (1 * 1024 * 1024), \ /* int epochs_before_eviction = */ 3, \ /* hbool_t apply_empty_reserve = */ TRUE, \ - /* double empty_reserve = */ 0.1 \ + /* double empty_reserve = */ 0.1, \ + /* int dirty_bytes_threshold = */ (256 * 1024) \ } diff --git a/src/H5ACpublic.h b/src/H5ACpublic.h index 2381ccc..5db8c5a 100644 --- a/src/H5ACpublic.h +++ b/src/H5ACpublic.h @@ -40,9 +40,18 @@ extern "C" { * structure H5AC_cache_config_t * * H5AC_cache_config_t is a public structure intended for use in public APIs. - * At least in its initial incarnation, it is a essentially a copy of - * struct H5C_auto_size_ctl_t, minus the report_fcn field. This is omitted, - * as including it would require us to make H5C_t structure public. + * At least in its initial incarnation, it is basicaly a copy of struct + * H5C_auto_size_ctl_t, minus the report_fcn field, and plus the + * dirty_bytes_threshold field. + * + * The report_fcn field is omitted, as including it would require us to + * make H5C_t structure public. + * + * The dirty_bytes_threshold field does not appear in H5C_auto_size_ctl_t, + * as synchronization between caches on different processes is handled at + * the H5AC level, not at the level of H5C. Note however that there is + * considerable interaction between this value and the other fields in this + * structure. * * The structure is in H5ACpublic.h as we may wish to allow different * configuration options for metadata and raw data caches. @@ -226,6 +235,34 @@ extern "C" { * The value of this field must be in the range [0.0, 1.0]. I would * expect typical values to be in the range of 0.01 to 0.1. * + * + * Parallel Configuration Fields: + * + * In PHDF5, all operations that modify metadata must be executed collectively. + * We used to think that this was enough to ensure consistency across the + * metadata caches, but since we allow processes to read metadata individually, + * the order of dirty entries in the LRU list can vary across processes, + * which can result in inconsistencies between the caches. + * + * To prevent this, only the metadata cache on process 0 is allowed to write + * to file, and then only after synchronizing with the other caches. After + * it writes entries to file, it sends the base addresses of the now clean + * entries to the other caches, so they can mark these entries clean as well. + * + * The different caches know when to synchronize caches by counting the + * number of bytes of dirty metadata created by the collective operations + * modifying metadata. Whenever this count exceeds a user specified + * threshold (see below), process 0 flushes down to its minimum clean size, + * and then sends the list of newly cleaned entries to the other caches. + * + * dirty_bytes_threshold: Threshold of dirty byte creation used to + * synchronize updates between caches. (See above for outline and + * motivation.) + * + * This value MUST be consistant across all processes accessing the + * file. This field is ignored unless HDF5 has been compiled for + * parallel. + * ****************************************************************************/ #define H5AC__CURR_CACHE_CONFIG_VERSION 1 @@ -274,6 +311,10 @@ typedef struct H5AC_cache_config_t hbool_t apply_empty_reserve; double empty_reserve; + + /* parallel configuration fields: */ + int dirty_bytes_threshold; + } H5AC_cache_config_t; @@ -908,6 +908,38 @@ if ( ( (cache_ptr) == NULL ) || \ H5C__UPDATE_STATS_FOR_HT_SEARCH(cache_ptr, (entry_ptr != NULL), depth) \ } +#define H5C__SEARCH_INDEX_NO_STATS(cache_ptr, Addr, entry_ptr, fail_val) \ +{ \ + int k; \ + int depth = 0; \ + H5C__PRE_HT_SEARCH_SC(cache_ptr, Addr, fail_val) \ + k = H5C__HASH_FCN(Addr); \ + entry_ptr = ((cache_ptr)->index)[k]; \ + while ( ( entry_ptr ) && ( H5F_addr_ne(Addr, (entry_ptr)->addr) ) ) \ + { \ + (entry_ptr) = (entry_ptr)->ht_next; \ + (depth)++; \ + } \ + if ( entry_ptr ) \ + { \ + H5C__POST_SUC_HT_SEARCH_SC(cache_ptr, entry_ptr, Addr, k, fail_val) \ + if ( entry_ptr != ((cache_ptr)->index)[k] ) \ + { \ + if ( (entry_ptr)->ht_next ) \ + { \ + (entry_ptr)->ht_next->ht_prev = (entry_ptr)->ht_prev; \ + } \ + HDassert( (entry_ptr)->ht_prev != NULL ); \ + (entry_ptr)->ht_prev->ht_next = (entry_ptr)->ht_next; \ + ((cache_ptr)->index)[k]->ht_prev = (entry_ptr); \ + (entry_ptr)->ht_next = ((cache_ptr)->index)[k]; \ + (entry_ptr)->ht_prev = NULL; \ + ((cache_ptr)->index)[k] = (entry_ptr); \ + H5C__POST_HT_SHIFT_TO_FRONT(cache_ptr, entry_ptr, k, fail_val) \ + } \ + } \ +} + #define H5C__UPDATE_INDEX_FOR_SIZE_CHANGE(cache_ptr, old_size, new_size) \ { \ H5C__PRE_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size) \ @@ -1088,6 +1120,117 @@ if ( ( (cache_ptr) == NULL ) || \ /*------------------------------------------------------------------------- * + * Macro: H5C__FAKE_RP_FOR_MOST_RECENT_ACCESS + * + * Purpose: For efficiency, we sometimes change the order of flushes -- + * but doing so can confuse the replacement policy. This + * macro exists to allow us to specify an entry as the + * most recently touched so we can repair any such + * confusion. + * + * At present, we only support the modified LRU policy, so + * this function deals with that case unconditionally. If + * we ever support other replacement policies, the macro + * should switch on the current policy and act accordingly. + * + * Return: N/A + * + * Programmer: John Mainzer, 10/13/05 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +#if H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS + +#define H5C__FAKE_RP_FOR_MOST_RECENT_ACCESS(cache_ptr, entry_ptr, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C__H5C_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( (entry_ptr)->size > 0 ); \ + \ + /* modified LRU specific code */ \ + \ + /* remove the entry from the LRU list, and re-insert it at the head. */ \ + \ + H5C__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + H5C__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* Use the dirty flag to infer whether the entry is on the clean or \ + * dirty LRU list, and remove it. Then insert it at the head of the \ + * same LRU list. \ + * \ + * At least initially, all entries should be clean. That may change, \ + * so we may as well deal with both cases now. \ + */ \ + \ + if ( (entry_ptr)->is_dirty ) { \ + H5C__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ + (cache_ptr)->dLRU_tail_ptr, \ + (cache_ptr)->dLRU_list_len, \ + (cache_ptr)->dLRU_list_size, (fail_val)) \ + \ + H5C__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ + (cache_ptr)->dLRU_tail_ptr, \ + (cache_ptr)->dLRU_list_len, \ + (cache_ptr)->dLRU_list_size, (fail_val)) \ + } else { \ + H5C__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ + (cache_ptr)->cLRU_tail_ptr, \ + (cache_ptr)->cLRU_list_len, \ + (cache_ptr)->cLRU_list_size, (fail_val)) \ + \ + H5C__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ + (cache_ptr)->cLRU_tail_ptr, \ + (cache_ptr)->cLRU_list_len, \ + (cache_ptr)->cLRU_list_size, (fail_val)) \ + } \ + \ + /* End modified LRU specific code. */ \ + \ +} /* H5C__FAKE_RP_FOR_MOST_RECENT_ACCESS */ + +#else /* H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + +#define H5C__FAKE_RP_FOR_MOST_RECENT_ACCESS(cache_ptr, entry_ptr, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C__H5C_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( (entry_ptr)->size > 0 ); \ + \ + /* modified LRU specific code */ \ + \ + /* remove the entry from the LRU list, and re-insert it at the head. */ \ + \ + H5C__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + H5C__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* End modified LRU specific code. */ \ + \ +} /* H5C__FAKE_RP_FOR_MOST_RECENT_ACCESS */ + +#endif /* H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + + +/*------------------------------------------------------------------------- + * * Macro: H5C__UPDATE_RP_FOR_EVICTION * * Purpose: Update the replacement policy data structures for an @@ -2030,6 +2173,9 @@ done: * 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. + * *------------------------------------------------------------------------- */ @@ -2199,6 +2345,7 @@ H5C_create(size_t max_cache_size, cache_ptr->skip_file_checks = FALSE; cache_ptr->skip_dxpl_id_checks = FALSE; + cache_ptr->prefix[0] = '\0'; /* empty string */ /* Set return value */ ret_value = cache_ptr; @@ -2244,6 +2391,10 @@ done: * Reworked function to adapt it to the addition of the * ageout method of cache size reduction. * + * JRM -- 1/19/06 + * Updated function for display the new prefix field of + * H5C_t in output. + * *------------------------------------------------------------------------- */ void @@ -2263,25 +2414,27 @@ H5C_def_auto_resize_rpt_fcn(H5C_t * cache_ptr, switch ( status ) { case in_spec: - HDfprintf(stdout, "Auto cache resize -- no change. "); - HDfprintf(stdout, "(hit rate = %lf)\n", hit_rate); + HDfprintf(stdout, + "%sAuto cache resize -- no change. (hit rate = %lf)\n", + cache_ptr->prefix, hit_rate); break; case increase: HDassert( hit_rate < (cache_ptr->resize_ctl).lower_hr_threshold ); HDassert( old_max_cache_size < new_max_cache_size ); - HDfprintf(stdout, "Auto cache resize -- hit rate (%lf) ", hit_rate); - - HDfprintf(stdout, "out of bounds low (%6.5lf).\n", + HDfprintf(stdout, + "%sAuto cache resize -- hit rate (%lf) out of bounds low (%6.5lf).\n", + cache_ptr->prefix, hit_rate, (cache_ptr->resize_ctl).lower_hr_threshold); HDfprintf(stdout, - " cache size increased from (%Zu/%Zu) to (%Zu/%Zu).\n", - old_max_cache_size, - old_min_clean_size, - new_max_cache_size, - new_min_clean_size); + "%s cache size increased from (%Zu/%Zu) to (%Zu/%Zu).\n", + cache_ptr->prefix, + old_max_cache_size, + old_min_clean_size, + new_max_cache_size, + new_min_clean_size); break; case decrease: @@ -2294,20 +2447,19 @@ H5C_def_auto_resize_rpt_fcn(H5C_t * cache_ptr, (cache_ptr->resize_ctl).upper_hr_threshold ); HDfprintf(stdout, - "Auto cache resize -- decrease by threshold. "); - - HDfprintf(stdout, "HR = %lf > %6.5lf\n", - hit_rate, + "%sAuto cache resize -- decrease by threshold. HR = %lf > %6.5lf\n", + cache_ptr->prefix, hit_rate, (cache_ptr->resize_ctl).upper_hr_threshold); - HDfprintf(stdout, "out of bounds high (%6.5lf).\n", + HDfprintf(stdout, "%sout of bounds high (%6.5lf).\n", + cache_ptr->prefix, (cache_ptr->resize_ctl).upper_hr_threshold); break; case H5C_decr__age_out: HDfprintf(stdout, - "Auto cache resize -- decrease by ageout. "); - HDfprintf(stdout, "HR = %lf\n", hit_rate); + "%sAuto cache resize -- decrease by ageout. HR = %lf\n", + cache_ptr->prefix, hit_rate); break; case H5C_decr__age_out_with_threshold: @@ -2315,20 +2467,20 @@ H5C_def_auto_resize_rpt_fcn(H5C_t * cache_ptr, (cache_ptr->resize_ctl).upper_hr_threshold ); HDfprintf(stdout, - "Auto cache resize -- decrease by ageout with "); - HDfprintf(stdout, "threshold. HR = %lf > %6.5lf\n", - hit_rate, + "%sAuto cache resize -- decrease by ageout with threshold. HR = %lf > %6.5lf\n", + cache_ptr->prefix, hit_rate, (cache_ptr->resize_ctl).upper_hr_threshold); break; default: HDfprintf(stdout, - "Auto cache resize -- decrease by unknown mode."); - HDfprintf(stdout, " HR = %lf\n", hit_rate); + "%sAuto cache resize -- decrease by unknown mode. HR = %lf\n", + cache_ptr->prefix, hit_rate); } HDfprintf(stdout, - " cache size decreased from (%Zu/%Zu) to (%Zu/%Zu).\n", + "%s cache size decreased from (%Zu/%Zu) to (%Zu/%Zu).\n", + cache_ptr->prefix, old_max_cache_size, old_min_clean_size, new_max_cache_size, @@ -2336,39 +2488,50 @@ H5C_def_auto_resize_rpt_fcn(H5C_t * cache_ptr, break; case at_max_size: - HDfprintf(stdout, "Auto cache resize -- hit rate (%lf) ", hit_rate); - HDfprintf(stdout, "out of bounds low (%6.5lf).\n", + HDfprintf(stdout, + "%sAuto cache resize -- hit rate (%lf) out of bounds low (%6.5lf).\n", + cache_ptr->prefix, hit_rate, (cache_ptr->resize_ctl).lower_hr_threshold); - HDfprintf(stdout, " cache already at maximum size so no change.\n"); + HDfprintf(stdout, + "%s cache already at maximum size so no change.\n", + cache_ptr->prefix); break; case at_min_size: - HDfprintf(stdout, "Auto cache resize -- hit rate (%lf) ", hit_rate); - HDfprintf(stdout, "-- can't decrease.\n"); - HDfprintf(stdout, " cache already at minimum size.\n"); + HDfprintf(stdout, + "%sAuto cache resize -- hit rate (%lf) -- can't decrease.\n", + cache_ptr->prefix, hit_rate); + HDfprintf(stdout, "%s cache already at minimum size.\n", + cache_ptr->prefix); break; case increase_disabled: - HDfprintf(stdout, "Auto cache resize -- increase disabled -- "); - HDfprintf(stdout, "HR = %lf.", hit_rate); + HDfprintf(stdout, + "%sAuto cache resize -- increase disabled -- HR = %lf.", + cache_ptr->prefix, hit_rate); break; case decrease_disabled: - HDfprintf(stdout, "Auto cache resize -- decrease disabled -- "); - HDfprintf(stdout, "HR = %lf.\n", hit_rate); + HDfprintf(stdout, + "%sAuto cache resize -- decrease disabled -- HR = %lf.\n", + cache_ptr->prefix, hit_rate); break; case not_full: HDassert( hit_rate < (cache_ptr->resize_ctl).lower_hr_threshold ); - HDfprintf(stdout, "Auto cache resize -- hit rate (%lf) ", hit_rate); - HDfprintf(stdout, "out of bounds low (%6.5lf).\n", + HDfprintf(stdout, + "%sAuto cache resize -- hit rate (%lf) out of bounds low (%6.5lf).\n", + cache_ptr->prefix, hit_rate, (cache_ptr->resize_ctl).lower_hr_threshold); - HDfprintf(stdout, " cache not full so no increase in size.\n"); + HDfprintf(stdout, + "%s cache not full so no increase in size.\n", + cache_ptr->prefix); break; default: - HDfprintf(stdout, "Auto cache resize -- unknown status code.\n"); + HDfprintf(stdout, "%sAuto cache resize -- unknown status code.\n", + cache_ptr->prefix); break; } @@ -2549,6 +2712,21 @@ done: * H5C__FLUSH_MARKED_ENTRIES_FLAG, it will only apply to * the marked entries. * + * JRM -- 10/15/05 + * Added code supporting the new + * H5C__FLUSH_IGNORE_PROTECTED_FLAG. We need this flag, as + * we now use this function to flush large number of entries + * in increasing address order. We do this by marking the + * entries to be flushed, calling this function to flush them, + * and then restoring LRU order. + * + * However, it is possible that the cache will contain other, + * unmarked entries, when we make this call. This new flag + * allows us to ignore this. + * + * Note that even with this flag set, it is still an error + * to try to flush a protected entry. + * *------------------------------------------------------------------------- */ herr_t @@ -2563,6 +2741,8 @@ H5C_flush_cache(H5F_t * f, hbool_t destroy; hbool_t flush_marked_entries; hbool_t first_flush = TRUE; + hbool_t ignore_protected; + hbool_t tried_to_flush_protected_entry = FALSE; int32_t protected_entries = 0; int32_t i; H5SL_node_t * node_ptr = NULL; @@ -2581,6 +2761,8 @@ H5C_flush_cache(H5F_t * f, HDassert( cache_ptr->skip_file_checks || f ); HDassert( cache_ptr->slist_ptr ); + ignore_protected = ( (flags & H5C__FLUSH_IGNORE_PROTECTED_FLAG) != 0 ); + destroy = ( (flags & H5C__FLUSH_INVALIDATE_FLAG) != 0 ); /* note that flush_marked_entries is set to FALSE if destroy is TRUE */ @@ -2589,6 +2771,8 @@ H5C_flush_cache(H5F_t * f, ( ! destroy ) ); + HDassert( ! ( destroy && ignore_protected ) ); + if ( ( destroy ) && ( cache_ptr->epoch_markers_active > 0 ) ) { status = H5C__autoadjust__ageout__remove_all_markers(cache_ptr); @@ -2643,9 +2827,11 @@ H5C_flush_cache(H5F_t * f, if ( entry_ptr->is_protected ) { - /* we have major problems -- but lets flush everything - * we can before we flag an error. + /* 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++; } else { @@ -2777,7 +2963,9 @@ H5C_flush_cache(H5F_t * f, HDassert( protected_entries <= cache_ptr->pl_len ); - if ( cache_ptr->pl_len > 0 ) { + if ( ( ( cache_ptr->pl_len > 0 ) && ( !ignore_protected ) ) + || + ( tried_to_flush_protected_entry ) ) { HGOTO_ERROR(H5E_CACHE, H5E_PROTECT, FAIL, "cache has protected items") } @@ -2813,8 +3001,26 @@ done: * * Modifications: * - * None. + * Re-wrote function to flush dirty entries in increasing + * address order, while maintaining LRU order in the LRU list + * upon return. + * + * Do this by scanning up the dirty LRU list for entries to + * flush to reach min clean size, setting their flush_marker + * flags, and recording their addresses in the order + * encountered. + * + * Then call H5C_flush_cache() to flush the marked entries. * + * Finally, use the list of marked entries to force the + * correct LRU list order after the flush. + * + * JRM - 10/13/05 + * + * This change had the oposite of the desired effect. Lets + * leave it in (albeit commented out for now). If we can't + * find a case where it helps, lets get rid of it. + * *------------------------------------------------------------------------- */ herr_t @@ -2823,10 +3029,18 @@ H5C_flush_to_min_clean(H5F_t * f, hid_t secondary_dxpl_id, H5C_t * cache_ptr) { - herr_t result; + herr_t result; herr_t ret_value = SUCCEED; hbool_t first_flush = TRUE; hbool_t write_permitted; +#if 0 /* modified code -- commented out for now */ + int i; + int flushed_entries_count = 0; + size_t flushed_entries_size = 0; + size_t space_needed = 0; + haddr_t * flushed_entries_list = NULL; + H5C_cache_entry_t * entry_ptr = NULL; +#endif /* JRM */ FUNC_ENTER_NOAPI(H5C_flush_to_min_clean, FAIL) @@ -2855,8 +3069,7 @@ H5C_flush_to_min_clean(H5F_t * f, HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ "cache write is not permitted!?!\n"); } - - +#if 1 /* original code */ result = H5C_make_space_in_cache(f, primary_dxpl_id, secondary_dxpl_id, @@ -2870,6 +3083,115 @@ H5C_flush_to_min_clean(H5F_t * f, HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ "H5C_make_space_in_cache failed.") } +#else /* modified code -- commented out for now */ + 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 ) { + + space_needed = 0; + + } else { + + space_needed = cache_ptr->min_clean_size - + ((cache_ptr->max_cache_size - cache_ptr->index_size) + + cache_ptr->cLRU_list_size); + } + } else { + + if ( cache_ptr->min_clean_size <= cache_ptr->cLRU_list_size ) { + + space_needed = 0; + + } else { + + space_needed = cache_ptr->min_clean_size - + cache_ptr->cLRU_list_size; + } + } + + if ( space_needed > 0 ) { /* we have work to do */ + + HDassert( cache_ptr->slist_len > 0 ); + + /* allocate an array to keep a list of the entries that we + * mark for flush. We need this list to touch up the LRU + * list after the flush. + */ + flushed_entries_list = (haddr_t *)H5MM_malloc(sizeof(haddr_t) * + (size_t)(cache_ptr->slist_len)); + + if ( flushed_entries_list == NULL ) { + + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ + "memory allocation failed for flushed entries list") + } + + /* Scan the dirty LRU list from tail forward and mark sufficient + * entries to free up the necessary space. Keep a list of the + * entries marked in the order in which they are encountered. + */ + entry_ptr = cache_ptr->dLRU_tail_ptr; + + while ( ( flushed_entries_size < space_needed ) && + ( flushed_entries_count < cache_ptr->slist_len ) && + ( entry_ptr != NULL ) ) + { + HDassert( ! (entry_ptr->is_protected) ); + HDassert( entry_ptr->is_dirty ); + HDassert( entry_ptr->in_slist ); + + entry_ptr->flush_marker = TRUE; + flushed_entries_size += entry_ptr->size; + flushed_entries_list[flushed_entries_count] = entry_ptr->addr; + flushed_entries_count++; + entry_ptr = entry_ptr->aux_prev; + } + + if ( ( flushed_entries_count > cache_ptr->slist_len) || + ( flushed_entries_size < space_needed ) ) { + HDfprintf(stdout, "flushed_entries_count = %d <= %d = slist_size\n", + (int)flushed_entries_count, (int)(cache_ptr->slist_size)); + HDfprintf(stdout, + "flushed_entries_size = %d < %d = space_needed.\n", + (int)flushed_entries_size, (int)space_needed); + } + + HDassert( flushed_entries_count <= cache_ptr->slist_len ); + HDassert( flushed_entries_size >= space_needed ); + + + /* Flush the marked entries */ + result = H5C_flush_cache(f, primary_dxpl_id, secondary_dxpl_id, + cache_ptr, H5C__FLUSH_MARKED_ENTRIES_FLAG | + H5C__FLUSH_IGNORE_PROTECTED_FLAG); + + if ( result < 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C_flush_cache failed.") + } + + /* Now touch up the LRU list so as to place the flushed entries in + * the order they they would be in if we had flushed them in the + * order we encountered them in. + */ + + i = 0; + while ( i < flushed_entries_count ) + { + H5C__SEARCH_INDEX_NO_STATS(cache_ptr, flushed_entries_list[i], \ + entry_ptr, FAIL) + + /* At present, the above search must always succeed. However, + * that may change. Write the code so we need only remove the + * following assert in that event. + */ + HDassert( entry_ptr != NULL ); + H5C__FAKE_RP_FOR_MOST_RECENT_ACCESS(cache_ptr, entry_ptr, FAIL) + i++; + } + } /* if ( space_needed > 0 ) */ +#endif /* end modified code -- commented out for now */ done: @@ -3445,6 +3767,15 @@ done: * * Modifications: * + * Reworked function to flush entries in LRU order instead + * of increasing address order. The hope is that this will + * improve the hit rate on the slave caches. + * + * JRM - 10/13/05 + * + * Leave the old code in place for now (commented out) for + * benchmarking. + * *------------------------------------------------------------------------- */ @@ -3459,11 +3790,15 @@ H5C_mark_entries_as_clean(H5F_t * f, { herr_t ret_value = SUCCEED; /* Return value */ hbool_t first_flush = TRUE; + int entries_cleared; + int entries_examined; int i; + int initial_list_len; haddr_t addr; #if H5C_DO_SANITY_CHECKS haddr_t last_addr; #endif /* H5C_DO_SANITY_CHECKS */ + H5C_cache_entry_t * clear_ptr = NULL; H5C_cache_entry_t * entry_ptr = NULL; FUNC_ENTER_NOAPI(H5C_mark_entries_as_clean, FAIL) @@ -3540,7 +3875,7 @@ H5C_mark_entries_as_clean(H5F_t * f, #endif /* H5C_DO_SANITY_CHECKS */ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ "Listed entry not dirty?!?!?.") - +#if 0 /* original code */ } else if ( entry_ptr->is_protected ) { entry_ptr->clear_on_unprotect = TRUE; @@ -3560,7 +3895,75 @@ H5C_mark_entries_as_clean(H5F_t * f, HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't clear entry.") } } +#else /* modified code -- commented out for now */ + } else { + /* Mark the entry to be cleared on unprotect. We will + * scan the LRU list shortly, and clear all those entries + * not currently protected. + */ + entry_ptr->clear_on_unprotect = TRUE; + } +#endif /* end modified code */ + } +#if 1 /* modified code -- commented out for now */ + /* Scan through the LRU list from back to front, and flush the + * entries whose clear_on_unprotect flags are set. Observe that + * any protected entries will not be on the LRU, and therefore + * will not be flushed at this time. + */ + + entries_cleared = 0; + entries_examined = 0; + initial_list_len = cache_ptr->LRU_list_len; + entry_ptr = cache_ptr->LRU_tail_ptr; + + while ( ( entry_ptr != NULL ) && + ( entries_examined <= initial_list_len ) && + ( entries_cleared < ce_array_len ) ) + { + if ( entry_ptr->clear_on_unprotect ) { + + entry_ptr->clear_on_unprotect = FALSE; + clear_ptr = entry_ptr; + entry_ptr = entry_ptr->prev; + entries_cleared++; + + if ( H5C_flush_single_entry(f, + primary_dxpl_id, + secondary_dxpl_id, + cache_ptr, + clear_ptr->type, + clear_ptr->addr, + H5C__FLUSH_CLEAR_ONLY_FLAG, + &first_flush, + TRUE) < 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't clear entry.") + } + } else { + + entry_ptr = entry_ptr->prev; + } + entries_examined++; + } + + HDassert( ( entries_cleared == ce_array_len ) || + ( (ce_array_len - entries_cleared) <= cache_ptr->pl_len ) ); + +#if H5C_DO_SANITY_CHECKS + i = 0; + entry_ptr = cache_ptr->pl_head_ptr; + while ( entry_ptr != NULL ) + { + if ( entry_ptr->clear_on_unprotect ) { + + i++; + } + entry_ptr = entry_ptr->next; } + HDassert( (entries_cleared + i) == ce_array_len ); +#endif /* H5C_DO_SANITY_CHECKS */ +#endif /* modified code -- commented out for now */ done: @@ -3772,6 +4175,9 @@ done: * JRM -- 6/24/05 * Added support for the new write_permitted field of H5C_t. * + * JRM -- 10/22/05 + * Hand optimizations. + * *------------------------------------------------------------------------- */ @@ -3785,14 +4191,14 @@ H5C_protect(H5F_t * f, const void * udata1, void * udata2) { - hbool_t hit = FALSE; - hbool_t first_flush = TRUE; + hbool_t hit; + hbool_t first_flush; hbool_t have_write_permitted = FALSE; - hbool_t write_permitted = TRUE; + hbool_t write_permitted; herr_t result; - void * thing = NULL; + void * thing; H5C_cache_entry_t * entry_ptr; - void * ret_value = NULL; /* Return value */ + void * ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5C_protect, NULL) @@ -3858,12 +4264,16 @@ H5C_protect(H5F_t * f, } else { have_write_permitted = TRUE; + + first_flush = TRUE; } } else { write_permitted = cache_ptr->write_permitted; have_write_permitted = TRUE; + + first_flush = TRUE; } HDassert( entry_ptr->size <= H5C_MAX_ENTRY_SIZE ); @@ -3966,12 +4376,16 @@ H5C_protect(H5F_t * f, } else { have_write_permitted = TRUE; + + first_flush = TRUE; } } else { write_permitted = cache_ptr->write_permitted; have_write_permitted = TRUE; + + first_flush = TRUE; } } @@ -4327,6 +4741,49 @@ done: /*------------------------------------------------------------------------- + * Function: H5C_set_prefix + * + * Purpose: Set the values of the prefix field of H5C_t. This + * filed is used to label some debugging output. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: John Mainzer + * 1/20/06 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +herr_t +H5C_set_prefix(H5C_t * cache_ptr, + char * prefix) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5C_set_prefix, FAIL) + + /* This would normally be an assert, but we need to use an HGOTO_ERROR + * call to shut up the compiler. + */ + if ( ( ! cache_ptr ) || ( cache_ptr->magic != H5C__H5C_T_MAGIC ) ) { + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad cache_ptr") + } + + HDassert( prefix ); + HDassert( HDstrlen(prefix) < H5C__PREFIX_LEN ) ; + + HDstrcpy(&(cache_ptr->prefix[0]), prefix); + +done: + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5C_set_prefix() */ + + +/*------------------------------------------------------------------------- * Function: H5C_set_skip_flags * * Purpose: Set the values of the skip sanity check flags. @@ -4390,6 +4847,10 @@ done: * Updated function for the addition of cache entry size * change statistics. * + * JRM -- 1/13/06 + * Added code to use the prefix field of H5C_t to allow + * tagging of statistics output. + * *------------------------------------------------------------------------- */ @@ -4489,93 +4950,109 @@ H5C_stats(H5C_t * cache_ptr, } - HDfprintf(stdout, "\nH5C: cache statistics for %s\n", - cache_name); + HDfprintf(stdout, "\n%sH5C: cache statistics for %s\n", + cache_ptr->prefix, cache_name); HDfprintf(stdout, "\n"); HDfprintf(stdout, - " hash table insertion / deletions = %ld / %ld\n", + "%s hash table insertion / deletions = %ld / %ld\n", + cache_ptr->prefix, (long)(cache_ptr->total_ht_insertions), (long)(cache_ptr->total_ht_deletions)); HDfprintf(stdout, - " HT successful / failed searches = %ld / %ld\n", + "%s HT successful / failed searches = %ld / %ld\n", + cache_ptr->prefix, (long)(cache_ptr->successful_ht_searches), (long)(cache_ptr->failed_ht_searches)); HDfprintf(stdout, - " Av. HT suc / failed search depth = %f / %f\n", + "%s Av. HT suc / failed search depth = %f / %f\n", + cache_ptr->prefix, average_successful_search_depth, average_failed_search_depth); HDfprintf(stdout, - " current (max) index size / length = %ld (%ld) / %ld (%ld)\n", + "%s current (max) index size / length = %ld (%ld) / %ld (%ld)\n", + cache_ptr->prefix, (long)(cache_ptr->index_size), (long)(cache_ptr->max_index_size), (long)(cache_ptr->index_len), (long)(cache_ptr->max_index_len)); HDfprintf(stdout, - " current (max) slist size / length = %ld (%ld) / %ld (%ld)\n", + "%s current (max) slist size / length = %ld (%ld) / %ld (%ld)\n", + cache_ptr->prefix, (long)(cache_ptr->slist_size), (long)(cache_ptr->max_slist_size), (long)(cache_ptr->slist_len), (long)(cache_ptr->max_slist_len)); HDfprintf(stdout, - " current (max) PL size / length = %ld (%ld) / %ld (%ld)\n", + "%s current (max) PL size / length = %ld (%ld) / %ld (%ld)\n", + cache_ptr->prefix, (long)(cache_ptr->pl_size), (long)(cache_ptr->max_pl_size), (long)(cache_ptr->pl_len), (long)(cache_ptr->max_pl_len)); HDfprintf(stdout, - " current LRU list size / length = %ld / %ld\n", + "%s current LRU list size / length = %ld / %ld\n", + cache_ptr->prefix, (long)(cache_ptr->LRU_list_size), (long)(cache_ptr->LRU_list_len)); HDfprintf(stdout, - " current clean LRU size / length = %ld / %ld\n", + "%s current clean LRU size / length = %ld / %ld\n", + cache_ptr->prefix, (long)(cache_ptr->cLRU_list_size), (long)(cache_ptr->cLRU_list_len)); HDfprintf(stdout, - " current dirty LRU size / length = %ld / %ld\n", + "%s current dirty LRU size / length = %ld / %ld\n", + cache_ptr->prefix, (long)(cache_ptr->dLRU_list_size), (long)(cache_ptr->dLRU_list_len)); HDfprintf(stdout, - " Total hits / misses / hit_rate = %ld / %ld / %f\n", + "%s Total hits / misses / hit_rate = %ld / %ld / %f\n", + cache_ptr->prefix, (long)total_hits, (long)total_misses, hit_rate); HDfprintf(stdout, - " Total clears / flushes / evictions = %ld / %ld / %ld\n", + "%s Total clears / flushes / evictions = %ld / %ld / %ld\n", + cache_ptr->prefix, (long)total_clears, (long)total_flushes, (long)total_evictions); - HDfprintf(stdout, " Total insertions / renames = %ld / %ld\n", + HDfprintf(stdout, "%s Total insertions / renames = %ld / %ld\n", + cache_ptr->prefix, (long)total_insertions, (long)total_renames); - HDfprintf(stdout, " Total entry size incrs / decrs = %ld / %ld\n", + HDfprintf(stdout, "%s Total entry size incrs / decrs = %ld / %ld\n", + cache_ptr->prefix, (long)total_size_increases, (long)total_size_decreases); #if H5C_COLLECT_CACHE_ENTRY_STATS - HDfprintf(stdout, " aggregate max / min accesses = %d / %d\n", + HDfprintf(stdout, "%s aggregate max / min accesses = %d / %d\n", + cache_ptr->prefix, (int)aggregate_max_accesses, (int)aggregate_min_accesses); - HDfprintf(stdout, " aggregate max_clears / max_flushes = %d / %d\n", + HDfprintf(stdout, "%s aggregate max_clears / max_flushes = %d / %d\n", + cache_ptr->prefix, (int)aggregate_max_clears, (int)aggregate_max_flushes); - HDfprintf(stdout, " aggregate max_size = %d\n", + HDfprintf(stdout, "%s aggregate max_size = %d\n", + cache_ptr->prefix, (int)aggregate_max_size); @@ -4588,7 +5065,8 @@ H5C_stats(H5C_t * cache_ptr, HDfprintf(stdout, "\n"); - HDfprintf(stdout, " Stats on %s:\n", + HDfprintf(stdout, "%s Stats on %s:\n", + cache_ptr->prefix, ((cache_ptr->type_name_table_ptr))[i]); if ( ( cache_ptr->hits[i] > 0 ) || ( cache_ptr->misses[i] > 0 ) ) { @@ -4600,41 +5078,48 @@ H5C_stats(H5C_t * cache_ptr, } HDfprintf(stdout, - " hits / misses / hit_rate = %ld / %ld / %f\n", + "%s hits / misses / hit_rate = %ld / %ld / %f\n", + cache_ptr->prefix, (long)(cache_ptr->hits[i]), (long)(cache_ptr->misses[i]), hit_rate); HDfprintf(stdout, - " clears / flushes / evictions = %ld / %ld / %ld\n", + "%s clears / flushes / evictions = %ld / %ld / %ld\n", + cache_ptr->prefix, (long)(cache_ptr->clears[i]), (long)(cache_ptr->flushes[i]), (long)(cache_ptr->evictions[i])); HDfprintf(stdout, - " insertions / renames = %ld / %ld\n", + "%s insertions / renames = %ld / %ld\n", + cache_ptr->prefix, (long)(cache_ptr->insertions[i]), (long)(cache_ptr->renames[i])); HDfprintf(stdout, - " size increases / decreases = %ld / %ld\n", + "%s size increases / decreases = %ld / %ld\n", + cache_ptr->prefix, (long)(cache_ptr->size_increases[i]), (long)(cache_ptr->size_decreases[i])); #if H5C_COLLECT_CACHE_ENTRY_STATS HDfprintf(stdout, - " entry max / min accesses = %d / %d\n", + "%s entry max / min accesses = %d / %d\n", + cache_ptr->prefix, cache_ptr->max_accesses[i], cache_ptr->min_accesses[i]); HDfprintf(stdout, - " entry max_clears / max_flushes = %d / %d\n", + "%s entry max_clears / max_flushes = %d / %d\n", + cache_ptr->prefix, cache_ptr->max_clears[i], cache_ptr->max_flushes[i]); HDfprintf(stdout, - " entry max_size = %d\n", + "%s entry max_size = %d\n", + cache_ptr->prefix, (int)(cache_ptr->max_size[i])); @@ -6903,6 +7388,11 @@ done: * JRM -- 12/13/04 * Added code to skip over epoch markers if present. * + * JRM -- 1/3/06 + * Modified function to work correctly when the the cache + * is not full. This case occurs when we need to flush to + * min clean size before the cache has filled. + * *------------------------------------------------------------------------- */ @@ -6919,6 +7409,9 @@ H5C_make_space_in_cache(H5F_t * f, herr_t result; int32_t entries_examined = 0; int32_t initial_list_len; +#if H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS + size_t empty_space; +#endif /* H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ H5C_cache_entry_t * entry_ptr; H5C_cache_entry_t * prev_ptr; @@ -6995,7 +7488,17 @@ H5C_make_space_in_cache(H5F_t * f, initial_list_len = cache_ptr->dLRU_list_len; entry_ptr = cache_ptr->dLRU_tail_ptr; - while ( ( cache_ptr->cLRU_list_size < cache_ptr->min_clean_size ) && + if ( cache_ptr->index_size < cache_ptr->max_cache_size ) { + + empty_space = cache_ptr->max_cache_size - cache_ptr->index_size; + + } else { + + empty_space = 0; + } + + while ( ( (cache_ptr->cLRU_list_size + empty_space) + < cache_ptr->min_clean_size ) && ( entries_examined <= initial_list_len ) && ( entry_ptr != NULL ) ) diff --git a/src/H5Cpkg.h b/src/H5Cpkg.h index 007f30f..eb8db3a 100644 --- a/src/H5Cpkg.h +++ b/src/H5Cpkg.h @@ -187,7 +187,8 @@ * on how frequently the cache is flushed. We will see how it goes. * * For now at least, I will not remove dirty entries from the list as they - * are flushed. + * are flushed. (this has been changed -- dirty entries are now removed from + * the skip list as they are flushed. JRM - 10/25/05) * * slist_len: Number of entries currently in the skip list * used to maintain a sorted list of dirty entries in the @@ -601,10 +602,15 @@ * When this flag is set, all sanity checks on the dxpl_id * parameters are skipped. The field defaults to FALSE. * + * prefix Array of char used to prefix debugging output. The + * field is intended to allow marking of output of with + * the processes mpi rank. + * ****************************************************************************/ #define H5C__H5C_T_MAGIC 0x005CAC0E -#define H5C__MAX_NUM_TYPE_IDS 12 +#define H5C__MAX_NUM_TYPE_IDS 13 +#define H5C__PREFIX_LEN 32 struct H5C_t { @@ -715,7 +721,7 @@ struct H5C_t hbool_t skip_file_checks; hbool_t skip_dxpl_id_checks; - + char prefix[H5C__PREFIX_LEN]; }; #endif /* _H5Cpkg_H */ diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h index 57d74af..c7d0313 100644 --- a/src/H5Cprivate.h +++ b/src/H5Cprivate.h @@ -699,20 +699,25 @@ typedef struct H5C_auto_size_ctl_t */ /* Generic "no flags set" value for all function calls */ -#define H5C__NO_FLAGS_SET 0x0000 +#define H5C__NO_FLAGS_SET 0x0000 /* These flags apply to H5C_insert_entry() & H5C_unprotect() */ -#define H5C__SET_FLUSH_MARKER_FLAG 0x0001 -#define H5C__DELETED_FLAG 0x0002 +#define H5C__SET_FLUSH_MARKER_FLAG 0x0001 +#define H5C__DELETED_FLAG 0x0002 /* These flags applies only to H5C_unprotect() */ -#define H5C__DIRTIED_FLAG 0x0004 -#define H5C__SIZE_CHANGED_FLAG 0x0008 +#define H5C__DIRTIED_FLAG 0x0004 +#define H5C__SIZE_CHANGED_FLAG 0x0008 -/* These flags apply to H5C_flush() & H5C_flush_single_entry() */ -#define H5C__FLUSH_INVALIDATE_FLAG 0x0010 -#define H5C__FLUSH_CLEAR_ONLY_FLAG 0x0020 -#define H5C__FLUSH_MARKED_ENTRIES_FLAG 0x0040 +/* These flags apply to H5C_flush_cache() & H5C_flush_single_entry() */ +#define H5C__FLUSH_INVALIDATE_FLAG 0x0010 +#define H5C__FLUSH_CLEAR_ONLY_FLAG 0x0020 +#define H5C__FLUSH_MARKED_ENTRIES_FLAG 0x0040 + +/* This flag applies to H5C_flush_cache() only. It is an error to use + * it in combination with the H5C__FLUSH_INVALIDATE_FLAG + */ +#define H5C__FLUSH_IGNORE_PROTECTED_FLAG 0x0080 H5_DLL H5C_t * H5C_create(size_t max_cache_size, @@ -805,6 +810,8 @@ H5_DLL herr_t H5C_reset_cache_hit_rate_stats(H5C_t * cache_ptr); 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_prefix(H5C_t * cache_ptr, char * prefix); + H5_DLL herr_t H5C_set_skip_flags(H5C_t * cache_ptr, hbool_t skip_file_checks, hbool_t skip_dxpl_id_checks); |