summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJohn Mainzer <mainzer@hdfgroup.org>2006-01-27 22:58:48 (GMT)
committerJohn Mainzer <mainzer@hdfgroup.org>2006-01-27 22:58:48 (GMT)
commitdfb1f40cbbe847d25368861c6cc1e60cf6dcb17a (patch)
tree0e343f04aa60fd4ae003869e5482044fd5ea080a /src
parent22e5198407aefbc9fb6b514262f99cd868377011 (diff)
downloadhdf5-dfb1f40cbbe847d25368861c6cc1e60cf6dcb17a.zip
hdf5-dfb1f40cbbe847d25368861c6cc1e60cf6dcb17a.tar.gz
hdf5-dfb1f40cbbe847d25368861c6cc1e60cf6dcb17a.tar.bz2
[svn-r11897] Purpose:
1) Add parallel test for metadata cache 2) Split serial test for metadata cache into two parts 3) Fix bug in which cache was flushed needlessly when the cache wasn't full. 4) Performance improvements 5) Update API for parallel cache coherency bug fix. Description: See above. Solution: See above. Platforms tested: h5committest Misc. update:
Diffstat (limited to 'src')
-rw-r--r--src/H5AC.c289
-rw-r--r--src/H5ACprivate.h8
-rw-r--r--src/H5ACpublic.h47
-rw-r--r--src/H5C.c657
-rw-r--r--src/H5Cpkg.h12
-rw-r--r--src/H5Cprivate.h25
6 files changed, 873 insertions, 165 deletions
diff --git a/src/H5AC.c b/src/H5AC.c
index 4b00b52..6e814a4 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -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;
diff --git a/src/H5C.c b/src/H5C.c
index 8ac73e7..b934529 100644
--- a/src/H5C.c
+++ b/src/H5C.c
@@ -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);