#include "H5Cmodule.h"
#define H5F_FRIEND
#include "H5private.h"
#include "H5Cpkg.h"
#include "H5CXprivate.h"
#include "H5Eprivate.h"
#include "H5Fpkg.h"
#include "H5FLprivate.h"
#include "H5Iprivate.h"
#include "H5MFprivate.h"
#include "H5MMprivate.h"
#include "H5Pprivate.h"
#if H5C_DO_MEMORY_SANITY_CHECKS
#define H5C_IMAGE_EXTRA_SPACE 8
#define H5C_IMAGE_SANITY_VALUE "DeadBeef"
#else
#define H5C_IMAGE_EXTRA_SPACE 0
#endif
static herr_t H5C__pin_entry_from_client(H5C_t *cache_ptr,
H5C_cache_entry_t *entry_ptr);
static herr_t H5C__unpin_entry_real(H5C_t *cache_ptr,
H5C_cache_entry_t *entry_ptr, hbool_t update_rp);
static herr_t H5C__unpin_entry_from_client(H5C_t *cache_ptr,
H5C_cache_entry_t *entry_ptr, hbool_t update_rp);
static herr_t H5C__auto_adjust_cache_size(H5F_t *f, hbool_t write_permitted);
static herr_t H5C__autoadjust__ageout(H5F_t * f,
double hit_rate,
enum H5C_resize_status * status_ptr,
size_t * new_max_cache_size_ptr,
hbool_t write_permitted);
static herr_t H5C__autoadjust__ageout__cycle_epoch_marker(H5C_t * cache_ptr);
static herr_t H5C__autoadjust__ageout__evict_aged_out_entries(H5F_t * f,
hbool_t write_permitted);
static herr_t H5C__autoadjust__ageout__insert_new_marker(H5C_t * cache_ptr);
static herr_t H5C__autoadjust__ageout__remove_all_markers(H5C_t * cache_ptr);
static herr_t H5C__autoadjust__ageout__remove_excess_markers(H5C_t * cache_ptr);
static herr_t H5C__flash_increase_cache_size(H5C_t * cache_ptr,
size_t old_entry_size, size_t new_entry_size);
static herr_t H5C__flush_invalidate_cache(H5F_t *f, unsigned flags);
static herr_t H5C_flush_invalidate_ring(H5F_t *f, H5C_ring_t ring, unsigned flags);
static herr_t H5C__flush_ring(H5F_t *f, H5C_ring_t ring, unsigned flags);
static void * H5C_load_entry(H5F_t * f,
#ifdef H5_HAVE_PARALLEL
hbool_t coll_access,
#endif
const H5C_class_t * type,
haddr_t addr,
void * udata);
static herr_t H5C__mark_flush_dep_dirty(H5C_cache_entry_t * entry);
static herr_t H5C__mark_flush_dep_clean(H5C_cache_entry_t * entry);
static herr_t H5C__serialize_ring(H5F_t *f, H5C_ring_t ring);
static herr_t H5C__serialize_single_entry(H5F_t *f, H5C_t *cache_ptr,
H5C_cache_entry_t *entry_ptr);
static herr_t H5C__verify_len_eoa(H5F_t *f, const H5C_class_t * type,
haddr_t addr, size_t *len, hbool_t actual);
#if H5C_DO_SLIST_SANITY_CHECKS
static hbool_t H5C_entry_in_skip_list(H5C_t * cache_ptr,
H5C_cache_entry_t *target_ptr);
#endif
#if H5C_DO_EXTREME_SANITY_CHECKS
static herr_t H5C_validate_lru_list(H5C_t * cache_ptr);
static herr_t H5C_validate_pinned_entry_list(H5C_t * cache_ptr);
static herr_t H5C_validate_protected_entry_list(H5C_t * cache_ptr);
#endif
#ifndef NDEBUG
static void H5C__assert_flush_dep_nocycle(const H5C_cache_entry_t * entry,
const H5C_cache_entry_t * base_entry);
#endif
hbool_t H5_PKG_INIT_VAR = FALSE;
H5FL_DEFINE(H5C_tag_info_t);
H5FL_DEFINE_STATIC(H5C_t);
H5FL_BLK_DEFINE_STATIC(parent);
H5C_t *
H5C_create(size_t max_cache_size,
size_t min_clean_size,
int max_type_id,
const H5C_class_t * const * class_table_ptr,
H5C_write_permitted_func_t check_write_permitted,
hbool_t write_permitted,
H5C_log_flush_func_t log_flush,
void * aux_ptr)
{
int i;
H5C_t * cache_ptr = NULL;
H5C_t * ret_value = NULL;
FUNC_ENTER_NOAPI(NULL)
HDassert( max_cache_size >= H5C__MIN_MAX_CACHE_SIZE );
HDassert( max_cache_size <= H5C__MAX_MAX_CACHE_SIZE );
HDassert( min_clean_size <= max_cache_size );
HDassert( max_type_id >= 0 );
HDassert( max_type_id < H5C__MAX_NUM_TYPE_IDS );
HDassert( class_table_ptr );
for ( i = 0; i <= max_type_id; i++ ) {
HDassert( (class_table_ptr)[i] );
HDassert(HDstrlen((class_table_ptr)[i]->name) > 0);
}
if(NULL == (cache_ptr = H5FL_CALLOC(H5C_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
if(NULL == (cache_ptr->slist_ptr = H5SL_create(H5SL_TYPE_HADDR, NULL)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, NULL, "can't create skip list")
if(NULL == (cache_ptr->tag_list = H5SL_create(H5SL_TYPE_HADDR, NULL)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, NULL, "can't create skip list for tagged entry addresses")
cache_ptr->magic = H5C__H5C_T_MAGIC;
cache_ptr->flush_in_progress = FALSE;
if(NULL == (cache_ptr->log_info = (H5C_log_info_t *)H5MM_calloc(sizeof(H5C_log_info_t))))
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, NULL, "memory allocation failed")
cache_ptr->aux_ptr = aux_ptr;
cache_ptr->max_type_id = max_type_id;
cache_ptr->class_table_ptr = class_table_ptr;
cache_ptr->max_cache_size = max_cache_size;
cache_ptr->min_clean_size = min_clean_size;
cache_ptr->check_write_permitted = check_write_permitted;
cache_ptr->write_permitted = write_permitted;
cache_ptr->log_flush = log_flush;
cache_ptr->evictions_enabled = TRUE;
cache_ptr->close_warning_received = FALSE;
cache_ptr->index_len = 0;
cache_ptr->index_size = (size_t)0;
cache_ptr->clean_index_size = (size_t)0;
cache_ptr->dirty_index_size = (size_t)0;
for(i = 0; i < H5C_RING_NTYPES; i++) {
cache_ptr->index_ring_len[i] = 0;
cache_ptr->index_ring_size[i] = (size_t)0;
cache_ptr->clean_index_ring_size[i] = (size_t)0;
cache_ptr->dirty_index_ring_size[i] = (size_t)0;
cache_ptr->slist_ring_len[i] = 0;
cache_ptr->slist_ring_size[i] = (size_t)0;
}
for(i = 0; i < H5C__HASH_TABLE_LEN; i++)
(cache_ptr->index)[i] = NULL;
cache_ptr->il_len = 0;
cache_ptr->il_size = (size_t)0;
cache_ptr->il_head = NULL;
cache_ptr->il_tail = NULL;
cache_ptr->ignore_tags = FALSE;
cache_ptr->num_objs_corked = 0;
cache_ptr->slist_enabled = ! H5C__SLIST_OPT_ENABLED;
cache_ptr->slist_changed = FALSE;
cache_ptr->slist_len = 0;
cache_ptr->slist_size = (size_t)0;
#if H5C_DO_SANITY_CHECKS
cache_ptr->slist_len_increase = 0;
cache_ptr->slist_size_increase = 0;
#endif
cache_ptr->entries_removed_counter = 0;
cache_ptr->last_entry_removed_ptr = NULL;
cache_ptr->entry_watched_for_removal = NULL;
cache_ptr->pl_len = 0;
cache_ptr->pl_size = (size_t)0;
cache_ptr->pl_head_ptr = NULL;
cache_ptr->pl_tail_ptr = NULL;
cache_ptr->pel_len = 0;
cache_ptr->pel_size = (size_t)0;
cache_ptr->pel_head_ptr = NULL;
cache_ptr->pel_tail_ptr = NULL;
cache_ptr->LRU_list_len = 0;
cache_ptr->LRU_list_size = (size_t)0;
cache_ptr->LRU_head_ptr = NULL;
cache_ptr->LRU_tail_ptr = NULL;
#ifdef H5_HAVE_PARALLEL
cache_ptr->coll_list_len = 0;
cache_ptr->coll_list_size = (size_t)0;
cache_ptr->coll_head_ptr = NULL;
cache_ptr->coll_tail_ptr = NULL;
cache_ptr->coll_write_list = NULL;
#endif
#if H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS
cache_ptr->cLRU_list_len = 0;
cache_ptr->cLRU_list_size = (size_t)0;
cache_ptr->cLRU_head_ptr = NULL;
cache_ptr->cLRU_tail_ptr = NULL;
cache_ptr->dLRU_list_len = 0;
cache_ptr->dLRU_list_size = (size_t)0;
cache_ptr->dLRU_head_ptr = NULL;
cache_ptr->dLRU_tail_ptr = NULL;
#endif
cache_ptr->size_increase_possible = FALSE;
cache_ptr->flash_size_increase_possible = FALSE;
cache_ptr->flash_size_increase_threshold = 0;
cache_ptr->size_decrease_possible = FALSE;
cache_ptr->resize_enabled = FALSE;
cache_ptr->cache_full = FALSE;
cache_ptr->size_decreased = FALSE;
cache_ptr->resize_in_progress = FALSE;
cache_ptr->msic_in_progress = FALSE;
(cache_ptr->resize_ctl).version = H5C__CURR_AUTO_SIZE_CTL_VER;
(cache_ptr->resize_ctl).rpt_fcn = NULL;
(cache_ptr->resize_ctl).set_initial_size = FALSE;
(cache_ptr->resize_ctl).initial_size = H5C__DEF_AR_INIT_SIZE;
(cache_ptr->resize_ctl).min_clean_fraction = H5C__DEF_AR_MIN_CLEAN_FRAC;
(cache_ptr->resize_ctl).max_size = H5C__DEF_AR_MAX_SIZE;
(cache_ptr->resize_ctl).min_size = H5C__DEF_AR_MIN_SIZE;
(cache_ptr->resize_ctl).epoch_length = H5C__DEF_AR_EPOCH_LENGTH;
(cache_ptr->resize_ctl).incr_mode = H5C_incr__off;
(cache_ptr->resize_ctl).lower_hr_threshold = H5C__DEF_AR_LOWER_THRESHHOLD;
(cache_ptr->resize_ctl).increment = H5C__DEF_AR_INCREMENT;
(cache_ptr->resize_ctl).apply_max_increment = TRUE;
(cache_ptr->resize_ctl).max_increment = H5C__DEF_AR_MAX_INCREMENT;
(cache_ptr->resize_ctl).flash_incr_mode = H5C_flash_incr__off;
(cache_ptr->resize_ctl).flash_multiple = 1.0f;
(cache_ptr->resize_ctl).flash_threshold = 0.25f;
(cache_ptr->resize_ctl).decr_mode = H5C_decr__off;
(cache_ptr->resize_ctl).upper_hr_threshold = H5C__DEF_AR_UPPER_THRESHHOLD;
(cache_ptr->resize_ctl).decrement = H5C__DEF_AR_DECREMENT;
(cache_ptr->resize_ctl).apply_max_decrement = TRUE;
(cache_ptr->resize_ctl).max_decrement = H5C__DEF_AR_MAX_DECREMENT;
(cache_ptr->resize_ctl).epochs_before_eviction = H5C__DEF_AR_EPCHS_B4_EVICT;
(cache_ptr->resize_ctl).apply_empty_reserve = TRUE;
(cache_ptr->resize_ctl).empty_reserve = H5C__DEF_AR_EMPTY_RESERVE;
cache_ptr->epoch_markers_active = 0;
cache_ptr->epoch_marker_ringbuf_first = 1;
cache_ptr->epoch_marker_ringbuf_last = 0;
cache_ptr->epoch_marker_ringbuf_size = 0;
HDmemset(cache_ptr->epoch_markers, 0, sizeof(cache_ptr->epoch_markers));
for ( i = 0; i < H5C__MAX_EPOCH_MARKERS; i++ )
{
((cache_ptr->epoch_markers)[i]).magic =
H5C__H5C_CACHE_ENTRY_T_MAGIC;
((cache_ptr->epoch_markers)[i]).addr = (haddr_t)i;
((cache_ptr->epoch_markers)[i]).type = H5AC_EPOCH_MARKER;
}
cache_ptr->image_ctl.version = H5C__CURR_CACHE_IMAGE_CTL_VER;
cache_ptr->image_ctl.generate_image = FALSE;
cache_ptr->image_ctl.save_resize_status = FALSE;
cache_ptr->image_ctl.entry_ageout = -1;
cache_ptr->image_ctl.flags = H5C_CI__ALL_FLAGS;
cache_ptr->serialization_in_progress= FALSE;
cache_ptr->load_image = FALSE;
cache_ptr->image_loaded = FALSE;
cache_ptr->delete_image = FALSE;
cache_ptr->image_addr = HADDR_UNDEF;
cache_ptr->image_len = 0;
cache_ptr->image_data_len = 0;
cache_ptr->entries_loaded_counter = 0;
cache_ptr->entries_inserted_counter = 0;
cache_ptr->entries_relocated_counter = 0;
cache_ptr->entry_fd_height_change_counter = 0;
cache_ptr->num_entries_in_image = 0;
cache_ptr->image_entries = NULL;
cache_ptr->image_buffer = NULL;
cache_ptr->rdfsm_settled = FALSE;
cache_ptr->mdfsm_settled = FALSE;
if(H5C_reset_cache_hit_rate_stats(cache_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, NULL, "H5C_reset_cache_hit_rate_stats failed")
H5C_stats__reset(cache_ptr);
cache_ptr->prefix[0] = '\0';
#ifndef NDEBUG
cache_ptr->get_entry_ptr_from_addr_counter = 0;
#endif
ret_value = cache_ptr;
done:
if(NULL == ret_value) {
if(cache_ptr != NULL) {
if(cache_ptr->slist_ptr != NULL)
H5SL_close(cache_ptr->slist_ptr);
if(cache_ptr->tag_list != NULL)
H5SL_close(cache_ptr->tag_list);
if(cache_ptr->log_info != NULL)
H5MM_xfree(cache_ptr->log_info);
cache_ptr->magic = 0;
cache_ptr = H5FL_FREE(H5C_t, cache_ptr);
}
}
FUNC_LEAVE_NOAPI(ret_value)
}
void
H5C_def_auto_resize_rpt_fcn(H5C_t * cache_ptr,
#ifndef NDEBUG
int32_t version,
#else
int32_t H5_ATTR_UNUSED version,
#endif
double hit_rate,
enum H5C_resize_status status,
size_t old_max_cache_size,
size_t new_max_cache_size,
size_t old_min_clean_size,
size_t new_min_clean_size)
{
HDassert( cache_ptr != NULL );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
HDassert( version == H5C__CURR_AUTO_RESIZE_RPT_FCN_VER );
switch ( status )
{
case in_spec:
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,
"%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,
"%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 flash_increase:
HDassert( old_max_cache_size < new_max_cache_size );
HDfprintf(stdout,
"%sflash cache resize(%d) -- size threshold = %Zu.\n",
cache_ptr->prefix,
(int)((cache_ptr->resize_ctl).flash_incr_mode),
cache_ptr->flash_size_increase_threshold);
HDfprintf(stdout,
"%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:
HDassert( old_max_cache_size > new_max_cache_size );
switch ( (cache_ptr->resize_ctl).decr_mode )
{
case H5C_decr__off:
HDfprintf(stdout,
"%sAuto cache resize -- decrease off. HR = %lf\n",
cache_ptr->prefix, hit_rate);
break;
case H5C_decr__threshold:
HDassert( hit_rate >
(cache_ptr->resize_ctl).upper_hr_threshold );
HDfprintf(stdout,
"%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, "%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,
"%sAuto cache resize -- decrease by ageout. HR = %lf\n",
cache_ptr->prefix, hit_rate);
break;
case H5C_decr__age_out_with_threshold:
HDassert( hit_rate >
(cache_ptr->resize_ctl).upper_hr_threshold );
HDfprintf(stdout,
"%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,
"%sAuto cache resize -- decrease by unknown mode. HR = %lf\n",
cache_ptr->prefix, hit_rate);
}
HDfprintf(stdout,
"%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,
new_min_clean_size);
break;
case at_max_size:
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,
"%s cache already at maximum size so no change.\n",
cache_ptr->prefix);
break;
case at_min_size:
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,
"%sAuto cache resize -- increase disabled -- HR = %lf.",
cache_ptr->prefix, hit_rate);
break;
case decrease_disabled:
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,
"%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,
"%s cache not full so no increase in size.\n",
cache_ptr->prefix);
break;
default:
HDfprintf(stdout, "%sAuto cache resize -- unknown status code.\n",
cache_ptr->prefix);
break;
}
return;
}
static herr_t
H5C_free_tag_list_cb(void *_item, void H5_ATTR_UNUSED *key, void H5_ATTR_UNUSED *op_data)
{
H5C_tag_info_t *tag_info = (H5C_tag_info_t *)_item;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(tag_info);
tag_info = H5FL_FREE(H5C_tag_info_t, tag_info);
FUNC_LEAVE_NOAPI(0)
}
herr_t
H5C_prep_for_file_close(H5F_t *f)
{
H5C_t * cache_ptr;
hbool_t image_generated = FALSE;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(f);
HDassert(f->shared);
HDassert(f->shared->cache);
cache_ptr = f->shared->cache;
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
if(cache_ptr->close_warning_received)
HGOTO_DONE(SUCCEED)
cache_ptr->close_warning_received = TRUE;
HDassert(cache_ptr->pl_len == 0);
if(H5C__prep_image_for_file_close(f, &image_generated) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, FAIL, "can't create cache image")
#ifdef H5_HAVE_PARALLEL
if ( ( H5F_INTENT(f) & H5F_ACC_RDWR ) &&
( ! image_generated ) &&
( cache_ptr->aux_ptr != NULL ) &&
( f->shared->fs_persist ) ) {
if(H5C__serialize_cache(f) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTSERIALIZE, FAIL, "serialization of the cache failed")
}
#endif
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_dest(H5F_t * f)
{
H5C_t * cache_ptr = f->shared->cache;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(cache_ptr->close_warning_received);
#if H5AC_DUMP_IMAGE_STATS_ON_CLOSE
if(H5C_image_stats(cache_ptr, TRUE) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't display cache image stats")
#endif
if ( H5C_set_slist_enabled(f->shared->cache, TRUE, FALSE) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "set slist enabled failed")
if ( H5C__flush_invalidate_cache(f, H5C__NO_FLAGS_SET) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache")
if ( cache_ptr->image_ctl.generate_image ) {
if ( H5C__generate_cache_image(f, cache_ptr) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, FAIL, \
"Can't generate metadata cache image")
}
if ( cache_ptr->slist_ptr != NULL ) {
HDassert(cache_ptr->slist_len == 0);
HDassert(cache_ptr->slist_size == 0);
H5SL_close(cache_ptr->slist_ptr);
cache_ptr->slist_ptr = NULL;
}
if(cache_ptr->tag_list != NULL) {
H5SL_destroy(cache_ptr->tag_list, H5C_free_tag_list_cb, NULL);
cache_ptr->tag_list = NULL;
}
if(cache_ptr->log_info != NULL) {
H5MM_xfree(cache_ptr->log_info);
}
#ifndef NDEBUG
#if H5C_DO_SANITY_CHECKS
if ( cache_ptr->get_entry_ptr_from_addr_counter > 0 ) {
HDfprintf(stdout,
"*** %ld calls to H5C_get_entry_ptr_from_add(). ***\n",
cache_ptr->get_entry_ptr_from_addr_counter);
}
#endif
cache_ptr->magic = 0;
#endif
cache_ptr = H5FL_FREE(H5C_t, cache_ptr);
done:
if ( ( ret_value < 0 ) && ( cache_ptr ) && ( cache_ptr->slist_ptr ) ) {
if ( H5C_set_slist_enabled(f->shared->cache, FALSE, FALSE) < 0 )
HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"disable slist on flush dest failure failed")
}
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_evict(H5F_t * f)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(f);
if ( H5C_set_slist_enabled(f->shared->cache, TRUE, FALSE) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "set slist enabled failed")
if ( H5C__flush_invalidate_cache(f, H5C__EVICT_ALLOW_LAST_PINS_FLAG) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL,
"unable to evict entries in the cache")
if ( H5C_set_slist_enabled(f->shared->cache, FALSE, TRUE) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "set slist disabled failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_expunge_entry(H5F_t *f, const H5C_class_t *type, haddr_t addr, unsigned flags)
{
H5C_t * cache_ptr;
H5C_cache_entry_t * entry_ptr = NULL;
unsigned flush_flags = (H5C__FLUSH_INVALIDATE_FLAG | H5C__FLUSH_CLEAR_ONLY_FLAG);
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(f);
HDassert(f->shared);
cache_ptr = f->shared->cache;
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(type);
HDassert(H5F_addr_defined(addr));
#if H5C_DO_EXTREME_SANITY_CHECKS
if(H5C_validate_lru_list(cache_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "LRU extreme sanity check failed on entry")
#endif
H5C__SEARCH_INDEX(cache_ptr, addr, entry_ptr, FAIL)
if((entry_ptr == NULL) || (entry_ptr->type != type))
HGOTO_DONE(SUCCEED)
HDassert(entry_ptr->addr == addr);
HDassert(entry_ptr->type == type);
if(entry_ptr->is_protected)
HGOTO_ERROR(H5E_CACHE, H5E_CANTEXPUNGE, FAIL, "Target entry is protected")
if(entry_ptr->is_pinned)
HGOTO_ERROR(H5E_CACHE, H5E_CANTEXPUNGE, FAIL, "Target entry is pinned")
flush_flags |= (flags & H5C__FREE_FILE_SPACE_FLAG);
flush_flags |= H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG;
if(H5C__flush_single_entry(f, entry_ptr, flush_flags) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTEXPUNGE, FAIL, "can't flush entry")
done:
#if H5C_DO_EXTREME_SANITY_CHECKS
if(H5C_validate_lru_list(cache_ptr) < 0)
HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "LRU extreme sanity check failed on exit")
#endif
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_flush_cache(H5F_t *f, unsigned flags)
{
#if H5C_DO_SANITY_CHECKS
int i;
uint32_t index_len = 0;
size_t index_size = (size_t)0;
size_t clean_index_size = (size_t)0;
size_t dirty_index_size = (size_t)0;
size_t slist_size = (size_t)0;
uint32_t slist_len = 0;
#endif
H5C_ring_t ring;
H5C_t * cache_ptr;
hbool_t destroy;
hbool_t ignore_protected;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(f);
HDassert(f->shared);
cache_ptr = f->shared->cache;
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(cache_ptr->slist_ptr);
#if H5C_DO_SANITY_CHECKS
HDassert(cache_ptr->index_ring_len[H5C_RING_UNDEFINED] == 0);
HDassert(cache_ptr->index_ring_size[H5C_RING_UNDEFINED] == (size_t)0);
HDassert(cache_ptr->clean_index_ring_size[H5C_RING_UNDEFINED] == (size_t)0);
HDassert(cache_ptr->dirty_index_ring_size[H5C_RING_UNDEFINED] == (size_t)0);
HDassert(cache_ptr->slist_ring_len[H5C_RING_UNDEFINED] == 0);
HDassert(cache_ptr->slist_ring_size[H5C_RING_UNDEFINED] == (size_t)0);
for(i = H5C_RING_USER; i < H5C_RING_NTYPES; i++) {
index_len += cache_ptr->index_ring_len[i];
index_size += cache_ptr->index_ring_size[i];
clean_index_size += cache_ptr->clean_index_ring_size[i];
dirty_index_size += cache_ptr->dirty_index_ring_size[i];
slist_len += cache_ptr->slist_ring_len[i];
slist_size += cache_ptr->slist_ring_size[i];
}
HDassert(cache_ptr->index_len == index_len);
HDassert(cache_ptr->index_size == index_size);
HDassert(cache_ptr->clean_index_size == clean_index_size);
HDassert(cache_ptr->dirty_index_size == dirty_index_size);
HDassert(cache_ptr->slist_len == slist_len);
HDassert(cache_ptr->slist_size == slist_size);
#endif
#if H5C_DO_EXTREME_SANITY_CHECKS
if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
(H5C_validate_pinned_entry_list(cache_ptr) < 0) ||
(H5C_validate_lru_list(cache_ptr) < 0))
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on entry")
#endif
ignore_protected = ( (flags & H5C__FLUSH_IGNORE_PROTECTED_FLAG) != 0 );
destroy = ( (flags & H5C__FLUSH_INVALIDATE_FLAG) != 0 );
HDassert( ! ( destroy && ignore_protected ) );
HDassert( ! ( cache_ptr->flush_in_progress ) );
cache_ptr->flush_in_progress = TRUE;
if(destroy) {
if(H5C__flush_invalidate_cache(f, flags) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "flush invalidate failed")
}
else {
ring = H5C_RING_USER;
while(ring < H5C_RING_NTYPES) {
if(cache_ptr->close_warning_received) {
switch(ring) {
case H5C_RING_USER:
break;
case H5C_RING_RDFSM:
if(!cache_ptr->rdfsm_settled)
if(H5MF_settle_raw_data_fsm(f, &cache_ptr->rdfsm_settled) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "RD FSM settle failed")
break;
case H5C_RING_MDFSM:
if(!cache_ptr->mdfsm_settled)
if(H5MF_settle_meta_data_fsm(f, &cache_ptr->mdfsm_settled) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "MD FSM settle failed")
break;
case H5C_RING_SBE:
case H5C_RING_SB:
break;
default:
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Unknown ring?!?!")
break;
}
}
if(H5C__flush_ring(f, ring, flags) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "flush ring failed")
ring++;
}
}
done:
cache_ptr->flush_in_progress = FALSE;
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_flush_to_min_clean(H5F_t * f)
{
H5C_t * cache_ptr;
hbool_t write_permitted;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert( f );
HDassert( f->shared );
cache_ptr = f->shared->cache;
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
if(cache_ptr->check_write_permitted != NULL) {
if((cache_ptr->check_write_permitted)(f, &write_permitted) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "can't get write_permitted")
}
else
write_permitted = cache_ptr->write_permitted;
if(!write_permitted)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "cache write is not permitted!?!")
if(H5C__make_space_in_cache(f, (size_t)0, write_permitted) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C__make_space_in_cache failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_insert_entry(H5F_t * f,
const H5C_class_t * type,
haddr_t addr,
void * thing,
unsigned int flags)
{
H5C_t *cache_ptr;
H5AC_ring_t ring = H5C_RING_UNDEFINED;
hbool_t insert_pinned;
hbool_t flush_last;
#ifdef H5_HAVE_PARALLEL
hbool_t coll_access = FALSE;
#endif
hbool_t set_flush_marker;
hbool_t write_permitted = TRUE;
size_t empty_space;
H5C_cache_entry_t *entry_ptr = NULL;
H5C_cache_entry_t *test_entry_ptr;
hbool_t entry_tagged = FALSE;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert( f );
HDassert( f->shared );
cache_ptr = f->shared->cache;
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
HDassert( type );
HDassert( type->mem_type == cache_ptr->class_table_ptr[type->id]->mem_type );
HDassert( type->image_len );
HDassert( H5F_addr_defined(addr) );
HDassert( thing );
#if H5C_DO_EXTREME_SANITY_CHECKS
if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
(H5C_validate_pinned_entry_list(cache_ptr) < 0) ||
(H5C_validate_lru_list(cache_ptr) < 0))
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on entry")
#endif
set_flush_marker = ( (flags & H5C__SET_FLUSH_MARKER_FLAG) != 0 );
insert_pinned = ( (flags & H5C__PIN_ENTRY_FLAG) != 0 );
flush_last = ( (flags & H5C__FLUSH_LAST_FLAG) != 0 );
ring = H5CX_get_ring();
entry_ptr = (H5C_cache_entry_t *)thing;
H5C__SEARCH_INDEX(cache_ptr, addr, test_entry_ptr, FAIL)
if(test_entry_ptr != NULL) {
if(test_entry_ptr == entry_ptr)
HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, "entry already in cache")
else
HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, "duplicate entry in cache")
}
entry_ptr->magic = H5C__H5C_CACHE_ENTRY_T_MAGIC;
entry_ptr->cache_ptr = cache_ptr;
entry_ptr->addr = addr;
entry_ptr->type = type;
entry_ptr->image_ptr = NULL;
entry_ptr->image_up_to_date = FALSE;
entry_ptr->is_protected = FALSE;
entry_ptr->is_read_only = FALSE;
entry_ptr->ro_ref_count = 0;
entry_ptr->is_pinned = insert_pinned;
entry_ptr->pinned_from_client = insert_pinned;
entry_ptr->pinned_from_cache = FALSE;
entry_ptr->flush_me_last = flush_last;
entry_ptr->is_dirty = TRUE;
entry_ptr->dirtied = FALSE;
if((type->image_len)(thing, &(entry_ptr->size)) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTGETSIZE, FAIL, "can't get size of thing")
HDassert(entry_ptr->size > 0 && entry_ptr->size < H5C_MAX_ENTRY_SIZE);
entry_ptr->in_slist = FALSE;
#ifdef H5_HAVE_PARALLEL
entry_ptr->clear_on_unprotect = FALSE;
entry_ptr->flush_immediately = FALSE;
#endif
entry_ptr->flush_in_progress = FALSE;
entry_ptr->destroy_in_progress = FALSE;
entry_ptr->ring = ring;
entry_ptr->flush_dep_parent = NULL;
entry_ptr->flush_dep_nparents = 0;
entry_ptr->flush_dep_parent_nalloc = 0;
entry_ptr->flush_dep_nchildren = 0;
entry_ptr->flush_dep_ndirty_children = 0;
entry_ptr->flush_dep_nunser_children = 0;
entry_ptr->ht_next = NULL;
entry_ptr->ht_prev = NULL;
entry_ptr->il_next = NULL;
entry_ptr->il_prev = NULL;
entry_ptr->next = NULL;
entry_ptr->prev = NULL;
#if H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS
entry_ptr->aux_next = NULL;
entry_ptr->aux_prev = NULL;
#endif
#ifdef H5_HAVE_PARALLEL
entry_ptr->coll_next = NULL;
entry_ptr->coll_prev = NULL;
#endif
entry_ptr->include_in_image = FALSE;
entry_ptr->lru_rank = 0;
entry_ptr->image_dirty = FALSE;
entry_ptr->fd_parent_count = 0;
entry_ptr->fd_parent_addrs = NULL;
entry_ptr->fd_child_count = 0;
entry_ptr->fd_dirty_child_count = 0;
entry_ptr->image_fd_height = 0;
entry_ptr->prefetched = FALSE;
entry_ptr->prefetch_type_id = 0;
entry_ptr->age = 0;
entry_ptr->prefetched_dirty = FALSE;
#ifndef NDEBUG
entry_ptr->serialization_count = 0;
#endif
entry_ptr->tl_next = NULL;
entry_ptr->tl_prev = NULL;
entry_ptr->tag_info = NULL;
if(H5C__tag_entry(cache_ptr, entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTTAG, FAIL, "Cannot tag metadata entry")
entry_tagged = TRUE;
H5C__RESET_CACHE_ENTRY_STATS(entry_ptr)
if(cache_ptr->flash_size_increase_possible &&
(entry_ptr->size > cache_ptr->flash_size_increase_threshold))
if(H5C__flash_increase_cache_size(cache_ptr, 0, entry_ptr->size) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, "H5C__flash_increase_cache_size failed")
if(cache_ptr->index_size >= cache_ptr->max_cache_size)
empty_space = 0;
else
empty_space = cache_ptr->max_cache_size - cache_ptr->index_size;
if(cache_ptr->evictions_enabled &&
(((cache_ptr->index_size + entry_ptr->size) > cache_ptr->max_cache_size)
||
(((empty_space + cache_ptr->clean_index_size) < cache_ptr->min_clean_size)))) {
size_t space_needed;
if(empty_space <= entry_ptr->size)
cache_ptr->cache_full = TRUE;
if(cache_ptr->check_write_permitted != NULL) {
if((cache_ptr->check_write_permitted)(f, &write_permitted) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, "Can't get write_permitted")
}
else
write_permitted = cache_ptr->write_permitted;
HDassert(entry_ptr->size <= H5C_MAX_ENTRY_SIZE);
space_needed = entry_ptr->size;
if(space_needed > cache_ptr->max_cache_size)
space_needed = cache_ptr->max_cache_size;
if(H5C__make_space_in_cache(f, space_needed, write_permitted) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, "H5C__make_space_in_cache failed")
}
H5C__INSERT_IN_INDEX(cache_ptr, entry_ptr, FAIL)
HDassert(entry_ptr->is_dirty);
entry_ptr->flush_marker = set_flush_marker;
H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL)
H5C__UPDATE_RP_FOR_INSERTION(cache_ptr, entry_ptr, FAIL)
#if H5C_DO_EXTREME_SANITY_CHECKS
if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
(H5C_validate_pinned_entry_list(cache_ptr) < 0) ||
(H5C_validate_lru_list(cache_ptr) < 0))
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed just before done")
#endif
if(entry_ptr->type->notify &&
(entry_ptr->type->notify)(H5C_NOTIFY_ACTION_AFTER_INSERT, entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client about entry inserted into cache")
H5C__UPDATE_STATS_FOR_INSERTION(cache_ptr, entry_ptr)
#ifdef H5_HAVE_PARALLEL
if(H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI))
coll_access = H5CX_get_coll_metadata_read();
entry_ptr->coll_access = coll_access;
if(coll_access) {
H5C__INSERT_IN_COLL_LIST(cache_ptr, entry_ptr, FAIL)
if(cache_ptr->max_cache_size * 80 < cache_ptr->coll_list_size * 100)
if(H5C_clear_coll_entries(cache_ptr, TRUE) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't clear collective metadata entries")
}
#endif
done:
#if H5C_DO_EXTREME_SANITY_CHECKS
if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
(H5C_validate_pinned_entry_list(cache_ptr) < 0) ||
(H5C_validate_lru_list(cache_ptr) < 0))
HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on exit")
#endif
if(ret_value < 0 && entry_tagged)
if(H5C__untag_entry(cache_ptr, entry_ptr) < 0)
HDONE_ERROR(H5E_CACHE, H5E_CANTREMOVE, FAIL, "can't remove entry from tag list")
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_mark_entry_dirty(void *thing)
{
H5C_t * cache_ptr;
H5C_cache_entry_t * entry_ptr = (H5C_cache_entry_t *)thing;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(entry_ptr);
HDassert(H5F_addr_defined(entry_ptr->addr));
cache_ptr = entry_ptr->cache_ptr;
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
if ( entry_ptr->is_protected ) {
HDassert( ! ((entry_ptr)->is_read_only) );
entry_ptr->dirtied = TRUE;
if(entry_ptr->image_up_to_date) {
entry_ptr->image_up_to_date = FALSE;
if(entry_ptr->flush_dep_nparents > 0)
if(H5C__mark_flush_dep_unserialized(entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "Can't propagate serialization status to fd parents")
}
}
else if ( entry_ptr->is_pinned ) {
hbool_t was_clean;
hbool_t image_was_up_to_date;
was_clean = !entry_ptr->is_dirty;
image_was_up_to_date = entry_ptr->image_up_to_date;
entry_ptr->is_dirty = TRUE;
entry_ptr->image_up_to_date = FALSE;
if(was_clean)
H5C__UPDATE_INDEX_FOR_ENTRY_DIRTY(cache_ptr, entry_ptr)
if(!entry_ptr->in_slist)
H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL)
H5C__UPDATE_STATS_FOR_DIRTY_PIN(cache_ptr, entry_ptr)
if(was_clean) {
if(entry_ptr->type->notify &&
(entry_ptr->type->notify)(H5C_NOTIFY_ACTION_ENTRY_DIRTIED, entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client about entry dirty flag set")
if(entry_ptr->flush_dep_nparents > 0)
if(H5C__mark_flush_dep_dirty(entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, "Can't propagate flush dep dirty flag")
}
if(image_was_up_to_date)
if(entry_ptr->flush_dep_nparents > 0)
if(H5C__mark_flush_dep_unserialized(entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "Can't propagate serialization status to fd parents")
}
else
HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, "Entry is neither pinned nor protected??")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_mark_entry_clean(void *_thing)
{
H5C_t * cache_ptr;
H5C_cache_entry_t * entry_ptr = (H5C_cache_entry_t *)_thing;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(entry_ptr);
HDassert(H5F_addr_defined(entry_ptr->addr));
cache_ptr = entry_ptr->cache_ptr;
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
if(entry_ptr->is_protected)
HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKCLEAN, FAIL, "entry is protected")
else if(entry_ptr->is_pinned) {
hbool_t was_dirty;
was_dirty = entry_ptr->is_dirty;
entry_ptr->is_dirty = FALSE;
entry_ptr->flush_marker = FALSE;
if(was_dirty)
H5C__UPDATE_INDEX_FOR_ENTRY_CLEAN(cache_ptr, entry_ptr)
if(entry_ptr->in_slist)
H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr, FALSE)
H5C__UPDATE_STATS_FOR_CLEAR(cache_ptr, entry_ptr)
if(was_dirty) {
if(entry_ptr->type->notify &&
(entry_ptr->type->notify)(H5C_NOTIFY_ACTION_ENTRY_CLEANED, entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client about entry dirty flag cleared")
if(entry_ptr->flush_dep_nparents > 0)
if(H5C__mark_flush_dep_clean(entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKCLEAN, FAIL, "Can't propagate flush dep clean")
}
}
else
HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKCLEAN, FAIL, "Entry is not pinned??")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_mark_entry_unserialized(void *thing)
{
H5C_cache_entry_t *entry = (H5C_cache_entry_t *)thing;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(entry);
HDassert(H5F_addr_defined(entry->addr));
if(entry->is_protected || entry->is_pinned) {
HDassert(!entry->is_read_only);
if(entry->image_up_to_date) {
entry->image_up_to_date = FALSE;
if(entry->flush_dep_nparents > 0)
if(H5C__mark_flush_dep_unserialized(entry) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTSET, FAIL, "Can't propagate serialization status to fd parents")
}
}
else
HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKUNSERIALIZED, FAIL, "Entry to unserialize is neither pinned nor protected??")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_mark_entry_serialized(void *_thing)
{
H5C_cache_entry_t *entry = (H5C_cache_entry_t *)_thing;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(entry);
HDassert(H5F_addr_defined(entry->addr));
if(entry->is_protected)
HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKSERIALIZED, FAIL, "entry is protected")
else if(entry->is_pinned) {
if(!entry->image_up_to_date) {
entry->image_up_to_date = TRUE;
if(entry->flush_dep_nparents > 0)
if(H5C__mark_flush_dep_serialized(entry) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKSERIALIZED, FAIL, "Can't propagate flush dep serialize")
}
}
else
HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKSERIALIZED, FAIL, "Entry is not pinned??")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_move_entry(H5C_t * cache_ptr,
const H5C_class_t * type,
haddr_t old_addr,
haddr_t new_addr)
{
H5C_cache_entry_t * entry_ptr = NULL;
H5C_cache_entry_t * test_entry_ptr = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(type);
HDassert(H5F_addr_defined(old_addr));
HDassert(H5F_addr_defined(new_addr));
HDassert(H5F_addr_ne(old_addr, new_addr));
#if H5C_DO_EXTREME_SANITY_CHECKS
if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
(H5C_validate_pinned_entry_list(cache_ptr) < 0) ||
(H5C_validate_lru_list(cache_ptr) < 0))
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on entry")
#endif
H5C__SEARCH_INDEX(cache_ptr, old_addr, entry_ptr, FAIL)
if(entry_ptr == NULL || entry_ptr->type != type)
HGOTO_DONE(SUCCEED)
HDassert(entry_ptr->addr == old_addr);
HDassert(entry_ptr->type == type);
if(entry_ptr->is_read_only)
HGOTO_ERROR(H5E_CACHE, H5E_CANTMOVE, FAIL, "can't move R/O entry")
H5C__SEARCH_INDEX(cache_ptr, new_addr, test_entry_ptr, FAIL)
if(test_entry_ptr != NULL) {
if(test_entry_ptr->type == type)
HGOTO_ERROR(H5E_CACHE, H5E_CANTMOVE, FAIL, "target already moved & reinserted???")
else
HGOTO_ERROR(H5E_CACHE, H5E_CANTMOVE, FAIL, "new address already in use?")
}
if(!entry_ptr->destroy_in_progress) {
H5C__DELETE_FROM_INDEX(cache_ptr, entry_ptr, FAIL)
if(entry_ptr->in_slist) {
HDassert(cache_ptr->slist_ptr);
H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr, FALSE)
}
}
entry_ptr->addr = new_addr;
if(!entry_ptr->destroy_in_progress) {
hbool_t was_dirty;
was_dirty = entry_ptr->is_dirty;
entry_ptr->is_dirty = TRUE;
if(entry_ptr->image_up_to_date) {
entry_ptr->image_up_to_date = FALSE;
if(entry_ptr->flush_dep_nparents > 0)
if(H5C__mark_flush_dep_unserialized(entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "Can't propagate serialization status to fd parents")
}
H5C__INSERT_IN_INDEX(cache_ptr, entry_ptr, FAIL)
H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL)
if(!entry_ptr->flush_in_progress) {
H5C__UPDATE_RP_FOR_MOVE(cache_ptr, entry_ptr, was_dirty, FAIL)
if(!was_dirty) {
if(entry_ptr->type->notify &&
(entry_ptr->type->notify)(H5C_NOTIFY_ACTION_ENTRY_DIRTIED, entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client about entry dirty flag set")
if(entry_ptr->flush_dep_nparents > 0)
if(H5C__mark_flush_dep_dirty(entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, "Can't propagate flush dep dirty flag")
}
}
}
H5C__UPDATE_STATS_FOR_MOVE(cache_ptr, entry_ptr)
done:
#if H5C_DO_EXTREME_SANITY_CHECKS
if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
(H5C_validate_pinned_entry_list(cache_ptr) < 0) ||
(H5C_validate_lru_list(cache_ptr) < 0))
HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on exit")
#endif
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_resize_entry(void *thing, size_t new_size)
{
H5C_t * cache_ptr;
H5C_cache_entry_t * entry_ptr = (H5C_cache_entry_t *)thing;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(entry_ptr);
HDassert(H5F_addr_defined(entry_ptr->addr));
cache_ptr = entry_ptr->cache_ptr;
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
if(new_size <= 0)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "New size is non-positive")
if(!(entry_ptr->is_pinned || entry_ptr->is_protected))
HGOTO_ERROR(H5E_CACHE, H5E_BADTYPE, FAIL, "Entry isn't pinned or protected??")
#if H5C_DO_EXTREME_SANITY_CHECKS
if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
(H5C_validate_pinned_entry_list(cache_ptr) < 0))
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on entry")
#endif
if ( entry_ptr->size != new_size ) {
hbool_t was_clean;
was_clean = !entry_ptr->is_dirty;
entry_ptr->is_dirty = TRUE;
if(entry_ptr->image_up_to_date) {
entry_ptr->image_up_to_date = FALSE;
if(entry_ptr->flush_dep_nparents > 0)
if(H5C__mark_flush_dep_unserialized(entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "Can't propagate serialization status to fd parents")
}
if(entry_ptr->image_ptr)
entry_ptr->image_ptr = H5MM_xfree(entry_ptr->image_ptr);
if ( cache_ptr->flash_size_increase_possible ) {
if ( new_size > entry_ptr->size ) {
size_t size_increase;
size_increase = new_size - entry_ptr->size;
if(size_increase >= cache_ptr->flash_size_increase_threshold) {
if(H5C__flash_increase_cache_size(cache_ptr, entry_ptr->size, new_size) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTRESIZE, FAIL, "flash cache increase failed")
}
}
}
if(entry_ptr->is_pinned) {
H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr->pel_len), \
(cache_ptr->pel_size), \
(entry_ptr->size), (new_size))
}
if(entry_ptr->is_protected) {
H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr->pl_len), \
(cache_ptr->pl_size), \
(entry_ptr->size), (new_size))
}
#ifdef H5_HAVE_PARALLEL
if(entry_ptr->coll_access) {
H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr->coll_list_len), \
(cache_ptr->coll_list_size), \
(entry_ptr->size), (new_size))
}
#endif
H5C__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE(cache_ptr, entry_ptr, new_size);
H5C__UPDATE_INDEX_FOR_SIZE_CHANGE(cache_ptr, entry_ptr->size, \
new_size, entry_ptr, was_clean);
if(entry_ptr->in_slist)
H5C__UPDATE_SLIST_FOR_SIZE_CHANGE(cache_ptr, entry_ptr->size, new_size);
entry_ptr->size = new_size;
if(!entry_ptr->in_slist)
H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL)
if(entry_ptr->is_pinned)
H5C__UPDATE_STATS_FOR_DIRTY_PIN(cache_ptr, entry_ptr)
if(was_clean) {
if(entry_ptr->type->notify &&
(entry_ptr->type->notify)(H5C_NOTIFY_ACTION_ENTRY_DIRTIED, entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client about entry dirty flag set")
if(entry_ptr->flush_dep_nparents > 0)
if(H5C__mark_flush_dep_dirty(entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, "Can't propagate flush dep dirty flag")
}
}
done:
#if H5C_DO_EXTREME_SANITY_CHECKS
if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
(H5C_validate_pinned_entry_list(cache_ptr) < 0))
HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on exit")
#endif
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_pin_protected_entry(void *thing)
{
H5C_t * cache_ptr;
H5C_cache_entry_t * entry_ptr = (H5C_cache_entry_t *)thing;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(entry_ptr);
HDassert(H5F_addr_defined(entry_ptr->addr));
cache_ptr = entry_ptr->cache_ptr;
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
#if H5C_DO_EXTREME_SANITY_CHECKS
if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
(H5C_validate_pinned_entry_list(cache_ptr) < 0) ||
(H5C_validate_lru_list(cache_ptr) < 0))
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on entry")
#endif
if(!entry_ptr->is_protected)
HGOTO_ERROR(H5E_CACHE, H5E_CANTPIN, FAIL, "Entry isn't protected")
if(H5C__pin_entry_from_client(cache_ptr, entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTPIN, FAIL, "Can't pin entry by client")
done:
#if H5C_DO_EXTREME_SANITY_CHECKS
if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
(H5C_validate_pinned_entry_list(cache_ptr) < 0) ||
(H5C_validate_lru_list(cache_ptr) < 0))
HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on exit")
#endif
FUNC_LEAVE_NOAPI(ret_value)
}
void *
H5C_protect(H5F_t * f,
const H5C_class_t * type,
haddr_t addr,
void * udata,
unsigned flags)
{
H5C_t * cache_ptr;
H5AC_ring_t ring = H5C_RING_UNDEFINED;
hbool_t hit;
hbool_t have_write_permitted = FALSE;
hbool_t read_only = FALSE;
hbool_t flush_last;
#ifdef H5_HAVE_PARALLEL
hbool_t coll_access = FALSE;
#endif
hbool_t write_permitted;
hbool_t was_loaded = FALSE;
size_t empty_space;
void * thing;
H5C_cache_entry_t * entry_ptr;
void * ret_value = NULL;
FUNC_ENTER_NOAPI(NULL)
HDassert( f );
HDassert( f->shared );
cache_ptr = f->shared->cache;
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
HDassert( type );
HDassert( type->mem_type == cache_ptr->class_table_ptr[type->id]->mem_type );
HDassert( H5F_addr_defined(addr) );
#if H5C_DO_EXTREME_SANITY_CHECKS
if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
(H5C_validate_pinned_entry_list(cache_ptr) < 0) ||
(H5C_validate_lru_list(cache_ptr) < 0))
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, NULL, "an extreme sanity check failed on entry")
#endif
if(cache_ptr->load_image) {
cache_ptr->load_image = FALSE;
if(H5C__load_cache_image(f) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "Can't load cache image")
}
read_only = ( (flags & H5C__READ_ONLY_FLAG) != 0 );
flush_last = ( (flags & H5C__FLUSH_LAST_FLAG) != 0 );
ring = H5CX_get_ring();
#ifdef H5_HAVE_PARALLEL
if(H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI))
coll_access = H5CX_get_coll_metadata_read();
#endif
H5C__SEARCH_INDEX(cache_ptr, addr, entry_ptr, NULL)
if(entry_ptr != NULL) {
if(entry_ptr->ring != ring)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, NULL, "ring type mismatch occurred for cache entry")
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
if(entry_ptr->prefetched) {
if(H5C__deserialize_prefetched_entry(f, cache_ptr, &entry_ptr, type, addr, udata) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "can't deserialize prefetched entry")
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(!entry_ptr->prefetched);
HDassert(entry_ptr->addr == addr);
}
if(entry_ptr->type != type)
HGOTO_ERROR(H5E_CACHE, H5E_BADTYPE, NULL, "incorrect cache entry type")
#ifdef H5_HAVE_PARALLEL
if(coll_access) {
if(!(entry_ptr->is_dirty) && !(entry_ptr->coll_access)) {
MPI_Comm comm;
int mpi_code;
int buf_size;
if(MPI_COMM_NULL == (comm = H5F_mpi_get_comm(f)))
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "get_comm request failed")
if(entry_ptr->image_ptr == NULL) {
int mpi_rank;
if((mpi_rank = H5F_mpi_get_rank(f)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "Can't get MPI rank")
if(NULL == (entry_ptr->image_ptr = H5MM_malloc(entry_ptr->size + H5C_IMAGE_EXTRA_SPACE)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, NULL, "memory allocation failed for on disk image buffer")
#if H5C_DO_MEMORY_SANITY_CHECKS
H5MM_memcpy(((uint8_t *)entry_ptr->image_ptr) + entry_ptr->size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif
if(0 == mpi_rank)
if(H5C__generate_image(f, cache_ptr, entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, NULL, "can't generate entry's image")
}
HDassert(entry_ptr->image_ptr);
H5_CHECKED_ASSIGN(buf_size, int, entry_ptr->size, size_t);
if(MPI_SUCCESS != (mpi_code = MPI_Bcast(entry_ptr->image_ptr, buf_size, MPI_BYTE, 0, comm)))
HMPI_GOTO_ERROR(NULL, "MPI_Bcast failed", mpi_code)
entry_ptr->coll_access = TRUE;
H5C__INSERT_IN_COLL_LIST(cache_ptr, entry_ptr, NULL)
}
else if(entry_ptr->coll_access) {
H5C__MOVE_TO_TOP_IN_COLL_LIST(cache_ptr, entry_ptr, NULL)
}
}
#endif
#if H5C_DO_TAGGING_SANITY_CHECKS
{
if(cache_ptr->ignore_tags != TRUE) {
haddr_t tag;
tag = H5CX_get_tag();
if(H5C_verify_tag(entry_ptr->type->id, tag) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, NULL, "tag verification failed")
}
}
#endif
hit = TRUE;
thing = (void *)entry_ptr;
} else {
hit = FALSE;
if(NULL == (thing = H5C_load_entry(f,
#ifdef H5_HAVE_PARALLEL
coll_access,
#endif
type, addr, udata)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "can't load entry")
entry_ptr = (H5C_cache_entry_t *)thing;
cache_ptr->entries_loaded_counter++;
entry_ptr->ring = ring;
#ifdef H5_HAVE_PARALLEL
if(H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI) && entry_ptr->coll_access)
H5C__INSERT_IN_COLL_LIST(cache_ptr, entry_ptr, NULL)
#endif
if(H5C__tag_entry(cache_ptr, entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTTAG, NULL, "Cannot tag metadata entry")
if ( ( cache_ptr->flash_size_increase_possible ) &&
( entry_ptr->size > cache_ptr->flash_size_increase_threshold ) ) {
if(H5C__flash_increase_cache_size(cache_ptr, 0, entry_ptr->size) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, NULL, "H5C__flash_increase_cache_size failed")
}
if(cache_ptr->index_size >= cache_ptr->max_cache_size)
empty_space = 0;
else
empty_space = cache_ptr->max_cache_size - cache_ptr->index_size;
if ( ( cache_ptr->evictions_enabled ) &&
( ( (cache_ptr->index_size + entry_ptr->size) >
cache_ptr->max_cache_size)
||
( ( empty_space + cache_ptr->clean_index_size ) <
cache_ptr->min_clean_size )
)
) {
size_t space_needed;
if(empty_space <= entry_ptr->size)
cache_ptr->cache_full = TRUE;
if(cache_ptr->check_write_permitted != NULL) {
if((cache_ptr->check_write_permitted)(f, &write_permitted) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, NULL, "Can't get write_permitted 1")
else
have_write_permitted = TRUE;
}
else {
write_permitted = cache_ptr->write_permitted;
have_write_permitted = TRUE;
}
HDassert(entry_ptr->size <= H5C_MAX_ENTRY_SIZE);
space_needed = entry_ptr->size;
if(space_needed > cache_ptr->max_cache_size)
space_needed = cache_ptr->max_cache_size;
if(H5C__make_space_in_cache(f, space_needed, write_permitted) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, NULL, "H5C__make_space_in_cache failed")
}
entry_ptr->flush_me_last = flush_last;
H5C__INSERT_IN_INDEX(cache_ptr, entry_ptr, NULL)
if ( ( entry_ptr->is_dirty ) && ( ! (entry_ptr->in_slist) ) ) {
H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, NULL)
}
H5C__UPDATE_RP_FOR_INSERTION(cache_ptr, entry_ptr, NULL)
was_loaded = TRUE;
}
HDassert(entry_ptr->addr == addr);
HDassert(entry_ptr->type == type);
if(entry_ptr->is_protected) {
if(read_only && entry_ptr->is_read_only) {
HDassert(entry_ptr->ro_ref_count > 0);
(entry_ptr->ro_ref_count)++;
}
else
HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, NULL, "Target already protected & not read only?!?")
}
else {
H5C__UPDATE_RP_FOR_PROTECT(cache_ptr, entry_ptr, NULL)
entry_ptr->is_protected = TRUE;
if ( read_only ) {
entry_ptr->is_read_only = TRUE;
entry_ptr->ro_ref_count = 1;
}
entry_ptr->dirtied = FALSE;
}
H5C__UPDATE_CACHE_HIT_RATE_STATS(cache_ptr, hit)
H5C__UPDATE_STATS_FOR_PROTECT(cache_ptr, entry_ptr, hit)
ret_value = thing;
if ( ( cache_ptr->evictions_enabled ) &&
( ( cache_ptr->size_decreased ) ||
( ( cache_ptr->resize_enabled ) &&
( cache_ptr->cache_accesses >=
(cache_ptr->resize_ctl).epoch_length ) ) ) ) {
if ( ! have_write_permitted ) {
if ( cache_ptr->check_write_permitted != NULL ) {
if((cache_ptr->check_write_permitted)(f, &write_permitted) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, NULL, "Can't get write_permitted")
else
have_write_permitted = TRUE;
} else {
write_permitted = cache_ptr->write_permitted;
have_write_permitted = TRUE;
}
}
if(cache_ptr->resize_enabled &&
(cache_ptr->cache_accesses >= (cache_ptr->resize_ctl).epoch_length)) {
if(H5C__auto_adjust_cache_size(f, write_permitted) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, NULL, "Cache auto-resize failed")
}
if(cache_ptr->size_decreased) {
cache_ptr->size_decreased = FALSE;
if(cache_ptr->index_size >= cache_ptr->max_cache_size)
empty_space = 0;
else
empty_space = cache_ptr->max_cache_size - cache_ptr->index_size;
if ( ( cache_ptr->index_size > cache_ptr->max_cache_size )
||
( ( empty_space + cache_ptr->clean_index_size ) <
cache_ptr->min_clean_size) ) {
if(cache_ptr->index_size > cache_ptr->max_cache_size)
cache_ptr->cache_full = TRUE;
if(H5C__make_space_in_cache(f, (size_t)0, write_permitted) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, NULL, "H5C__make_space_in_cache failed")
}
}
}
if(was_loaded) {
if(entry_ptr->type->notify &&
(entry_ptr->type->notify)(H5C_NOTIFY_ACTION_AFTER_LOAD, entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, NULL, "can't notify client about entry inserted into cache")
}
#ifdef H5_HAVE_PARALLEL
if(coll_access)
if(cache_ptr->max_cache_size * 80 < cache_ptr->coll_list_size * 100)
if(H5C_clear_coll_entries(cache_ptr, TRUE) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, NULL, "can't clear collective metadata entries")
#endif
done:
#if H5C_DO_EXTREME_SANITY_CHECKS
if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
(H5C_validate_pinned_entry_list(cache_ptr) < 0) ||
(H5C_validate_lru_list(cache_ptr) < 0))
HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, NULL, "an extreme sanity check failed on exit")
#endif
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_reset_cache_hit_rate_stats(H5C_t * cache_ptr)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
if((cache_ptr == NULL) || (cache_ptr->magic != H5C__H5C_T_MAGIC))
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "bad cache_ptr on entry")
cache_ptr->cache_hits = 0;
cache_ptr->cache_accesses = 0;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_set_cache_auto_resize_config(H5C_t *cache_ptr,
H5C_auto_size_ctl_t *config_ptr)
{
size_t new_max_cache_size;
size_t new_min_clean_size;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
if((cache_ptr == NULL) || (cache_ptr->magic != H5C__H5C_T_MAGIC))
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "bad cache_ptr on entry")
if(config_ptr == NULL)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "NULL config_ptr on entry")
if(config_ptr->version != H5C__CURR_AUTO_SIZE_CTL_VER)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "unknown config version")
if(H5C_validate_resize_config(config_ptr, H5C_RESIZE_CFG__VALIDATE_GENERAL) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "error in general configuration fields of new config")
if(H5C_validate_resize_config(config_ptr, H5C_RESIZE_CFG__VALIDATE_INCREMENT) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "error in the size increase control fields of new config")
if(H5C_validate_resize_config(config_ptr, H5C_RESIZE_CFG__VALIDATE_DECREMENT) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "error in the size decrease control fields of new config")
if(H5C_validate_resize_config(config_ptr, H5C_RESIZE_CFG__VALIDATE_INTERACTIONS) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "conflicting threshold fields in new config")
cache_ptr->size_increase_possible = TRUE;
cache_ptr->flash_size_increase_possible = TRUE;
cache_ptr->size_decrease_possible = TRUE;
switch(config_ptr->incr_mode) {
case H5C_incr__off:
cache_ptr->size_increase_possible = FALSE;
break;
case H5C_incr__threshold:
if((config_ptr->lower_hr_threshold <= (double)0.0f) ||
(config_ptr->increment <= (double)1.0f) ||
((config_ptr->apply_max_increment) && (config_ptr->max_increment <= 0)))
cache_ptr->size_increase_possible = FALSE;
break;
default:
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Unknown incr_mode?!?!?")
}
switch(config_ptr->decr_mode) {
case H5C_decr__off:
cache_ptr->size_decrease_possible = FALSE;
break;
case H5C_decr__threshold:
if((config_ptr->upper_hr_threshold >= (double)1.0f) ||
(config_ptr->decrement >= (double)1.0f) ||
((config_ptr->apply_max_decrement) && (config_ptr->max_decrement <= 0)))
cache_ptr->size_decrease_possible = FALSE;
break;
case H5C_decr__age_out:
if(((config_ptr->apply_empty_reserve) && (config_ptr->empty_reserve >= (double)1.0f)) ||
((config_ptr->apply_max_decrement) && (config_ptr->max_decrement <= 0)))
cache_ptr->size_decrease_possible = FALSE;
break;
case H5C_decr__age_out_with_threshold:
if(((config_ptr->apply_empty_reserve) && (config_ptr->empty_reserve >= (double)1.0f)) ||
((config_ptr->apply_max_decrement) && (config_ptr->max_decrement <= 0)) ||
(config_ptr->upper_hr_threshold >= (double)1.0f))
cache_ptr->size_decrease_possible = FALSE;
break;
default:
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Unknown decr_mode?!?!?")
}
if(config_ptr->max_size == config_ptr->min_size) {
cache_ptr->size_increase_possible = FALSE;
cache_ptr->flash_size_increase_possible = FALSE;
cache_ptr->size_decrease_possible = FALSE;
}
cache_ptr->resize_enabled = cache_ptr->size_increase_possible ||
cache_ptr->size_decrease_possible;
cache_ptr->resize_ctl = *config_ptr;
if(cache_ptr->resize_ctl.set_initial_size)
new_max_cache_size = cache_ptr->resize_ctl.initial_size;
else if(cache_ptr->max_cache_size > cache_ptr->resize_ctl.max_size)
new_max_cache_size = cache_ptr->resize_ctl.max_size;
else if(cache_ptr->max_cache_size < cache_ptr->resize_ctl.min_size)
new_max_cache_size = cache_ptr->resize_ctl.min_size;
else
new_max_cache_size = cache_ptr->max_cache_size;
new_min_clean_size = (size_t)((double)new_max_cache_size *
((cache_ptr->resize_ctl).min_clean_fraction));
HDassert(new_min_clean_size <= new_max_cache_size);
HDassert(cache_ptr->resize_ctl.min_size <= new_max_cache_size);
HDassert(new_max_cache_size <= cache_ptr->resize_ctl.max_size);
if(new_max_cache_size < cache_ptr->max_cache_size)
cache_ptr->size_decreased = TRUE;
cache_ptr->max_cache_size = new_max_cache_size;
cache_ptr->min_clean_size = new_min_clean_size;
if(H5C_reset_cache_hit_rate_stats(cache_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C_reset_cache_hit_rate_stats failed")
if((config_ptr->decr_mode == H5C_decr__age_out_with_threshold) ||
(config_ptr->decr_mode == H5C_decr__age_out)) {
if(cache_ptr->epoch_markers_active > cache_ptr->resize_ctl.epochs_before_eviction)
if(H5C__autoadjust__ageout__remove_excess_markers(cache_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "can't remove excess epoch markers")
}
else if(cache_ptr->epoch_markers_active > 0) {
if(H5C__autoadjust__ageout__remove_all_markers(cache_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "error removing all epoch markers")
}
if(cache_ptr->flash_size_increase_possible) {
switch(config_ptr->flash_incr_mode) {
case H5C_flash_incr__off:
cache_ptr->flash_size_increase_possible = FALSE;
break;
case H5C_flash_incr__add_space:
cache_ptr->flash_size_increase_possible = TRUE;
cache_ptr->flash_size_increase_threshold = (size_t)(((double)(cache_ptr->max_cache_size)) *
((cache_ptr->resize_ctl).flash_threshold));
break;
default:
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Unknown flash_incr_mode?!?!?")
break;
}
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_set_evictions_enabled(H5C_t *cache_ptr, hbool_t evictions_enabled)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
if((cache_ptr == NULL) || (cache_ptr->magic != H5C__H5C_T_MAGIC))
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad cache_ptr on entry")
if((evictions_enabled != TRUE) &&
((cache_ptr->resize_ctl.incr_mode != H5C_incr__off) ||
(cache_ptr->resize_ctl.decr_mode != H5C_decr__off)))
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't disable evictions when auto resize enabled")
cache_ptr->evictions_enabled = evictions_enabled;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_set_slist_enabled(H5C_t *cache_ptr, hbool_t slist_enabled,
hbool_t clear_slist)
{
H5C_cache_entry_t * entry_ptr;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
if ( ( cache_ptr == NULL ) || ( cache_ptr->magic != H5C__H5C_T_MAGIC ) )
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad cache_ptr on entry")
#if H5C__SLIST_OPT_ENABLED
if ( slist_enabled ) {
if ( cache_ptr->slist_enabled ) {
HDassert(FALSE);
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "slist already enabled?")
}
if ( ( cache_ptr->slist_len != 0 ) ||
( cache_ptr->slist_size != 0 ) ) {
HDassert(FALSE);
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "slist not empty (1)?")
}
cache_ptr->slist_enabled = TRUE;
entry_ptr = cache_ptr->il_head;
while ( entry_ptr != NULL ) {
HDassert( entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC );
if ( entry_ptr->is_dirty ) {
H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL)
}
entry_ptr = entry_ptr->il_next;
}
HDassert( cache_ptr->dirty_index_size == cache_ptr->slist_size );
} else {
if ( ! cache_ptr->slist_enabled ) {
HDassert(FALSE);
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "slist already disabled?")
}
if ( ( cache_ptr->slist_len != 0 ) ||
( cache_ptr->slist_size != 0 ) ) {
if ( clear_slist ) {
H5SL_node_t *node_ptr;
node_ptr = H5SL_first(cache_ptr->slist_ptr);
while ( node_ptr != NULL ) {
entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr, FALSE);
node_ptr = H5SL_first(cache_ptr->slist_ptr);
}
} else {
HDassert(FALSE);
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "slist not empty (2)?")
}
}
cache_ptr->slist_enabled = FALSE;
HDassert( 0 == cache_ptr->slist_len );
HDassert( 0 == cache_ptr->slist_size );
}
#else
HDassert(cache_ptr->slist_enabled);
#endif
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_unpin_entry(void *_entry_ptr)
{
H5C_t * cache_ptr;
H5C_cache_entry_t * entry_ptr = (H5C_cache_entry_t *)_entry_ptr;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(entry_ptr);
cache_ptr = entry_ptr->cache_ptr;
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
#if H5C_DO_EXTREME_SANITY_CHECKS
if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
(H5C_validate_pinned_entry_list(cache_ptr) < 0) ||
(H5C_validate_lru_list(cache_ptr) < 0))
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on entry")
#endif
if(H5C__unpin_entry_from_client(cache_ptr, entry_ptr, TRUE) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPIN, FAIL, "Can't unpin entry from client")
done:
#if H5C_DO_EXTREME_SANITY_CHECKS
if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
(H5C_validate_pinned_entry_list(cache_ptr) < 0) ||
(H5C_validate_lru_list(cache_ptr) < 0))
HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on exit")
#endif
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_unprotect(H5F_t *f, haddr_t addr, void *thing, unsigned flags)
{
H5C_t * cache_ptr;
hbool_t deleted;
hbool_t dirtied;
hbool_t set_flush_marker;
hbool_t pin_entry;
hbool_t unpin_entry;
hbool_t free_file_space;
hbool_t take_ownership;
hbool_t was_clean;
#ifdef H5_HAVE_PARALLEL
hbool_t clear_entry = FALSE;
#endif
H5C_cache_entry_t * entry_ptr;
H5C_cache_entry_t * test_entry_ptr;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
deleted = ((flags & H5C__DELETED_FLAG) != 0);
dirtied = ((flags & H5C__DIRTIED_FLAG) != 0);
set_flush_marker = ((flags & H5C__SET_FLUSH_MARKER_FLAG) != 0);
pin_entry = ((flags & H5C__PIN_ENTRY_FLAG) != 0);
unpin_entry = ((flags & H5C__UNPIN_ENTRY_FLAG) != 0);
free_file_space = ((flags & H5C__FREE_FILE_SPACE_FLAG) != 0);
take_ownership = ((flags & H5C__TAKE_OWNERSHIP_FLAG) != 0);
HDassert( f );
HDassert( f->shared );
cache_ptr = f->shared->cache;
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
HDassert( H5F_addr_defined(addr) );
HDassert( thing );
HDassert( ! ( pin_entry && unpin_entry ) );
HDassert( ( ! free_file_space ) || ( deleted ) );
HDassert( ( ! take_ownership ) || ( deleted ) );
HDassert( ! ( free_file_space && take_ownership ) );
entry_ptr = (H5C_cache_entry_t *)thing;
HDassert( entry_ptr->addr == addr );
dirtied |= entry_ptr->dirtied;
was_clean = ! ( entry_ptr->is_dirty );
#if H5C_DO_EXTREME_SANITY_CHECKS
if ( ( H5C_validate_protected_entry_list(cache_ptr) < 0 ) ||
( H5C_validate_pinned_entry_list(cache_ptr) < 0 ) ||
( H5C_validate_lru_list(cache_ptr) < 0 ) )
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"an extreme sanity check failed on entry")
#endif
if ( entry_ptr->ro_ref_count > 1 ) {
HDassert(entry_ptr->is_protected);
HDassert(entry_ptr->is_read_only);
if ( dirtied )
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \
"Read only entry modified??")
(entry_ptr->ro_ref_count)--;
if ( pin_entry ) {
if ( H5C__pin_entry_from_client(cache_ptr, entry_ptr) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTPIN, FAIL, \
"Can't pin entry by client")
} else if ( unpin_entry ) {
if ( H5C__unpin_entry_from_client(cache_ptr, entry_ptr, FALSE) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPIN, FAIL, \
"Can't unpin entry by client")
}
} else {
if ( entry_ptr->is_read_only ) {
HDassert(entry_ptr->ro_ref_count == 1);
if ( dirtied )
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \
"Read only entry modified??")
entry_ptr->is_read_only = FALSE;
entry_ptr->ro_ref_count = 0;
}
#ifdef H5_HAVE_PARALLEL
if(entry_ptr->clear_on_unprotect) {
HDassert(entry_ptr->is_dirty);
entry_ptr->clear_on_unprotect = FALSE;
if(!dirtied)
clear_entry = TRUE;
}
#endif
if ( ! entry_ptr->is_protected )
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \
"Entry already unprotected??")
entry_ptr->is_dirty = (entry_ptr->is_dirty || dirtied);
if ( dirtied ) {
if ( entry_ptr->image_up_to_date ) {
entry_ptr->image_up_to_date = FALSE;
if ( entry_ptr->flush_dep_nparents > 0 ) {
if ( H5C__mark_flush_dep_unserialized(entry_ptr) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \
"Can't propagate serialization status to fd parents")
}
}
}
if ( was_clean && entry_ptr->is_dirty ) {
H5C__UPDATE_INDEX_FOR_ENTRY_DIRTY(cache_ptr, entry_ptr)
if ( ( entry_ptr->type->notify ) &&
( (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_ENTRY_DIRTIED,
entry_ptr) < 0 ) )
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \
"can't notify client about entry dirty flag set")
if ( entry_ptr->flush_dep_nparents > 0 ) {
if ( H5C__mark_flush_dep_dirty(entry_ptr) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, \
"Can't propagate flush dep dirty flag")
}
}
else if ( ! was_clean && ! entry_ptr->is_dirty ) {
if ( ( entry_ptr->type->notify ) &&
( (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_ENTRY_CLEANED,
entry_ptr) < 0 ) )
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \
"can't notify client about entry dirty flag cleared")
if ( entry_ptr->flush_dep_nparents > 0 ) {
if ( H5C__mark_flush_dep_clean(entry_ptr) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, \
"Can't propagate flush dep dirty flag")
}
}
if ( pin_entry ) {
if ( H5C__pin_entry_from_client(cache_ptr, entry_ptr) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTPIN, FAIL, \
"Can't pin entry by client")
} else if ( unpin_entry ) {
if ( H5C__unpin_entry_from_client(cache_ptr, entry_ptr, FALSE) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPIN, FAIL, \
"Can't unpin entry by client")
}
H5C__UPDATE_RP_FOR_UNPROTECT(cache_ptr, entry_ptr, FAIL)
entry_ptr->is_protected = FALSE;
if ( entry_ptr->is_dirty ) {
entry_ptr->flush_marker |= set_flush_marker;
if ( !entry_ptr->in_slist ) {
H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL)
}
}
if ( deleted ) {
unsigned flush_flags = (H5C__FLUSH_CLEAR_ONLY_FLAG |
H5C__FLUSH_INVALIDATE_FLAG);
H5C__SEARCH_INDEX(cache_ptr, addr, test_entry_ptr, FAIL)
if ( test_entry_ptr == NULL )
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \
"entry not in hash table?!?")
else if ( test_entry_ptr != entry_ptr )
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \
"hash table contains multiple entries for addr?!?")
if ( free_file_space ) {
flush_flags |= H5C__FREE_FILE_SPACE_FLAG;
}
if ( take_ownership ) {
flush_flags |= H5C__TAKE_OWNERSHIP_FLAG;
}
flush_flags |= H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG;
HDassert( ( ! cache_ptr->slist_enabled ) || \
( ( ( ! was_clean ) || dirtied ) == \
( entry_ptr->in_slist ) ) );
if ( H5C__flush_single_entry(f, entry_ptr, flush_flags) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \
"Can't flush entry")
}
#ifdef H5_HAVE_PARALLEL
else if ( clear_entry ) {
H5C__SEARCH_INDEX(cache_ptr, addr, test_entry_ptr, FAIL)
if ( test_entry_ptr == NULL )
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \
"entry not in hash table?!?")
else if ( test_entry_ptr != entry_ptr )
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \
"hash table contains multiple entries for addr?!?")
if ( H5C__flush_single_entry(f, entry_ptr,
H5C__FLUSH_CLEAR_ONLY_FLAG |
H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \
"Can't clear entry")
}
#endif
}
H5C__UPDATE_STATS_FOR_UNPROTECT(cache_ptr)
done:
#if H5C_DO_EXTREME_SANITY_CHECKS
if ( ( H5C_validate_protected_entry_list(cache_ptr) < 0 ) ||
( H5C_validate_pinned_entry_list(cache_ptr) < 0 ) ||
( H5C_validate_lru_list(cache_ptr) < 0 ) ) {
HDONE_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"an extreme sanity check failed on exit")
#endif
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_unsettle_entry_ring(void *_entry)
{
H5C_cache_entry_t *entry = (H5C_cache_entry_t *)_entry;
H5C_t *cache;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(entry);
HDassert(entry->ring != H5C_RING_UNDEFINED);
HDassert((H5C_RING_USER == entry->ring) || (H5C_RING_RDFSM == entry->ring) || (H5C_RING_MDFSM == entry->ring));
cache = entry->cache_ptr;
HDassert(cache);
HDassert(cache->magic == H5C__H5C_T_MAGIC);
switch(entry->ring) {
case H5C_RING_USER:
break;
case H5C_RING_RDFSM:
if(cache->rdfsm_settled) {
if(cache->flush_in_progress || cache->close_warning_received)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unexpected rdfsm ring unsettle")
cache->rdfsm_settled = FALSE;
}
break;
case H5C_RING_MDFSM:
if(cache->mdfsm_settled) {
if(cache->flush_in_progress || cache->close_warning_received)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unexpected mdfsm ring unsettle")
cache->mdfsm_settled = FALSE;
}
break;
default:
HDassert(FALSE);
break;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_unsettle_ring(H5F_t * f, H5C_ring_t ring)
{
H5C_t * cache_ptr;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(f);
HDassert(f->shared);
HDassert(f->shared->cache);
HDassert((H5C_RING_RDFSM == ring) || (H5C_RING_MDFSM == ring));
cache_ptr = f->shared->cache;
HDassert(H5C__H5C_T_MAGIC == cache_ptr->magic);
switch(ring) {
case H5C_RING_RDFSM:
if(cache_ptr->rdfsm_settled) {
if(cache_ptr->close_warning_received)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unexpected rdfsm ring unsettle")
cache_ptr->rdfsm_settled = FALSE;
}
break;
case H5C_RING_MDFSM:
if(cache_ptr->mdfsm_settled) {
if(cache_ptr->close_warning_received)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unexpected mdfsm ring unsettle")
cache_ptr->mdfsm_settled = FALSE;
}
break;
default:
HDassert(FALSE);
break;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_validate_resize_config(H5C_auto_size_ctl_t * config_ptr,
unsigned int tests)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
if(config_ptr == NULL)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "NULL config_ptr on entry")
if(config_ptr->version != H5C__CURR_AUTO_SIZE_CTL_VER)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Unknown config version")
if((tests & H5C_RESIZE_CFG__VALIDATE_GENERAL) != 0) {
if(config_ptr->max_size > H5C__MAX_MAX_CACHE_SIZE)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "max_size too big")
if(config_ptr->min_size < H5C__MIN_MAX_CACHE_SIZE)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "min_size too small")
if(config_ptr->min_size > config_ptr->max_size)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "min_size > max_size")
if(config_ptr->set_initial_size &&
((config_ptr->initial_size < config_ptr->min_size) ||
(config_ptr->initial_size > config_ptr->max_size)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "initial_size must be in the interval [min_size, max_size]")
if((config_ptr->min_clean_fraction < (double)0.0f) ||
(config_ptr->min_clean_fraction > (double)1.0f))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "min_clean_fraction must be in the interval [0.0, 1.0]")
if(config_ptr->epoch_length < H5C__MIN_AR_EPOCH_LENGTH)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "epoch_length too small")
if(config_ptr->epoch_length > H5C__MAX_AR_EPOCH_LENGTH)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "epoch_length too big")
}
if((tests & H5C_RESIZE_CFG__VALIDATE_INCREMENT) != 0) {
if((config_ptr->incr_mode != H5C_incr__off) &&
(config_ptr->incr_mode != H5C_incr__threshold))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Invalid incr_mode")
if(config_ptr->incr_mode == H5C_incr__threshold) {
if((config_ptr->lower_hr_threshold < (double)0.0f) ||
(config_ptr->lower_hr_threshold > (double)1.0f))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "lower_hr_threshold must be in the range [0.0, 1.0]")
if(config_ptr->increment < (double)1.0f)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "increment must be greater than or equal to 1.0")
}
switch(config_ptr->flash_incr_mode) {
case H5C_flash_incr__off:
break;
case H5C_flash_incr__add_space:
if((config_ptr->flash_multiple < (double)0.1f) ||
(config_ptr->flash_multiple > (double)10.0f))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "flash_multiple must be in the range [0.1, 10.0]")
if((config_ptr->flash_threshold < (double)0.1f) ||
(config_ptr->flash_threshold > (double)1.0f))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "flash_threshold must be in the range [0.1, 1.0]")
break;
default:
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Invalid flash_incr_mode")
break;
}
}
if ( (tests & H5C_RESIZE_CFG__VALIDATE_DECREMENT) != 0 ) {
if ( ( config_ptr->decr_mode != H5C_decr__off ) &&
( config_ptr->decr_mode != H5C_decr__threshold ) &&
( config_ptr->decr_mode != H5C_decr__age_out ) &&
( config_ptr->decr_mode != H5C_decr__age_out_with_threshold )
) {
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Invalid decr_mode")
}
if ( config_ptr->decr_mode == H5C_decr__threshold ) {
if(config_ptr->upper_hr_threshold > (double)1.0f)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "upper_hr_threshold must be <= 1.0")
if((config_ptr->decrement > (double)1.0f) ||
(config_ptr->decrement < (double)0.0f))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "decrement must be in the interval [0.0, 1.0]")
}
if((config_ptr->decr_mode == H5C_decr__age_out) ||
(config_ptr->decr_mode == H5C_decr__age_out_with_threshold)) {
if(config_ptr->epochs_before_eviction < 1)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "epochs_before_eviction must be positive")
if(config_ptr->epochs_before_eviction > H5C__MAX_EPOCH_MARKERS)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "epochs_before_eviction too big")
if((config_ptr->apply_empty_reserve) &&
((config_ptr->empty_reserve > (double)1.0f) ||
(config_ptr->empty_reserve < (double)0.0f)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "empty_reserve must be in the interval [0.0, 1.0]")
}
if(config_ptr->decr_mode == H5C_decr__age_out_with_threshold) {
if((config_ptr->upper_hr_threshold > (double)1.0f) ||
(config_ptr->upper_hr_threshold < (double)0.0f))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "upper_hr_threshold must be in the interval [0.0, 1.0]")
}
}
if ( (tests & H5C_RESIZE_CFG__VALIDATE_INTERACTIONS) != 0 ) {
if((config_ptr->incr_mode == H5C_incr__threshold)
&& ((config_ptr->decr_mode == H5C_decr__threshold) ||
(config_ptr->decr_mode == H5C_decr__age_out_with_threshold))
&& (config_ptr->lower_hr_threshold >= config_ptr->upper_hr_threshold))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "conflicting threshold fields in config")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_create_flush_dependency(void * parent_thing, void * child_thing)
{
H5C_t * cache_ptr;
H5C_cache_entry_t * parent_entry = (H5C_cache_entry_t *)parent_thing;
H5C_cache_entry_t * child_entry = (H5C_cache_entry_t *)child_thing;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(parent_entry);
HDassert(parent_entry->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(H5F_addr_defined(parent_entry->addr));
HDassert(child_entry);
HDassert(child_entry->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(H5F_addr_defined(child_entry->addr));
cache_ptr = parent_entry->cache_ptr;
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(cache_ptr == child_entry->cache_ptr);
#ifndef NDEBUG
{
unsigned u;
for(u = 0; u < child_entry->flush_dep_nparents; u++)
HDassert(child_entry->flush_dep_parent[u] != parent_entry);
}
#endif
if(child_entry == parent_entry)
HGOTO_ERROR(H5E_CACHE, H5E_CANTDEPEND, FAIL, "Child entry flush dependency parent can't be itself")
if(!(parent_entry->is_protected || parent_entry->is_pinned))
HGOTO_ERROR(H5E_CACHE, H5E_CANTDEPEND, FAIL, "Parent entry isn't pinned or protected")
if(!parent_entry->is_pinned) {
HDassert(parent_entry->flush_dep_nchildren == 0);
HDassert(!parent_entry->pinned_from_client);
HDassert(!parent_entry->pinned_from_cache);
parent_entry->is_pinned = TRUE;
H5C__UPDATE_STATS_FOR_PIN(cache_ptr, parent_entry)
}
parent_entry->pinned_from_cache = TRUE;
if(child_entry->flush_dep_nparents >= child_entry->flush_dep_parent_nalloc) {
if(child_entry->flush_dep_parent_nalloc == 0) {
HDassert(!child_entry->flush_dep_parent);
if(NULL == (child_entry->flush_dep_parent = (H5C_cache_entry_t **)H5FL_BLK_MALLOC(parent, H5C_FLUSH_DEP_PARENT_INIT * sizeof(H5C_cache_entry_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for flush dependency parent list")
child_entry->flush_dep_parent_nalloc = H5C_FLUSH_DEP_PARENT_INIT;
}
else {
HDassert(child_entry->flush_dep_parent);
if(NULL == (child_entry->flush_dep_parent = (H5C_cache_entry_t **)H5FL_BLK_REALLOC(parent, child_entry->flush_dep_parent, 2 * child_entry->flush_dep_parent_nalloc * sizeof(H5C_cache_entry_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for flush dependency parent list")
child_entry->flush_dep_parent_nalloc *= 2;
}
cache_ptr->entry_fd_height_change_counter++;
}
child_entry->flush_dep_parent[child_entry->flush_dep_nparents] = parent_entry;
child_entry->flush_dep_nparents++;
parent_entry->flush_dep_nchildren++;
if(child_entry->is_dirty) {
HDassert(parent_entry->flush_dep_ndirty_children < parent_entry->flush_dep_nchildren);
parent_entry->flush_dep_ndirty_children++;
if(parent_entry->type->notify &&
(parent_entry->type->notify)(H5C_NOTIFY_ACTION_CHILD_DIRTIED, parent_entry) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify parent about child entry dirty flag set")
}
if(!child_entry->image_up_to_date) {
HDassert(parent_entry->flush_dep_nunser_children < parent_entry->flush_dep_nchildren);
parent_entry->flush_dep_nunser_children++;
if(parent_entry->type->notify &&
(parent_entry->type->notify)(H5C_NOTIFY_ACTION_CHILD_UNSERIALIZED, parent_entry) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify parent about child entry serialized flag reset")
}
HDassert(parent_entry->is_pinned);
HDassert(parent_entry->flush_dep_nchildren > 0);
HDassert(child_entry->flush_dep_parent);
HDassert(child_entry->flush_dep_nparents > 0);
HDassert(child_entry->flush_dep_parent_nalloc > 0);
#ifndef NDEBUG
H5C__assert_flush_dep_nocycle(parent_entry, child_entry);
#endif
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_destroy_flush_dependency(void *parent_thing, void * child_thing)
{
H5C_t * cache_ptr;
H5C_cache_entry_t * parent_entry = (H5C_cache_entry_t *)parent_thing;
H5C_cache_entry_t * child_entry = (H5C_cache_entry_t *)child_thing;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(parent_entry);
HDassert(parent_entry->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(H5F_addr_defined(parent_entry->addr));
HDassert(child_entry);
HDassert(child_entry->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(H5F_addr_defined(child_entry->addr));
cache_ptr = parent_entry->cache_ptr;
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(cache_ptr == child_entry->cache_ptr);
if(!parent_entry->is_pinned)
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "Parent entry isn't pinned")
if(NULL == child_entry->flush_dep_parent)
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "Child entry doesn't have a flush dependency parent array")
if(0 == parent_entry->flush_dep_nchildren)
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "Parent entry flush dependency ref. count has no child dependencies")
for(u = 0; u < child_entry->flush_dep_nparents; u++)
if(child_entry->flush_dep_parent[u] == parent_entry)
break;
if(u == child_entry->flush_dep_nparents)
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "Parent entry isn't a flush dependency parent for child entry")
if(u < (child_entry->flush_dep_nparents - 1))
HDmemmove(&child_entry->flush_dep_parent[u],
&child_entry->flush_dep_parent[u + 1],
(child_entry->flush_dep_nparents - u - 1) * sizeof(child_entry->flush_dep_parent[0]));
child_entry->flush_dep_nparents--;
parent_entry->flush_dep_nchildren--;
if(0 == parent_entry->flush_dep_nchildren) {
HDassert(parent_entry->pinned_from_cache);
if(!parent_entry->pinned_from_client)
if(H5C__unpin_entry_real(cache_ptr, parent_entry, TRUE) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPIN, FAIL, "Can't unpin entry")
parent_entry->pinned_from_cache = FALSE;
}
if(child_entry->is_dirty) {
HDassert(parent_entry->flush_dep_ndirty_children > 0);
parent_entry->flush_dep_ndirty_children--;
if(parent_entry->type->notify &&
(parent_entry->type->notify)(H5C_NOTIFY_ACTION_CHILD_CLEANED, parent_entry) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify parent about child entry dirty flag reset")
}
if(!child_entry->image_up_to_date) {
HDassert(parent_entry->flush_dep_nunser_children > 0);
parent_entry->flush_dep_nunser_children--;
if(parent_entry->type->notify &&
(parent_entry->type->notify)(H5C_NOTIFY_ACTION_CHILD_SERIALIZED, parent_entry) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify parent about child entry serialized flag set")
}
if(child_entry->flush_dep_nparents == 0) {
child_entry->flush_dep_parent = (H5C_cache_entry_t **)H5FL_BLK_FREE(parent, child_entry->flush_dep_parent);
child_entry->flush_dep_parent_nalloc = 0;
}
else if(child_entry->flush_dep_parent_nalloc > H5C_FLUSH_DEP_PARENT_INIT
&& child_entry->flush_dep_nparents <= (child_entry->flush_dep_parent_nalloc / 4)) {
if(NULL == (child_entry->flush_dep_parent = (H5C_cache_entry_t **)H5FL_BLK_REALLOC(parent, child_entry->flush_dep_parent, (child_entry->flush_dep_parent_nalloc / 4) * sizeof(H5C_cache_entry_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for flush dependency parent list")
child_entry->flush_dep_parent_nalloc /= 4;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
#if H5C_COLLECT_CACHE_STATS
static herr_t
H5C__pin_entry_from_client(H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr)
#else
static herr_t
H5C__pin_entry_from_client(H5C_t H5_ATTR_UNUSED *cache_ptr, H5C_cache_entry_t *entry_ptr)
#endif
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(cache_ptr);
HDassert(entry_ptr);
HDassert(entry_ptr->is_protected);
if(entry_ptr->is_pinned) {
if(entry_ptr->pinned_from_client)
HGOTO_ERROR(H5E_CACHE, H5E_CANTPIN, FAIL, "entry is already pinned")
}
else {
entry_ptr->is_pinned = TRUE;
H5C__UPDATE_STATS_FOR_PIN(cache_ptr, entry_ptr)
}
entry_ptr->pinned_from_client = TRUE;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__unpin_entry_real(H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr,
hbool_t update_rp)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(cache_ptr);
HDassert(entry_ptr);
HDassert(entry_ptr->is_pinned);
if(update_rp && !entry_ptr->is_protected)
H5C__UPDATE_RP_FOR_UNPIN(cache_ptr, entry_ptr, FAIL)
entry_ptr->is_pinned = FALSE;
H5C__UPDATE_STATS_FOR_UNPIN(cache_ptr, entry_ptr)
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__unpin_entry_from_client(H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr,
hbool_t update_rp)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(cache_ptr);
HDassert(entry_ptr);
if(!entry_ptr->is_pinned)
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPIN, FAIL, "entry isn't pinned")
if(!entry_ptr->pinned_from_client)
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPIN, FAIL, "entry wasn't pinned by cache client")
if(!entry_ptr->pinned_from_cache)
if(H5C__unpin_entry_real(cache_ptr, entry_ptr, update_rp) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPIN, FAIL, "can't unpin entry")
entry_ptr->pinned_from_client = FALSE;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__auto_adjust_cache_size(H5F_t *f, hbool_t write_permitted)
{
H5C_t * cache_ptr = f->shared->cache;
hbool_t reentrant_call = FALSE;
hbool_t inserted_epoch_marker = FALSE;
size_t new_max_cache_size = 0;
size_t old_max_cache_size = 0;
size_t new_min_clean_size = 0;
size_t old_min_clean_size = 0;
double hit_rate;
enum H5C_resize_status status = in_spec;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
HDassert( f );
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
HDassert( cache_ptr->cache_accesses >=
(cache_ptr->resize_ctl).epoch_length );
HDassert( (double)0.0f <= (cache_ptr->resize_ctl).min_clean_fraction );
HDassert( (cache_ptr->resize_ctl).min_clean_fraction <= (double)100.0f );
if(cache_ptr->resize_in_progress) {
reentrant_call = TRUE;
HGOTO_DONE(SUCCEED)
}
cache_ptr->resize_in_progress = TRUE;
if(!cache_ptr->resize_enabled)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Auto cache resize disabled")
HDassert(((cache_ptr->resize_ctl).incr_mode != H5C_incr__off) || \
((cache_ptr->resize_ctl).decr_mode != H5C_decr__off));
if(H5C_get_cache_hit_rate(cache_ptr, &hit_rate) != SUCCEED)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't get hit rate")
HDassert( ( (double)0.0f <= hit_rate ) && ( hit_rate <= (double)1.0f ) );
switch((cache_ptr->resize_ctl).incr_mode) {
case H5C_incr__off:
if(cache_ptr->size_increase_possible)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "size_increase_possible but H5C_incr__off?!?!?")
break;
case H5C_incr__threshold:
if ( hit_rate < (cache_ptr->resize_ctl).lower_hr_threshold ) {
if ( ! cache_ptr->size_increase_possible ) {
status = increase_disabled;
} else if ( cache_ptr->max_cache_size >=
(cache_ptr->resize_ctl).max_size ) {
HDassert( cache_ptr->max_cache_size == \
(cache_ptr->resize_ctl).max_size );
status = at_max_size;
} else if ( ! cache_ptr->cache_full ) {
status = not_full;
} else {
new_max_cache_size = (size_t)
(((double)(cache_ptr->max_cache_size)) *
(cache_ptr->resize_ctl).increment);
if ( new_max_cache_size >
(cache_ptr->resize_ctl).max_size ) {
new_max_cache_size = (cache_ptr->resize_ctl).max_size;
}
if ( ( (cache_ptr->resize_ctl).apply_max_increment ) &&
( (cache_ptr->max_cache_size +
(cache_ptr->resize_ctl).max_increment) <
new_max_cache_size ) ) {
new_max_cache_size = cache_ptr->max_cache_size +
(cache_ptr->resize_ctl).max_increment;
}
status = increase;
}
}
break;
default:
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unknown incr_mode")
}
if ( ( ( (cache_ptr->resize_ctl).decr_mode == H5C_decr__age_out )
||
( (cache_ptr->resize_ctl).decr_mode ==
H5C_decr__age_out_with_threshold
)
)
&&
( cache_ptr->epoch_markers_active <
(cache_ptr->resize_ctl).epochs_before_eviction
)
) {
if(H5C__autoadjust__ageout__insert_new_marker(cache_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "can't insert new epoch marker")
inserted_epoch_marker = TRUE;
}
if ( status == in_spec ) {
switch ( (cache_ptr->resize_ctl).decr_mode )
{
case H5C_decr__off:
break;
case H5C_decr__threshold:
if ( hit_rate > (cache_ptr->resize_ctl).upper_hr_threshold ) {
if ( ! cache_ptr->size_decrease_possible ) {
status = decrease_disabled;
} else if ( cache_ptr->max_cache_size <=
(cache_ptr->resize_ctl).min_size ) {
HDassert( cache_ptr->max_cache_size ==
(cache_ptr->resize_ctl).min_size );
status = at_min_size;
} else {
new_max_cache_size = (size_t)
(((double)(cache_ptr->max_cache_size)) *
(cache_ptr->resize_ctl).decrement);
if ( new_max_cache_size <
(cache_ptr->resize_ctl).min_size ) {
new_max_cache_size =
(cache_ptr->resize_ctl).min_size;
}
if ( ( (cache_ptr->resize_ctl).apply_max_decrement ) &&
( ((cache_ptr->resize_ctl).max_decrement +
new_max_cache_size) <
cache_ptr->max_cache_size ) ) {
new_max_cache_size = cache_ptr->max_cache_size -
(cache_ptr->resize_ctl).max_decrement;
}
status = decrease;
}
}
break;
case H5C_decr__age_out_with_threshold:
case H5C_decr__age_out:
if(!inserted_epoch_marker) {
if(!cache_ptr->size_decrease_possible)
status = decrease_disabled;
else {
if(H5C__autoadjust__ageout(f, hit_rate, &status, &new_max_cache_size, write_permitted) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "ageout code failed")
}
}
break;
default:
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unknown incr_mode")
}
}
if ( ( ( (cache_ptr->resize_ctl).decr_mode == H5C_decr__age_out )
||
( (cache_ptr->resize_ctl).decr_mode ==
H5C_decr__age_out_with_threshold
)
)
&&
( ! inserted_epoch_marker )
) {
if(H5C__autoadjust__ageout__cycle_epoch_marker(cache_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "error cycling epoch marker")
}
if ( ( status == increase ) || ( status == decrease ) ) {
old_max_cache_size = cache_ptr->max_cache_size;
old_min_clean_size = cache_ptr->min_clean_size;
new_min_clean_size = (size_t)
((double)new_max_cache_size *
((cache_ptr->resize_ctl).min_clean_fraction));
HDassert( new_min_clean_size <= new_max_cache_size );
HDassert( (cache_ptr->resize_ctl).min_size <= new_max_cache_size );
HDassert( new_max_cache_size <= (cache_ptr->resize_ctl).max_size );
cache_ptr->max_cache_size = new_max_cache_size;
cache_ptr->min_clean_size = new_min_clean_size;
if ( status == increase ) {
cache_ptr->cache_full = FALSE;
} else if ( status == decrease ) {
cache_ptr->size_decreased = TRUE;
}
if ( cache_ptr->flash_size_increase_possible ) {
switch ( (cache_ptr->resize_ctl).flash_incr_mode )
{
case H5C_flash_incr__off:
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "flash_size_increase_possible but H5C_flash_incr__off?!")
break;
case H5C_flash_incr__add_space:
cache_ptr->flash_size_increase_threshold =
(size_t)
(((double)(cache_ptr->max_cache_size)) *
((cache_ptr->resize_ctl).flash_threshold));
break;
default:
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Unknown flash_incr_mode?!?!?")
break;
}
}
}
if ( (cache_ptr->resize_ctl).rpt_fcn != NULL ) {
(*((cache_ptr->resize_ctl).rpt_fcn))
(cache_ptr,
H5C__CURR_AUTO_RESIZE_RPT_FCN_VER,
hit_rate,
status,
old_max_cache_size,
new_max_cache_size,
old_min_clean_size,
new_min_clean_size);
}
if(H5C_reset_cache_hit_rate_stats(cache_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C_reset_cache_hit_rate_stats failed")
done:
HDassert(cache_ptr->resize_in_progress);
if(!reentrant_call)
cache_ptr->resize_in_progress = FALSE;
HDassert((!reentrant_call) || (cache_ptr->resize_in_progress));
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__autoadjust__ageout(H5F_t * f, double hit_rate, enum H5C_resize_status * status_ptr,
size_t * new_max_cache_size_ptr, hbool_t write_permitted)
{
H5C_t * cache_ptr = f->shared->cache;
size_t test_size;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
HDassert( f );
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
HDassert( ( status_ptr ) && ( *status_ptr == in_spec ) );
HDassert( ( new_max_cache_size_ptr ) && ( *new_max_cache_size_ptr == 0 ) );
if(cache_ptr->epoch_markers_active > (cache_ptr->resize_ctl).epochs_before_eviction)
if(H5C__autoadjust__ageout__remove_excess_markers(cache_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "can't remove excess epoch markers")
if ( ( (cache_ptr->resize_ctl).decr_mode == H5C_decr__age_out )
||
( ( (cache_ptr->resize_ctl).decr_mode ==
H5C_decr__age_out_with_threshold
)
&&
( hit_rate >= (cache_ptr->resize_ctl).upper_hr_threshold )
)
) {
if ( cache_ptr->max_cache_size > (cache_ptr->resize_ctl).min_size ){
if(H5C__autoadjust__ageout__evict_aged_out_entries(f, write_permitted) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "error flushing aged out entries")
if ( cache_ptr->index_size < cache_ptr->max_cache_size ) {
if ( (cache_ptr->resize_ctl).apply_empty_reserve ) {
test_size = (size_t)(((double)cache_ptr->index_size) /
(1 - (cache_ptr->resize_ctl).empty_reserve));
if ( test_size < cache_ptr->max_cache_size ) {
*status_ptr = decrease;
*new_max_cache_size_ptr = test_size;
}
} else {
*status_ptr = decrease;
*new_max_cache_size_ptr = cache_ptr->index_size;
}
if ( *status_ptr == decrease ) {
if ( *new_max_cache_size_ptr <
(cache_ptr->resize_ctl).min_size ) {
*new_max_cache_size_ptr =
(cache_ptr->resize_ctl).min_size;
}
if ( ( (cache_ptr->resize_ctl).apply_max_decrement ) &&
( ((cache_ptr->resize_ctl).max_decrement +
*new_max_cache_size_ptr) <
cache_ptr->max_cache_size ) ) {
*new_max_cache_size_ptr = cache_ptr->max_cache_size -
(cache_ptr->resize_ctl).max_decrement;
}
}
}
} else {
*status_ptr = at_min_size;
}
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__autoadjust__ageout__cycle_epoch_marker(H5C_t * cache_ptr)
{
herr_t ret_value = SUCCEED;
int i;
FUNC_ENTER_NOAPI_NOINIT
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
if(cache_ptr->epoch_markers_active <= 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "No active epoch markers on entry?!?!?")
i = cache_ptr->epoch_marker_ringbuf[cache_ptr->epoch_marker_ringbuf_first];
cache_ptr->epoch_marker_ringbuf_first =
(cache_ptr->epoch_marker_ringbuf_first + 1) %
(H5C__MAX_EPOCH_MARKERS + 1);
cache_ptr->epoch_marker_ringbuf_size -= 1;
if(cache_ptr->epoch_marker_ringbuf_size < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "ring buffer underflow")
if((cache_ptr->epoch_marker_active)[i] != TRUE)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unused marker in LRU?!?")
H5C__DLL_REMOVE((&((cache_ptr->epoch_markers)[i])), \
(cache_ptr)->LRU_head_ptr, \
(cache_ptr)->LRU_tail_ptr, \
(cache_ptr)->LRU_list_len, \
(cache_ptr)->LRU_list_size, \
(FAIL))
HDassert(((cache_ptr->epoch_markers)[i]).addr == (haddr_t)i);
HDassert(((cache_ptr->epoch_markers)[i]).next == NULL);
HDassert(((cache_ptr->epoch_markers)[i]).prev == NULL);
cache_ptr->epoch_marker_ringbuf_last =
(cache_ptr->epoch_marker_ringbuf_last + 1) %
(H5C__MAX_EPOCH_MARKERS + 1);
(cache_ptr->epoch_marker_ringbuf)[cache_ptr->epoch_marker_ringbuf_last] = i;
cache_ptr->epoch_marker_ringbuf_size += 1;
if(cache_ptr->epoch_marker_ringbuf_size > H5C__MAX_EPOCH_MARKERS)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "ring buffer overflow")
H5C__DLL_PREPEND((&((cache_ptr->epoch_markers)[i])), \
(cache_ptr)->LRU_head_ptr, \
(cache_ptr)->LRU_tail_ptr, \
(cache_ptr)->LRU_list_len, \
(cache_ptr)->LRU_list_size, \
(FAIL))
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__autoadjust__ageout__evict_aged_out_entries(H5F_t *f, hbool_t write_permitted)
{
H5C_t * cache_ptr = f->shared->cache;
size_t eviction_size_limit;
size_t bytes_evicted = 0;
hbool_t prev_is_dirty = FALSE;
hbool_t restart_scan;
H5C_cache_entry_t * entry_ptr;
H5C_cache_entry_t * next_ptr;
H5C_cache_entry_t * prev_ptr;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
HDassert( f );
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
if ( (cache_ptr->resize_ctl).apply_max_decrement ) {
eviction_size_limit = (cache_ptr->resize_ctl).max_decrement;
} else {
eviction_size_limit = cache_ptr->index_size;
}
if ( write_permitted ) {
restart_scan = FALSE;
entry_ptr = cache_ptr->LRU_tail_ptr;
while ( ( entry_ptr != NULL ) &&
( (entry_ptr->type)->id != H5AC_EPOCH_MARKER_ID ) &&
( bytes_evicted < eviction_size_limit ) )
{
hbool_t skipping_entry = FALSE;
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert( ! (entry_ptr->is_protected) );
HDassert( ! (entry_ptr->is_read_only) );
HDassert( (entry_ptr->ro_ref_count) == 0 );
next_ptr = entry_ptr->next;
prev_ptr = entry_ptr->prev;
if(prev_ptr != NULL)
prev_is_dirty = prev_ptr->is_dirty;
if(entry_ptr->is_dirty ) {
HDassert(!entry_ptr->prefetched_dirty);
if(entry_ptr->tag_info && entry_ptr->tag_info->corked)
skipping_entry = TRUE;
else {
cache_ptr->entries_removed_counter = 0;
cache_ptr->last_entry_removed_ptr = NULL;
if(H5C__flush_single_entry(f, entry_ptr, H5C__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush entry")
if(cache_ptr->entries_removed_counter > 1 || cache_ptr->last_entry_removed_ptr == prev_ptr)
restart_scan = TRUE;
}
}
else if(!entry_ptr->prefetched_dirty) {
bytes_evicted += entry_ptr->size;
if(H5C__flush_single_entry(f, entry_ptr, H5C__FLUSH_INVALIDATE_FLAG | H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush entry")
}
else {
HDassert(!entry_ptr->is_dirty);
HDassert(entry_ptr->prefetched_dirty);
skipping_entry = TRUE;
}
if(prev_ptr != NULL) {
if(skipping_entry)
entry_ptr = prev_ptr;
else if(restart_scan || (prev_ptr->is_dirty != prev_is_dirty)
|| (prev_ptr->next != next_ptr)
|| (prev_ptr->is_protected)
|| (prev_ptr->is_pinned)) {
restart_scan = FALSE;
entry_ptr = cache_ptr->LRU_tail_ptr;
H5C__UPDATE_STATS_FOR_LRU_SCAN_RESTART(cache_ptr)
}
else
entry_ptr = prev_ptr;
}
else
entry_ptr = NULL;
}
}
else {
HDassert(H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS);
entry_ptr = cache_ptr->LRU_tail_ptr;
while(entry_ptr != NULL &&
((entry_ptr->type)->id != H5AC_EPOCH_MARKER_ID) &&
(bytes_evicted < eviction_size_limit)) {
HDassert(!(entry_ptr->is_protected));
prev_ptr = entry_ptr->prev;
if(!(entry_ptr->is_dirty) && !(entry_ptr->prefetched_dirty))
if(H5C__flush_single_entry(f, entry_ptr, H5C__FLUSH_INVALIDATE_FLAG | H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush clean entry")
entry_ptr = prev_ptr;
}
}
if(cache_ptr->index_size < cache_ptr->max_cache_size)
cache_ptr->cache_full = FALSE;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__autoadjust__ageout__insert_new_marker(H5C_t * cache_ptr)
{
herr_t ret_value = SUCCEED;
int i;
FUNC_ENTER_NOAPI_NOINIT
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
if(cache_ptr->epoch_markers_active >= (cache_ptr->resize_ctl).epochs_before_eviction)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Already have a full complement of markers")
i = 0;
while((cache_ptr->epoch_marker_active)[i] && i < H5C__MAX_EPOCH_MARKERS)
i++;
if(i >= H5C__MAX_EPOCH_MARKERS)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't find unused marker")
HDassert( ((cache_ptr->epoch_markers)[i]).addr == (haddr_t)i );
HDassert( ((cache_ptr->epoch_markers)[i]).next == NULL );
HDassert( ((cache_ptr->epoch_markers)[i]).prev == NULL );
(cache_ptr->epoch_marker_active)[i] = TRUE;
cache_ptr->epoch_marker_ringbuf_last =
(cache_ptr->epoch_marker_ringbuf_last + 1) %
(H5C__MAX_EPOCH_MARKERS + 1);
(cache_ptr->epoch_marker_ringbuf)[cache_ptr->epoch_marker_ringbuf_last] = i;
cache_ptr->epoch_marker_ringbuf_size += 1;
if ( cache_ptr->epoch_marker_ringbuf_size > H5C__MAX_EPOCH_MARKERS ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "ring buffer overflow")
}
H5C__DLL_PREPEND((&((cache_ptr->epoch_markers)[i])), \
(cache_ptr)->LRU_head_ptr, \
(cache_ptr)->LRU_tail_ptr, \
(cache_ptr)->LRU_list_len, \
(cache_ptr)->LRU_list_size, \
(FAIL))
cache_ptr->epoch_markers_active += 1;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__autoadjust__ageout__remove_all_markers(H5C_t * cache_ptr)
{
herr_t ret_value = SUCCEED;
int i;
int ring_buf_index;
FUNC_ENTER_NOAPI_NOINIT
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
while ( cache_ptr->epoch_markers_active > 0 )
{
ring_buf_index = cache_ptr->epoch_marker_ringbuf_first;
i = (cache_ptr->epoch_marker_ringbuf)[ring_buf_index];
cache_ptr->epoch_marker_ringbuf_first =
(cache_ptr->epoch_marker_ringbuf_first + 1) %
(H5C__MAX_EPOCH_MARKERS + 1);
cache_ptr->epoch_marker_ringbuf_size -= 1;
if(cache_ptr->epoch_marker_ringbuf_size < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "ring buffer underflow")
if((cache_ptr->epoch_marker_active)[i] != TRUE)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unused marker in LRU?!?")
H5C__DLL_REMOVE((&((cache_ptr->epoch_markers)[i])), \
(cache_ptr)->LRU_head_ptr, \
(cache_ptr)->LRU_tail_ptr, \
(cache_ptr)->LRU_list_len, \
(cache_ptr)->LRU_list_size, \
(FAIL))
(cache_ptr->epoch_marker_active)[i] = FALSE;
HDassert( ((cache_ptr->epoch_markers)[i]).addr == (haddr_t)i );
HDassert( ((cache_ptr->epoch_markers)[i]).next == NULL );
HDassert( ((cache_ptr->epoch_markers)[i]).prev == NULL );
cache_ptr->epoch_markers_active -= 1;
HDassert( cache_ptr->epoch_markers_active == \
cache_ptr->epoch_marker_ringbuf_size );
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__autoadjust__ageout__remove_excess_markers(H5C_t * cache_ptr)
{
herr_t ret_value = SUCCEED;
int i;
int ring_buf_index;
FUNC_ENTER_NOAPI_NOINIT
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
if(cache_ptr->epoch_markers_active <= (cache_ptr->resize_ctl).epochs_before_eviction)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "no excess markers on entry")
while(cache_ptr->epoch_markers_active > (cache_ptr->resize_ctl).epochs_before_eviction) {
ring_buf_index = cache_ptr->epoch_marker_ringbuf_first;
i = (cache_ptr->epoch_marker_ringbuf)[ring_buf_index];
cache_ptr->epoch_marker_ringbuf_first =
(cache_ptr->epoch_marker_ringbuf_first + 1) %
(H5C__MAX_EPOCH_MARKERS + 1);
cache_ptr->epoch_marker_ringbuf_size -= 1;
if(cache_ptr->epoch_marker_ringbuf_size < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "ring buffer underflow")
if((cache_ptr->epoch_marker_active)[i] != TRUE)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unused marker in LRU?!?")
H5C__DLL_REMOVE((&((cache_ptr->epoch_markers)[i])), \
(cache_ptr)->LRU_head_ptr, \
(cache_ptr)->LRU_tail_ptr, \
(cache_ptr)->LRU_list_len, \
(cache_ptr)->LRU_list_size, \
(FAIL))
(cache_ptr->epoch_marker_active)[i] = FALSE;
HDassert( ((cache_ptr->epoch_markers)[i]).addr == (haddr_t)i );
HDassert( ((cache_ptr->epoch_markers)[i]).next == NULL );
HDassert( ((cache_ptr->epoch_markers)[i]).prev == NULL );
cache_ptr->epoch_markers_active -= 1;
HDassert( cache_ptr->epoch_markers_active == \
cache_ptr->epoch_marker_ringbuf_size );
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__flash_increase_cache_size(H5C_t * cache_ptr,
size_t old_entry_size,
size_t new_entry_size)
{
size_t new_max_cache_size = 0;
size_t old_max_cache_size = 0;
size_t new_min_clean_size = 0;
size_t old_min_clean_size = 0;
size_t space_needed;
enum H5C_resize_status status = flash_increase;
double hit_rate;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
HDassert( cache_ptr->flash_size_increase_possible );
HDassert( new_entry_size > cache_ptr->flash_size_increase_threshold );
HDassert( old_entry_size < new_entry_size );
if(old_entry_size >= new_entry_size)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "old_entry_size >= new_entry_size")
space_needed = new_entry_size - old_entry_size;
if ( ( (cache_ptr->index_size + space_needed) >
cache_ptr->max_cache_size ) &&
( cache_ptr->max_cache_size < (cache_ptr->resize_ctl).max_size ) ) {
switch ( (cache_ptr->resize_ctl).flash_incr_mode )
{
case H5C_flash_incr__off:
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "flash_size_increase_possible but H5C_flash_incr__off?!")
break;
case H5C_flash_incr__add_space:
if ( cache_ptr->index_size < cache_ptr->max_cache_size ) {
HDassert( (cache_ptr->max_cache_size - cache_ptr->index_size)
< space_needed );
space_needed -= cache_ptr->max_cache_size -
cache_ptr->index_size;
}
space_needed =
(size_t)(((double)space_needed) *
(cache_ptr->resize_ctl).flash_multiple);
new_max_cache_size = cache_ptr->max_cache_size + space_needed;
break;
default:
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Unknown flash_incr_mode?!?!?")
break;
}
if ( new_max_cache_size > (cache_ptr->resize_ctl).max_size ) {
new_max_cache_size = (cache_ptr->resize_ctl).max_size;
}
HDassert( new_max_cache_size > cache_ptr->max_cache_size );
new_min_clean_size = (size_t)
((double)new_max_cache_size *
((cache_ptr->resize_ctl).min_clean_fraction));
HDassert( new_min_clean_size <= new_max_cache_size );
old_max_cache_size = cache_ptr->max_cache_size;
old_min_clean_size = cache_ptr->min_clean_size;
cache_ptr->max_cache_size = new_max_cache_size;
cache_ptr->min_clean_size = new_min_clean_size;
HDassert ( cache_ptr->flash_size_increase_possible );
switch ( (cache_ptr->resize_ctl).flash_incr_mode )
{
case H5C_flash_incr__off:
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "flash_size_increase_possible but H5C_flash_incr__off?!")
break;
case H5C_flash_incr__add_space:
cache_ptr->flash_size_increase_threshold =
(size_t)
(((double)(cache_ptr->max_cache_size)) *
((cache_ptr->resize_ctl).flash_threshold));
break;
default:
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Unknown flash_incr_mode?!?!?")
break;
}
if ( (cache_ptr->resize_ctl).rpt_fcn != NULL ) {
if(H5C_get_cache_hit_rate(cache_ptr, &hit_rate) != SUCCEED)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't get hit rate")
(*((cache_ptr->resize_ctl).rpt_fcn))
(cache_ptr,
H5C__CURR_AUTO_RESIZE_RPT_FCN_VER,
hit_rate,
status,
old_max_cache_size,
new_max_cache_size,
old_min_clean_size,
new_min_clean_size);
}
if(H5C_reset_cache_hit_rate_stats(cache_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C_reset_cache_hit_rate_stats failed")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__flush_invalidate_cache(H5F_t *f, unsigned flags)
{
H5C_t * cache_ptr;
H5C_ring_t ring;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(f);
HDassert(f->shared);
cache_ptr = f->shared->cache;
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(cache_ptr->slist_ptr);
HDassert(cache_ptr->slist_enabled);
#if H5C_DO_SANITY_CHECKS
{
int32_t i;
uint32_t index_len = 0;
uint32_t slist_len = 0;
size_t index_size = (size_t)0;
size_t clean_index_size = (size_t)0;
size_t dirty_index_size = (size_t)0;
size_t slist_size = (size_t)0;
HDassert(cache_ptr->index_ring_len[H5C_RING_UNDEFINED] == 0);
HDassert(cache_ptr->index_ring_size[H5C_RING_UNDEFINED] == (size_t)0);
HDassert(cache_ptr->clean_index_ring_size[H5C_RING_UNDEFINED] == (size_t)0);
HDassert(cache_ptr->dirty_index_ring_size[H5C_RING_UNDEFINED] == (size_t)0);
HDassert(cache_ptr->slist_ring_len[H5C_RING_UNDEFINED] == 0);
HDassert(cache_ptr->slist_ring_size[H5C_RING_UNDEFINED] == (size_t)0);
for ( i = H5C_RING_USER; i < H5C_RING_NTYPES; i++ ) {
index_len += cache_ptr->index_ring_len[i];
index_size += cache_ptr->index_ring_size[i];
clean_index_size += cache_ptr->clean_index_ring_size[i];
dirty_index_size += cache_ptr->dirty_index_ring_size[i];
slist_len += cache_ptr->slist_ring_len[i];
slist_size += cache_ptr->slist_ring_size[i];
}
HDassert(cache_ptr->index_len == index_len);
HDassert(cache_ptr->index_size == index_size);
HDassert(cache_ptr->clean_index_size == clean_index_size);
HDassert(cache_ptr->dirty_index_size == dirty_index_size);
HDassert(cache_ptr->slist_len == slist_len);
HDassert(cache_ptr->slist_size == slist_size);
}
#endif
if ( cache_ptr->epoch_markers_active > 0 ) {
if ( H5C__autoadjust__ageout__remove_all_markers(cache_ptr) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"error removing all epoch markers")
}
ring = H5C_RING_USER;
while ( ring < H5C_RING_NTYPES) {
if(H5C_flush_invalidate_ring(f, ring, flags) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL,
"flush invalidate ring failed")
ring++;
}
if( ! ( flags & H5C__EVICT_ALLOW_LAST_PINS_FLAG ) ) {
HDassert(cache_ptr->index_size == 0);
HDassert(cache_ptr->clean_index_size == 0);
HDassert(cache_ptr->pel_len == 0);
HDassert(cache_ptr->pel_size == 0);
}
else {
H5C_cache_entry_t *entry_ptr;
unsigned u;
for ( u = H5C_RING_USER; u < H5C_RING_SB; u++ ) {
HDassert(cache_ptr->index_ring_len[u] == 0);
HDassert(cache_ptr->index_ring_size[u] == 0);
HDassert(cache_ptr->clean_index_ring_size[u] == 0);
}
entry_ptr = cache_ptr->pel_head_ptr;
while(entry_ptr) {
HDassert(entry_ptr->ring == H5C_RING_SB);
entry_ptr = entry_ptr->next;
}
}
HDassert(cache_ptr->dirty_index_size == 0);
HDassert(cache_ptr->slist_len == 0);
HDassert(cache_ptr->slist_size == 0);
HDassert(cache_ptr->pl_len == 0);
HDassert(cache_ptr->pl_size == 0);
HDassert(cache_ptr->LRU_list_len == 0);
HDassert(cache_ptr->LRU_list_size == 0);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C_flush_invalidate_ring(H5F_t * f, H5C_ring_t ring, unsigned flags)
{
H5C_t *cache_ptr;
hbool_t restart_slist_scan;
uint32_t protected_entries = 0;
int32_t i;
int32_t cur_ring_pel_len;
int32_t old_ring_pel_len;
unsigned cooked_flags;
unsigned evict_flags;
H5SL_node_t *node_ptr = NULL;
H5C_cache_entry_t *entry_ptr = NULL;
H5C_cache_entry_t *next_entry_ptr = NULL;
#if H5C_DO_SANITY_CHECKS
uint32_t initial_slist_len = 0;
size_t initial_slist_size = 0;
#endif
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(f);
HDassert(f->shared);
cache_ptr = f->shared->cache;
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(cache_ptr->slist_enabled);
HDassert(cache_ptr->slist_ptr);
HDassert(ring > H5C_RING_UNDEFINED);
HDassert(ring < H5C_RING_NTYPES);
HDassert(cache_ptr->epoch_markers_active == 0);
cooked_flags = flags & H5C__FLUSH_CLEAR_ONLY_FLAG;
evict_flags = flags & H5C__EVICT_ALLOW_LAST_PINS_FLAG;
entry_ptr = cache_ptr->pel_head_ptr;
cur_ring_pel_len = 0;
while ( entry_ptr != NULL ) {
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(entry_ptr->ring >= ring);
if(entry_ptr->ring == ring)
cur_ring_pel_len++;
entry_ptr = entry_ptr->next;
}
old_ring_pel_len = cur_ring_pel_len;
while(cache_ptr->index_ring_len[ring] > 0) {
#if H5C_DO_SANITY_CHECKS
initial_slist_len = cache_ptr->slist_len;
initial_slist_size = cache_ptr->slist_size;
cache_ptr->slist_len_increase = 0;
cache_ptr->slist_size_increase = 0;
#endif
cache_ptr->slist_changed = FALSE;
restart_slist_scan = TRUE;
while ( restart_slist_scan || ( node_ptr != NULL ) ) {
if ( restart_slist_scan ) {
restart_slist_scan = FALSE;
node_ptr = H5SL_first(cache_ptr->slist_ptr);
if ( node_ptr == NULL )
break;
next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
if ( NULL == next_entry_ptr )
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"next_entry_ptr == NULL ?!?!")
HDassert(next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(next_entry_ptr->is_dirty);
HDassert(next_entry_ptr->in_slist);
HDassert(next_entry_ptr->ring >= ring);
}
entry_ptr = next_entry_ptr;
HDassert(entry_ptr != NULL);
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(entry_ptr->in_slist);
HDassert(entry_ptr->is_dirty);
HDassert(entry_ptr->ring >= ring);
node_ptr = H5SL_next(node_ptr);
if(node_ptr != NULL) {
next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
if(NULL == next_entry_ptr)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"next_entry_ptr == NULL ?!?!")
HDassert(next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(next_entry_ptr->is_dirty);
HDassert(next_entry_ptr->in_slist);
HDassert(next_entry_ptr->ring >= ring);
HDassert(entry_ptr != next_entry_ptr);
}
else {
next_entry_ptr = NULL;
}
if ( ( ( !entry_ptr->flush_me_last ) ||
( ( entry_ptr->flush_me_last ) &&
( cache_ptr->num_last_entries >= cache_ptr->slist_len ) )
) &&
( entry_ptr->flush_dep_nchildren == 0 ) &&
( entry_ptr->ring == ring ) ) {
if ( entry_ptr->is_protected ) {
protected_entries++;
}
else if ( entry_ptr->is_pinned ) {
if ( H5C__flush_single_entry(f, entry_ptr,
H5C__DURING_FLUSH_FLAG) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
"dirty pinned entry flush failed")
if ( cache_ptr->slist_changed ) {
restart_slist_scan = TRUE;
cache_ptr->slist_changed = FALSE;
H5C__UPDATE_STATS_FOR_SLIST_SCAN_RESTART(cache_ptr);
}
}
else {
if ( H5C__flush_single_entry(f, entry_ptr,
(cooked_flags |
H5C__DURING_FLUSH_FLAG |
H5C__FLUSH_INVALIDATE_FLAG |
H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG) ) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL,
"dirty entry flush destroy failed")
if ( cache_ptr->slist_changed ) {
restart_slist_scan = TRUE;
cache_ptr->slist_changed = FALSE;
H5C__UPDATE_STATS_FOR_SLIST_SCAN_RESTART(cache_ptr)
}
}
}
}
#if H5C_DO_SANITY_CHECKS
if ( node_ptr == NULL ) {
HDassert(cache_ptr->slist_len ==
(uint32_t)((int32_t)initial_slist_len +
cache_ptr->slist_len_increase));
HDassert(cache_ptr->slist_size ==
(size_t)((ssize_t)initial_slist_size +
cache_ptr->slist_size_increase));
}
#endif
cache_ptr->entries_loaded_counter = 0;
cache_ptr->entries_inserted_counter = 0;
cache_ptr->entries_relocated_counter = 0;
next_entry_ptr = cache_ptr->il_head;
while ( next_entry_ptr != NULL ) {
entry_ptr = next_entry_ptr;
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(entry_ptr->ring >= ring);
next_entry_ptr = entry_ptr->il_next;
HDassert((next_entry_ptr == NULL) ||
(next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC));
if ( ( ( ! entry_ptr->flush_me_last ) ||
( entry_ptr->flush_me_last &&
( cache_ptr->num_last_entries >= cache_ptr->slist_len ) )
) &&
( entry_ptr->flush_dep_nchildren == 0 ) &&
( entry_ptr->ring == ring ) ) {
if ( entry_ptr->is_protected ) {
protected_entries++;
if ( ! entry_ptr->in_slist ) {
HDassert(!(entry_ptr->is_dirty));
}
}
else if ( ! ( entry_ptr->is_pinned ) ) {
cache_ptr->entry_watched_for_removal = next_entry_ptr;
if ( H5C__flush_single_entry(f, entry_ptr,
(cooked_flags |
H5C__DURING_FLUSH_FLAG |
H5C__FLUSH_INVALIDATE_FLAG |
H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG)) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
"Entry flush destroy failed")
if ( ( ( NULL != next_entry_ptr ) &&
( NULL == cache_ptr->entry_watched_for_removal )
) ||
( cache_ptr->entries_loaded_counter > 0 ) ||
( cache_ptr->entries_inserted_counter > 0 ) ||
( cache_ptr->entries_relocated_counter > 0 ) ) {
next_entry_ptr = cache_ptr->il_head;
cache_ptr->entries_loaded_counter = 0;
cache_ptr->entries_inserted_counter = 0;
cache_ptr->entries_relocated_counter = 0;
H5C__UPDATE_STATS_FOR_INDEX_SCAN_RESTART(cache_ptr)
}
else {
cache_ptr->entry_watched_for_removal = NULL;
}
}
}
}
old_ring_pel_len = cur_ring_pel_len;
entry_ptr = cache_ptr->pel_head_ptr;
cur_ring_pel_len = 0;
while ( entry_ptr != NULL ) {
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(entry_ptr->ring >= ring);
if ( entry_ptr->ring == ring ) {
cur_ring_pel_len++;
}
entry_ptr = entry_ptr->next;
}
if ( ( cur_ring_pel_len > 0 ) &&
( cur_ring_pel_len >= old_ring_pel_len ) ) {
if ( evict_flags ) {
HGOTO_DONE(TRUE)
}
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
"Pinned entry count not decreasing, cur_ring_pel_len = %d, old_ring_pel_len = %d, ring = %d", \
(int)cur_ring_pel_len, \
(int)old_ring_pel_len, (int)ring)
}
HDassert(protected_entries == cache_ptr->pl_len);
if ( ( protected_entries > 0 ) &&
( protected_entries == cache_ptr->index_len ) )
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
"Only protected entries left in cache, protected_entries = %d",\
(int)protected_entries)
}
for ( i = (int)H5C_RING_UNDEFINED; i <= (int)ring; i++ ) {
HDassert(cache_ptr->index_ring_len[i] == 0);
HDassert(cache_ptr->index_ring_size[i] == (size_t)0);
HDassert(cache_ptr->clean_index_ring_size[i] == (size_t)0);
HDassert(cache_ptr->dirty_index_ring_size[i] == (size_t)0);
HDassert(cache_ptr->slist_ring_len[i] == 0);
HDassert(cache_ptr->slist_ring_size[i] == (size_t)0);
}
HDassert(protected_entries <= cache_ptr->pl_len);
if ( protected_entries > 0 ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
"Cache has protected entries")
} else if ( cur_ring_pel_len > 0 ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
"Can't unpin all pinned entries in ring")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__flush_ring(H5F_t *f, H5C_ring_t ring, unsigned flags)
{
H5C_t * cache_ptr = f->shared->cache;
hbool_t flushed_entries_last_pass;
hbool_t flush_marked_entries;
hbool_t ignore_protected;
hbool_t tried_to_flush_protected_entry = FALSE;
hbool_t restart_slist_scan;
uint32_t protected_entries = 0;
H5SL_node_t * node_ptr = NULL;
H5C_cache_entry_t * entry_ptr = NULL;
H5C_cache_entry_t * next_entry_ptr = NULL;
#if H5C_DO_SANITY_CHECKS
uint32_t initial_slist_len = 0;
size_t initial_slist_size = 0;
#endif
int i;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(cache_ptr->slist_enabled);
HDassert(cache_ptr->slist_ptr);
HDassert((flags & H5C__FLUSH_INVALIDATE_FLAG) == 0);
HDassert(ring > H5C_RING_UNDEFINED);
HDassert(ring < H5C_RING_NTYPES);
#if H5C_DO_EXTREME_SANITY_CHECKS
if ( ( H5C_validate_protected_entry_list(cache_ptr) < 0 ) ||
( H5C_validate_pinned_entry_list(cache_ptr ) < 0 ) ||
( H5C_validate_lru_list(cache_ptr) < 0 ) )
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL,
"an extreme sanity check failed on entry")
#endif
ignore_protected = ( (flags & H5C__FLUSH_IGNORE_PROTECTED_FLAG) != 0 );
flush_marked_entries = ( (flags & H5C__FLUSH_MARKED_ENTRIES_FLAG) != 0 );
if ( ! flush_marked_entries ) {
for ( i = (int)H5C_RING_UNDEFINED; i < (int)ring; i++ ) {
HDassert(cache_ptr->slist_ring_len[i] == 0);
}
}
HDassert(cache_ptr->flush_in_progress);
flushed_entries_last_pass = TRUE;
cache_ptr->slist_changed = FALSE;
while ( ( cache_ptr->slist_ring_len[ring] > 0 ) &&
( protected_entries == 0 ) &&
( flushed_entries_last_pass ) ) {
flushed_entries_last_pass = FALSE;
#if H5C_DO_SANITY_CHECKS
initial_slist_len = cache_ptr->slist_len;
initial_slist_size = cache_ptr->slist_size;
cache_ptr->slist_len_increase = 0;
cache_ptr->slist_size_increase = 0;
#endif
restart_slist_scan = TRUE;
while ( ( restart_slist_scan ) || ( node_ptr != NULL ) ) {
if ( restart_slist_scan ) {
restart_slist_scan = FALSE;
node_ptr = H5SL_first(cache_ptr->slist_ptr);
if ( node_ptr == NULL ) {
break;
}
next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
if ( NULL == next_entry_ptr )
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"next_entry_ptr == NULL ?!?!")
HDassert(next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(next_entry_ptr->is_dirty);
HDassert(next_entry_ptr->in_slist);
}
entry_ptr = next_entry_ptr;
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(entry_ptr->in_slist);
HDassert(entry_ptr->is_dirty);
if ( ( ! flush_marked_entries ) || ( entry_ptr->flush_marker ) ) {
HDassert(entry_ptr->ring >= ring);
}
node_ptr = H5SL_next(node_ptr);
if ( node_ptr != NULL ) {
next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
if ( NULL == next_entry_ptr )
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"next_entry_ptr == NULL ?!?!")
HDassert(next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(next_entry_ptr->is_dirty);
HDassert(next_entry_ptr->in_slist);
if ( ! flush_marked_entries || next_entry_ptr->flush_marker ) {
HDassert(next_entry_ptr->ring >= ring);
}
HDassert(entry_ptr != next_entry_ptr);
}
else {
next_entry_ptr = NULL;
}
if ( ( ! flush_marked_entries || entry_ptr->flush_marker ) &&
( ( ! entry_ptr->flush_me_last ) ||
( ( entry_ptr->flush_me_last ) &&
( ( cache_ptr->num_last_entries >= cache_ptr->slist_len )||
( flush_marked_entries && entry_ptr->flush_marker ) )
)
) &&
( ( entry_ptr->flush_dep_nchildren == 0 ) ||
( entry_ptr->flush_dep_ndirty_children == 0 ) ) &&
( entry_ptr->ring == ring ) ) {
HDassert(entry_ptr->flush_dep_nunser_children == 0);
if ( entry_ptr->is_protected ) {
tried_to_flush_protected_entry = TRUE;
protected_entries++;
}
else {
if ( H5C__flush_single_entry(f, entry_ptr,
(flags | H5C__DURING_FLUSH_FLAG)) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
"Can't flush entry")
if ( cache_ptr->slist_changed ) {
restart_slist_scan = TRUE;
cache_ptr->slist_changed = FALSE;
H5C__UPDATE_STATS_FOR_SLIST_SCAN_RESTART(cache_ptr)
}
flushed_entries_last_pass = TRUE;
}
}
}
#if H5C_DO_SANITY_CHECKS
HDassert((uint32_t)((int32_t)initial_slist_len + \
cache_ptr->slist_len_increase) == cache_ptr->slist_len);
HDassert((size_t)((ssize_t)initial_slist_size + \
cache_ptr->slist_size_increase) == cache_ptr->slist_size);
#endif
}
HDassert(protected_entries <= cache_ptr->pl_len);
if ( ( ( cache_ptr->pl_len > 0 ) && ( ! ignore_protected ) ) ||
( tried_to_flush_protected_entry ) )
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
"cache has protected items")
#if H5C_DO_SANITY_CHECKS
if ( ! flush_marked_entries ) {
HDassert(cache_ptr->slist_ring_len[ring] == 0);
HDassert(cache_ptr->slist_ring_size[ring] == 0);
}
#endif
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags)
{
H5C_t * cache_ptr;
hbool_t destroy;
hbool_t clear_only;
hbool_t free_file_space;
hbool_t take_ownership;
hbool_t del_from_slist_on_destroy;
hbool_t during_flush;
hbool_t write_entry;
hbool_t destroy_entry;
hbool_t generate_image;
hbool_t update_page_buffer;
hbool_t was_dirty;
hbool_t suppress_image_entry_writes = FALSE;
hbool_t suppress_image_entry_frees = FALSE;
haddr_t entry_addr = HADDR_UNDEF;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(f);
cache_ptr = f->shared->cache;
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(entry_ptr);
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(entry_ptr->ring != H5C_RING_UNDEFINED);
HDassert(entry_ptr->type);
destroy = ((flags & H5C__FLUSH_INVALIDATE_FLAG) != 0);
clear_only = ((flags & H5C__FLUSH_CLEAR_ONLY_FLAG) != 0);
free_file_space = ((flags & H5C__FREE_FILE_SPACE_FLAG) != 0);
take_ownership = ((flags & H5C__TAKE_OWNERSHIP_FLAG) != 0);
del_from_slist_on_destroy =
((flags & H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG) != 0);
during_flush = ((flags & H5C__DURING_FLUSH_FLAG) != 0);
generate_image = ((flags & H5C__GENERATE_IMAGE_FLAG) != 0);
update_page_buffer = ((flags & H5C__UPDATE_PAGE_BUFFER_FLAG) != 0);
if ( take_ownership ) {
destroy_entry = FALSE;
} else {
destroy_entry = destroy;
}
if ( entry_ptr->is_dirty && !clear_only ) {
write_entry = TRUE;
} else {
write_entry = FALSE;
}
if ( ( cache_ptr->close_warning_received ) &&
( cache_ptr->image_ctl.generate_image ) &&
( cache_ptr->num_entries_in_image > 0 ) &&
( cache_ptr->image_entries != NULL ) ) {
HDassert(entry_ptr->image_up_to_date || !(entry_ptr->include_in_image));
HDassert(entry_ptr->image_ptr || !(entry_ptr->include_in_image));
HDassert((!clear_only) || !(entry_ptr->include_in_image));
HDassert((!take_ownership) || !(entry_ptr->include_in_image));
HDassert((!free_file_space) || !(entry_ptr->include_in_image));
suppress_image_entry_frees = TRUE;
if ( cache_ptr->image_ctl.flags & H5C_CI__SUPRESS_ENTRY_WRITES ) {
suppress_image_entry_writes = TRUE;
}
}
#if H5C_DO_SANITY_CHECKS
if ( cache_ptr->slist_enabled ) {
if ( entry_ptr->in_slist ) {
HDassert(entry_ptr->is_dirty);
if ( ( entry_ptr->flush_marker ) && ( ! entry_ptr->is_dirty ) )
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"entry in slist failed sanity checks")
}
else {
HDassert(!entry_ptr->is_dirty);
HDassert(!entry_ptr->flush_marker);
if ( ( entry_ptr->is_dirty ) || ( entry_ptr->flush_marker ) )
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"entry failed sanity checks")
}
} else {
HDassert( ! entry_ptr->in_slist );
if ( ! entry_ptr->is_dirty ) {
if ( entry_ptr->flush_marker )
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"flush marked clean entry?")
}
}
#endif
if ( entry_ptr->is_protected ) {
HDassert(!entry_ptr->is_protected);
HGOTO_ERROR(H5E_CACHE, H5E_PROTECT, FAIL, \
"Attempt to flush a protected entry")
}
entry_ptr->flush_in_progress = TRUE;
entry_ptr->flush_marker = FALSE;
was_dirty = entry_ptr->is_dirty;
if ( write_entry || generate_image ) {
HDassert(entry_ptr->is_dirty);
if ( NULL == entry_ptr->image_ptr ) {
if ( NULL == (entry_ptr->image_ptr =
H5MM_malloc(entry_ptr->size + H5C_IMAGE_EXTRA_SPACE)) )
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, \
"memory allocation failed for on disk image buffer")
#if H5C_DO_MEMORY_SANITY_CHECKS
H5MM_memcpy(((uint8_t *)entry_ptr->image_ptr) + entry_ptr->size,
H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif
}
if ( ! ( entry_ptr->image_up_to_date ) ) {
HDassert(!entry_ptr->prefetched);
if ( H5C__generate_image(f, cache_ptr, entry_ptr) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, \
"can't generate entry's image")
}
}
if ( write_entry ) {
HDassert(entry_ptr->is_dirty);
#if H5C_DO_SANITY_CHECKS
if ( ( cache_ptr->check_write_permitted ) &&
( ! ( cache_ptr->write_permitted ) ) )
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"Write when writes are always forbidden!?!?!")
#endif
if ( ( ( ! suppress_image_entry_writes ) ||
( ! entry_ptr->include_in_image ) ) &&
( ( (entry_ptr->type->flags) & H5C__CLASS_SKIP_WRITES) == 0 ) ) {
H5FD_mem_t mem_type = H5FD_MEM_DEFAULT;
#ifdef H5_HAVE_PARALLEL
if ( cache_ptr->coll_write_list ) {
if ( H5SL_insert(cache_ptr->coll_write_list, entry_ptr,
&entry_ptr->addr) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTINSERT, FAIL, \
"unable to insert skip list item")
}
else
{
#endif
if ( entry_ptr->prefetched ) {
HDassert(entry_ptr->type->id == H5AC_PREFETCHED_ENTRY_ID);
mem_type = cache_ptr->
class_table_ptr[entry_ptr->prefetch_type_id]->
mem_type;
}
else {
mem_type = entry_ptr->type->mem_type;
}
if ( H5F_block_write(f, mem_type, entry_ptr->addr,
entry_ptr->size, entry_ptr->image_ptr) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
"Can't write image to file")
#ifdef H5_HAVE_PARALLEL
}
#endif
}
if ( ( entry_ptr->type->notify ) &&
( (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_AFTER_FLUSH,
entry_ptr) < 0 ) )
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \
"can't notify client of entry flush")
}
if ( clear_only ) {
if ( was_dirty ) {
H5C__UPDATE_STATS_FOR_CLEAR(cache_ptr, entry_ptr)
}
} else if(write_entry) {
HDassert(was_dirty);
H5C__UPDATE_STATS_FOR_FLUSH(cache_ptr, entry_ptr)
}
if ( destroy ) {
if ( take_ownership ) {
HDassert(!destroy_entry);
} else {
HDassert(destroy_entry);
}
HDassert(!entry_ptr->is_pinned);
H5C__UPDATE_STATS_FOR_EVICTION(cache_ptr, entry_ptr, take_ownership)
if ( ( entry_ptr->type->notify ) &&
( (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_BEFORE_EVICT,
entry_ptr) < 0 ) )
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \
"can't notify client about entry to evict")
H5C__DELETE_FROM_INDEX(cache_ptr, entry_ptr, FAIL)
if ( ( entry_ptr->in_slist ) && ( del_from_slist_on_destroy ) ) {
H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr, during_flush)
}
#ifdef H5_HAVE_PARALLEL
if ( entry_ptr->coll_access ) {
entry_ptr->coll_access = FALSE;
H5C__REMOVE_FROM_COLL_LIST(cache_ptr, entry_ptr, FAIL)
}
#endif
H5C__UPDATE_RP_FOR_EVICTION(cache_ptr, entry_ptr, FAIL)
if ( H5C__untag_entry(cache_ptr, entry_ptr) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTREMOVE, FAIL, \
"can't remove entry from tag list")
HDassert(entry_ptr->flush_dep_nparents == 0);
HDassert(entry_ptr->flush_dep_nchildren == 0);
}
else {
HDassert(clear_only || write_entry);
HDassert(entry_ptr->is_dirty);
HDassert((!cache_ptr->slist_enabled) || (entry_ptr->in_slist));
H5C__UPDATE_RP_FOR_FLUSH(cache_ptr, entry_ptr, FAIL)
H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr, during_flush)
entry_ptr->is_dirty = FALSE;
H5C__UPDATE_INDEX_FOR_ENTRY_CLEAN(cache_ptr, entry_ptr);
if ( was_dirty ) {
if ( ( entry_ptr->type->notify ) &&
( (entry_ptr->type->notify)(H5C_NOTIFY_ACTION_ENTRY_CLEANED,
entry_ptr) < 0 ) )
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \
"can't notify client about entry dirty flag cleared")
if ( entry_ptr->flush_dep_ndirty_children != 0 ) {
HDassert(entry_ptr->flush_dep_ndirty_children == 0);
}
if ( entry_ptr->flush_dep_nparents > 0 ) {
if ( H5C__mark_flush_dep_clean(entry_ptr) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKCLEAN, FAIL, \
"Can't propagate flush dep clean flag")
}
}
}
entry_ptr->flush_in_progress = FALSE;
entry_addr = entry_ptr->addr;
if ( destroy ) {
HDassert(0 == entry_ptr->flush_dep_nparents);
if ( suppress_image_entry_frees && entry_ptr->include_in_image ) {
entry_ptr->image_ptr = NULL;
} else if ( entry_ptr->image_ptr != NULL ) {
entry_ptr->image_ptr = H5MM_xfree(entry_ptr->image_ptr);
}
if ( ! entry_ptr->prefetched ) {
HDassert(0 == entry_ptr->fd_parent_count);
HDassert(NULL == entry_ptr->fd_parent_addrs);
}
if ( free_file_space ) {
hsize_t fsf_size;
HDassert(H5F_addr_defined(entry_ptr->addr));
HDassert(!H5F_IS_TMP_ADDR(f, entry_ptr->addr));
#ifndef NDEBUG
{
size_t curr_len;
entry_ptr->type->image_len((void *)entry_ptr, &curr_len);
HDassert(curr_len == entry_ptr->size);
}
#endif
if ( entry_ptr->type->fsf_size ) {
if ( (entry_ptr->type->fsf_size)((void *)entry_ptr, &fsf_size)
< 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, \
"unable to get file space free size")
}
else {
fsf_size = entry_ptr->size;
}
if ( H5MF_xfree(f, entry_ptr->type->mem_type,
entry_ptr->addr, fsf_size) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, \
"unable to free file space for cache entry")
}
entry_ptr->cache_ptr = NULL;
cache_ptr->entries_removed_counter++;
cache_ptr->last_entry_removed_ptr = entry_ptr;
if ( entry_ptr == cache_ptr->entry_watched_for_removal ) {
cache_ptr->entry_watched_for_removal = NULL;
}
if ( destroy_entry ) {
if ( entry_ptr->is_dirty ) {
entry_ptr->is_dirty = FALSE;
if ( ( entry_ptr->type->notify ) &&
( (entry_ptr->type->notify)
(H5C_NOTIFY_ACTION_ENTRY_CLEANED, entry_ptr) < 0 ) )
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \
"can't notify client about entry dirty flag cleared")
}
entry_ptr->magic = H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC;
HDassert(entry_ptr->image_ptr == NULL);
if ( entry_ptr->type->free_icr((void *)entry_ptr) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
"free_icr callback failed")
}
else {
HDassert(take_ownership);
entry_ptr->magic = H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC;
}
}
if ( update_page_buffer ) {
HDassert(!destroy);
HDassert(entry_ptr->image_ptr);
if ( ( f->shared->page_buf ) &&
( f->shared->page_buf->page_size >= entry_ptr->size ) ) {
if ( H5PB_update_entry(f->shared->page_buf, entry_ptr->addr,
entry_ptr->size, entry_ptr->image_ptr) > 0 )
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"Failed to update PB with metadata cache")
}
}
if ( cache_ptr->log_flush ) {
if ( (cache_ptr->log_flush)(cache_ptr, entry_addr,
was_dirty, flags) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
"log_flush callback failed")
}
done:
HDassert( ( ret_value != SUCCEED ) || ( destroy_entry ) ||
( ! entry_ptr->flush_in_progress ) );
HDassert( ( ret_value != SUCCEED ) || ( destroy_entry ) ||
( take_ownership ) || ( ! entry_ptr->is_dirty ) );
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__verify_len_eoa(H5F_t *f, const H5C_class_t *type, haddr_t addr,
size_t *len, hbool_t actual)
{
H5FD_mem_t cooked_type;
haddr_t eoa;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
cooked_type = (type->mem_type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : type->mem_type;
eoa = H5F_get_eoa(f, cooked_type);
if(!H5F_addr_defined(eoa))
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "invalid EOA address for file")
if(H5F_addr_gt(addr, eoa))
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "address of object past end of allocation")
if(H5F_addr_gt((addr + *len), eoa)) {
if(actual)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "actual len exceeds EOA")
else
*len = (size_t)(eoa - addr);
}
if(*len <= 0)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "len not positive after adjustment for EOA")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static void *
H5C_load_entry(H5F_t * f,
#ifdef H5_HAVE_PARALLEL
hbool_t coll_access,
#endif
const H5C_class_t * type,
haddr_t addr,
void * udata)
{
hbool_t dirty = FALSE;
uint8_t * image = NULL;
void * thing = NULL;
H5C_cache_entry_t *entry = NULL;
size_t len;
#ifdef H5_HAVE_PARALLEL
int mpi_rank = 0;
MPI_Comm comm = MPI_COMM_NULL;
int mpi_code;
#endif
void * ret_value = NULL;
FUNC_ENTER_NOAPI_NOINIT
HDassert(f);
HDassert(f->shared);
HDassert(f->shared->cache);
HDassert(type);
HDassert(H5F_addr_defined(addr));
HDassert(type->get_initial_load_size);
if(type->flags & H5C__CLASS_SPECULATIVE_LOAD_FLAG)
HDassert(type->get_final_load_size);
else
HDassert(NULL == type->get_final_load_size);
HDassert(type->deserialize);
HDassert(!((type->flags & H5C__CLASS_SKIP_READS) &&
(type->flags & H5C__CLASS_SPECULATIVE_LOAD_FLAG)));
if(type->get_initial_load_size(udata, &len) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, NULL, "can't retrieve image size")
HDassert(len > 0);
if(type->flags & H5C__CLASS_SPECULATIVE_LOAD_FLAG)
if(H5C__verify_len_eoa(f, type, addr, &len, FALSE) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, NULL, "invalid len with respect to EOA")
if(NULL == (image = (uint8_t *)H5MM_malloc(len + H5C_IMAGE_EXTRA_SPACE)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, NULL, "memory allocation failed for on disk image buffer")
#if H5C_DO_MEMORY_SANITY_CHECKS
H5MM_memcpy(image + len, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif
#ifdef H5_HAVE_PARALLEL
if(H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI)) {
if((mpi_rank = H5F_mpi_get_rank(f)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "Can't get MPI rank")
if((comm = H5F_mpi_get_comm(f)) == MPI_COMM_NULL)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "get_comm request failed")
}
#endif
if(0 == (type->flags & H5C__CLASS_SKIP_READS)) {
unsigned tries, max_tries;
unsigned retries;
htri_t chk_ret;
size_t actual_len = len;
uint64_t nanosec = 1;
void *new_image;
hbool_t len_changed = TRUE;
max_tries = tries = H5F_GET_READ_ATTEMPTS(f);
do {
if(actual_len != len) {
if(NULL == (new_image = H5MM_realloc(image, len + H5C_IMAGE_EXTRA_SPACE)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, NULL, "image null after H5MM_realloc()")
image = (uint8_t *)new_image;
#if H5C_DO_MEMORY_SANITY_CHECKS
H5MM_memcpy(image + len, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif
}
#ifdef H5_HAVE_PARALLEL
if(!coll_access || 0 == mpi_rank) {
#endif
if(H5F_block_read(f, type->mem_type, addr, len, image) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_READERROR, NULL, "Can't read image*")
#ifdef H5_HAVE_PARALLEL
}
if(coll_access) {
int buf_size;
H5_CHECKED_ASSIGN(buf_size, int, len, size_t);
if(MPI_SUCCESS != (mpi_code = MPI_Bcast(image, buf_size, MPI_BYTE, 0, comm)))
HMPI_GOTO_ERROR(NULL, "MPI_Bcast failed", mpi_code)
}
#endif
if((type->flags & H5C__CLASS_SPECULATIVE_LOAD_FLAG) && len_changed) {
actual_len = len;
if(type->get_final_load_size(image, len, udata, &actual_len) < 0)
continue;
if(actual_len != len) {
if(H5C__verify_len_eoa(f, type, addr, &actual_len, TRUE) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, NULL, "actual_len exceeds EOA")
if(NULL == (new_image = H5MM_realloc(image, actual_len + H5C_IMAGE_EXTRA_SPACE)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, NULL, "image null after H5MM_realloc()")
image = (uint8_t *)new_image;
#if H5C_DO_MEMORY_SANITY_CHECKS
H5MM_memcpy(image + actual_len, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif
if(actual_len > len) {
#ifdef H5_HAVE_PARALLEL
if(!coll_access || 0 == mpi_rank) {
#endif
if(H5F_block_read(f, type->mem_type, addr + len, actual_len - len, image + len) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "can't read image")
#ifdef H5_HAVE_PARALLEL
}
if(coll_access) {
int buf_size;
H5_CHECKED_ASSIGN(buf_size, int, actual_len - len, size_t);
if(MPI_SUCCESS != (mpi_code = MPI_Bcast(image + len, buf_size, MPI_BYTE, 0, comm)))
HMPI_GOTO_ERROR(NULL, "MPI_Bcast failed", mpi_code)
}
#endif
}
}
else {
len_changed = FALSE;
len = actual_len;
}
}
if(type->verify_chksum == NULL)
break;
if((chk_ret = type->verify_chksum(image, actual_len, udata)) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, NULL, "failure from verify_chksum callback")
if(chk_ret == TRUE)
break;
H5_nanosleep(nanosec);
nanosec *= 2;
} while(--tries);
if(tries == 0)
HGOTO_ERROR(H5E_CACHE, H5E_READERROR, NULL, "incorrect metadatda checksum after all read attempts")
retries = max_tries - tries;
if(retries)
if(H5F_track_metadata_read_retries(f, (unsigned)type->mem_type, retries) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, NULL, "cannot track read tries = %u ", retries)
len = actual_len;
}
if(NULL == (thing = type->deserialize(image, len, udata, &dirty)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "Can't deserialize image")
entry = (H5C_cache_entry_t *)thing;
HDassert( ( dirty == FALSE ) || ( type->id == 5 || type->id == 6) );
entry->magic = H5C__H5C_CACHE_ENTRY_T_MAGIC;
entry->cache_ptr = f->shared->cache;
entry->addr = addr;
entry->size = len;
HDassert(entry->size < H5C_MAX_ENTRY_SIZE);
entry->image_ptr = image;
entry->image_up_to_date = !dirty;
entry->type = type;
entry->is_dirty = dirty;
entry->dirtied = FALSE;
entry->is_protected = FALSE;
entry->is_read_only = FALSE;
entry->ro_ref_count = 0;
entry->is_pinned = FALSE;
entry->in_slist = FALSE;
entry->flush_marker = FALSE;
#ifdef H5_HAVE_PARALLEL
entry->clear_on_unprotect = FALSE;
entry->flush_immediately = FALSE;
entry->coll_access = coll_access;
#endif
entry->flush_in_progress = FALSE;
entry->destroy_in_progress = FALSE;
entry->ring = H5C_RING_UNDEFINED;
entry->flush_dep_parent = NULL;
entry->flush_dep_nparents = 0;
entry->flush_dep_parent_nalloc = 0;
entry->flush_dep_nchildren = 0;
entry->flush_dep_ndirty_children = 0;
entry->flush_dep_nunser_children = 0;
entry->ht_next = NULL;
entry->ht_prev = NULL;
entry->il_next = NULL;
entry->il_prev = NULL;
entry->next = NULL;
entry->prev = NULL;
#if H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS
entry->aux_next = NULL;
entry->aux_prev = NULL;
#endif
#ifdef H5_HAVE_PARALLEL
entry->coll_next = NULL;
entry->coll_prev = NULL;
#endif
entry->include_in_image = FALSE;
entry->lru_rank = 0;
entry->image_dirty = FALSE;
entry->fd_parent_count = 0;
entry->fd_parent_addrs = NULL;
entry->fd_child_count = 0;
entry->fd_dirty_child_count = 0;
entry->image_fd_height = 0;
entry->prefetched = FALSE;
entry->prefetch_type_id = 0;
entry->age = 0;
entry->prefetched_dirty = FALSE;
#ifndef NDEBUG
entry->serialization_count = 0;
#endif
entry->tl_next = NULL;
entry->tl_prev = NULL;
entry->tag_info = NULL;
H5C__RESET_CACHE_ENTRY_STATS(entry);
ret_value = thing;
done:
if(NULL == ret_value) {
if(thing && type->free_icr(thing) < 0)
HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, NULL, "free_icr callback failed")
if(image)
image = (uint8_t *)H5MM_xfree(image);
}
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C__make_space_in_cache(H5F_t *f, size_t space_needed, hbool_t write_permitted)
{
H5C_t * cache_ptr = f->shared->cache;
#if H5C_COLLECT_CACHE_STATS
int32_t clean_entries_skipped = 0;
int32_t dirty_pf_entries_skipped = 0;
int32_t total_entries_scanned = 0;
#endif
uint32_t entries_examined = 0;
uint32_t initial_list_len;
size_t empty_space;
hbool_t reentrant_call = FALSE;
hbool_t prev_is_dirty = FALSE;
hbool_t didnt_flush_entry = FALSE;
hbool_t restart_scan;
H5C_cache_entry_t * entry_ptr;
H5C_cache_entry_t * prev_ptr;
H5C_cache_entry_t * next_ptr;
uint32_t num_corked_entries = 0;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(f);
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(cache_ptr->index_size == (cache_ptr->clean_index_size + cache_ptr->dirty_index_size));
if(cache_ptr->msic_in_progress) {
reentrant_call = TRUE;
HGOTO_DONE(SUCCEED);
}
cache_ptr->msic_in_progress = TRUE;
if ( write_permitted ) {
restart_scan = FALSE;
initial_list_len = cache_ptr->LRU_list_len;
entry_ptr = cache_ptr->LRU_tail_ptr;
if(cache_ptr->index_size >= cache_ptr->max_cache_size)
empty_space = 0;
else
empty_space = cache_ptr->max_cache_size - cache_ptr->index_size;
while ( ( ( (cache_ptr->index_size + space_needed)
>
cache_ptr->max_cache_size
)
||
(
( empty_space + cache_ptr->clean_index_size )
<
( cache_ptr->min_clean_size )
)
)
&&
( entries_examined <= (2 * initial_list_len) )
&&
( entry_ptr != NULL )
)
{
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert( !(entry_ptr->is_protected) );
HDassert( ! (entry_ptr->is_read_only) );
HDassert( (entry_ptr->ro_ref_count) == 0 );
next_ptr = entry_ptr->next;
prev_ptr = entry_ptr->prev;
if(prev_ptr != NULL)
prev_is_dirty = prev_ptr->is_dirty;
if(entry_ptr->is_dirty &&
(entry_ptr->tag_info && entry_ptr->tag_info->corked)) {
++num_corked_entries;
didnt_flush_entry = TRUE;
} else if ( ( (entry_ptr->type)->id != H5AC_EPOCH_MARKER_ID ) &&
( ! entry_ptr->flush_in_progress ) &&
( ! entry_ptr->prefetched_dirty ) ) {
didnt_flush_entry = FALSE;
if ( entry_ptr->is_dirty ) {
#if H5C_COLLECT_CACHE_STATS
if ( (cache_ptr->index_size + space_needed)
>
cache_ptr->max_cache_size ) {
cache_ptr->entries_scanned_to_make_space++;
}
#endif
cache_ptr->entries_removed_counter = 0;
cache_ptr->last_entry_removed_ptr = NULL;
if(H5C__flush_single_entry(f, entry_ptr, H5C__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush entry")
if ( ( cache_ptr->entries_removed_counter > 1 ) ||
( cache_ptr->last_entry_removed_ptr == prev_ptr ) )
restart_scan = TRUE;
} else if ( (cache_ptr->index_size + space_needed) > cache_ptr->max_cache_size
#ifdef H5_HAVE_PARALLEL
&& !(entry_ptr->coll_access)
#endif
) {
#if H5C_COLLECT_CACHE_STATS
cache_ptr->entries_scanned_to_make_space++;
#endif
if(H5C__flush_single_entry(f, entry_ptr, H5C__FLUSH_INVALIDATE_FLAG | H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush entry")
} else {
#if H5C_COLLECT_CACHE_STATS
clean_entries_skipped++;
#endif
didnt_flush_entry = TRUE;
}
#if H5C_COLLECT_CACHE_STATS
total_entries_scanned++;
#endif
} else {
didnt_flush_entry = TRUE;
#if H5C_COLLECT_CACHE_STATS
if(entry_ptr->prefetched_dirty)
dirty_pf_entries_skipped++;
#endif
}
if ( prev_ptr != NULL ) {
if ( didnt_flush_entry ) {
entry_ptr = prev_ptr;
} else if ( ( restart_scan )
||
( prev_ptr->is_dirty != prev_is_dirty )
||
( prev_ptr->next != next_ptr )
||
( prev_ptr->is_protected )
||
( prev_ptr->is_pinned ) ) {
restart_scan = FALSE;
entry_ptr = cache_ptr->LRU_tail_ptr;
H5C__UPDATE_STATS_FOR_LRU_SCAN_RESTART(cache_ptr)
} else {
entry_ptr = prev_ptr;
}
} else {
entry_ptr = NULL;
}
entries_examined++;
if ( cache_ptr->index_size >= cache_ptr->max_cache_size ) {
empty_space = 0;
} else {
empty_space = cache_ptr->max_cache_size - cache_ptr->index_size;
}
HDassert( cache_ptr->index_size ==
(cache_ptr->clean_index_size +
cache_ptr->dirty_index_size) );
}
#if H5C_COLLECT_CACHE_STATS
cache_ptr->calls_to_msic++;
cache_ptr->total_entries_skipped_in_msic += clean_entries_skipped;
cache_ptr->total_dirty_pf_entries_skipped_in_msic += dirty_pf_entries_skipped;
cache_ptr->total_entries_scanned_in_msic += total_entries_scanned;
if ( clean_entries_skipped > cache_ptr->max_entries_skipped_in_msic ) {
cache_ptr->max_entries_skipped_in_msic = clean_entries_skipped;
}
if(dirty_pf_entries_skipped > cache_ptr->max_dirty_pf_entries_skipped_in_msic)
cache_ptr->max_dirty_pf_entries_skipped_in_msic = dirty_pf_entries_skipped;
if ( total_entries_scanned > cache_ptr->max_entries_scanned_in_msic ) {
cache_ptr->max_entries_scanned_in_msic = total_entries_scanned;
}
#endif
HDassert( ( entries_examined > (2 * initial_list_len) ) ||
( (cache_ptr->pl_size + cache_ptr->pel_size + cache_ptr->min_clean_size) >
cache_ptr->max_cache_size ) ||
( ( cache_ptr->clean_index_size + empty_space )
>= cache_ptr->min_clean_size ) ||
( ( num_corked_entries )));
#if H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS
HDassert( ( entries_examined > (2 * initial_list_len) ) ||
( cache_ptr->cLRU_list_size <= cache_ptr->clean_index_size ) );
HDassert( ( entries_examined > (2 * initial_list_len) ) ||
( cache_ptr->dLRU_list_size <= cache_ptr->dirty_index_size ) );
#endif
} else {
HDassert( H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS );
#if H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS
initial_list_len = cache_ptr->cLRU_list_len;
entry_ptr = cache_ptr->cLRU_tail_ptr;
while ( ( (cache_ptr->index_size + space_needed)
>
cache_ptr->max_cache_size
)
&&
( entries_examined <= initial_list_len )
&&
( entry_ptr != NULL )
)
{
HDassert( ! (entry_ptr->is_protected) );
HDassert( ! (entry_ptr->is_read_only) );
HDassert( (entry_ptr->ro_ref_count) == 0 );
HDassert( ! (entry_ptr->is_dirty) );
prev_ptr = entry_ptr->aux_prev;
if ( ( !(entry_ptr->prefetched_dirty) )
#ifdef H5_HAVE_PARALLEL
&& ( ! (entry_ptr->coll_access) )
#endif
) {
if(H5C__flush_single_entry(f, entry_ptr,
H5C__FLUSH_INVALIDATE_FLAG | H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush entry")
}
entry_ptr = prev_ptr;
entries_examined++;
}
#endif
}
done:
HDassert(cache_ptr->msic_in_progress);
if(!reentrant_call)
cache_ptr->msic_in_progress = FALSE;
HDassert((!reentrant_call) || (cache_ptr->msic_in_progress));
FUNC_LEAVE_NOAPI(ret_value)
}
#if H5C_DO_EXTREME_SANITY_CHECKS
static herr_t
H5C_validate_lru_list(H5C_t * cache_ptr)
{
herr_t ret_value = SUCCEED;
int32_t len = 0;
size_t size = 0;
H5C_cache_entry_t * entry_ptr = NULL;
FUNC_ENTER_NOAPI_NOINIT
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
if ( ( ( cache_ptr->LRU_head_ptr == NULL )
||
( cache_ptr->LRU_tail_ptr == NULL )
)
&&
( cache_ptr->LRU_head_ptr != cache_ptr->LRU_tail_ptr )
) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 1 failed")
}
if(cache_ptr->LRU_list_len < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 2 failed")
if ( ( cache_ptr->LRU_list_len == 1 )
&&
( ( cache_ptr->LRU_head_ptr != cache_ptr->LRU_tail_ptr )
||
( cache_ptr->LRU_head_ptr == NULL )
||
( cache_ptr->LRU_head_ptr->size != cache_ptr->LRU_list_size )
)
) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 3 failed")
}
if ( ( cache_ptr->LRU_list_len >= 1 )
&&
( ( cache_ptr->LRU_head_ptr == NULL )
||
( cache_ptr->LRU_head_ptr->prev != NULL )
||
( cache_ptr->LRU_tail_ptr == NULL )
||
( cache_ptr->LRU_tail_ptr->next != NULL )
)
) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 4 failed")
}
entry_ptr = cache_ptr->LRU_head_ptr;
while ( entry_ptr != NULL )
{
if ( ( entry_ptr != cache_ptr->LRU_head_ptr ) &&
( ( entry_ptr->prev == NULL ) ||
( entry_ptr->prev->next != entry_ptr ) ) ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 5 failed")
}
if ( ( entry_ptr != cache_ptr->LRU_tail_ptr ) &&
( ( entry_ptr->next == NULL ) ||
( entry_ptr->next->prev != entry_ptr ) ) ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 6 failed")
}
if ( ( entry_ptr->is_pinned ) ||
( entry_ptr->pinned_from_client ) ||
( entry_ptr->pinned_from_cache ) ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 7 failed")
}
len++;
size += entry_ptr->size;
entry_ptr = entry_ptr->next;
}
if ( ( cache_ptr->LRU_list_len != len ) ||
( cache_ptr->LRU_list_size != size ) ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 8 failed")
}
done:
if ( ret_value != SUCCEED ) {
HDassert(0);
}
FUNC_LEAVE_NOAPI(ret_value)
}
#endif
#if H5C_DO_EXTREME_SANITY_CHECKS
static herr_t
H5C_validate_pinned_entry_list(H5C_t * cache_ptr)
{
herr_t ret_value = SUCCEED;
int32_t len = 0;
size_t size = 0;
H5C_cache_entry_t * entry_ptr = NULL;
FUNC_ENTER_NOAPI_NOINIT
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
if ( ( ( cache_ptr->pel_head_ptr == NULL )
||
( cache_ptr->pel_tail_ptr == NULL )
)
&&
( cache_ptr->pel_head_ptr != cache_ptr->pel_tail_ptr )
) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 1 failed")
}
if(cache_ptr->pel_len < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 2 failed")
if ( ( cache_ptr->pel_len == 1 )
&&
( ( cache_ptr->pel_head_ptr != cache_ptr->pel_tail_ptr )
||
( cache_ptr->pel_head_ptr == NULL )
||
( cache_ptr->pel_head_ptr->size != cache_ptr->pel_size )
)
) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 3 failed")
}
if ( ( cache_ptr->pel_len >= 1 )
&&
( ( cache_ptr->pel_head_ptr == NULL )
||
( cache_ptr->pel_head_ptr->prev != NULL )
||
( cache_ptr->pel_tail_ptr == NULL )
||
( cache_ptr->pel_tail_ptr->next != NULL )
)
) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 4 failed")
}
entry_ptr = cache_ptr->pel_head_ptr;
while ( entry_ptr != NULL )
{
if ( ( entry_ptr != cache_ptr->pel_head_ptr ) &&
( ( entry_ptr->prev == NULL ) ||
( entry_ptr->prev->next != entry_ptr ) ) ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 5 failed")
}
if ( ( entry_ptr != cache_ptr->pel_tail_ptr ) &&
( ( entry_ptr->next == NULL ) ||
( entry_ptr->next->prev != entry_ptr ) ) ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 6 failed")
}
if ( ! entry_ptr->is_pinned ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 7 failed")
}
if ( ! ( ( entry_ptr->pinned_from_client ) ||
( entry_ptr->pinned_from_cache ) ) ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 8 failed")
}
len++;
size += entry_ptr->size;
entry_ptr = entry_ptr->next;
}
if ( ( cache_ptr->pel_len != len ) ||
( cache_ptr->pel_size != size ) ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 9 failed")
}
done:
if ( ret_value != SUCCEED ) {
HDassert(0);
}
FUNC_LEAVE_NOAPI(ret_value)
}
#endif
#if H5C_DO_EXTREME_SANITY_CHECKS
static herr_t
H5C_validate_protected_entry_list(H5C_t * cache_ptr)
{
herr_t ret_value = SUCCEED;
int32_t len = 0;
size_t size = 0;
H5C_cache_entry_t * entry_ptr = NULL;
FUNC_ENTER_NOAPI_NOINIT
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
if(((cache_ptr->pl_head_ptr == NULL) || (cache_ptr->pl_tail_ptr == NULL))
&& (cache_ptr->pl_head_ptr != cache_ptr->pl_tail_ptr))
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 1 failed")
if(cache_ptr->pl_len < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 2 failed")
if ( ( cache_ptr->pl_len == 1 )
&&
( ( cache_ptr->pl_head_ptr != cache_ptr->pl_tail_ptr )
||
( cache_ptr->pl_head_ptr == NULL )
||
( cache_ptr->pl_head_ptr->size != cache_ptr->pl_size )
)
) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 3 failed")
}
if ( ( cache_ptr->pl_len >= 1 )
&&
( ( cache_ptr->pl_head_ptr == NULL )
||
( cache_ptr->pl_head_ptr->prev != NULL )
||
( cache_ptr->pl_tail_ptr == NULL )
||
( cache_ptr->pl_tail_ptr->next != NULL )
)
) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 4 failed")
}
entry_ptr = cache_ptr->pl_head_ptr;
while ( entry_ptr != NULL )
{
if ( ( entry_ptr != cache_ptr->pl_head_ptr ) &&
( ( entry_ptr->prev == NULL ) ||
( entry_ptr->prev->next != entry_ptr ) ) ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 5 failed")
}
if ( ( entry_ptr != cache_ptr->pl_tail_ptr ) &&
( ( entry_ptr->next == NULL ) ||
( entry_ptr->next->prev != entry_ptr ) ) ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 6 failed")
}
if ( ! entry_ptr->is_protected ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 7 failed")
}
if ( ( entry_ptr->is_read_only ) &&
( entry_ptr->ro_ref_count <= 0 ) ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 8 failed")
}
len++;
size += entry_ptr->size;
entry_ptr = entry_ptr->next;
}
if ( ( cache_ptr->pl_len != len ) ||
( cache_ptr->pl_size != size ) ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Check 9 failed")
}
done:
if ( ret_value != SUCCEED ) {
HDassert(0);
}
FUNC_LEAVE_NOAPI(ret_value)
}
#endif
#if H5C_DO_SLIST_SANITY_CHECKS
static hbool_t
H5C_entry_in_skip_list(H5C_t * cache_ptr, H5C_cache_entry_t *target_ptr)
{
hbool_t in_slist = FALSE;
H5SL_node_t * node_ptr = NULL;
H5C_cache_entry_t * entry_ptr = NULL;
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
HDassert( cache_ptr->slist_ptr );
node_ptr = H5SL_first(cache_ptr->slist_ptr);
while ( ( node_ptr != NULL ) && ( ! in_slist ) )
{
entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
HDassert( entry_ptr );
HDassert( entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC );
HDassert( entry_ptr->is_dirty );
HDassert( entry_ptr->in_slist );
if ( entry_ptr == target_ptr ) {
in_slist = TRUE;
} else {
node_ptr = H5SL_next(node_ptr);
}
}
return(in_slist);
}
#endif
herr_t
H5C__flush_marked_entries(H5F_t * f)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(f != NULL);
if ( H5C_set_slist_enabled(f->shared->cache, TRUE, FALSE) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "set slist enabled failed")
if ( H5C_flush_cache(f, H5C__FLUSH_MARKED_ENTRIES_FLAG |
H5C__FLUSH_IGNORE_PROTECTED_FLAG) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush cache")
if ( H5C_set_slist_enabled(f->shared->cache, FALSE, TRUE) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "disable slist failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_cork(H5C_t *cache_ptr, haddr_t obj_addr, unsigned action, hbool_t *corked)
{
H5C_tag_info_t *tag_info;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
HDassert(cache_ptr != NULL);
HDassert(H5F_addr_defined(obj_addr));
HDassert(action == H5C__SET_CORK || action == H5C__UNCORK || action == H5C__GET_CORKED);
tag_info = (H5C_tag_info_t *)H5SL_search(cache_ptr->tag_list, &obj_addr);
if(H5C__GET_CORKED == action) {
HDassert(corked);
if(tag_info != NULL && tag_info->corked)
*corked = TRUE;
else
*corked = FALSE;
}
else {
HDassert(H5C__SET_CORK == action || H5C__UNCORK == action);
if(H5C__SET_CORK == action) {
if(NULL == tag_info) {
if(NULL == (tag_info = H5FL_CALLOC(H5C_tag_info_t)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "can't allocate tag info for cache entry")
tag_info->tag = obj_addr;
if(H5SL_insert(cache_ptr->tag_list, tag_info, &(tag_info->tag)) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTINSERT, FAIL, "can't insert tag info in skip list")
}
else {
if(tag_info->corked)
HGOTO_ERROR(H5E_CACHE, H5E_CANTCORK, FAIL, "object already corked")
HDassert(tag_info->entry_cnt > 0 && tag_info->head);
}
tag_info->corked = TRUE;
cache_ptr->num_objs_corked++;
}
else {
HDassert(tag_info);
if(!tag_info->corked)
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNCORK, FAIL, "object already uncorked")
tag_info->corked = FALSE;
cache_ptr->num_objs_corked--;
if(0 == tag_info->entry_cnt) {
HDassert(NULL == tag_info->head);
if(H5SL_remove(cache_ptr->tag_list, &(tag_info->tag)) != tag_info)
HGOTO_ERROR(H5E_CACHE, H5E_CANTREMOVE, FAIL, "can't remove tag info from list")
tag_info = H5FL_FREE(H5C_tag_info_t, tag_info);
}
else
HDassert(NULL != tag_info->head);
}
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__mark_flush_dep_dirty(H5C_cache_entry_t * entry)
{
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(entry);
for(u = 0; u < entry->flush_dep_nparents; u++) {
HDassert(entry->flush_dep_parent[u]->flush_dep_ndirty_children < entry->flush_dep_parent[u]->flush_dep_nchildren);
entry->flush_dep_parent[u]->flush_dep_ndirty_children++;
if(entry->flush_dep_parent[u]->type->notify &&
(entry->flush_dep_parent[u]->type->notify)(H5C_NOTIFY_ACTION_CHILD_DIRTIED, entry->flush_dep_parent[u]) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify parent about child entry dirty flag set")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__mark_flush_dep_clean(H5C_cache_entry_t * entry)
{
int i;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(entry);
for(i = ((int)entry->flush_dep_nparents) - 1; i >= 0; i--) {
HDassert(entry->flush_dep_parent[i]->flush_dep_ndirty_children > 0);
entry->flush_dep_parent[i]->flush_dep_ndirty_children--;
if(entry->flush_dep_parent[i]->type->notify &&
(entry->flush_dep_parent[i]->type->notify)(H5C_NOTIFY_ACTION_CHILD_CLEANED, entry->flush_dep_parent[i]) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify parent about child entry dirty flag reset")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C__mark_flush_dep_serialized(H5C_cache_entry_t * entry_ptr)
{
int i;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(entry_ptr);
for(i = ((int)entry_ptr->flush_dep_nparents) - 1; i >= 0; i--) {
HDassert(entry_ptr->flush_dep_parent);
HDassert(entry_ptr->flush_dep_parent[i]->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(entry_ptr->flush_dep_parent[i]->flush_dep_nunser_children > 0);
entry_ptr->flush_dep_parent[i]->flush_dep_nunser_children--;
if(entry_ptr->flush_dep_parent[i]->type->notify &&
(entry_ptr->flush_dep_parent[i]->type->notify)(H5C_NOTIFY_ACTION_CHILD_SERIALIZED, entry_ptr->flush_dep_parent[i]) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify parent about child entry serialized flag set")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C__mark_flush_dep_unserialized(H5C_cache_entry_t * entry_ptr)
{
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(entry_ptr);
for(u = 0; u < entry_ptr->flush_dep_nparents; u++) {
HDassert(entry_ptr->flush_dep_parent);
HDassert(entry_ptr->flush_dep_parent[u]->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(entry_ptr->flush_dep_parent[u]->flush_dep_nunser_children <
entry_ptr->flush_dep_parent[u]->flush_dep_nchildren);
entry_ptr->flush_dep_parent[u]->flush_dep_nunser_children++;
if(entry_ptr->flush_dep_parent[u]->type->notify &&
(entry_ptr->flush_dep_parent[u]->type->notify)(H5C_NOTIFY_ACTION_CHILD_UNSERIALIZED, entry_ptr->flush_dep_parent[u]) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify parent about child entry serialized flag reset")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
#ifndef NDEBUG
static void
H5C__assert_flush_dep_nocycle(const H5C_cache_entry_t * entry,
const H5C_cache_entry_t * base_entry)
{
unsigned u;
FUNC_ENTER_STATIC_NOERR
HDassert(entry);
HDassert(base_entry);
HDassert(base_entry != entry);
for(u = 0; u < entry->flush_dep_nparents; u++)
H5C__assert_flush_dep_nocycle(entry->flush_dep_parent[u], base_entry);
FUNC_LEAVE_NOAPI_VOID
}
#endif
herr_t
H5C__serialize_cache(H5F_t *f)
{
#if H5C_DO_SANITY_CHECKS
int i;
uint32_t index_len = 0;
size_t index_size = (size_t)0;
size_t clean_index_size = (size_t)0;
size_t dirty_index_size = (size_t)0;
size_t slist_size = (size_t)0;
uint32_t slist_len = 0;
#endif
H5C_ring_t ring;
H5C_t * cache_ptr;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(f);
HDassert(f->shared);
cache_ptr = f->shared->cache;
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(cache_ptr->slist_ptr);
#if H5C_DO_SANITY_CHECKS
HDassert(cache_ptr->index_ring_len[H5C_RING_UNDEFINED] == 0);
HDassert(cache_ptr->index_ring_size[H5C_RING_UNDEFINED] == (size_t)0);
HDassert(cache_ptr->clean_index_ring_size[H5C_RING_UNDEFINED] == (size_t)0);
HDassert(cache_ptr->dirty_index_ring_size[H5C_RING_UNDEFINED] == (size_t)0);
HDassert(cache_ptr->slist_ring_len[H5C_RING_UNDEFINED] == 0);
HDassert(cache_ptr->slist_ring_size[H5C_RING_UNDEFINED] == (size_t)0);
for(i = H5C_RING_USER; i < H5C_RING_NTYPES; i++) {
index_len += cache_ptr->index_ring_len[i];
index_size += cache_ptr->index_ring_size[i];
clean_index_size += cache_ptr->clean_index_ring_size[i];
dirty_index_size += cache_ptr->dirty_index_ring_size[i];
slist_len += cache_ptr->slist_ring_len[i];
slist_size += cache_ptr->slist_ring_size[i];
}
HDassert(cache_ptr->index_len == index_len);
HDassert(cache_ptr->index_size == index_size);
HDassert(cache_ptr->clean_index_size == clean_index_size);
HDassert(cache_ptr->dirty_index_size == dirty_index_size);
HDassert(cache_ptr->slist_len == slist_len);
HDassert(cache_ptr->slist_size == slist_size);
#endif
#if H5C_DO_EXTREME_SANITY_CHECKS
if((H5C_validate_protected_entry_list(cache_ptr) < 0) ||
(H5C_validate_pinned_entry_list(cache_ptr) < 0) ||
(H5C_validate_lru_list(cache_ptr) < 0))
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "an extreme sanity check failed on entry")
#endif
#ifndef NDEBUG
{
H5C_cache_entry_t * scan_ptr = NULL;
scan_ptr = cache_ptr->il_head;
while(scan_ptr != NULL) {
HDassert(scan_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
scan_ptr->serialization_count = 0;
scan_ptr = scan_ptr->il_next;
}
}
#endif
HDassert(!cache_ptr->serialization_in_progress);
cache_ptr->serialization_in_progress = TRUE;
ring = H5C_RING_USER;
while(ring < H5C_RING_NTYPES) {
HDassert(cache_ptr->close_warning_received);
switch(ring) {
case H5C_RING_USER:
break;
case H5C_RING_RDFSM:
if(!cache_ptr->rdfsm_settled)
if(H5MF_settle_raw_data_fsm(f, &cache_ptr->rdfsm_settled) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "RD FSM settle failed")
break;
case H5C_RING_MDFSM:
if(!cache_ptr->mdfsm_settled)
if(H5MF_settle_meta_data_fsm(f, &cache_ptr->mdfsm_settled) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "MD FSM settle failed")
break;
case H5C_RING_SBE:
case H5C_RING_SB:
break;
default:
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Unknown ring?!?!")
break;
}
if(H5C__serialize_ring(f, ring) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTSERIALIZE, FAIL, "serialize ring failed")
ring++;
}
#ifndef NDEBUG
{
H5C_cache_entry_t * scan_ptr = NULL;
scan_ptr = cache_ptr->il_head;
while(scan_ptr != NULL) {
HDassert(scan_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(scan_ptr->serialization_count <= 1);
scan_ptr = scan_ptr->il_next;
}
}
#endif
done:
cache_ptr->serialization_in_progress = FALSE;
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__serialize_ring(H5F_t *f, H5C_ring_t ring)
{
hbool_t done = FALSE;
H5C_t * cache_ptr;
H5C_cache_entry_t * entry_ptr;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(f);
HDassert(f->shared);
cache_ptr = f->shared->cache;
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(ring > H5C_RING_UNDEFINED);
HDassert(ring < H5C_RING_NTYPES);
HDassert(cache_ptr->serialization_in_progress);
while(!done) {
cache_ptr->entries_loaded_counter = 0;
cache_ptr->entries_inserted_counter = 0;
cache_ptr->entries_relocated_counter = 0;
done = TRUE;
entry_ptr = cache_ptr->il_head;
while(entry_ptr != NULL) {
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert((entry_ptr->ring >= ring) || (entry_ptr->image_up_to_date));
if(!entry_ptr->flush_me_last && entry_ptr->ring == ring) {
if(!entry_ptr->image_up_to_date)
done = FALSE;
if(!entry_ptr->image_up_to_date && entry_ptr->flush_dep_nunser_children == 0) {
HDassert(entry_ptr->serialization_count == 0);
if(H5C__serialize_single_entry(f, cache_ptr, entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTSERIALIZE, FAIL, "entry serialization failed")
HDassert(entry_ptr->flush_dep_nunser_children == 0);
HDassert(entry_ptr->serialization_count == 0);
#ifndef NDEBUG
entry_ptr->serialization_count++;
#endif
}
}
if((cache_ptr->entries_loaded_counter > 0) ||
(cache_ptr->entries_inserted_counter > 0) ||
(cache_ptr->entries_relocated_counter > 0)) {
#if H5C_COLLECT_CACHE_STATS
H5C__UPDATE_STATS_FOR_INDEX_SCAN_RESTART(cache_ptr);
#endif
cache_ptr->entries_loaded_counter = 0;
cache_ptr->entries_inserted_counter = 0;
cache_ptr->entries_relocated_counter = 0;
entry_ptr = cache_ptr->il_head;
}
else
entry_ptr = entry_ptr->il_next;
}
}
cache_ptr->entries_loaded_counter = 0;
cache_ptr->entries_inserted_counter = 0;
cache_ptr->entries_relocated_counter = 0;
entry_ptr = cache_ptr->il_head;
while(entry_ptr != NULL) {
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(entry_ptr->ring > H5C_RING_UNDEFINED);
HDassert(entry_ptr->ring < H5C_RING_NTYPES);
HDassert((entry_ptr->ring >= ring) || (entry_ptr->image_up_to_date));
if(entry_ptr->ring == ring) {
if(entry_ptr->flush_me_last) {
if(!entry_ptr->image_up_to_date) {
HDassert(entry_ptr->serialization_count == 0);
HDassert(entry_ptr->flush_dep_nunser_children == 0);
if(H5C__serialize_single_entry(f, cache_ptr, entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTSERIALIZE, FAIL, "entry serialization failed")
if((cache_ptr->entries_loaded_counter > 0) ||
(cache_ptr->entries_inserted_counter > 0) ||
(cache_ptr->entries_relocated_counter > 0))
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "flush_me_last entry serialization triggered restart")
HDassert(entry_ptr->flush_dep_nunser_children == 0);
HDassert(entry_ptr->serialization_count == 0);
#ifndef NDEBUG
entry_ptr->serialization_count++;
#endif
}
}
else {
HDassert(entry_ptr->image_up_to_date);
HDassert(entry_ptr->serialization_count <= 1);
HDassert(entry_ptr->flush_dep_nunser_children == 0);
}
}
entry_ptr = entry_ptr->il_next;
}
done:
HDassert(cache_ptr->serialization_in_progress);
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5C__serialize_single_entry(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(f);
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(entry_ptr);
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(!entry_ptr->prefetched);
HDassert(!entry_ptr->image_up_to_date);
HDassert(entry_ptr->is_dirty);
HDassert(!entry_ptr->is_protected);
HDassert(!entry_ptr->flush_in_progress);
HDassert(entry_ptr->type);
entry_ptr->flush_in_progress = TRUE;
if(NULL == entry_ptr->image_ptr) {
HDassert(entry_ptr->size > 0);
if(NULL == (entry_ptr->image_ptr = H5MM_malloc(entry_ptr->size + H5C_IMAGE_EXTRA_SPACE)) )
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for on disk image buffer")
#if H5C_DO_MEMORY_SANITY_CHECKS
H5MM_memcpy(((uint8_t *)entry_ptr->image_ptr) + image_size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif
}
if(H5C__generate_image(f, cache_ptr, entry_ptr) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTSERIALIZE, FAIL, "Can't generate image for cache entry")
entry_ptr->flush_in_progress = FALSE;
done:
HDassert((ret_value != SUCCEED) || (!entry_ptr->flush_in_progress));
HDassert((ret_value != SUCCEED) || (entry_ptr->image_up_to_date));
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr)
{
haddr_t new_addr = HADDR_UNDEF;
haddr_t old_addr = HADDR_UNDEF;
size_t new_len = 0;
unsigned serialize_flags = H5C__SERIALIZE_NO_FLAGS_SET;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(f);
HDassert(cache_ptr);
HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
HDassert(entry_ptr);
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(!entry_ptr->image_up_to_date);
HDassert(entry_ptr->is_dirty);
HDassert(!entry_ptr->is_protected);
HDassert(entry_ptr->type);
old_addr = entry_ptr->addr;
if ( ( entry_ptr->type->pre_serialize ) &&
( (entry_ptr->type->pre_serialize)(f, (void *)entry_ptr,
entry_ptr->addr, entry_ptr->size,
&new_addr, &new_len,
&serialize_flags) < 0 ) )
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
"unable to pre-serialize entry")
if ( serialize_flags != H5C__SERIALIZE_NO_FLAGS_SET ) {
if ( serialize_flags & ~(H5C__SERIALIZE_RESIZED_FLAG |
H5C__SERIALIZE_MOVED_FLAG) )
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
"unknown serialize flag(s)")
#ifdef H5_HAVE_PARALLEL
if ( cache_ptr->aux_ptr != NULL )
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"resize/move in serialize occurred in parallel case")
#endif
if ( serialize_flags & H5C__SERIALIZE_RESIZED_FLAG ) {
HDassert(new_len > 0);
if ( NULL == (entry_ptr->image_ptr =
H5MM_realloc(entry_ptr->image_ptr,
new_len + H5C_IMAGE_EXTRA_SPACE)) )
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, \
"memory allocation failed for on disk image buffer")
#if H5C_DO_MEMORY_SANITY_CHECKS
H5MM_memcpy(((uint8_t *)entry_ptr->image_ptr) + new_len,
H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif
H5C__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE(cache_ptr, entry_ptr, \
new_len);
H5C__UPDATE_INDEX_FOR_SIZE_CHANGE(cache_ptr, entry_ptr->size, \
new_len, entry_ptr, !(entry_ptr->is_dirty));
H5C__UPDATE_RP_FOR_SIZE_CHANGE(cache_ptr, entry_ptr, new_len);
HDassert(entry_ptr->is_dirty);
HDassert((entry_ptr->in_slist) || (!cache_ptr->slist_enabled));
H5C__UPDATE_SLIST_FOR_SIZE_CHANGE(cache_ptr, entry_ptr->size, \
new_len);
entry_ptr->size = new_len;
}
if ( serialize_flags & H5C__SERIALIZE_MOVED_FLAG ) {
H5C__UPDATE_STATS_FOR_MOVE(cache_ptr, entry_ptr)
if ( entry_ptr->addr == old_addr ) {
H5C__DELETE_FROM_INDEX(cache_ptr, entry_ptr, FAIL);
H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr, FALSE);
entry_ptr->addr = new_addr;
H5C__INSERT_IN_INDEX(cache_ptr, entry_ptr, FAIL);
H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL);
}
else {
HDassert(entry_ptr->addr == new_addr);
}
}
}
if ( entry_ptr->type->serialize(f, entry_ptr->image_ptr, entry_ptr->size,
(void *)entry_ptr) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to serialize entry")
#if H5C_DO_MEMORY_SANITY_CHECKS
HDassert(0 == HDmemcmp(((uint8_t *)entry_ptr->image_ptr) + entry_ptr->size,\
H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE));
#endif
entry_ptr->image_up_to_date = TRUE;
HDassert(entry_ptr->flush_dep_nunser_children == 0);
if ( entry_ptr->flush_dep_nparents > 0 ) {
if ( H5C__mark_flush_dep_serialized(entry_ptr) < 0 )
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, \
"Can't propagate serialization status to fd parents")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5C_remove_entry(void *_entry)
{
H5C_cache_entry_t *entry = (H5C_cache_entry_t *)_entry;
H5C_t *cache;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(entry);
HDassert(entry->ring != H5C_RING_UNDEFINED);
cache = entry->cache_ptr;
HDassert(cache);
HDassert(cache->magic == H5C__H5C_T_MAGIC);
if(entry->is_dirty)
HGOTO_ERROR(H5E_CACHE, H5E_CANTREMOVE, FAIL, "can't remove dirty entry from cache")
if(entry->is_protected)
HGOTO_ERROR(H5E_CACHE, H5E_CANTREMOVE, FAIL, "can't remove protected entry from cache")
if(entry->is_pinned)
HGOTO_ERROR(H5E_CACHE, H5E_CANTREMOVE, FAIL, "can't remove pinned entry from cache")
if(entry->flush_dep_nparents > 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTREMOVE, FAIL, "can't remove entry with flush dependency parents from cache")
if(entry->flush_dep_nchildren > 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTREMOVE, FAIL, "can't remove entry with flush dependency children from cache")
HDassert(!entry->in_slist);
HDassert(!entry->flush_marker);
HDassert(!entry->flush_in_progress);
H5C__UPDATE_STATS_FOR_EVICTION(cache, entry, TRUE)
if(entry->type->notify && (entry->type->notify)(H5C_NOTIFY_ACTION_BEFORE_EVICT, entry) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTNOTIFY, FAIL, "can't notify client about entry to evict")
H5C__DELETE_FROM_INDEX(cache, entry, FAIL)
#ifdef H5_HAVE_PARALLEL
if(entry->coll_access) {
entry->coll_access = FALSE;
H5C__REMOVE_FROM_COLL_LIST(cache, entry, FAIL)
}
#endif
H5C__UPDATE_RP_FOR_EVICTION(cache, entry, FAIL)
if(H5C__untag_entry(cache, entry) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTREMOVE, FAIL, "can't remove entry from tag list")
cache->entries_removed_counter++;
cache->last_entry_removed_ptr = entry;
if(entry == cache->entry_watched_for_removal)
cache->entry_watched_for_removal = NULL;
if(entry->image_ptr != NULL)
entry->image_ptr = H5MM_xfree(entry->image_ptr);
entry->cache_ptr = NULL;
entry->magic = H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC;
done:
FUNC_LEAVE_NOAPI(ret_value)
}