hdf5/test/cache_api.c
2023-10-03 09:01:28 -07:00

2231 lines
69 KiB
C

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the COPYING file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* This file contains tests for the API calls associated
* with the cache implemented in H5C.c
*/
#include "cache_common.h"
/* extern declarations */
/* global variable declarations: */
static const char *FILENAME[] = {"cache_api_test", NULL};
/* macro definitions */
/* private function declarations: */
static bool check_fapl_mdc_api_calls(unsigned paged, hid_t fcpl_id);
static bool check_file_mdc_api_calls(unsigned paged, hid_t fcpl_id);
static bool mdc_api_call_smoke_check(int express_test, unsigned paged, hid_t fcpl_id);
static H5AC_cache_config_t *init_invalid_configs(void);
static bool check_fapl_mdc_api_errs(void);
static bool check_file_mdc_api_errs(unsigned paged, hid_t fcpl_id);
/**************************************************************************/
/**************************************************************************/
/********************************* tests: *********************************/
/**************************************************************************/
/**************************************************************************/
/*-------------------------------------------------------------------------
* Function: check_fapl_mdc_api_calls()
*
* Purpose: Verify that the file access property list related
* metadata cache related API calls are functioning
* correctly.
*
* Since we have tested the H5C code elsewhere, it should
* be sufficient to verify that the desired configuration
* data is getting to the cache.
*
* Return: Test pass status (true/false)
*
*-------------------------------------------------------------------------
*/
static bool
check_fapl_mdc_api_calls(unsigned paged, hid_t fcpl_id)
{
char filename[512];
herr_t result;
hid_t fapl_id = H5I_INVALID_HID;
hid_t test_fapl_id = H5I_INVALID_HID;
hid_t file_id = H5I_INVALID_HID;
H5F_t *file_ptr = NULL;
H5C_t *cache_ptr = NULL;
H5AC_cache_config_t default_config = H5AC__DEFAULT_CACHE_CONFIG;
H5AC_cache_config_t mod_config = {
/* int version = */ H5AC__CURR_CACHE_CONFIG_VERSION,
/* bool rpt_fcn_enabled = */ false,
/* bool open_trace_file = */ false,
/* bool close_trace_file = */ false,
/* char trace_file_name[] = */ "",
/* bool evictions_enabled = */ true,
/* bool set_initial_size = */ true,
/* size_t initial_size = */ (1 * 1024 * 1024 + 1),
/* double min_clean_fraction = */ 0.2,
/* size_t max_size = */ (16 * 1024 * 1024 + 1),
/* size_t min_size = */ (1 * 1024 * 1024 + 1),
/* long int epoch_length = */ 50001,
/* enum H5C_cache_incr_mode incr_mode = */ H5C_incr__threshold,
/* double lower_hr_threshold = */ 0.91,
/* double increment = */ 2.1,
/* bool apply_max_increment = */ true,
/* size_t max_increment = */ (4 * 1024 * 1024 + 1),
/* enum H5C_cache_flash_incr_mode */
/* flash_incr_mode = */ H5C_flash_incr__off,
/* double flash_multiple = */ 2.0,
/* double flash_threshold = */ 0.5,
/* enum H5C_cache_decr_mode decr_mode = */ H5C_decr__age_out,
/* double upper_hr_threshold = */ 0.998,
/* double decrement = */ 0.91,
/* bool apply_max_decrement = */ true,
/* size_t max_decrement = */ (1 * 1024 * 1024 - 1),
/* int epochs_before_eviction = */ 4,
/* bool apply_empty_reserve = */ true,
/* double empty_reserve = */ 0.05,
/* int dirty_bytes_threshold = */ (256 * 1024),
/* int metadata_write_strategy = */
H5AC__DEFAULT_METADATA_WRITE_STRATEGY};
H5AC_cache_config_t scratch;
H5C_auto_size_ctl_t default_auto_size_ctl;
H5C_auto_size_ctl_t mod_auto_size_ctl;
if (paged)
TESTING("MDC/FAPL related API calls for paged aggregation strategy");
else
TESTING("MDC/FAPL related API calls");
pass = true;
XLATE_EXT_TO_INT_MDC_CONFIG(default_auto_size_ctl, default_config)
XLATE_EXT_TO_INT_MDC_CONFIG(mod_auto_size_ctl, mod_config)
/* Create a FAPL and verify that it contains the default
* initial mdc configuration
*/
if (pass) {
fapl_id = H5Pcreate(H5P_FILE_ACCESS);
if (fapl_id < 0) {
pass = false;
failure_mssg = "H5Pcreate(H5P_FILE_ACCESS) failed.\n";
}
}
if (pass) {
scratch.version = H5C__CURR_AUTO_SIZE_CTL_VER;
result = H5Pget_mdc_config(fapl_id, &scratch);
if (result < 0) {
pass = false;
failure_mssg = "H5Pget_mdc_config() failed.\n";
}
else if (!CACHE_CONFIGS_EQUAL(default_config, scratch, true, true)) {
pass = false;
failure_mssg = "retrieved config doesn't match default.";
}
}
/* Modify the initial mdc configuration in a FAPL, and verify that
* the changes can be read back
*/
if (pass) {
result = H5Pset_mdc_config(fapl_id, &mod_config);
if (result < 0) {
pass = false;
failure_mssg = "H5Pset_mdc_config() failed.\n";
}
}
if (pass) {
scratch.version = H5C__CURR_AUTO_SIZE_CTL_VER;
result = H5Pget_mdc_config(fapl_id, &scratch);
if (result < 0) {
pass = false;
failure_mssg = "H5Pget_mdc_config() failed.\n";
}
else if (!CACHE_CONFIGS_EQUAL(mod_config, scratch, true, true)) {
pass = false;
failure_mssg = "retrieved config doesn't match mod config.";
}
}
if (pass) {
if (H5Pclose(fapl_id) < 0) {
pass = false;
failure_mssg = "H5Pclose() failed.\n";
}
}
/* Open a file using the default FAPL. Verify that the resulting
* metadata cache uses the default configuration as well. Get a
* copy of the FAPL from the file, and verify that it contains the
* default initial meta data cache configuration. Close and delete
* the file.
*/
/* setup the file name */
if (pass) {
if (h5_fixname(FILENAME[0], H5P_DEFAULT, filename, sizeof(filename)) == NULL) {
pass = false;
failure_mssg = "h5_fixname() failed.\n";
}
}
/* create the file using the default FAPL */
if (pass) {
file_id = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
if (file_id < 0) {
pass = false;
failure_mssg = "H5Fcreate() failed.\n";
}
}
/* get a pointer to the files internal data structure */
if (pass) {
file_ptr = (H5F_t *)H5VL_object_verify(file_id, H5I_FILE);
if (file_ptr == NULL) {
pass = false;
failure_mssg = "Can't get file_ptr.\n";
}
else {
cache_ptr = file_ptr->shared->cache;
}
}
/* verify that we can access the internal version of the cache config */
if (pass) {
if (cache_ptr == NULL || cache_ptr->resize_ctl.version != H5C__CURR_AUTO_SIZE_CTL_VER) {
pass = false;
failure_mssg = "Can't access cache resize_ctl.\n";
}
}
/* compare the cache's internal configuration with the expected value */
if (pass) {
if (!resize_configs_are_equal(&default_auto_size_ctl, &cache_ptr->resize_ctl, true)) {
pass = false;
failure_mssg = "Unexpected value(s) in cache resize_ctl 1.\n";
}
}
/* get a copy of the files FAPL */
if (pass) {
fapl_id = H5Fget_access_plist(file_id);
if (fapl_id < 0) {
pass = false;
failure_mssg = "H5Fget_access_plist() failed.\n";
}
}
/* compare the initial cache config from the copy of the file's FAPL
* to the expected value. If all goes well, close the copy of the FAPL.
*/
if (pass) {
scratch.version = H5C__CURR_AUTO_SIZE_CTL_VER;
result = H5Pget_mdc_config(fapl_id, &scratch);
if (result < 0) {
pass = false;
failure_mssg = "H5Pget_mdc_config() failed.\n";
}
else if (!CACHE_CONFIGS_EQUAL(default_config, scratch, true, true)) {
pass = false;
failure_mssg = "config retrieved from file doesn't match default.";
}
else if (H5Pclose(fapl_id) < 0) {
pass = false;
failure_mssg = "H5Pclose() failed.\n";
}
}
/* close the file and delete it */
if (pass) {
if (H5Fclose(file_id) < 0) {
pass = false;
failure_mssg = "H5Fclose() failed.\n";
}
else if (H5Fdelete(filename, H5P_DEFAULT) < 0) {
pass = false;
failure_mssg = "H5Fdelete() failed.\n";
}
}
/* Open a file using a FAPL with a modified initial metadata cache
* configuration. Verify that the resulting metadata cache uses the
* modified configuration as well. Get a copy of the FAPL from the
* file, and verify that it contains the modified initial meta data
* cache configuration. Close and delete the file.
*/
/* Create a FAPL */
if (pass) {
fapl_id = H5Pcreate(H5P_FILE_ACCESS);
if (fapl_id < 0) {
pass = false;
failure_mssg = "H5Pcreate(H5P_FILE_ACCESS) failed.\n";
}
}
/* Modify the initial mdc configuration in the FAPL. */
if (pass) {
result = H5Pset_mdc_config(fapl_id, &mod_config);
if (result < 0) {
pass = false;
failure_mssg = "H5Pset_mdc_config() failed.\n";
}
}
/* setup the file name */
if (pass) {
if (h5_fixname(FILENAME[0], H5P_DEFAULT, filename, sizeof(filename)) == NULL) {
pass = false;
failure_mssg = "h5_fixname() failed.\n";
}
}
/* create the file using the modified FAPL */
if (pass) {
file_id = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl_id, fapl_id);
if (file_id < 0) {
pass = false;
failure_mssg = "H5Fcreate() failed.\n";
}
}
/* get a pointer to the files internal data structure */
if (pass) {
file_ptr = (H5F_t *)H5VL_object_verify(file_id, H5I_FILE);
if (file_ptr == NULL) {
pass = false;
failure_mssg = "Can't get file_ptr.\n";
}
else {
cache_ptr = file_ptr->shared->cache;
}
}
/* verify that we can access the internal version of the cache config */
if (pass) {
if (cache_ptr == NULL || cache_ptr->resize_ctl.version != H5C__CURR_AUTO_SIZE_CTL_VER) {
pass = false;
failure_mssg = "Can't access cache resize_ctl.\n";
}
}
/* compare the cache's internal configuration with the expected value */
if (pass) {
if (!resize_configs_are_equal(&mod_auto_size_ctl, &cache_ptr->resize_ctl, true)) {
pass = false;
failure_mssg = "Unexpected value(s) in cache resize_ctl 2.\n";
}
}
/* get a copy of the files FAPL */
if (pass) {
test_fapl_id = H5Fget_access_plist(file_id);
if (test_fapl_id < 0) {
pass = false;
failure_mssg = "H5Fget_access_plist() failed.\n";
}
}
/* compare the initial cache config from the copy of the file's FAPL
* to the expected value. If all goes well, close the copy of the FAPL.
*/
if (pass) {
scratch.version = H5C__CURR_AUTO_SIZE_CTL_VER;
result = H5Pget_mdc_config(test_fapl_id, &scratch);
if (result < 0) {
pass = false;
failure_mssg = "H5Pget_mdc_config() failed.\n";
}
else if (!CACHE_CONFIGS_EQUAL(mod_config, scratch, true, true)) {
pass = false;
failure_mssg = "config retrieved from file doesn't match.";
}
else if (H5Pclose(test_fapl_id) < 0) {
pass = false;
failure_mssg = "H5Pclose() failed.\n";
}
}
/* close the file and delete it */
if (pass) {
if (H5Fclose(file_id) < 0) {
pass = false;
failure_mssg = "H5Fclose() failed.\n";
}
else if (H5Fdelete(filename, fapl_id) < 0) {
pass = false;
failure_mssg = "H5Fdelete() failed.\n";
}
}
/* close the fapl used to create the file */
if (pass) {
if (H5Pclose(fapl_id) < 0) {
pass = false;
failure_mssg = "H5Pclose() failed.\n";
}
}
if (pass) {
PASSED();
}
else {
H5_FAILED();
}
if (!pass) {
fprintf(stdout, "%s: failure_mssg = \"%s\".\n", __func__, failure_mssg);
}
return pass;
} /* check_fapl_mdc_api_calls() */
/*-------------------------------------------------------------------------
* Function: check_file_mdc_api_calls()
*
* Purpose: Verify that the file related metadata cache API calls are
* functioning correctly.
*
* Since we have tested the H5C code elsewhere, it should
* be sufficient to verify that the desired configuration
* data is getting in and out of the cache. Similarly,
* we need only verify that the cache monitoring calls
* return the data that the cache thinks they should return.
* We shouldn't need to verify data correctness beyond that
* point.
*
* Return: Test pass status (true/false)
*
*-------------------------------------------------------------------------
*/
static bool
check_file_mdc_api_calls(unsigned paged, hid_t fcpl_id)
{
char filename[512];
hid_t file_id = H5I_INVALID_HID;
size_t max_size;
size_t min_clean_size;
size_t cur_size;
int cur_num_entries;
double hit_rate;
H5AC_cache_config_t default_config = H5AC__DEFAULT_CACHE_CONFIG;
H5AC_cache_config_t mod_config_1 = {
/* int version = */ H5C__CURR_AUTO_SIZE_CTL_VER,
/* bool rpt_fcn_enabled = */ false,
/* bool open_trace_file = */ false,
/* bool close_trace_file = */ false,
/* char trace_file_name[] = */ "",
/* bool evictions_enabled = */ true,
/* bool set_initial_size = */ true,
/* size_t initial_size = */ (1 * 1024 * 1024 + 1),
/* double min_clean_fraction = */ 0.2,
/* size_t max_size = */ (16 * 1024 * 1024 + 1),
/* size_t min_size = */ (1 * 1024 * 1024 + 1),
/* long int epoch_length = */ 50001,
/* enum H5C_cache_incr_mode incr_mode = */ H5C_incr__threshold,
/* double lower_hr_threshold = */ 0.91,
/* double increment = */ 2.1,
/* bool apply_max_increment = */ true,
/* size_t max_increment = */ (4 * 1024 * 1024 + 1),
/* enum H5C_cache_flash_incr_mode */
/* flash_incr_mode = */ H5C_flash_incr__off,
/* double flash_multiple = */ 2.0,
/* double flash_threshold = */ 0.5,
/* enum H5C_cache_decr_mode decr_mode = */ H5C_decr__age_out,
/* double upper_hr_threshold = */ 0.998,
/* double decrement = */ 0.91,
/* bool apply_max_decrement = */ true,
/* size_t max_decrement = */ (1 * 1024 * 1024 - 1),
/* int epochs_before_eviction = */ 4,
/* bool apply_empty_reserve = */ true,
/* double empty_reserve = */ 0.05,
/* int dirty_bytes_threshold = */ (256 * 1024),
/* int metadata_write_strategy = */
H5AC__DEFAULT_METADATA_WRITE_STRATEGY};
H5AC_cache_config_t mod_config_2 = {
/* int version = */ H5C__CURR_AUTO_SIZE_CTL_VER,
/* bool rpt_fcn_enabled = */ true,
/* bool open_trace_file = */ false,
/* bool close_trace_file = */ false,
/* char trace_file_name[] = */ "",
/* bool evictions_enabled = */ true,
/* bool set_initial_size = */ true,
/* size_t initial_size = */ (512 * 1024),
/* double min_clean_fraction = */ 0.1,
/* size_t max_size = */ (8 * 1024 * 1024),
/* size_t min_size = */ (512 * 1024),
/* long int epoch_length = */ 25000,
/* enum H5C_cache_incr_mode incr_mode = */ H5C_incr__threshold,
/* double lower_hr_threshold = */ 0.9,
/* double increment = */ 2.0,
/* bool apply_max_increment = */ true,
/* size_t max_increment = */ (2 * 1024 * 1024),
/* enum H5C_cache_flash_incr_mode */
/* flash_incr_mode = */ H5C_flash_incr__off,
/* double flash_multiple = */ 1.5,
/* double flash_threshold = */ 0.4,
/* enum H5C_cache_decr_mode decr_mode = */ H5C_decr__threshold,
/* double upper_hr_threshold = */ 0.9995,
/* double decrement = */ 0.95,
/* bool apply_max_decrement = */ true,
/* size_t max_decrement = */ (512 * 1024),
/* int epochs_before_eviction = */ 4,
/* bool apply_empty_reserve = */ true,
/* double empty_reserve = */ 0.05,
/* int dirty_bytes_threshold = */ (256 * 1024),
/* int metadata_write_strategy = */
H5AC__DEFAULT_METADATA_WRITE_STRATEGY};
H5AC_cache_config_t mod_config_3 = {
/* int version = */ H5C__CURR_AUTO_SIZE_CTL_VER,
/* bool rpt_fcn_enabled = */ false,
/* bool open_trace_file = */ false,
/* bool close_trace_file = */ false,
/* char trace_file_name[] = */ "",
/* bool evictions_enabled = */ true,
/* bool set_initial_size = */ true,
/* size_t initial_size = */ (1 * 1024 * 1024),
/* double min_clean_fraction = */ 0.2,
/* size_t max_size = */ (16 * 1024 * 1024),
/* size_t min_size = */ (1 * 1024 * 1024),
/* long int epoch_length = */ 50000,
/* enum H5C_cache_incr_mode incr_mode = */ H5C_incr__off,
/* double lower_hr_threshold = */ 0.90,
/* double increment = */ 2.0,
/* bool apply_max_increment = */ true,
/* size_t max_increment = */ (4 * 1024 * 1024),
/* enum H5C_cache_flash_incr_mode */
/* flash_incr_mode = */ H5C_flash_incr__off,
/* double flash_multiple = */ 2.1,
/* double flash_threshold = */ 0.6,
/* enum H5C_cache_decr_mode decr_mode = */ H5C_decr__off,
/* double upper_hr_threshold = */ 0.999,
/* double decrement = */ 0.9,
/* bool apply_max_decrement = */ false,
/* size_t max_decrement = */ (1 * 1024 * 1024 - 1),
/* int epochs_before_eviction = */ 3,
/* bool apply_empty_reserve = */ false,
/* double empty_reserve = */ 0.05,
/* int dirty_bytes_threshold = */ (256 * 1024),
/* int metadata_write_strategy = */
H5AC__DEFAULT_METADATA_WRITE_STRATEGY};
H5AC_cache_config_t mod_config_4 = {
/* int version = */ H5C__CURR_AUTO_SIZE_CTL_VER,
/* bool rpt_fcn_enabled = */ false,
/* bool open_trace_file = */ false,
/* bool close_trace_file = */ false,
/* char trace_file_name[] = */ "",
/* bool evictions_enabled = */ true,
/* bool set_initial_size = */ true,
/* size_t initial_size = */ (1 * 1024 * 1024),
/* double min_clean_fraction = */ 0.15,
/* size_t max_size = */ (20 * 1024 * 1024),
/* size_t min_size = */ (1 * 1024 * 1024),
/* long int epoch_length = */ 75000,
/* enum H5C_cache_incr_mode incr_mode = */ H5C_incr__threshold,
/* double lower_hr_threshold = */ 0.9,
/* double increment = */ 2.0,
/* bool apply_max_increment = */ true,
/* size_t max_increment = */ (2 * 1024 * 1024),
/* enum H5C_cache_flash_incr_mode */
/* flash_incr_mode = */ H5C_flash_incr__off,
/* double flash_multiple = */ 1.1,
/* double flash_threshold = */ 0.3,
/* enum H5C_cache_decr_mode decr_mode = */
H5C_decr__age_out_with_threshold,
/* double upper_hr_threshold = */ 0.999,
/* double decrement = */ 0.9,
/* bool apply_max_decrement = */ true,
/* size_t max_decrement = */ (1 * 1024 * 1024),
/* int epochs_before_eviction = */ 3,
/* bool apply_empty_reserve = */ true,
/* double empty_reserve = */ 0.1,
/* int dirty_bytes_threshold = */ (256 * 1024),
/* int metadata_write_strategy = */
H5AC__DEFAULT_METADATA_WRITE_STRATEGY};
if (paged)
TESTING("MDC/FILE related API calls for paged aggregation strategy");
else
TESTING("MDC/FILE related API calls");
pass = true;
/* Open a file with the default FAPL. Verify that the cache is
* configured as per the default both by looking at its internal
* configuration, and via the H5Fget_mdc_config() call.
*
* Then set several different configurations, and verify that
* they took as per above.
*/
/* setup the file name */
if (pass) {
if (h5_fixname(FILENAME[0], H5P_DEFAULT, filename, sizeof(filename)) == NULL) {
pass = false;
failure_mssg = "h5_fixname() failed.\n";
}
}
/* create the file using the default FAPL */
if (pass) {
file_id = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
if (file_id < 0) {
pass = false;
failure_mssg = "H5Fcreate() failed.\n";
}
}
/* verify that the cache is set to the default config */
validate_mdc_config(file_id, &default_config, true, 1);
/* set alternate config 1 */
if (pass) {
if (H5Fset_mdc_config(file_id, &mod_config_1) < 0) {
pass = false;
failure_mssg = "H5Fset_mdc_config() failed 1.\n";
}
}
/* verify that the cache is now set to the alternate config */
validate_mdc_config(file_id, &mod_config_1, true, 2);
/* set alternate config 2 */
if (pass) {
if (H5Fset_mdc_config(file_id, &mod_config_2) < 0) {
pass = false;
failure_mssg = "H5Fset_mdc_config() failed 2.\n";
}
}
/* verify that the cache is now set to the alternate config */
validate_mdc_config(file_id, &mod_config_2, true, 3);
/* set alternate config 3 */
if (pass) {
if (H5Fset_mdc_config(file_id, &mod_config_3) < 0) {
pass = false;
failure_mssg = "H5Fset_mdc_config() failed 3.\n";
}
}
/* verify that the cache is now set to the alternate config */
validate_mdc_config(file_id, &mod_config_3, true, 4);
/* set alternate config 4 */
if (pass) {
if (H5Fset_mdc_config(file_id, &mod_config_4) < 0) {
pass = false;
failure_mssg = "H5Fset_mdc_config() failed 4.\n";
}
}
/* verify that the cache is now set to the alternate config */
validate_mdc_config(file_id, &mod_config_4, true, 5);
/* Run some quick smoke checks on the cache status monitoring
* calls -- no interesting data as the cache hasn't had a
* chance to do much yet.
*/
if (pass) {
if (H5Fget_mdc_hit_rate(file_id, &hit_rate) < 0) {
pass = false;
failure_mssg = "H5Fget_mdc_hit_rate() failed 1.\n";
}
else if (!H5_DBL_ABS_EQUAL(hit_rate, 0.0)) {
pass = false;
failure_mssg = "H5Fget_mdc_hit_rate() returned unexpected hit rate.\n";
}
}
if (pass) {
if (H5Fget_mdc_size(file_id, &max_size, &min_clean_size, &cur_size, &cur_num_entries) < 0) {
pass = false;
failure_mssg = "H5Fget_mdc_size() failed 1.\n";
}
else if ((mod_config_4.initial_size != max_size) ||
(min_clean_size != (size_t)((double)max_size * mod_config_4.min_clean_fraction))) {
pass = false;
failure_mssg = "H5Fget_mdc_size() returned unexpected value(s).\n";
}
}
/* close the file and delete it */
if (pass) {
if (H5Fclose(file_id) < 0) {
pass = false;
failure_mssg = "H5Fclose() failed.\n";
}
else if (H5Fdelete(filename, H5P_DEFAULT) < 0) {
pass = false;
failure_mssg = "H5Fdelete() failed.\n";
}
}
if (pass) {
PASSED();
}
else {
H5_FAILED();
}
if (!pass) {
fprintf(stdout, "%s: failure_mssg = \"%s\".\n", __func__, failure_mssg);
}
return pass;
} /* check_file_mdc_api_calls() */
/*-------------------------------------------------------------------------
* Function: mdc_api_call_smoke_check()
*
* Purpose: Initial basic functional test to see if there are problems
* with the cache API calls.
*
* NOTE: This test takes some time to run and checks the
* testing express level value.
*
* Return: Test pass status (true/false)
*
*-------------------------------------------------------------------------
*/
#define CHUNK_SIZE 2
#define DSET_SIZE (200 * CHUNK_SIZE)
#define NUM_DSETS 6
#define NUM_RANDOM_ACCESSES 200000
static bool
mdc_api_call_smoke_check(int express_test, unsigned paged, hid_t fcpl_id)
{
char filename[512];
bool valid_chunk;
bool dump_hit_rate = false;
int64_t min_accesses = 1000;
double min_hit_rate = 0.90;
bool dump_cache_size = false;
hid_t file_id = H5I_INVALID_HID;
hid_t dataspace_id = H5I_INVALID_HID;
hid_t filespace_ids[NUM_DSETS];
hid_t memspace_id = H5I_INVALID_HID;
hid_t dataset_ids[NUM_DSETS];
hid_t properties = H5I_INVALID_HID;
char dset_name[64];
int i, j, k, l, m, n;
herr_t status;
hsize_t dims[2];
hsize_t a_size[2];
hsize_t offset[2];
hsize_t chunk_size[2];
int data_chunk[CHUNK_SIZE][CHUNK_SIZE];
H5AC_cache_config_t default_config = H5AC__DEFAULT_CACHE_CONFIG;
H5AC_cache_config_t mod_config_1 = {
/* int version = */ H5C__CURR_AUTO_SIZE_CTL_VER,
/* bool rpt_fcn_enabled = */ false,
/* bool open_trace_file = */ false,
/* bool close_trace_file = */ false,
/* char trace_file_name[] = */ "",
/* bool evictions_enabled = */ true,
/* bool set_initial_size = */ true,
/* size_t initial_size = */ 500000,
/* double min_clean_fraction = */ 0.1,
/* size_t max_size = */ 16000000,
/* size_t min_size = */ 250000,
/* long int epoch_length = */ 50000,
/* enum H5C_cache_incr_mode incr_mode = */ H5C_incr__off,
/* double lower_hr_threshold = */ 0.95,
/* double increment = */ 2.0,
/* bool apply_max_increment = */ false,
/* size_t max_increment = */ 4000000,
/* enum H5C_cache_flash_incr_mode */
/* flash_incr_mode = */ H5C_flash_incr__off,
/* double flash_multiple = */ 2.0,
/* double flash_threshold = */ 0.5,
/* enum H5C_cache_decr_mode decr_mode = */ H5C_decr__off,
/* double upper_hr_threshold = */ 0.999,
/* double decrement = */ 0.9,
/* bool apply_max_decrement = */ false,
/* size_t max_decrement = */ 1000000,
/* int epochs_before_eviction = */ 2,
/* bool apply_empty_reserve = */ true,
/* double empty_reserve = */ 0.05,
/* int dirty_bytes_threshold = */ (256 * 1024),
/* int metadata_write_strategy = */
H5AC__DEFAULT_METADATA_WRITE_STRATEGY};
H5AC_cache_config_t mod_config_2 = {
/* int version = */ H5C__CURR_AUTO_SIZE_CTL_VER,
/* bool rpt_fcn_enabled = */ false,
/* bool open_trace_file = */ false,
/* bool close_trace_file = */ false,
/* char trace_file_name[] = */ "",
/* bool evictions_enabled = */ true,
/* bool set_initial_size = */ true,
/* size_t initial_size = */ 12000000,
/* double min_clean_fraction = */ 0.1,
/* size_t max_size = */ 16000000,
/* size_t min_size = */ 250000,
/* long int epoch_length = */ 50000,
/* enum H5C_cache_incr_mode incr_mode = */ H5C_incr__off,
/* double lower_hr_threshold = */ 0.95,
/* double increment = */ 2.0,
/* bool apply_max_increment = */ false,
/* size_t max_increment = */ 4000000,
/* enum H5C_cache_flash_incr_mode */
/* flash_incr_mode = */ H5C_flash_incr__off,
/* double flash_multiple = */ 2.0,
/* double flash_threshold = */ 0.5,
/* enum H5C_cache_decr_mode decr_mode = */ H5C_decr__off,
/* double upper_hr_threshold = */ 0.999,
/* double decrement = */ 0.9,
/* bool apply_max_decrement = */ false,
/* size_t max_decrement = */ 1000000,
/* int epochs_before_eviction = */ 2,
/* bool apply_empty_reserve = */ true,
/* double empty_reserve = */ 0.05,
/* int dirty_bytes_threshold = */ (256 * 1024),
/* int metadata_write_strategy = */
H5AC__DEFAULT_METADATA_WRITE_STRATEGY};
H5AC_cache_config_t mod_config_3 = {
/* int version = */ H5C__CURR_AUTO_SIZE_CTL_VER,
/* bool rpt_fcn_enabled = */ false,
/* bool open_trace_file = */ false,
/* bool close_trace_file = */ false,
/* char trace_file_name[] = */ "",
/* bool evictions_enabled = */ true,
/* bool set_initial_size = */ true,
/* size_t initial_size = */ 2000000,
/* double min_clean_fraction = */ 0.1,
/* size_t max_size = */ 16000000,
/* size_t min_size = */ 250000,
/* long int epoch_length = */ 50000,
/* enum H5C_cache_incr_mode incr_mode = */ H5C_incr__off,
/* double lower_hr_threshold = */ 0.95,
/* double increment = */ 2.0,
/* bool apply_max_increment = */ false,
/* size_t max_increment = */ 4000000,
/* enum H5C_cache_flash_incr_mode */
/* flash_incr_mode = */ H5C_flash_incr__off,
/* double flash_multiple = */ 2.0,
/* double flash_threshold = */ 0.5,
/* enum H5C_cache_decr_mode decr_mode = */ H5C_decr__off,
/* double upper_hr_threshold = */ 0.999,
/* double decrement = */ 0.9,
/* bool apply_max_decrement = */ false,
/* size_t max_decrement = */ 1000000,
/* int epochs_before_eviction = */ 2,
/* bool apply_empty_reserve = */ true,
/* double empty_reserve = */ 0.05,
/* int dirty_bytes_threshold = */ (256 * 1024),
/* int metadata_write_strategy = */
H5AC__DEFAULT_METADATA_WRITE_STRATEGY};
if (paged)
TESTING("MDC API smoke check for paged aggregation strategy");
else
TESTING("MDC API smoke check");
pass = true;
if (express_test > 0) {
SKIPPED();
fprintf(stdout, " Long tests disabled.\n");
return pass;
}
/* Open a file with the default FAPL. Verify that the cache is
* configured as per the default both by looking at its internal
* configuration, and via the H5Fget_mdc_config() call.
*
* Then set the cache to mod_config_1, which fixes cache size at
* 500000 bytes, and turns off automatic cache resize.
*/
/* setup the file name */
if (pass) {
if (h5_fixname(FILENAME[0], H5P_DEFAULT, filename, sizeof(filename)) == NULL) {
pass = false;
failure_mssg = "h5_fixname() failed.\n";
}
}
/* create the file using the default FAPL */
if (pass) {
file_id = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
if (file_id < 0) {
pass = false;
failure_mssg = "H5Fcreate() failed.\n";
}
}
/* verify that the cache is set to the default config */
validate_mdc_config(file_id, &default_config, true, 1);
/* set alternate config 1 */
if (pass) {
if (H5Fset_mdc_config(file_id, &mod_config_1) < 0) {
pass = false;
failure_mssg = "H5Fset_mdc_config() failed 1.\n";
}
}
/* verify that the cache is now set to the alternate config */
validate_mdc_config(file_id, &mod_config_1, true, 2);
/* create the datasets */
if (pass) {
i = 0;
while ((pass) && (i < NUM_DSETS)) {
/* create a dataspace for the chunked dataset */
dims[0] = DSET_SIZE;
dims[1] = DSET_SIZE;
dataspace_id = H5Screate_simple(2, dims, NULL);
if (dataspace_id < 0) {
pass = false;
failure_mssg = "H5Screate_simple() failed.";
}
/* set the dataset creation plist to specify that the raw data is
* to be partitioned into 10X10 element chunks.
*/
if (pass) {
chunk_size[0] = CHUNK_SIZE;
chunk_size[1] = CHUNK_SIZE;
properties = H5Pcreate(H5P_DATASET_CREATE);
if (properties < 0) {
pass = false;
failure_mssg = "H5Pcreate() failed.";
}
}
if (pass) {
if (H5Pset_chunk(properties, 2, chunk_size) < 0) {
pass = false;
failure_mssg = "H5Pset_chunk() failed.";
}
}
/* create the dataset */
if (pass) {
snprintf(dset_name, sizeof(dset_name), "/dset%03d", i);
dataset_ids[i] = H5Dcreate2(file_id, dset_name, H5T_STD_I32BE, dataspace_id, H5P_DEFAULT,
properties, H5P_DEFAULT);
if (dataset_ids[i] < 0) {
pass = false;
failure_mssg = "H5Dcreate2() failed.";
}
}
/* get the file space ID */
if (pass) {
filespace_ids[i] = H5Dget_space(dataset_ids[i]);
if (filespace_ids[i] < 0) {
pass = false;
failure_mssg = "H5Dget_space() failed.";
}
}
i++;
}
}
/* create the mem space to be used to read and write chunks */
if (pass) {
dims[0] = CHUNK_SIZE;
dims[1] = CHUNK_SIZE;
memspace_id = H5Screate_simple(2, dims, NULL);
if (memspace_id < 0) {
pass = false;
failure_mssg = "H5Screate_simple() failed.";
}
}
/* select in memory hyperslab */
if (pass) {
offset[0] = 0; /*offset of hyperslab in memory*/
offset[1] = 0;
a_size[0] = CHUNK_SIZE; /*size of hyperslab*/
a_size[1] = CHUNK_SIZE;
status = H5Sselect_hyperslab(memspace_id, H5S_SELECT_SET, offset, NULL, a_size, NULL);
if (status < 0) {
pass = false;
failure_mssg = "H5Sselect_hyperslab() failed.";
}
}
/* initialize all datasets on a round robin basis */
i = 0;
while ((pass) && (i < DSET_SIZE)) {
j = 0;
while ((pass) && (j < DSET_SIZE)) {
m = 0;
while ((pass) && (m < NUM_DSETS)) {
/* initialize the slab */
for (k = 0; k < CHUNK_SIZE; k++) {
for (l = 0; l < CHUNK_SIZE; l++) {
data_chunk[k][l] = (DSET_SIZE * DSET_SIZE * m) + (DSET_SIZE * (i + k)) + j + l;
}
}
/* select on disk hyperslab */
offset[0] = (hsize_t)i; /*offset of hyperslab in file*/
offset[1] = (hsize_t)j;
a_size[0] = CHUNK_SIZE; /*size of hyperslab*/
a_size[1] = CHUNK_SIZE;
status = H5Sselect_hyperslab(filespace_ids[m], H5S_SELECT_SET, offset, NULL, a_size, NULL);
if (status < 0) {
pass = false;
failure_mssg = "disk H5Sselect_hyperslab() failed.";
}
/* write the chunk to file */
status = H5Dwrite(dataset_ids[m], H5T_NATIVE_INT, memspace_id, filespace_ids[m], H5P_DEFAULT,
data_chunk);
if (status < 0) {
pass = false;
failure_mssg = "H5Dwrite() failed.";
}
m++;
}
j += CHUNK_SIZE;
}
/* check the cache hit rate, and reset the counters.
* Hit rate should be just about unity here, so we will just
* get the data and (possibly) print it without checking it
* beyond ensuring that it agrees with the cache internal
* data structures.
*
* similarly, check cache size.
*/
if ((pass) && (i % (DSET_SIZE / 4) == 0)) {
check_and_validate_cache_hit_rate(file_id, NULL, dump_hit_rate, min_accesses, min_hit_rate);
check_and_validate_cache_size(file_id, NULL, NULL, NULL, NULL, dump_cache_size);
}
i += CHUNK_SIZE;
}
/* set alternate config 2 */
if (pass) {
if (H5Fset_mdc_config(file_id, &mod_config_2) < 0) {
pass = false;
failure_mssg = "H5Fset_mdc_config() failed 2.\n";
}
}
/* verify that the cache is now set to the alternate config */
validate_mdc_config(file_id, &mod_config_2, true, 3);
/* do random reads on all datasets */
n = 0;
while ((pass) && (n < NUM_RANDOM_ACCESSES)) {
m = HDrand() % NUM_DSETS;
i = (HDrand() % (DSET_SIZE / CHUNK_SIZE)) * CHUNK_SIZE;
j = (HDrand() % (DSET_SIZE / CHUNK_SIZE)) * CHUNK_SIZE;
/* select on disk hyperslab */
offset[0] = (hsize_t)i; /*offset of hyperslab in file*/
offset[1] = (hsize_t)j;
a_size[0] = CHUNK_SIZE; /*size of hyperslab*/
a_size[1] = CHUNK_SIZE;
status = H5Sselect_hyperslab(filespace_ids[m], H5S_SELECT_SET, offset, NULL, a_size, NULL);
if (status < 0) {
pass = false;
failure_mssg = "disk hyperslab create failed.";
}
/* read the chunk from file */
if (pass) {
status = H5Dread(dataset_ids[m], H5T_NATIVE_INT, memspace_id, filespace_ids[m], H5P_DEFAULT,
data_chunk);
if (status < 0) {
pass = false;
failure_mssg = "disk hyperslab create failed.";
}
}
/* validate the slab */
if (pass) {
valid_chunk = true;
for (k = 0; k < CHUNK_SIZE; k++) {
for (l = 0; l < CHUNK_SIZE; l++) {
if (data_chunk[k][l] != ((DSET_SIZE * DSET_SIZE * m) + (DSET_SIZE * (i + k)) + j + l)) {
valid_chunk = false;
}
}
}
if (!valid_chunk) {
pass = false;
failure_mssg = "slab validation failed.";
}
}
if ((pass) && (n % (NUM_RANDOM_ACCESSES / 4) == 0)) {
check_and_validate_cache_hit_rate(file_id, NULL, dump_hit_rate, min_accesses, min_hit_rate);
check_and_validate_cache_size(file_id, NULL, NULL, NULL, NULL, dump_cache_size);
}
n++;
}
/* close the file spaces we are done with */
i = 1;
while ((pass) && (i < NUM_DSETS)) {
if (H5Sclose(filespace_ids[i]) < 0) {
pass = false;
failure_mssg = "H5Sclose() failed.";
}
i++;
}
/* close the datasets we are done with */
i = 1;
while ((pass) && (i < NUM_DSETS)) {
if (H5Dclose(dataset_ids[i]) < 0) {
pass = false;
failure_mssg = "H5Dclose() failed.";
}
i++;
}
/* set alternate config 3 */
if (pass) {
if (H5Fset_mdc_config(file_id, &mod_config_3) < 0) {
pass = false;
failure_mssg = "H5Fset_mdc_config() failed 3.\n";
}
}
/* verify that the cache is now set to the alternate config */
validate_mdc_config(file_id, &mod_config_3, true, 4);
/* do random reads on data set 0 only */
m = 0;
n = 0;
while ((pass) && (n < NUM_RANDOM_ACCESSES)) {
i = (HDrand() % (DSET_SIZE / CHUNK_SIZE)) * CHUNK_SIZE;
j = (HDrand() % (DSET_SIZE / CHUNK_SIZE)) * CHUNK_SIZE;
/* select on disk hyperslab */
offset[0] = (hsize_t)i; /*offset of hyperslab in file*/
offset[1] = (hsize_t)j;
a_size[0] = CHUNK_SIZE; /*size of hyperslab*/
a_size[1] = CHUNK_SIZE;
status = H5Sselect_hyperslab(filespace_ids[m], H5S_SELECT_SET, offset, NULL, a_size, NULL);
if (status < 0) {
pass = false;
failure_mssg = "disk hyperslab create failed.";
}
/* read the chunk from file */
if (pass) {
status = H5Dread(dataset_ids[m], H5T_NATIVE_INT, memspace_id, filespace_ids[m], H5P_DEFAULT,
data_chunk);
if (status < 0) {
pass = false;
failure_mssg = "disk hyperslab create failed.";
}
}
/* validate the slab */
if (pass) {
valid_chunk = true;
for (k = 0; k < CHUNK_SIZE; k++) {
for (l = 0; l < CHUNK_SIZE; l++) {
if (data_chunk[k][l] != ((DSET_SIZE * DSET_SIZE * m) + (DSET_SIZE * (i + k)) + j + l)) {
valid_chunk = false;
}
}
}
if (!valid_chunk) {
pass = false;
failure_mssg = "slab validation failed.";
}
}
if ((pass) && (n % (NUM_RANDOM_ACCESSES / 4) == 0)) {
check_and_validate_cache_hit_rate(file_id, NULL, dump_hit_rate, min_accesses, min_hit_rate);
check_and_validate_cache_size(file_id, NULL, NULL, NULL, NULL, dump_cache_size);
}
n++;
}
/* close file space 0 */
if (pass) {
if (H5Sclose(filespace_ids[0]) < 0) {
pass = false;
failure_mssg = "H5Sclose(filespace_ids[0]) failed.";
}
}
/* close the data space */
if (pass) {
if (H5Sclose(dataspace_id) < 0) {
pass = false;
failure_mssg = "H5Sclose(dataspace) failed.";
}
}
/* close the mem space */
if (pass) {
if (H5Sclose(memspace_id) < 0) {
pass = false;
failure_mssg = "H5Sclose(memspace_id) failed.";
}
}
/* close dataset 0 */
if (pass) {
if (H5Dclose(dataset_ids[0]) < 0) {
pass = false;
failure_mssg = "H5Dclose(dataset_ids[0]) failed.";
}
}
/* close the file and delete it */
if (pass) {
if (H5Fclose(file_id) < 0) {
pass = false;
failure_mssg = "H5Fclose() failed.\n";
}
else if (H5Fdelete(filename, H5P_DEFAULT) < 0) {
pass = false;
failure_mssg = "H5Fdelete() failed.\n";
}
}
if (pass) {
PASSED();
}
else {
H5_FAILED();
}
if (!pass) {
fprintf(stdout, "%s: failure_mssg = \"%s\".\n", __func__, failure_mssg);
}
return pass;
} /* mdc_api_call_smoke_check() */
/*-------------------------------------------------------------------------
* Function: init_invalid_configs()
*
* Purpose: Initialize an array of invalid external MDC configurations
* that will be used to test error rejection in the MDC-
* related API calls.
*
* Note: It is assumed that boolean parameters are only set
* to true/false.
*
* Return: Success: Pointer to an array of cache configurations.
* Failure: NULL
*
*-------------------------------------------------------------------------
*/
#define NUM_INVALID_CONFIGS 36
static H5AC_cache_config_t *invalid_configs = NULL;
static H5AC_cache_config_t *
init_invalid_configs(void)
{
int i;
H5AC_cache_config_t *configs = NULL;
/* Allocate memory */
if (NULL == (configs = (H5AC_cache_config_t *)calloc(NUM_INVALID_CONFIGS, sizeof(H5AC_cache_config_t)))) {
return NULL;
}
/* Set defaults for all configs */
for (i = 0; i < NUM_INVALID_CONFIGS; i++) {
configs[i].version = H5C__CURR_AUTO_SIZE_CTL_VER;
configs[i].rpt_fcn_enabled = false;
configs[i].open_trace_file = false;
configs[i].close_trace_file = false;
/* trace file name set to all ASCII NUL by calloc() */
configs[i].evictions_enabled = true;
configs[i].set_initial_size = true;
configs[i].initial_size = (1 * 1024 * 1024);
configs[i].min_clean_fraction = 0.25;
configs[i].max_size = (16 * 1024 * 1024);
configs[i].min_size = (1 * 1024 * 1024);
configs[i].epoch_length = 50000;
configs[i].incr_mode = H5C_incr__threshold;
configs[i].lower_hr_threshold = 0.9;
configs[i].increment = 2.0;
configs[i].apply_max_increment = true;
configs[i].max_increment = (4 * 1024 * 1024);
configs[i].flash_incr_mode = H5C_flash_incr__off;
configs[i].flash_multiple = 2.0;
configs[i].flash_threshold = 0.5;
configs[i].decr_mode = H5C_decr__age_out_with_threshold;
configs[i].upper_hr_threshold = 0.999;
configs[i].decrement = 0.9;
configs[i].apply_max_decrement = true;
configs[i].max_decrement = (1 * 1024 * 1024);
configs[i].epochs_before_eviction = 3;
configs[i].apply_empty_reserve = true;
configs[i].empty_reserve = 0.1;
configs[i].dirty_bytes_threshold = (256 * 1024);
configs[i].metadata_write_strategy = H5AC__DEFAULT_METADATA_WRITE_STRATEGY;
}
/* Set badness for each config */
/* 0 -- bad version */
configs[0].version = -1;
/* 1 -- open_trace_file == true and empty trace_file_name */
configs[1].open_trace_file = true;
/* trace file name set to all ASCII NUL by calloc() */
/* 2 -- max_size too big */
configs[2].max_size = H5C__MAX_MAX_CACHE_SIZE + 1;
/* 3 -- min_size too small */
configs[3].min_size = H5C__MIN_MAX_CACHE_SIZE - 1;
/* 4 -- min_size > max_size */
configs[4].max_size = (16 * 1024 * 1024);
configs[4].min_size = (16 * 1024 * 1024 + 1);
/* 5 -- initial size out of range (too big) */
configs[5].initial_size = (16 * 1024 * 1024 + 1);
/* 6 -- initial_size out of range (too small) */
configs[6].initial_size = (1 * 1024 * 1024 - 1);
/* 7 -- min_clean_fraction too big */
configs[7].min_clean_fraction = 1.000001;
/* 8 -- min_clean_fraction too small */
configs[8].min_clean_fraction = -0.00000001;
/* 9 -- epoch_length too small */
configs[9].epoch_length = H5C__MIN_AR_EPOCH_LENGTH - 1;
/* 10 -- epoch_length too big */
configs[10].epoch_length = H5C__MAX_AR_EPOCH_LENGTH + 1;
/* 11 -- invalid incr_mode */
configs[11].incr_mode = (enum H5C_cache_incr_mode) - 1;
/* 12 -- lower_hr_threshold too small */
configs[12].lower_hr_threshold = -0.000001;
/* 13 -- lower_hr_threshold too big */
configs[13].lower_hr_threshold = 1.00000001;
/* 14 -- increment too small */
configs[14].increment = 0.999999999999;
/* 15 -- invalid flash_incr_mode */
configs[15].flash_incr_mode = (enum H5C_cache_flash_incr_mode) - 1;
/* 16 -- flash_multiple too small */
configs[16].flash_incr_mode = H5C_flash_incr__add_space;
configs[16].flash_multiple = 0.09;
/* 17 -- flash_multiple too big */
configs[17].flash_incr_mode = H5C_flash_incr__add_space;
configs[17].flash_multiple = 10.001;
/* 18 -- flash_threshold too small */
configs[18].flash_incr_mode = H5C_flash_incr__add_space;
configs[18].flash_threshold = 0.099;
/* 19 -- flash_threshold too big */
configs[19].flash_incr_mode = H5C_flash_incr__add_space;
configs[19].flash_threshold = 1.001;
/* 20 -- bad decr_mode */
configs[20].decr_mode = (enum H5C_cache_decr_mode) - 1;
/* 21 -- upper_hr_threshold too big */
configs[21].upper_hr_threshold = 1.00001;
/* 22 -- decrement too small */
configs[22].decr_mode = H5C_decr__threshold;
configs[22].decrement = -0.0000000001;
/* 23 -- decrement too big */
configs[23].decr_mode = H5C_decr__threshold;
configs[23].decrement = 1.0000000001;
/* 24 -- epochs_before_eviction too small */
configs[24].epochs_before_eviction = 0;
/* 25 -- epochs_before_eviction too big */
configs[25].epochs_before_eviction = H5C__MAX_EPOCH_MARKERS + 1;
/* 26 -- empty_reserve too small */
configs[26].empty_reserve = -0.0000000001;
/* 27 -- empty_reserve too big */
configs[27].empty_reserve = 1.00000000001;
/* 28 -- upper_hr_threshold too small */
configs[28].upper_hr_threshold = -0.000000001;
/* 29 -- upper_hr_threshold too big */
configs[29].upper_hr_threshold = 1.00000001;
/* 30 -- upper_hr_threshold <= lower_hr_threshold */
configs[30].lower_hr_threshold = 0.9;
configs[30].upper_hr_threshold = 0.9;
/* 31 -- dirty_bytes_threshold too small */
configs[31].dirty_bytes_threshold = (H5C__MIN_MAX_CACHE_SIZE / 2) - 1;
/* 32 -- dirty_bytes_threshold too big */
configs[32].dirty_bytes_threshold = (H5C__MAX_MAX_CACHE_SIZE / 4) + 1;
/* 33 -- attempt to disable evictions when auto incr enabled */
configs[33].evictions_enabled = false;
configs[33].decr_mode = H5C_decr__off;
/* 34 -- attempt to disable evictions when auto decr enabled */
configs[34].evictions_enabled = false;
configs[34].decr_mode = H5C_decr__age_out;
/* 35 -- unknown metadata write strategy */
configs[35].metadata_write_strategy = -1;
return configs;
} /* initialize_invalid_configs() */
/*-------------------------------------------------------------------------
* Function: check_fapl_mdc_api_errs()
*
* Purpose: Verify that the FAPL related MDC API calls reject input
* errors gracefully.
*
* Return: Test pass status (true/false)
*
*-------------------------------------------------------------------------
*/
static bool
check_fapl_mdc_api_errs(void)
{
static char msg[128];
int i;
herr_t result;
hid_t fapl_id = H5I_INVALID_HID;
H5AC_cache_config_t default_config = H5AC__DEFAULT_CACHE_CONFIG;
H5AC_cache_config_t scratch;
TESTING("MDC/FAPL related API input errors");
pass = true;
/* first test H5Pget_mdc_config().
*/
scratch.version = H5C__CURR_AUTO_SIZE_CTL_VER;
if (pass) {
H5E_BEGIN_TRY
{
result = H5Pget_mdc_config((hid_t)H5I_INVALID_HID, &scratch);
}
H5E_END_TRY
if (result >= 0) {
pass = false;
failure_mssg = "H5Pget_mdc_config() accepted invalid plist_id.";
}
}
/* Create a FAPL for test purposes, and verify that it contains the
* default MDC configuration.
*/
if (pass) {
fapl_id = H5Pcreate(H5P_FILE_ACCESS);
if (fapl_id < 0) {
pass = false;
failure_mssg = "H5Pcreate(H5P_FILE_ACCESS) failed.\n";
}
}
scratch.version = H5C__CURR_AUTO_SIZE_CTL_VER;
if ((pass) && ((H5Pget_mdc_config(fapl_id, &scratch) < 0) ||
(!CACHE_CONFIGS_EQUAL(default_config, scratch, true, true)))) {
pass = false;
failure_mssg = "New FAPL has unexpected metadata cache config?!?!?.\n";
}
if (pass) {
H5E_BEGIN_TRY
{
result = H5Pget_mdc_config(fapl_id, NULL);
}
H5E_END_TRY
if (result >= 0) {
pass = false;
failure_mssg = "H5Pget_mdc_config() accepted NULL config_ptr.";
}
}
/* one last test for H5Pget_mdc_config() */
scratch.version = -1; /* a convenient, invalid value */
if (pass) {
H5E_BEGIN_TRY
{
result = H5Pget_mdc_config(fapl_id, &scratch);
}
H5E_END_TRY
if (result >= 0) {
pass = false;
failure_mssg = "H5Pget_mdc_config() accepted bad config version.";
}
}
/* now test H5Pset_mdc_config()
*/
scratch.version = H5C__CURR_AUTO_SIZE_CTL_VER;
if (pass) {
H5E_BEGIN_TRY
{
result = H5Pset_mdc_config((hid_t)H5I_INVALID_HID, &default_config);
}
H5E_END_TRY
if (result >= 0) {
pass = false;
failure_mssg = "H5Pset_mdc_config() accepted bad invalid plist_id.";
}
}
if (pass) {
H5E_BEGIN_TRY
{
result = H5Pset_mdc_config(fapl_id, NULL);
}
H5E_END_TRY
if (result >= 0) {
pass = false;
failure_mssg = "H5Pset_mdc_config() accepted NULL config_ptr.";
}
}
i = 0;
while ((pass) && (i < NUM_INVALID_CONFIGS)) {
H5E_BEGIN_TRY
{
result = H5Pset_mdc_config(fapl_id, &(invalid_configs[i]));
}
H5E_END_TRY
if (result >= 0) {
pass = false;
snprintf(msg, (size_t)128, "H5Pset_mdc_config() accepted invalid_configs[%d].", i);
failure_mssg = msg;
}
i++;
}
/* verify that none of the above calls to H5Pset_mdc_config() changed
* the configuration in the FAPL.
*/
scratch.version = H5C__CURR_AUTO_SIZE_CTL_VER;
if ((pass) && ((H5Pget_mdc_config(fapl_id, &scratch) < 0) ||
(!CACHE_CONFIGS_EQUAL(default_config, scratch, true, true)))) {
pass = false;
failure_mssg = "FAPL metadata cache config changed???.\n";
}
if (pass) {
PASSED();
}
else {
H5_FAILED();
}
if (!pass) {
fprintf(stdout, "%s: failure_mssg = \"%s\".\n", __func__, failure_mssg);
}
return pass;
} /* check_fapl_mdc_api_errs() */
/*-------------------------------------------------------------------------
* Function: check_file_mdc_api_errs()
*
* Purpose: Verify that the file related MDC API calls reject input
* errors gracefully.
*
* Return: Test pass status (true/false)
*
*-------------------------------------------------------------------------
*/
static bool
check_file_mdc_api_errs(unsigned paged, hid_t fcpl_id)
{
char filename[512];
static char msg[128];
bool show_progress = false;
int i;
herr_t result;
hid_t file_id = H5I_INVALID_HID;
size_t max_size;
size_t min_clean_size;
size_t cur_size;
int cur_num_entries;
double hit_rate;
H5AC_cache_config_t default_config = H5AC__DEFAULT_CACHE_CONFIG;
H5AC_cache_config_t scratch;
if (paged)
TESTING("MDC/FILE related API input errors for paged aggregation strategy");
else
TESTING("MDC/FILE related API input errors");
pass = true;
/* Create a file for test purposes, and verify that its metadata cache
* set to the default MDC configuration.
*/
/* setup the file name */
if (pass) {
if (show_progress) {
fprintf(stdout, "%s: calling h5_fixname().\n", __func__);
}
if (h5_fixname(FILENAME[0], H5P_DEFAULT, filename, sizeof(filename)) == NULL) {
pass = false;
failure_mssg = "h5_fixname() failed.\n";
}
}
if (pass) {
if (show_progress) {
fprintf(stdout, "%s: calling H5Fcreate().\n", __func__);
}
file_id = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
if (file_id < 0) {
pass = false;
failure_mssg = "H5Fcreate() failed.\n";
}
}
validate_mdc_config(file_id, &default_config, true, 1);
/* test H5Fget_mdc_config(). */
scratch.version = H5C__CURR_AUTO_SIZE_CTL_VER;
if (pass) {
if (show_progress) {
fprintf(stdout, "%s: testing H5Fget_mdc_config() 1.\n", __func__);
}
H5E_BEGIN_TRY
{
result = H5Fget_mdc_config((hid_t)H5I_INVALID_HID, &scratch);
}
H5E_END_TRY
if (result >= 0) {
pass = false;
failure_mssg = "H5Fget_mdc_config() accepted invalid file_id.";
}
}
if (pass) {
if (show_progress) {
fprintf(stdout, "%s: testing H5Fget_mdc_config() 2.\n", __func__);
}
H5E_BEGIN_TRY
{
result = H5Fget_mdc_config(file_id, NULL);
}
H5E_END_TRY
if (result >= 0) {
pass = false;
failure_mssg = "H5Fget_mdc_config() accepted NULL config_ptr.";
}
}
scratch.version = -1; /* a convenient, invalid value */
if (pass) {
if (show_progress) {
fprintf(stdout, "%s: testing H5Fget_mdc_config() 3.\n", __func__);
}
H5E_BEGIN_TRY
{
result = H5Fget_mdc_config(file_id, &scratch);
}
H5E_END_TRY
if (result >= 0) {
pass = false;
failure_mssg = "H5Fget_mdc_config() accepted bad config version.";
}
}
/* test H5Fset_mdc_config() */
scratch.version = H5C__CURR_AUTO_SIZE_CTL_VER;
if (pass) {
if (show_progress) {
fprintf(stdout, "%s: testing H5Fset_mdc_config() 1.\n", __func__);
}
H5E_BEGIN_TRY
{
result = H5Fset_mdc_config((hid_t)H5I_INVALID_HID, &default_config);
}
H5E_END_TRY
if (result >= 0) {
pass = false;
failure_mssg = "H5Fset_mdc_config() accepted bad invalid file_id.";
}
}
if (pass) {
if (show_progress) {
fprintf(stdout, "%s: testing H5Fset_mdc_config() 2.\n", __func__);
}
H5E_BEGIN_TRY
{
result = H5Fset_mdc_config(file_id, NULL);
}
H5E_END_TRY
if (result >= 0) {
pass = false;
failure_mssg = "H5Fset_mdc_config() accepted NULL config_ptr.";
}
}
i = 0;
while ((pass) && (i < NUM_INVALID_CONFIGS)) {
if (show_progress) {
fprintf(stdout, "%s: testing H5Fset_mdc_config() with invalid config %d.\n", __func__, i);
}
H5E_BEGIN_TRY
{
result = H5Fset_mdc_config(file_id, &(invalid_configs[i]));
}
H5E_END_TRY
if (result >= 0) {
pass = false;
snprintf(msg, (size_t)128, "H5Fset_mdc_config() accepted invalid_configs[%d].", i);
failure_mssg = msg;
}
i++;
}
/* verify that none of the above calls to H5Fset_mdc_config() changed
* the configuration in the FAPL.
*/
validate_mdc_config(file_id, &default_config, true, 2);
/* test H5Fget_mdc_hit_rate() */
if (pass) {
if (show_progress) {
fprintf(stdout, "%s: testing H5Fget_mdc_hit_rate() 1.\n", __func__);
}
H5E_BEGIN_TRY
{
result = H5Fget_mdc_hit_rate((hid_t)H5I_INVALID_HID, &hit_rate);
}
H5E_END_TRY
if (result >= 0) {
pass = false;
failure_mssg = "H5Fget_mdc_hit_rate() accepted bad file_id.";
}
}
if (pass) {
if (show_progress) {
fprintf(stdout, "%s: testing H5Fget_mdc_hit_rate() 2.\n", __func__);
}
H5E_BEGIN_TRY
{
result = H5Fget_mdc_hit_rate(file_id, NULL);
}
H5E_END_TRY
if (result >= 0) {
pass = false;
failure_mssg = "H5Fget_mdc_hit_rate() accepted NULL hit_rate_ptr.";
}
}
/* test H5Freset_mdc_hit_rate_stats() */
if (pass) {
if (show_progress) {
fprintf(stdout, "%s: testing H5Freset_mdc_hit_rate_stats().\n", __func__);
}
H5E_BEGIN_TRY
{
result = H5Freset_mdc_hit_rate_stats((hid_t)H5I_INVALID_HID);
}
H5E_END_TRY
if (result >= 0) {
pass = false;
failure_mssg = "H5Freset_mdc_hit_rate_stats() accepted bad file_id.";
}
}
/* test H5Fget_mdc_size() */
if (pass) {
if (show_progress) {
fprintf(stdout, "%s: testing H5Fget_mdc_size() 1.\n", __func__);
}
H5E_BEGIN_TRY
{
result = H5Fget_mdc_size((hid_t)H5I_INVALID_HID, &max_size, &min_clean_size, &cur_size,
&cur_num_entries);
}
H5E_END_TRY
if (result >= 0) {
pass = false;
failure_mssg = "H5Fget_mdc_size() accepted bad file_id.";
}
}
if (pass) {
if (show_progress) {
fprintf(stdout, "%s: testing H5Fget_mdc_size() 2.\n", __func__);
}
if ((H5Fget_mdc_size(file_id, &max_size, NULL, NULL, NULL) < 0) ||
(H5Fget_mdc_size(file_id, NULL, &min_clean_size, NULL, NULL) < 0) ||
(H5Fget_mdc_size(file_id, NULL, NULL, &cur_size, NULL) < 0) ||
(H5Fget_mdc_size(file_id, NULL, NULL, NULL, &cur_num_entries) < 0) ||
(H5Fget_mdc_size(file_id, NULL, NULL, NULL, NULL) < 0)) {
pass = false;
failure_mssg = "H5Fget_mdc_size() failed to handle NULL params.";
}
}
/* close the file and delete it */
if (pass) {
if (show_progress) {
fprintf(stdout, "%s: cleaning up from tests.\n", __func__);
}
if (H5Fclose(file_id) < 0) {
pass = false;
failure_mssg = "H5Fclose() failed.\n";
}
else if (H5Fdelete(filename, H5P_DEFAULT) < 0) {
pass = false;
failure_mssg = "H5Fdelete() failed.\n";
}
}
if (pass) {
PASSED();
}
else {
H5_FAILED();
}
if (!pass) {
fprintf(stdout, "%s: failure_mssg = \"%s\".\n", __func__, failure_mssg);
}
return pass;
} /* check_file_mdc_api_errs() */
/*-------------------------------------------------------------------------
* Function: main
*
* Purpose: Run tests on the cache code contained in H5C.c
*
* Return: EXIT_SUCCESS/EXIT_FAILURE
*
*-------------------------------------------------------------------------
*/
int
main(void)
{
unsigned nerrs = 0;
int express_test;
hid_t fcpl_id = H5I_INVALID_HID;
hid_t fcpl2_id = H5I_INVALID_HID;
unsigned paged;
H5open();
express_test = GetTestExpress();
printf("===================================\n");
printf("Cache API tests\n");
printf(" express_test = %d\n", express_test);
printf("===================================\n");
/* Initialize invalid configurations.
*/
invalid_configs = init_invalid_configs();
if (NULL == invalid_configs) {
failure_mssg = "Unable to allocate memory for invalid configs.";
fprintf(stdout, "%s: failure_mssg = \"%s\".\n", __func__, failure_mssg);
return EXIT_FAILURE;
} /* end if */
if ((fcpl_id = H5Pcreate(H5P_FILE_CREATE)) < 0) {
failure_mssg = "H5Pcreate(H5P_FILE_CREATE) failed.\n";
fprintf(stdout, "%s: failure_mssg = \"%s\".\n", __func__, failure_mssg);
return EXIT_FAILURE;
} /* end if */
/* Set file space strategy to default or paged aggregation strategy */
if ((fcpl2_id = H5Pcopy(fcpl_id)) < 0) {
failure_mssg = "H5Pcreate(H5P_FILE_CREATE) failed.\n";
fprintf(stdout, "%s: failure_mssg = \"%s\".\n", __func__, failure_mssg);
return EXIT_FAILURE;
} /* end if */
if (H5Pset_file_space_strategy(fcpl2_id, H5F_FSPACE_STRATEGY_PAGE, 1, (hsize_t)1) < 0) {
failure_mssg = "H5Pset_file_space_strategy() failed.\n";
fprintf(stdout, "%s: failure_mssg = \"%s\".\n", __func__, failure_mssg);
return EXIT_FAILURE;
} /* end if */
/* Test with paged aggregation enabled or not */
/* The "my_fcpl" passed to each test has the paged or non-paged strategy set up accordingly */
for (paged = false; paged <= true; paged++) {
hid_t my_fcpl = fcpl_id;
if (paged) {
/* Only run paged aggregation tests with sec2/default driver */
if (!h5_using_default_driver(NULL))
continue;
else
my_fcpl = fcpl2_id;
}
if (!check_fapl_mdc_api_calls(paged, my_fcpl))
nerrs += 1;
if (!check_file_mdc_api_calls(paged, my_fcpl))
nerrs += 1;
if (!mdc_api_call_smoke_check(express_test, paged, my_fcpl))
nerrs += 1;
if (!check_file_mdc_api_errs(paged, my_fcpl))
nerrs += 1;
} /* end for paged */
if (!check_fapl_mdc_api_errs())
nerrs += 1;
if (invalid_configs)
free(invalid_configs);
if (H5Pclose(fcpl_id) < 0) {
failure_mssg = "H5Pclose() failed.\n";
fprintf(stdout, "%s: failure_mssg = \"%s\".\n", __func__, failure_mssg);
return EXIT_FAILURE;
} /* end if */
if (nerrs > 0)
return EXIT_FAILURE;
else
return EXIT_SUCCESS;
} /* main() */