diff options
author | John Mainzer <mainzer@hdfgroup.org> | 2006-10-18 10:51:26 (GMT) |
---|---|---|
committer | John Mainzer <mainzer@hdfgroup.org> | 2006-10-18 10:51:26 (GMT) |
commit | 2d6bb5932951242d23ccef420a328a033f3b4efa (patch) | |
tree | 3650df339b604f381873f55dcb24af501a83bd0b /test | |
parent | ce30ee9b28e9b68de817845aa5bc965d35ca8967 (diff) | |
download | hdf5-2d6bb5932951242d23ccef420a328a033f3b4efa.zip hdf5-2d6bb5932951242d23ccef420a328a033f3b4efa.tar.gz hdf5-2d6bb5932951242d23ccef420a328a033f3b4efa.tar.bz2 |
[svn-r12774] Modified flush code in the metadata cache to allow it to
handle flush callbacks which can dirty other entries, and
resize and/or rename the target entry.
This feature is needed by the fractal heap code.
Also added associated test code.
H5Commit tested. Test failed on heping, but the
error appears to be a syntax error in an un-related
file.
Tests on copper & sol passed, along with tests on
phoenix.
Diffstat (limited to 'test')
-rw-r--r-- | test/cache.c | 5429 | ||||
-rw-r--r-- | test/cache_common.c | 911 | ||||
-rw-r--r-- | test/cache_common.h | 215 |
3 files changed, 6501 insertions, 54 deletions
diff --git a/test/cache.c b/test/cache.c index 440b5e3..ac9d198 100644 --- a/test/cache.c +++ b/test/cache.c @@ -75,6 +75,19 @@ static void check_flush_cache__pinned_single_entry_test(H5C_t * cache_ptr, hbool_t expected_cleared, hbool_t expected_flushed, hbool_t expected_destroyed); +static void check_flush_cache__flush_ops(H5C_t * cache_ptr); +static void check_flush_cache__flush_op_test(H5C_t * cache_ptr, + int test_num, + unsigned int flush_flags, + int spec_size, + struct fo_flush_cache_test_spec spec[], + int init_expected_index_len, + size_t init_expected_index_size, + int expected_index_len, + size_t expected_index_size, + int check_size, + struct fo_flush_entry_check check[]); +static void check_flush_cache__flush_op_eviction_test(H5C_t * cache_ptr); static void check_flush_protected_err(void); static void check_get_entry_status(void); static void check_expunge_entry(void); @@ -2366,6 +2379,11 @@ check_flush_cache(void) if ( pass ) { + check_flush_cache__flush_ops(cache_ptr); + } + + if ( pass ) { + takedown_cache(cache_ptr, FALSE, FALSE); } @@ -4280,6 +4298,13 @@ check_flush_cache__multi_entry_test(H5C_t * cache_ptr, test_entry_t * base_addr; test_entry_t * entry_ptr; +#if 0 /* JRM */ + /* This gets used a lot, so lets leave it in. */ + + HDfprintf(stdout, "check_flush_cache__multi_entry_test: test %d\n", + test_num); +#endif /* JRM */ + if ( cache_ptr == NULL ) { pass = FALSE; @@ -4498,6 +4523,13 @@ check_flush_cache__pe_multi_entry_test(H5C_t * cache_ptr, test_entry_t * base_addr; test_entry_t * entry_ptr; +#if 0 /* JRM */ + /* This is useful debugging code. Leave it in for now. */ + + HDfprintf(stdout, "check_flush_cache__pe_multi_entry_test: test %d\n", + test_num); +#endif /* JRM */ + if ( cache_ptr == NULL ) { pass = FALSE; @@ -4697,6 +4729,5392 @@ check_flush_cache__pe_multi_entry_test(H5C_t * cache_ptr, /*------------------------------------------------------------------------- + * Function: check_flush_cache__flush_ops() + * + * Purpose: Run the flush ops cache tests. + * + * These are tests that test the cache's ability to handle + * the case in which the flush callback dirties, resizes, + * and/or renames entries. + * + * Do nothing if pass is FALSE on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 9/3/06 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +static void +check_flush_cache__flush_ops(H5C_t * cache_ptr) +{ + /* const char * fcn_name = "check_flush_cache__flush_ops"; */ + + if ( cache_ptr == NULL ) { + + pass = FALSE; + failure_mssg = "cache_ptr NULL on entry to flush ops test."; + } + else if ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) ) { + + pass = FALSE; + failure_mssg = "cache not empty at beginning of flush ops test."; + } + + if ( pass ) /* test #1 */ + { + /* start with a very simple test, in which there are two entries + * resident in cache, and the second entry dirties the first in + * the flush callback. No size changes, and no flush flags. + */ + int test_num = 1; + unsigned int flush_flags = H5C__NO_FLAGS_SET; + int spec_size = 2; + int init_expected_index_len = 2; + size_t init_expected_index_size = 2 * PICO_ENTRY_SIZE; + int expected_index_len = 2; + size_t expected_index_size = 2 * PICO_ENTRY_SIZE; + struct fo_flush_cache_test_spec spec[2] = + { + { + /* entry_num = */ 0, + /* entry_type = */ 0, + /* entry_index = */ 0, + /* insert_flag = */ FALSE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 0, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 1, + /* entry_type = */ 0, + /* entry_index = */ 1, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 1, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + } + }; + int check_size = 0; + struct fo_flush_entry_check checks[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ 0, + /* entry_index = */ 0, + /* expected_size = */ (size_t)0, + /* in_cache = */ FALSE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ FALSE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ FALSE, + /* expected_destroyed = */ FALSE + } + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + } + + if ( pass ) /* test #2 */ + { + /* Same as test 1, only this time set the flush invalidate flag. + * Note that we must repeat all tests with the flush invalidate flag + * as this triggers a different set of code to execute the flush. + * + * Create two entries resident in cache, and have the second entry + * dirty the first in the flush callback. + */ + int test_num = 2; + unsigned int flush_flags = H5C__FLUSH_INVALIDATE_FLAG; + int spec_size = 2; + int init_expected_index_len = 2; + size_t init_expected_index_size = 2 * PICO_ENTRY_SIZE; + int expected_index_len = 0; + size_t expected_index_size = 0; + struct fo_flush_cache_test_spec spec[2] = + { + { + /* entry_num = */ 0, + /* entry_type = */ PICO_ENTRY_TYPE, + /* entry_index = */ 0, + /* insert_flag = */ FALSE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 0, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 1, + /* entry_type = */ PICO_ENTRY_TYPE, + /* entry_index = */ 1, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 1, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, PICO_ENTRY_TYPE,0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + } + }; + int check_size = 0; + struct fo_flush_entry_check checks[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ 0, + /* entry_index = */ 0, + /* expected_size = */ (size_t)0, + /* in_cache = */ FALSE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ FALSE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ FALSE, + /* expected_destroyed = */ FALSE + } + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + } + + if ( pass ) /* test #3 */ + { + /* Single entry test verifying that the cache can handle the case in + * which the call back function resizes the entry for which it has + * been called. + */ + int test_num = 3; + unsigned int flush_flags = H5C__NO_FLAGS_SET; + int spec_size = 1; + int init_expected_index_len = 1; + size_t init_expected_index_size = VARIABLE_ENTRY_SIZE / 4; + int expected_index_len = 1; + size_t expected_index_size = VARIABLE_ENTRY_SIZE / 2; + struct fo_flush_cache_test_spec spec[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 0, + /* insert_flag = */ FALSE, + /* flags = */ H5C__SIZE_CHANGED_FLAG, + /* new_size = */ VARIABLE_ENTRY_SIZE / 4, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 1, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 0, FALSE, VARIABLE_ENTRY_SIZE / 2 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + } + }; + int check_size = 0; + struct fo_flush_entry_check checks[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ 0, + /* entry_index = */ 0, + /* expected_size = */ (size_t)0, + /* in_cache = */ FALSE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ FALSE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ FALSE, + /* expected_destroyed = */ FALSE + } + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + } + + if ( pass ) /* test #4 */ + { + /* Repeat test #4 with the flush invalidate flag. + * + * Single entry test verifying that the cache can handle the case in + * which the call back function resizes the entry for which it has + * been called. + */ + int test_num = 4; + unsigned int flush_flags = H5C__FLUSH_INVALIDATE_FLAG; + int spec_size = 1; + int init_expected_index_len = 1; + size_t init_expected_index_size = VARIABLE_ENTRY_SIZE / 4; + int expected_index_len = 0; + size_t expected_index_size = 0; + struct fo_flush_cache_test_spec spec[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 0, + /* insert_flag = */ FALSE, + /* flags = */ H5C__SIZE_CHANGED_FLAG, + /* new_size = */ VARIABLE_ENTRY_SIZE / 4, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 1, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 0, FALSE, VARIABLE_ENTRY_SIZE / 2 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + } + }; + int check_size = 0; + struct fo_flush_entry_check checks[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ 0, + /* entry_index = */ 0, + /* expected_size = */ (size_t)0, + /* in_cache = */ FALSE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ FALSE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ FALSE, + /* expected_destroyed = */ FALSE + } + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + } + + if ( pass ) /* test #5 & #6 */ + { + /* Single entry test verifying that the cache can handle the case in + * which the call back function renames the entry for which it has + * been called. + * + * Run this entry twice, as the first run moves the entry to its + * alternate address, and the second moves it back. + */ + int test_num = 5; /* and 6 */ + unsigned int flush_flags = H5C__NO_FLAGS_SET; + int spec_size = 1; + int init_expected_index_len = 1; + size_t init_expected_index_size = VARIABLE_ENTRY_SIZE; + int expected_index_len = 1; + size_t expected_index_size = VARIABLE_ENTRY_SIZE; + struct fo_flush_cache_test_spec spec[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 0, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 1, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + } + }; + int check_size = 0; + struct fo_flush_entry_check checks[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ 0, + /* entry_index = */ 0, + /* expected_size = */ (size_t)0, + /* in_cache = */ FALSE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ FALSE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ FALSE, + /* expected_destroyed = */ FALSE + } + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + + /* this change forces the rename to move the target entry back to its + * main address. The first test moved it to its alternate address. + * + * Note that these two tests are not the same, as in the first test, + * the renamed entry is moved forward in the slist. In the second + * it is moved backwards. + * + * Since there is only one entry in the cache, this doesn't really + * matter in this case. But we will do similar tests later with + * other entries in the cache. + */ + if ( pass ) { + + spec[0].flush_ops[0].flag = TRUE; + test_num = 6; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + } + } + + if ( pass ) /* test #7 & #8 */ + { + /* Run tests 5 & 6 again, using the flush invalidate flag on the + * second test. + * + * Single entry test verifying that the cache can handle the case in + * which the call back function renames the entry for which it has + * been called. + * + * Run this entry twice, as the first run moves the entry to its + * alternate address, and the second moves it back. + */ + int test_num = 7; /* and 8 */ + unsigned int flush_flags = H5C__NO_FLAGS_SET; + int spec_size = 1; + int init_expected_index_len = 1; + size_t init_expected_index_size = VARIABLE_ENTRY_SIZE; + int expected_index_len = 1; + size_t expected_index_size = VARIABLE_ENTRY_SIZE; + struct fo_flush_cache_test_spec spec[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 0, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 1, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + } + }; + int check_size = 0; + struct fo_flush_entry_check checks[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ 0, + /* entry_index = */ 0, + /* expected_size = */ (size_t)0, + /* in_cache = */ FALSE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ FALSE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ FALSE, + /* expected_destroyed = */ FALSE + } + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + + /* this change forces the rename to move the target entry back to its + * main address. The first test moved it to its alternate address. + * + * Note that these two tests are not the same, as in the first test, + * the renamed entry is moved forward in the slist. In the second + * it is moved backwards. + * + * Since there is only one entry in the cache, this doesn't really + * matter in this case. But we will do similar tests later with + * other entries in the cache. + */ + + if ( pass ) { + + test_num = 8; + flush_flags = H5C__FLUSH_INVALIDATE_FLAG; + expected_index_len = 0; + expected_index_size = 0; + spec[0].flush_ops[0].flag = TRUE; + spec[0].expected_destroyed = TRUE; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + } + } + + if ( pass ) /* test #9 & #10 */ + { + /* Single entry test verifying that the cache can handle the case in + * which the call back function both resizes and renames the entry + * for which it has been called. + * + * Again, we run this entry twice, as the first run moves the entry to its + * alternate address, and the second moves it back. + */ + int test_num = 9; /* and 10 */ + unsigned int flush_flags = H5C__NO_FLAGS_SET; + int spec_size = 1; + int init_expected_index_len = 1; + size_t init_expected_index_size = VARIABLE_ENTRY_SIZE / 2; + int expected_index_len = 1; + size_t expected_index_size = VARIABLE_ENTRY_SIZE / 4; + struct fo_flush_cache_test_spec spec[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 0, + /* insert_flag = */ FALSE, + /* flags = */ H5C__SIZE_CHANGED_FLAG, + /* new_size = */ VARIABLE_ENTRY_SIZE / 2, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 2, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 0, FALSE, VARIABLE_ENTRY_SIZE / 4 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + } + }; + int check_size = 0; + struct fo_flush_entry_check checks[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ 0, + /* entry_index = */ 0, + /* expected_size = */ (size_t)0, + /* in_cache = */ FALSE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ FALSE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ FALSE, + /* expected_destroyed = */ FALSE + } + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + + /* this change forces the rename to move the target entry back to its + * main address. The first test moved it to its alternate address. + * + * Note that these two tests are not the same, as in the first test, + * the renamed entry is moved forward in the slist. In the second + * it is moved backwards. + * + * Since there is only one entry in the cache, this doesn't really + * matter in this case. But we will do similar tests later with + * other entries in the cache. + */ + if ( pass ) { + + spec[0].flush_ops[0].flag = TRUE; + test_num = 10; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + } + } + + if ( pass ) /* test #11 & #12 */ + { + /* Repeat the previous test with the flush invalidate flag on the + * second test. + * + * Single entry test verifying that the cache can handle the case in + * which the call back function both resizes and renames the entry + * for which it has been called. + * + * Again, we run this entry twice, as the first run moves the entry to its + * alternate address, and the second moves it back. + */ + int test_num = 11; /* and 12 */ + unsigned int flush_flags = H5C__NO_FLAGS_SET; + int spec_size = 1; + int init_expected_index_len = 1; + size_t init_expected_index_size = VARIABLE_ENTRY_SIZE / 2; + int expected_index_len = 1; + size_t expected_index_size = VARIABLE_ENTRY_SIZE / 4; + struct fo_flush_cache_test_spec spec[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 0, + /* insert_flag = */ FALSE, + /* flags = */ H5C__SIZE_CHANGED_FLAG, + /* new_size = */ VARIABLE_ENTRY_SIZE / 2, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 2, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 0, FALSE, VARIABLE_ENTRY_SIZE / 4 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + } + }; + int check_size = 0; + struct fo_flush_entry_check checks[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ 0, + /* entry_index = */ 0, + /* expected_size = */ (size_t)0, + /* in_cache = */ FALSE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ FALSE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ FALSE, + /* expected_destroyed = */ FALSE + } + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + + /* this change forces the rename to move the target entry back to its + * main address. The first test moved it to its alternate address. + * + * Note that these two tests are not the same, as in the first test, + * the renamed entry is moved forward in the slist. In the second + * it is moved backwards. + * + * Since there is only one entry in the cache, this doesn't really + * matter in this case. But we will do similar tests later with + * other entries in the cache. + */ + if ( pass ) { + + test_num = 12; + flush_flags = H5C__FLUSH_INVALIDATE_FLAG; + expected_index_len = 0; + expected_index_size = 0; + spec[0].flush_ops[1].flag = TRUE; + spec[0].expected_destroyed = TRUE; + + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + } + } + + if ( pass ) /* test #13 */ + { + /* Test the ability of the cache to handle the case in which + * the flush function of an entry that is resident in cache + * dirties two entries that are not in cache. No size + * changes. + * + * At present, I am assured that this case will never occur, but + * lets make sure we can handle it regardless. + */ + int test_num = 13; + unsigned int flush_flags = H5C__NO_FLAGS_SET; + int spec_size = 1; + int init_expected_index_len = 1; + size_t init_expected_index_size = 1 * PICO_ENTRY_SIZE; + int expected_index_len = 3; + size_t expected_index_size = 3 * PICO_ENTRY_SIZE; + struct fo_flush_cache_test_spec spec[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ 0, + /* entry_index = */ 1, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 2, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, 0, 0, FALSE, 0 }, + { FLUSH_OP__DIRTY, 0, 2, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + } + }; + int check_size = 2; + struct fo_flush_entry_check checks[2] = + { + { + /* entry_num = */ 0, + /* entry_type = */ PICO_ENTRY_TYPE, + /* entry_index = */ 0, + /* expected_size = */ PICO_ENTRY_SIZE, + /* in_cache = */ TRUE, + /* at_main_addr = */ TRUE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 1, + /* entry_type = */ PICO_ENTRY_TYPE, + /* entry_index = */ 2, + /* expected_size = */ PICO_ENTRY_SIZE, + /* in_cache = */ TRUE, + /* at_main_addr = */ TRUE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + } + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + } + + if ( pass ) /* test #14 */ + { + /* Repeat previous test with the flush invalidate flag. + * + * Test the ability of the cache to handle the case in which + * the flush function of an entry that is resident in cache + * dirties two entries that are not in cache. No size + * changes. + * + * At present, I am assured that this case will never occur, but + * lets make sure we can handle it regardless. + */ + int test_num = 14; + unsigned int flush_flags = H5C__FLUSH_INVALIDATE_FLAG; + int spec_size = 1; + int init_expected_index_len = 1; + size_t init_expected_index_size = 1 * PICO_ENTRY_SIZE; + int expected_index_len = 0; + size_t expected_index_size = (size_t)0; + struct fo_flush_cache_test_spec spec[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ 0, + /* entry_index = */ 1, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 2, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, 0, 0, FALSE, 0 }, + { FLUSH_OP__DIRTY, 0, 2, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + } + }; + int check_size = 2; + struct fo_flush_entry_check checks[2] = + { + { + /* entry_num = */ 0, + /* entry_type = */ PICO_ENTRY_TYPE, + /* entry_index = */ 0, + /* expected_size = */ PICO_ENTRY_SIZE, + /* in_cache = */ FALSE, + /* at_main_addr = */ TRUE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 1, + /* entry_type = */ PICO_ENTRY_TYPE, + /* entry_index = */ 2, + /* expected_size = */ PICO_ENTRY_SIZE, + /* in_cache = */ FALSE, + /* at_main_addr = */ TRUE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + } + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + } + + if ( pass ) /* test #15 */ + { + /* Test the ability of the cache to handle the case in which + * the flush function of an entry that is resident in cache + * resizes and dirties two entries that are not in cache. + * + * At present, I am assured that this case will never occur, but + * lets make sure we can handle it regardless. + */ + int test_num = 15; + unsigned int flush_flags = H5C__NO_FLAGS_SET; + int spec_size = 1; + int init_expected_index_len = 1; + size_t init_expected_index_size = 1 * VARIABLE_ENTRY_SIZE; + int expected_index_len = 3; + size_t expected_index_size = VARIABLE_ENTRY_SIZE + + (VARIABLE_ENTRY_SIZE / 4) + + (VARIABLE_ENTRY_SIZE / 2); + struct fo_flush_cache_test_spec spec[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 1, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 4, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 0, FALSE, VARIABLE_ENTRY_SIZE / 4 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 0, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 2, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 2, FALSE, VARIABLE_ENTRY_SIZE / 2 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + } + }; + int check_size = 2; + struct fo_flush_entry_check checks[2] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 0, + /* expected_size = */ VARIABLE_ENTRY_SIZE / 4, + /* in_cache = */ TRUE, + /* at_main_addr = */ TRUE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 1, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 2, + /* expected_size = */ VARIABLE_ENTRY_SIZE / 2, + /* in_cache = */ TRUE, + /* at_main_addr = */ TRUE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + } + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + } + + if ( pass ) /* test #16 */ + { + /* Repeat previous test with the flush invalidate flag. + * + * Test the ability of the cache to handle the case in which + * the flush function of an entry that is resident in cache + * resizes and dirties two entries that are not in cache. + * + * At present, I am assured that this case will never occur, but + * lets make sure we can handle it regardless. + */ + int test_num = 16; + unsigned int flush_flags = H5C__FLUSH_INVALIDATE_FLAG; + int spec_size = 1; + int init_expected_index_len = 1; + size_t init_expected_index_size = 1 * VARIABLE_ENTRY_SIZE; + int expected_index_len = 0; + size_t expected_index_size = (size_t)0; + struct fo_flush_cache_test_spec spec[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 1, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 4, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 0, FALSE, VARIABLE_ENTRY_SIZE / 4 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 0, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 2, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 2, FALSE, VARIABLE_ENTRY_SIZE / 2 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + } + }; + int check_size = 2; + struct fo_flush_entry_check checks[2] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 0, + /* expected_size = */ VARIABLE_ENTRY_SIZE / 4, + /* in_cache = */ FALSE, + /* at_main_addr = */ TRUE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 1, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 2, + /* expected_size = */ VARIABLE_ENTRY_SIZE / 2, + /* in_cache = */ FALSE, + /* at_main_addr = */ TRUE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + } + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + } + + if ( pass ) /* test #17 & #18 */ + { + /* Test the ability of the cache to handle the case in which + * the flush function of an entry that is resident in cache + * resizes, dirties, and renames two entries that are not in cache. + * + * At present, I am assured that this case will never occur, but + * lets make sure we can handle it regardless. + */ + int test_num = 17; /* and 18 */ + unsigned int flush_flags = H5C__NO_FLAGS_SET; + int spec_size = 1; + int init_expected_index_len = 1; + size_t init_expected_index_size = 1 * VARIABLE_ENTRY_SIZE; + int expected_index_len = 3; + size_t expected_index_size = VARIABLE_ENTRY_SIZE + + (VARIABLE_ENTRY_SIZE / 4) + + (VARIABLE_ENTRY_SIZE / 2); + struct fo_flush_cache_test_spec spec[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 1, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 6, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 0, FALSE, VARIABLE_ENTRY_SIZE / 4 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 0, FALSE, 0 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 0, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 2, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 2, FALSE, VARIABLE_ENTRY_SIZE / 2 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 2, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + } + }; + int check_size = 2; + struct fo_flush_entry_check checks[2] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 0, + /* expected_size = */ VARIABLE_ENTRY_SIZE / 4, + /* in_cache = */ TRUE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 1, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 2, + /* expected_size = */ VARIABLE_ENTRY_SIZE / 2, + /* in_cache = */ TRUE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + } + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + + /* this change forces the renames to move the target entries back to + * their main address. The first test moved them to their alternate + * address. + * + * Note that these two tests are not the same, as in the first test, + * the renamed entries are moved forward in the slist. In the second + * they are moved backwards. + */ + if ( pass ) { + + test_num = 18; + spec[0].flush_ops[2].flag = TRUE; + spec[0].flush_ops[5].flag = TRUE; + checks[0].at_main_addr = TRUE; + checks[1].at_main_addr = TRUE; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + } + } + + if ( pass ) /* test #19 & #20 */ + { + /* Repeat the above test with the flush invalidate flag on the + * second test. + * + * Test the ability of the cache to handle the case in which + * the flush function of an entry that is resident in cache + * resizes, dirties, and renames two entries that are not in cache. + * + * At present, I am assured that this case will never occur, but + * lets make sure we can handle it regardless. + */ + int test_num = 19; /* and 20 */ + unsigned int flush_flags = H5C__NO_FLAGS_SET; + int spec_size = 1; + int init_expected_index_len = 1; + size_t init_expected_index_size = 1 * VARIABLE_ENTRY_SIZE; + int expected_index_len = 3; + size_t expected_index_size = VARIABLE_ENTRY_SIZE + + (VARIABLE_ENTRY_SIZE / 4) + + (VARIABLE_ENTRY_SIZE / 2); + struct fo_flush_cache_test_spec spec[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 1, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 6, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 0, FALSE, VARIABLE_ENTRY_SIZE / 4 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 0, FALSE, 0 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 0, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 2, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 2, FALSE, VARIABLE_ENTRY_SIZE / 2 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 2, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + } + }; + int check_size = 2; + struct fo_flush_entry_check checks[2] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 0, + /* expected_size = */ VARIABLE_ENTRY_SIZE / 4, + /* in_cache = */ TRUE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 1, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 2, + /* expected_size = */ VARIABLE_ENTRY_SIZE / 2, + /* in_cache = */ TRUE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + } + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + + /* this change forces the renames to move the target entries back to + * their main address. The first test moved them to their alternate + * address. + * + * Note that these two tests are not the same, as in the first test, + * the renamed entries are moved forward in the slist. In the second + * they are moved backwards. + */ + if ( pass ) { + + test_num = 20; + flush_flags = H5C__FLUSH_INVALIDATE_FLAG; + expected_index_len = 0; + expected_index_size = (size_t)0; + spec[0].expected_destroyed = TRUE; + spec[0].flush_ops[2].flag = TRUE; + spec[0].flush_ops[5].flag = TRUE; + checks[0].at_main_addr = TRUE; + checks[0].in_cache = FALSE; + checks[0].expected_destroyed = TRUE; + checks[1].at_main_addr = TRUE; + checks[1].in_cache = FALSE; + checks[1].expected_destroyed = TRUE; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + } + } + + if ( pass ) /* test #21 */ + { + /* Now mix things up a bit. + * + * Load several entries, two of which have flush functions that + * resize, dirty, and rename two entries that are not in the + * cache. Mark only one of these entries, and then flush the + * cache with the flush marked entries flag. + * + * This is the only test in which we test the + * H5C__FLUSH_MARKED_ENTRIES_FLAG. The hope is that since + * we test the two features extensively by themselves, so + * it should be sufficient to verify that they play together + * as expected. + */ + int test_num = 21; + unsigned int flush_flags = H5C__FLUSH_MARKED_ENTRIES_FLAG; + int spec_size = 4; + int init_expected_index_len = 4; + size_t init_expected_index_size = (2 * VARIABLE_ENTRY_SIZE) + (2 * PICO_ENTRY_SIZE); + int expected_index_len = 6; + size_t expected_index_size = (2 * VARIABLE_ENTRY_SIZE) + + (VARIABLE_ENTRY_SIZE / 4) + + (VARIABLE_ENTRY_SIZE / 2) + + (2 * PICO_ENTRY_SIZE); + struct fo_flush_cache_test_spec spec[4] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 1, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG | H5C__SET_FLUSH_MARKER_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 6, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 0, FALSE, VARIABLE_ENTRY_SIZE / 4 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 0, FALSE, 0 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 0, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 2, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 2, FALSE, VARIABLE_ENTRY_SIZE / 2 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 2, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 1, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 11, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 6, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 10, FALSE, VARIABLE_ENTRY_SIZE / 4 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 10, FALSE, 0 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 10, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 12, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 12, FALSE, VARIABLE_ENTRY_SIZE / 2 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 12, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ FALSE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 2, + /* entry_type = */ PICO_ENTRY_TYPE, + /* entry_index = */ 0, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG | H5C__SET_FLUSH_MARKER_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 0, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 3, + /* entry_type = */ PICO_ENTRY_TYPE, + /* entry_index = */ 1, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 0, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ FALSE, + /* expected_destroyed = */ FALSE + } + }; + int check_size = 4; + struct fo_flush_entry_check checks[4] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 0, + /* expected_size = */ VARIABLE_ENTRY_SIZE / 4, + /* in_cache = */ TRUE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ TRUE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ FALSE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 1, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 2, + /* expected_size = */ VARIABLE_ENTRY_SIZE / 2, + /* in_cache = */ TRUE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ TRUE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ FALSE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 2, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 10, + /* expected_size = */ VARIABLE_ENTRY_SIZE, + /* in_cache = */ FALSE, + /* at_main_addr = */ TRUE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ FALSE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ FALSE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 3, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 12, + /* expected_size = */ VARIABLE_ENTRY_SIZE, + /* in_cache = */ FALSE, + /* at_main_addr = */ TRUE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ FALSE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ FALSE, + /* expected_destroyed = */ FALSE + } + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + reset_entries(); + } + + if ( pass ) /* test #22 */ + { + /* Mix things up some more. + * + * Load lots of entries, some of which have flush functions that + * resize, dirty, and rename two entries that are not in the + * cache. + * + * Also load entries that have flush ops on entries that are in + * cache. + */ + int test_num = 22; + unsigned int flush_flags = H5C__NO_FLAGS_SET; + int spec_size = 6; + int init_expected_index_len = 6; + size_t init_expected_index_size = (2 * VARIABLE_ENTRY_SIZE) + (4 * PICO_ENTRY_SIZE); + int expected_index_len = 10; + size_t expected_index_size = (2 * VARIABLE_ENTRY_SIZE) + + (2 * (VARIABLE_ENTRY_SIZE / 4)) + + (2 * (VARIABLE_ENTRY_SIZE / 2)) + + (4 * PICO_ENTRY_SIZE); + struct fo_flush_cache_test_spec spec[6] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 1, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 6, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 0, FALSE, VARIABLE_ENTRY_SIZE / 4 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 0, FALSE, 0 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 0, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 2, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 2, FALSE, VARIABLE_ENTRY_SIZE / 2 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 2, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 1, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 11, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 6, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 10, FALSE, VARIABLE_ENTRY_SIZE / 4 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 10, FALSE, 0 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 10, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 12, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 12, FALSE, VARIABLE_ENTRY_SIZE / 2 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 12, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 2, + /* entry_type = */ PICO_ENTRY_TYPE, + /* entry_index = */ 0, + /* insert_flag = */ FALSE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 0, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 3, + /* entry_type = */ PICO_ENTRY_TYPE, + /* entry_index = */ 1, + /* insert_flag = */ FALSE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 0, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ FALSE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 4, + /* entry_type = */ PICO_ENTRY_TYPE, + /* entry_index = */ 10, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 1, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, PICO_ENTRY_TYPE, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 5, + /* entry_type = */ PICO_ENTRY_TYPE, + /* entry_index = */ 20, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 1, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, PICO_ENTRY_TYPE, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + } + }; + int check_size = 4; + struct fo_flush_entry_check checks[4] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 0, + /* expected_size = */ VARIABLE_ENTRY_SIZE / 4, + /* in_cache = */ TRUE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 1, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 2, + /* expected_size = */ VARIABLE_ENTRY_SIZE / 2, + /* in_cache = */ TRUE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 2, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 10, + /* expected_size = */ VARIABLE_ENTRY_SIZE / 4, + /* in_cache = */ TRUE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 3, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 12, + /* expected_size = */ VARIABLE_ENTRY_SIZE / 2, + /* in_cache = */ TRUE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + } + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + reset_entries(); + } + + if ( pass ) /* test #23 */ + { + /* Repeat test #23 with the flush invalidate flag set. + * + * Mix things up some more. + * + * Load lots of entries, some of which have flush functions that + * resize, dirty, and rename two entries that are not in the + * cache. + * + * Also load entries that have flush ops on entries that are in + * cache. + */ + int test_num = 23; + unsigned int flush_flags = H5C__FLUSH_INVALIDATE_FLAG; + int spec_size = 6; + int init_expected_index_len = 6; + size_t init_expected_index_size = (2 * VARIABLE_ENTRY_SIZE) + (4 * PICO_ENTRY_SIZE); + int expected_index_len = 0; + size_t expected_index_size = 0; + struct fo_flush_cache_test_spec spec[6] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 1, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 6, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 0, FALSE, VARIABLE_ENTRY_SIZE / 4 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 0, FALSE, 0 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 0, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 2, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 2, FALSE, VARIABLE_ENTRY_SIZE / 2 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 2, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 1, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 11, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 6, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 10, FALSE, VARIABLE_ENTRY_SIZE / 4 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 10, FALSE, 0 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 10, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 12, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 12, FALSE, VARIABLE_ENTRY_SIZE / 2 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 12, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 2, + /* entry_type = */ PICO_ENTRY_TYPE, + /* entry_index = */ 0, + /* insert_flag = */ FALSE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 0, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 3, + /* entry_type = */ PICO_ENTRY_TYPE, + /* entry_index = */ 1, + /* insert_flag = */ FALSE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 0, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 4, + /* entry_type = */ PICO_ENTRY_TYPE, + /* entry_index = */ 10, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 1, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, PICO_ENTRY_TYPE, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 5, + /* entry_type = */ PICO_ENTRY_TYPE, + /* entry_index = */ 20, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 1, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, PICO_ENTRY_TYPE, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + } + }; + int check_size = 4; + struct fo_flush_entry_check checks[4] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 0, + /* expected_size = */ VARIABLE_ENTRY_SIZE / 4, + /* in_cache = */ FALSE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 1, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 2, + /* expected_size = */ VARIABLE_ENTRY_SIZE / 2, + /* in_cache = */ FALSE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 2, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 10, + /* expected_size = */ VARIABLE_ENTRY_SIZE / 4, + /* in_cache = */ FALSE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 3, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 12, + /* expected_size = */ VARIABLE_ENTRY_SIZE / 2, + /* in_cache = */ FALSE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + } + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + reset_entries(); + } + + /* So much for tests involving only flush operations. + * + * Now create some tests mixing flush ops and pins. + */ + if ( pass ) /* test #24 */ + { + /* Pico entries 50 and 150 pin pico entry 100, and also dirty + * pico entry 100 on flush. + */ + int test_num = 24; + unsigned int flush_flags = H5C__NO_FLAGS_SET; + int spec_size = 3; + int init_expected_index_len = 3; + size_t init_expected_index_size = 3 * PICO_ENTRY_SIZE; + int expected_index_len = 3; + size_t expected_index_size = 3 * PICO_ENTRY_SIZE; + struct fo_flush_cache_test_spec spec[3] = + { + { + /* entry_num = */ 0, + /* entry_type = */ PICO_ENTRY_TYPE, + /* entry_index = */ 100, + /* insert_flag = */ FALSE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 0, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 1, + /* entry_type = */ PICO_ENTRY_TYPE, + /* entry_index = */ 50, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 1, + /* pin_type = */ {PICO_ENTRY_TYPE, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {100, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 1, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, PICO_ENTRY_TYPE, 100, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 2, + /* entry_type = */ PICO_ENTRY_TYPE, + /* entry_index = */ 150, + /* insert_flag = */ TRUE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 1, + /* pin_type = */ {PICO_ENTRY_TYPE, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {100, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 1, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, PICO_ENTRY_TYPE, 100, FALSE, 0 }, + { FLUSH_OP__DIRTY, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ FALSE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + } + }; + int check_size = 0; + struct fo_flush_entry_check checks[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ 0, + /* entry_index = */ 0, + /* expected_size = */ (size_t)0, + /* in_cache = */ FALSE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ FALSE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ FALSE, + /* expected_destroyed = */ FALSE + } + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + } + + if ( pass ) /* test #25 */ + { + /* Repeat the previous test with the flush invalidate flag. + * + * Pico entries 50 and 150 pin pico entry 100, and also dirty + * pico entry 100 on flush. + */ + int test_num = 25; + unsigned int flush_flags = H5C__FLUSH_INVALIDATE_FLAG; + int spec_size = 3; + int init_expected_index_len = 3; + size_t init_expected_index_size = 3 * PICO_ENTRY_SIZE; + int expected_index_len = 0; + size_t expected_index_size = (size_t)0; + struct fo_flush_cache_test_spec spec[3] = + { + { + /* entry_num = */ 0, + /* entry_type = */ PICO_ENTRY_TYPE, + /* entry_index = */ 100, + /* insert_flag = */ FALSE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 0, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 1, + /* entry_type = */ PICO_ENTRY_TYPE, + /* entry_index = */ 50, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 1, + /* pin_type = */ {PICO_ENTRY_TYPE, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {100, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 1, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, PICO_ENTRY_TYPE, 100, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 2, + /* entry_type = */ PICO_ENTRY_TYPE, + /* entry_index = */ 150, + /* insert_flag = */ TRUE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 1, + /* pin_type = */ {PICO_ENTRY_TYPE, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {100, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 1, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, PICO_ENTRY_TYPE, 100, FALSE, 0 }, + { FLUSH_OP__DIRTY, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ FALSE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + } + }; + int check_size = 0; + struct fo_flush_entry_check checks[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ 0, + /* entry_index = */ 0, + /* expected_size = */ (size_t)0, + /* in_cache = */ FALSE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ FALSE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ FALSE, + /* expected_destroyed = */ FALSE + } + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + } + + if ( pass ) /* test #26 */ + { + /* This one is complex. + * + * In the following overvies table, VET stands for + * VARIABLE_ENTRY_TYPE. + * + * In trying to follow what happens when we flush the + * set of entries constructed below, recall that each + * flush operation is executed the first time the + * entry is flushed, and then not executed again. + * This may be a weakness in the tests, but that + * is the way it is for now. + * + * After thinking about it for a while, I'm not sure that + * the interaction between pins and flush operations needs + * all that much testing, as the two are essentially + * orthoginal. Thus this is a bit of a smoke check to + * verify that we get the expected results. + * + * (VET, 100) initially not resident in cache + * + * (VET, 200) initially clean and resident in cache + * + * (VET, 300) initially not resident in cache + * + * (VET, 2100) initially clean and resident in cache + * + * (VET, 2200) initially not resident in cache + * + * (VET, 2300) initially clean and resident in cache + * + * (VET, 1000) initially clean, and in cache + * dirties (VET, 100) + * resizes (VET, 200) + * dirty (VET, 300) -- dirty first to bring into cache. + * renames (VET, 300) + * + * (VET, 2000) initially clean, and in cache + * dirties (VET, 2100) + * resizes (VET, 2200) + * renames (VET, 2300) + * + * (VET, 350) initially clean, and in cache + * pins (VET, 1000) + * dirties (VET, 1000) + * resizes (VET, 350) + * pins (VET, 2000) + * dirties (VET, 2000) + * + * (VET, 450) initially dirty, and in cache + * pins (VET, 1000) + * dirties (VET, 1000) + * renames (VET, 450) + * pins (VET, 2000) + * dirties (VET, 2000) + * + * (VET, 650) initially clean, and in cache + * pins (VET, 1000) + * dirties (VET, 1000) + * resizes (VET, 650) + * pins (VET, 2000) + * dirties (VET, 2000) + * + * (VET, 750) initially dirty, and in cache + * pins (VET, 1000) + * dirties (VET, 1000) + * resizes (VET, 750) + * pins (VET, 2000) + * dirties (VET, 2000) + * + * (VET, 500) initially dirty, and in cache + * dirties (VET, 350) + * dirties (VET, 450) + * dirties (VET, 650) + * dirties (VET, 750) + */ + int test_num = 26; + unsigned int flush_flags = H5C__NO_FLAGS_SET; + int spec_size = 10; + int init_expected_index_len = 10; + size_t init_expected_index_size = 10 * VARIABLE_ENTRY_SIZE; + int expected_index_len = 13; + size_t expected_index_size = 9 * VARIABLE_ENTRY_SIZE; + struct fo_flush_cache_test_spec spec[10] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 200, + /* insert_flag = */ FALSE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 0, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 1, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 2100, + /* insert_flag = */ FALSE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 0, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 2, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 2300, + /* insert_flag = */ TRUE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 0, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ FALSE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 3, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 1000, + /* insert_flag = */ TRUE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 4, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 100, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 200, FALSE, VARIABLE_ENTRY_SIZE / 2 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 300, FALSE, 0 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 300, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ FALSE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 4, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 2000, + /* insert_flag = */ FALSE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 3, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 2100, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 2200, FALSE, VARIABLE_ENTRY_SIZE / 2 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 2300, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 5, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 350, + /* insert_flag = */ FALSE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 2, + /* pin_type = */ {VARIABLE_ENTRY_TYPE, VARIABLE_ENTRY_TYPE, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {1000, 2000, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 3, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 1000, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 2000, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 350, FALSE, VARIABLE_ENTRY_SIZE / 4 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 6, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 450, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 2, + /* pin_type = */ {VARIABLE_ENTRY_TYPE, VARIABLE_ENTRY_TYPE, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {1000, 2000, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 3, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 1000, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 2000, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 450, FALSE, VARIABLE_ENTRY_SIZE / 4 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 7, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 650, + /* insert_flag = */ TRUE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 2, + /* pin_type = */ {VARIABLE_ENTRY_TYPE, VARIABLE_ENTRY_TYPE, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {1000, 2000, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 3, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 1000, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 2000, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 650, FALSE, VARIABLE_ENTRY_SIZE / 4 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ FALSE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 8, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 750, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 2, + /* pin_type = */ {VARIABLE_ENTRY_TYPE, VARIABLE_ENTRY_TYPE, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {1000, 2000, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 3, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 1000, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 2000, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 750, FALSE, VARIABLE_ENTRY_SIZE / 4 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 9, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 500, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 4, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 350, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 450, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 650, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 750, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + } + }; + int check_size = 3; + struct fo_flush_entry_check checks[3] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 100, + /* expected_size = */ VARIABLE_ENTRY_SIZE, + /* in_cache = */ TRUE, + /* at_main_addr = */ TRUE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 1, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 300, + /* expected_size = */ VARIABLE_ENTRY_SIZE, + /* in_cache = */ TRUE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 2, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 2200, + /* expected_size = */ VARIABLE_ENTRY_SIZE / 2, + /* in_cache = */ TRUE, + /* at_main_addr = */ TRUE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + } + + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + + reset_entries(); + } + + if ( pass ) /* test #27 */ + { + /* Repeat test #26 with the flush invalidate flag. + * + * In the following overview table, VET stands for + * VARIABLE_ENTRY_TYPE. + * + * In trying to follow what happens when we flush the + * set of entries constructed below, recall that each + * flush operation is executed the first time the + * entry is flushed, and then not executed again. + * This may be a weakness in the tests, but that + * is the way it is for now. + * + * After thinking about it for a while, I'm not sure that + * the interaction between pins and flush operations needs + * all that much testing, as the two are essentially + * orthoginal. The big thing is to verify that flushes of + * pinned entries with flush ops result in the expected + * updates of the cache. + * + * Thus this is a bit of a smoke check to * verify that we + * get the expected results. + * + * (VET, 100) initially not resident in cache + * + * (VET, 200) initially clean and resident in cache + * + * (VET, 300) initially not resident in cache + * + * (VET, 2100) initially clean and resident in cache + * + * (VET, 2200) initially not resident in cache + * + * (VET, 2300) initially clean and resident in cache + * + * (VET, 1000) initially clean, and in cache + * dirties (VET, 100) + * resizes (VET, 200) + * dirty (VET, 300) -- dirty first to bring into cache. + * renames (VET, 300) + * + * (VET, 2000) initially clean, and in cache + * dirties (VET, 2100) + * resizes (VET, 2200) + * renames (VET, 2300) + * + * (VET, 350) initially clean, and in cache + * pins (VET, 1000) + * dirties (VET, 1000) + * resizes (VET, 350) + * pins (VET, 2000) + * dirties (VET, 2000) + * + * (VET, 450) initially dirty, and in cache + * pins (VET, 1000) + * dirties (VET, 1000) + * renames (VET, 450) + * pins (VET, 2000) + * dirties (VET, 2000) + * + * (VET, 650) initially clean, and in cache + * pins (VET, 1000) + * dirties (VET, 1000) + * resizes (VET, 650) + * pins (VET, 2000) + * dirties (VET, 2000) + * + * (VET, 750) initially dirty, and in cache + * pins (VET, 1000) + * dirties (VET, 1000) + * resizes (VET, 750) + * pins (VET, 2000) + * dirties (VET, 2000) + * + * (VET, 500) initially dirty, and in cache + * dirties (VET, 350) + * dirties (VET, 450) + * dirties (VET, 650) + * dirties (VET, 750) + */ + int test_num = 27; + unsigned int flush_flags = H5C__FLUSH_INVALIDATE_FLAG; + int spec_size = 10; + int init_expected_index_len = 10; + size_t init_expected_index_size = 10 * VARIABLE_ENTRY_SIZE; + int expected_index_len = 0; + size_t expected_index_size = (size_t)0; + struct fo_flush_cache_test_spec spec[10] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 200, + /* insert_flag = */ FALSE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 0, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 1, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 2100, + /* insert_flag = */ FALSE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 0, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 2, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 2300, + /* insert_flag = */ TRUE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 0, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ FALSE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 3, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 1000, + /* insert_flag = */ TRUE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 4, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 100, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 200, FALSE, VARIABLE_ENTRY_SIZE / 2 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 300, FALSE, 0 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 300, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ FALSE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 4, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 2000, + /* insert_flag = */ FALSE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 3, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 2100, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 2200, FALSE, VARIABLE_ENTRY_SIZE / 2 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 2300, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 5, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 350, + /* insert_flag = */ FALSE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 2, + /* pin_type = */ {VARIABLE_ENTRY_TYPE, VARIABLE_ENTRY_TYPE, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {1000, 2000, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 3, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 1000, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 2000, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 350, FALSE, VARIABLE_ENTRY_SIZE / 4 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 6, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 450, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 2, + /* pin_type = */ {VARIABLE_ENTRY_TYPE, VARIABLE_ENTRY_TYPE, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {1000, 2000, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 3, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 1000, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 2000, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 450, FALSE, VARIABLE_ENTRY_SIZE / 4 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 7, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 650, + /* insert_flag = */ TRUE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 2, + /* pin_type = */ {VARIABLE_ENTRY_TYPE, VARIABLE_ENTRY_TYPE, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {1000, 2000, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 3, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 1000, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 2000, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 650, FALSE, VARIABLE_ENTRY_SIZE / 4 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ FALSE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 8, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 750, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 2, + /* pin_type = */ {VARIABLE_ENTRY_TYPE, VARIABLE_ENTRY_TYPE, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {1000, 2000, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 3, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 1000, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 2000, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 750, FALSE, VARIABLE_ENTRY_SIZE / 4 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 9, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 500, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 4, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 350, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 450, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 650, FALSE, 0 }, + { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 750, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + } + }; + int check_size = 3; + struct fo_flush_entry_check checks[3] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 100, + /* expected_size = */ VARIABLE_ENTRY_SIZE, + /* in_cache = */ FALSE, + /* at_main_addr = */ TRUE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 1, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 300, + /* expected_size = */ VARIABLE_ENTRY_SIZE, + /* in_cache = */ FALSE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 2, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 2200, + /* expected_size = */ VARIABLE_ENTRY_SIZE / 2, + /* in_cache = */ FALSE, + /* at_main_addr = */ TRUE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + } + + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + + reset_entries(); + } + + if ( pass ) /* test #28 */ + { + /* Test the expected fheap case, in which an entry dirties + * and resizes itself, and dirties an entry which it has + * pinned. + */ + int test_num = 28; + unsigned int flush_flags = H5C__NO_FLAGS_SET; + int spec_size = 5; + int init_expected_index_len = 5; + size_t init_expected_index_size = 3 * VARIABLE_ENTRY_SIZE; + int expected_index_len = 5; + size_t expected_index_size = 4 * VARIABLE_ENTRY_SIZE; + struct fo_flush_cache_test_spec spec[5] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 100, + /* insert_flag = */ FALSE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 0, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 1, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 200, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG | H5C__SIZE_CHANGED_FLAG, + /* new_size = */ VARIABLE_ENTRY_SIZE / 2, + /* num_pins = */ 1, + /* pin_type = */ {VARIABLE_ENTRY_TYPE, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {100, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 3, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 100, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 200, FALSE, VARIABLE_ENTRY_SIZE }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 200, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 2, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 300, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG | H5C__SIZE_CHANGED_FLAG, + /* new_size = */ VARIABLE_ENTRY_SIZE / 4, + /* num_pins = */ 1, + /* pin_type = */ {VARIABLE_ENTRY_TYPE, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {400, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 3, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 400, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 300, FALSE, VARIABLE_ENTRY_SIZE / 2 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 300, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 3, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 400, + /* insert_flag = */ FALSE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 0, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + }, + { + /* entry_num = */ 4, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 500, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG | H5C__SIZE_CHANGED_FLAG, + /* new_size = */ VARIABLE_ENTRY_SIZE / 4, + /* num_pins = */ 1, + /* pin_type = */ {VARIABLE_ENTRY_TYPE, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {100, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 3, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 100, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 500, FALSE, VARIABLE_ENTRY_SIZE / 2 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 500, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ FALSE + } + }; + int check_size = 0; + struct fo_flush_entry_check checks[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ 0, + /* entry_index = */ 0, + /* expected_size = */ 0, + /* in_cache = */ FALSE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ FALSE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ FALSE, + /* expected_destroyed = */ FALSE + } + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + + reset_entries(); + } + + if ( pass ) /* test #29 */ + { + /* Repeat test #28 with the flush invalidate flag. + * + * Test the expected fheap case, in which an entry dirties + * and resizes itself, and dirties an entry which it has + * pinned. + */ + int test_num = 29; + unsigned int flush_flags = H5C__FLUSH_INVALIDATE_FLAG; + int spec_size = 5; + int init_expected_index_len = 5; + size_t init_expected_index_size = 3 * VARIABLE_ENTRY_SIZE; + int expected_index_len = 0; + size_t expected_index_size = 0; + struct fo_flush_cache_test_spec spec[5] = + { + { + /* entry_num = */ 0, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 100, + /* insert_flag = */ FALSE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 0, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 1, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 200, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG | H5C__SIZE_CHANGED_FLAG, + /* new_size = */ VARIABLE_ENTRY_SIZE / 2, + /* num_pins = */ 1, + /* pin_type = */ {VARIABLE_ENTRY_TYPE, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {100, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 3, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 100, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 200, FALSE, VARIABLE_ENTRY_SIZE }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 200, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 2, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 300, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG | H5C__SIZE_CHANGED_FLAG, + /* new_size = */ VARIABLE_ENTRY_SIZE / 4, + /* num_pins = */ 1, + /* pin_type = */ {VARIABLE_ENTRY_TYPE, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {400, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 3, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 400, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 300, FALSE, VARIABLE_ENTRY_SIZE / 2 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 300, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 3, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 400, + /* insert_flag = */ FALSE, + /* flags = */ H5C__NO_FLAGS_SET, + /* new_size = */ 0, + /* num_pins = */ 0, + /* pin_type = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 0, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + }, + { + /* entry_num = */ 4, + /* entry_type = */ VARIABLE_ENTRY_TYPE, + /* entry_index = */ 500, + /* insert_flag = */ FALSE, + /* flags = */ H5C__DIRTIED_FLAG | H5C__SIZE_CHANGED_FLAG, + /* new_size = */ VARIABLE_ENTRY_SIZE / 4, + /* num_pins = */ 1, + /* pin_type = */ {VARIABLE_ENTRY_TYPE, 0, 0, 0, 0, 0, 0, 0}, + /* pin_idx = */ {100, 0, 0, 0, 0, 0, 0, 0}, + /* num_flush_ops = */ 3, + /* flush_ops = */ + /* op_code: type: idx: flag: size: */ + { { FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 100, FALSE, 0 }, + { FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 500, FALSE, VARIABLE_ENTRY_SIZE / 2 }, + { FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 500, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 }, + { FLUSH_OP__NO_OP, 0, 0, FALSE, 0 } }, + /* expected_loaded = */ TRUE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ TRUE, + /* expected_destroyed = */ TRUE + } + }; + int check_size = 0; + struct fo_flush_entry_check checks[1] = + { + { + /* entry_num = */ 0, + /* entry_type = */ 0, + /* entry_index = */ 0, + /* expected_size = */ 0, + /* in_cache = */ FALSE, + /* at_main_addr = */ FALSE, + /* is_dirty = */ FALSE, + /* is_protected = */ FALSE, + /* is_pinned = */ FALSE, + /* expected_loaded = */ FALSE, + /* expected_cleared = */ FALSE, + /* expected_flushed = */ FALSE, + /* expected_destroyed = */ FALSE + } + }; + + check_flush_cache__flush_op_test(cache_ptr, + test_num, + flush_flags, + spec_size, + spec, + init_expected_index_len, + init_expected_index_size, + expected_index_len, + expected_index_size, + check_size, + checks); + + reset_entries(); + } + + /* finally finish up with the flush ops eviction test */ + check_flush_cache__flush_op_eviction_test(cache_ptr); + + return; + +} /* check_flush_cache__flush_ops() */ + + +/*------------------------------------------------------------------------- + * Function: check_flush_cache__flush_op_test() + * + * Purpose: Run a flush op flush cache test. Of the nature of + * flush operations, this is a multi-entry test. + * + * Return: void + * + * Programmer: John Mainzer + * 9/3/06 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +static void +check_flush_cache__flush_op_test(H5C_t * cache_ptr, + int test_num, + unsigned int flush_flags, + int spec_size, + struct fo_flush_cache_test_spec spec[], + int init_expected_index_len, + size_t init_expected_index_size, + int expected_index_len, + size_t expected_index_size, + int check_size, + struct fo_flush_entry_check check[]) +{ + /* const char * fcn_name = "check_flush_cache__flush_op_test"; */ + static char msg[128]; + herr_t result; + int i; + int j; + test_entry_t * base_addr; + test_entry_t * entry_ptr; + +#if 0 /* This is useful debugging code -- lets keep it around. */ + HDfprintf(stdout, "check_flush_cache__flush_op_test: test %d\n", + test_num); +#endif + + if ( cache_ptr == NULL ) { + + pass = FALSE; + HDsnprintf(msg, (size_t)128, + "cache_ptr NULL on entry to flush op test #%d.", + test_num); + failure_mssg = msg; + } + else if ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) ) { + + pass = FALSE; + + HDsnprintf(msg, (size_t)128, + "cache not empty at beginning of flush op test #%d.", + test_num); + failure_mssg = msg; + } + else if ( ( spec_size < 1 ) || ( spec == NULL ) ) { + + pass = FALSE; + HDsnprintf(msg, (size_t)128, + "missing/bad test spec on entry to flush op test #%d.", + test_num); + failure_mssg = msg; + } + + i = 0; + while ( ( pass ) && ( i < spec_size ) ) + { + if ( ( spec[i].entry_num != i ) || + ( spec[i].entry_type < 0 ) || + ( spec[i].entry_type >= NUMBER_OF_ENTRY_TYPES ) || + ( spec[i].entry_index < 0 ) || + ( spec[i].entry_index > max_indices[spec[i].entry_type] ) || + ( spec[i].num_pins < 0 ) || + ( spec[i].num_pins > MAX_PINS ) || + ( spec[i].num_flush_ops < 0 ) || + ( spec[i].num_flush_ops > MAX_FLUSH_OPS ) ) { + + pass = FALSE; + HDsnprintf(msg, (size_t)128, + "bad data in spec[%d] on entry to flush op test #%d.", + i, test_num); + failure_mssg = msg; + } + i++; + } + + i = 0; + while ( ( pass ) && ( i < check_size ) ) + { + if ( ( check[i].entry_num != i ) || + ( check[i].entry_type < 0 ) || + ( check[i].entry_type >= NUMBER_OF_ENTRY_TYPES ) || + ( check[i].entry_index < 0 ) || + ( check[i].entry_index > max_indices[check[i].entry_type] ) || + ( check[i].expected_size <= (size_t)0 ) || + ( ( check[i].in_cache != TRUE ) && + ( check[i].in_cache != FALSE ) ) || + ( ( check[i].at_main_addr != TRUE ) && + ( check[i].at_main_addr != FALSE ) ) || + ( ( check[i].is_dirty != TRUE ) && + ( check[i].is_dirty != FALSE ) ) || + ( ( check[i].is_protected != TRUE ) && + ( check[i].is_protected != FALSE ) ) || + ( ( check[i].is_pinned != TRUE ) && + ( check[i].is_pinned != FALSE ) ) || + ( ( check[i].expected_loaded != TRUE ) && + ( check[i].expected_loaded != FALSE ) ) || + ( ( check[i].expected_cleared != TRUE ) && + ( check[i].expected_cleared != FALSE ) ) || + ( ( check[i].expected_flushed != TRUE ) && + ( check[i].expected_flushed != FALSE ) ) || + ( ( check[i].expected_destroyed != TRUE ) && + ( check[i].expected_destroyed != FALSE ) ) ) { + + pass = FALSE; + HDsnprintf(msg, (size_t)128, + "bad data in check[%d] on entry to flush op test #%d.", + i, test_num); + failure_mssg = msg; + } + i++; + } + + i = 0; + while ( ( pass ) && ( i < spec_size ) ) + { + if ( spec[i].insert_flag ) { + + insert_entry(cache_ptr, spec[i].entry_type, spec[i].entry_index, + TRUE, spec[i].flags); + + } else { + + protect_entry(cache_ptr, spec[i].entry_type, spec[i].entry_index); + + unprotect_entry_with_size_change(cache_ptr, spec[i].entry_type, + spec[i].entry_index, + spec[i].flags, spec[i].new_size); + } + + for ( j = 0; j < spec[i].num_pins; j++ ) + { + create_pinned_entry_dependency(cache_ptr, + spec[i].entry_type, + spec[i].entry_index, + spec[i].pin_type[j], + spec[i].pin_idx[j]); + } + + for ( j = 0; j < spec[i].num_flush_ops; j++ ) + { + add_flush_op(spec[i].entry_type, + spec[i].entry_index, + spec[i].flush_ops[j].op_code, + spec[i].flush_ops[j].type, + spec[i].flush_ops[j].idx, + spec[i].flush_ops[j].flag, + spec[i].flush_ops[j].size); + } + + i++; + } + + if ( pass ) { + + if ( ( cache_ptr->index_len != init_expected_index_len ) || + ( cache_ptr->index_size != init_expected_index_size ) ) { + + pass = FALSE; + HDsnprintf(msg, (size_t)128, + "Unexpected cache len/size before flush in flush op test #%d.", + test_num); + failure_mssg = msg; + } + } + + if ( pass ) { + + result = H5C_flush_cache(NULL, -1, -1, cache_ptr, flush_flags); + + if ( result < 0 ) { + + pass = FALSE; + HDsnprintf(msg, (size_t)128, + "flush with flags 0x%x failed in flush op test #%d.", + flush_flags, test_num); + failure_mssg = msg; + } + } + + + i = 0; + while ( ( pass ) && ( i < spec_size ) ) + { + base_addr = entries[spec[i].entry_type]; + entry_ptr = &(base_addr[spec[i].entry_index]); + + if ( ( entry_ptr->loaded != spec[i].expected_loaded ) || + ( entry_ptr->cleared != spec[i].expected_cleared ) || + ( entry_ptr->flushed != spec[i].expected_flushed ) || + ( entry_ptr->destroyed != spec[i].expected_destroyed ) ) { + +#if 0 /* This is useful debugging code. Lets keep it around. */ + + HDfprintf(stdout, + "loaded = %d(%d), clrd = %d(%d), flshd = %d(%d), dest = %d(%d)\n", + (int)(entry_ptr->loaded), + (int)(spec[i].expected_loaded), + (int)(entry_ptr->cleared), + (int)(spec[i].expected_cleared), + (int)(entry_ptr->flushed), + (int)(spec[i].expected_flushed), + (int)(entry_ptr->destroyed), + (int)(spec[i].expected_destroyed)); + + HDfprintf(stdout, "entry_ptr->header.is_dirty = %d\n", + (int)(entry_ptr->header.is_dirty)); +#endif + + pass = FALSE; + HDsnprintf(msg, (size_t)128, + "Bad status on entry %d after flush op test #%d.", + i, test_num); + failure_mssg = msg; + } + i++; + } + + if ( pass ) { + + i = 0; + while ( ( pass ) && ( i < check_size ) ) + { + if ( check[i].in_cache != entry_in_cache(cache_ptr, + check[i].entry_type, + check[i].entry_index) ) { + + pass = FALSE; + HDsnprintf(msg, (size_t)128, + "Check1 failed on entry %d after flush op test #%d.", + i, test_num); + failure_mssg = msg; + } + + base_addr = entries[check[i].entry_type]; + entry_ptr = &(base_addr[check[i].entry_index]); + + if ( ( entry_ptr->size != check[i].expected_size ) || + ( ( ! entry_ptr->header.destroy_in_progress ) && + ( check[i].in_cache ) && + ( entry_ptr->header.size != check[i].expected_size ) ) || + ( entry_ptr->at_main_addr != check[i].at_main_addr ) || + ( entry_ptr->is_dirty != check[i].is_dirty ) || + ( entry_ptr->header.is_dirty != check[i].is_dirty ) || + ( entry_ptr->is_protected != check[i].is_protected ) || + ( entry_ptr->header.is_protected != check[i].is_protected ) || + ( entry_ptr->is_pinned != check[i].is_pinned ) || + ( entry_ptr->header.is_pinned != check[i].is_pinned ) || + ( entry_ptr->loaded != check[i].expected_loaded ) || + ( entry_ptr->cleared != check[i].expected_cleared ) || + ( entry_ptr->flushed != check[i].expected_flushed ) || + ( entry_ptr->destroyed != check[i].expected_destroyed ) ) { + +#if 0 /* This is useful debugging code. Lets keep it around for a while. */ + + if ( entry_ptr->size != check[i].expected_size ) { + HDfprintf(stdout, "entry_ptr->size (expected) = %d (%d).\n", + (int)(entry_ptr->size), + (int)(check[i].expected_size)); + } + if ( ( ! entry_ptr->header.destroy_in_progress ) && + ( check[i].in_cache ) && + ( entry_ptr->header.size != check[i].expected_size ) ) { + HDfprintf(stdout, + "(!destroy in progress and in cache and size (expected) = %d (%d).\n", + (int)(entry_ptr->header.size), + (int)(check[i].expected_size)); + } + if ( entry_ptr->at_main_addr != check[i].at_main_addr ) { + HDfprintf(stdout, "(%d,%d) at main addr (expected) = %d (%d).\n", + (int)(check[i].entry_type), + (int)(check[i].entry_index), + (int)(entry_ptr->at_main_addr), + (int)(check[i].at_main_addr)); + } + if ( entry_ptr->is_dirty != check[i].is_dirty ) { + HDfprintf(stdout, "entry_ptr->is_dirty (expected) = %d (%d).\n", + (int)(entry_ptr->is_dirty), + (int)(check[i].is_dirty)); + } + if ( entry_ptr->header.is_dirty != check[i].is_dirty ) { + HDfprintf(stdout, "entry_ptr->header.is_dirty (expected) = %d (%d).\n", + (int)(entry_ptr->header.is_dirty), + (int)(check[i].is_dirty)); + } + if ( entry_ptr->is_protected != check[i].is_protected ) { + HDfprintf(stdout, "entry_ptr->is_protected (expected) = %d (%d).\n", + (int)(entry_ptr->is_protected), + (int)(check[i].is_protected)); + } + if ( entry_ptr->header.is_protected != check[i].is_protected ) { + HDfprintf(stdout, "entry_ptr->header.is_protected (expected) = %d (%d).\n", + (int)(entry_ptr->is_protected), + (int)(check[i].is_protected)); + } + if ( entry_ptr->is_pinned != check[i].is_pinned ) { + HDfprintf(stdout, "entry_ptr->is_pinned (expected) = %d (%d).\n", + (int)(entry_ptr->is_pinned), + (int)(check[i].is_pinned)); + } + if ( entry_ptr->header.is_pinned != check[i].is_pinned ) { + HDfprintf(stdout, "entry_ptr->header.is_pinned (expected) = %d (%d).\n", + (int)(entry_ptr->header.is_pinned), + (int)(check[i].is_pinned)); + } + if ( entry_ptr->loaded != check[i].expected_loaded ) { + HDfprintf(stdout, "entry_ptr->loaded (expected) = %d (%d).\n", + (int)(entry_ptr->loaded), + (int)(check[i].expected_loaded)); + } + if ( entry_ptr->cleared != check[i].expected_cleared ) { + HDfprintf(stdout, "entry_ptr->cleared (expected) = %d (%d).\n", + (int)(entry_ptr->cleared), + (int)(check[i].expected_cleared)); + } + if ( entry_ptr->flushed != check[i].expected_flushed ) { + HDfprintf(stdout, "entry_ptr->flushed (expected) = %d (%d).\n", + (int)(entry_ptr->flushed), + (int)(check[i].expected_flushed)); + } + if ( entry_ptr->destroyed != check[i].expected_destroyed ) { + HDfprintf(stdout, "entry_ptr->destroyed (expected) = %d (%d).\n", + (int)(entry_ptr->destroyed), + (int)(check[i].expected_destroyed)); + } +#endif + pass = FALSE; + HDsnprintf(msg, (size_t)128, + "Check2 failed on entry %d after flush op test #%d.", + i, test_num); + failure_mssg = msg; + } + i++; + } + } + + if ( pass ) { + + if ( ( ( (flush_flags & H5C__FLUSH_INVALIDATE_FLAG) == 0 ) + && + ( ( cache_ptr->index_len != expected_index_len ) + || + ( cache_ptr->index_size != expected_index_size ) + ) + ) + || + ( ( (flush_flags & H5C__FLUSH_INVALIDATE_FLAG) != 0 ) + && + ( ( cache_ptr->index_len != 0 ) + || + ( cache_ptr->index_size != 0 ) + ) + ) + ) { + + pass = FALSE; + HDsnprintf(msg, (size_t)128, + "Unexpected cache len/size after flush in flush op test #%d.", + test_num); + failure_mssg = msg; + } + } + + /* clean up the cache to prep for the next test */ + if ( pass ) { + + result = H5C_flush_cache(NULL, -1, -1, cache_ptr, + H5C__FLUSH_INVALIDATE_FLAG); + + if ( result < 0 ) { + + pass = FALSE; + HDsnprintf(msg, (size_t)128, + "Flush failed on cleanup in flush op test #%d.", + test_num); + failure_mssg = msg; + } + else if ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) ) { + + pass = FALSE; + HDsnprintf(msg, (size_t)128, + "Unexpected cache len/size after cleanup in flush op test #%d.", + test_num); + failure_mssg = msg; + + } + } + + i = 0; + while ( ( pass ) && ( i < spec_size ) ) + { + base_addr = entries[spec[i].entry_type]; + entry_ptr = &(base_addr[spec[i].entry_index]); + + entry_ptr->size = entry_sizes[spec[i].entry_type]; + + entry_ptr->loaded = FALSE; + entry_ptr->cleared = FALSE; + entry_ptr->flushed = FALSE; + entry_ptr->destroyed = FALSE; + + i++; + } + + i = 0; + while ( ( pass ) && ( i < check_size ) ) + { + base_addr = entries[check[i].entry_type]; + entry_ptr = &(base_addr[check[i].entry_index]); + + entry_ptr->size = entry_sizes[check[i].entry_type]; + + entry_ptr->loaded = FALSE; + entry_ptr->cleared = FALSE; + entry_ptr->flushed = FALSE; + entry_ptr->destroyed = FALSE; + + i++; + } + + return; + +} /* check_flush_cache__flush_op_test() */ + + +/*------------------------------------------------------------------------- + * Function: check_flush_cache__flush_op_eviction_test() + * + * Purpose: Verify that flush operations work as expected when an + * entry is evicted. + * + * Do nothing if pass is FALSE on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 10/3/06 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +static void +check_flush_cache__flush_op_eviction_test(H5C_t * cache_ptr) +{ + /* const char * fcn_name = "check_flush_cache__flush_op_eviction_test"; */ + int i; + int num_variable_entries = 8; + int num_monster_entries = 31; + int num_large_entries = 0; + herr_t result; + test_entry_t * entry_ptr; + test_entry_t * base_addr; + struct expected_entry_status expected[8 + 31 + 14] = + { + /* the expected array is used to maintain a table of the expected status of every + * entry used in this test. Note that since the function that processes this + * array only processes as much of it as it is told to, we don't have to + * worry about maintaining the status of entries that we haven't used yet. + */ + /* entry entry in at main */ + /* type: index: size: cache: addr: dirty: prot: pinned: loaded: clrd: flshd: dest: */ + { VARIABLE_ENTRY_TYPE, 0, VARIABLE_ENTRY_SIZE/2, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE }, + { VARIABLE_ENTRY_TYPE, 1, VARIABLE_ENTRY_SIZE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { VARIABLE_ENTRY_TYPE, 2, VARIABLE_ENTRY_SIZE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { VARIABLE_ENTRY_TYPE, 3, VARIABLE_ENTRY_SIZE/2, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { VARIABLE_ENTRY_TYPE, 4, VARIABLE_ENTRY_SIZE/2, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { VARIABLE_ENTRY_TYPE, 5, VARIABLE_ENTRY_SIZE/2, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { VARIABLE_ENTRY_TYPE, 6, VARIABLE_ENTRY_SIZE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { VARIABLE_ENTRY_TYPE, 7, VARIABLE_ENTRY_SIZE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 0, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 1, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 2, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 3, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 4, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 5, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 6, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 7, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 8, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 9, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 10, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 11, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 12, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 13, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 14, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 15, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 16, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 17, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 18, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 19, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 20, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 21, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 22, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 23, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 24, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 25, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 26, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 27, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 28, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 29, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { MONSTER_ENTRY_TYPE, 30, MONSTER_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { LARGE_ENTRY_TYPE, 0, LARGE_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { LARGE_ENTRY_TYPE, 1, LARGE_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { LARGE_ENTRY_TYPE, 2, LARGE_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { LARGE_ENTRY_TYPE, 3, LARGE_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { LARGE_ENTRY_TYPE, 4, LARGE_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { LARGE_ENTRY_TYPE, 5, LARGE_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { LARGE_ENTRY_TYPE, 6, LARGE_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { LARGE_ENTRY_TYPE, 7, LARGE_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { LARGE_ENTRY_TYPE, 8, LARGE_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { LARGE_ENTRY_TYPE, 9, LARGE_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { LARGE_ENTRY_TYPE, 10, LARGE_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { LARGE_ENTRY_TYPE, 11, LARGE_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { LARGE_ENTRY_TYPE, 12, LARGE_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { LARGE_ENTRY_TYPE, 13, LARGE_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE } + }; + + if ( cache_ptr == NULL ) { + + pass = FALSE; + failure_mssg = "cache_ptr NULL on entry to flush ops test."; + } + else if ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) ) { + + pass = FALSE; + failure_mssg = "cache not empty at start of flush ops eviction test."; + } + else if ( ( cache_ptr->max_cache_size != (2 * 1024 * 1024 ) ) || + ( cache_ptr->min_clean_size != (1 * 1024 * 1024 ) ) ) { + + pass = FALSE; + failure_mssg = "unexpected cache config at start of flush op eviction test."; + + } else { + + /* set min clean size to zero for this test as it simplifies + * computing the expected cache size after each operation. + */ + + cache_ptr->min_clean_size = 0; + } + + if ( pass ) { + + /* the basic idea in this test is to insert a bunch of entries + * with flush operations associated with them, and then load + * other entries into the cache until the cache is full. At + * that point, load yet more entries into the cache, and see + * if the flush operations are performed as expected. + * + * To make things a bit more interesting, we also include a + * couple of pins. + */ + + /* reset the stats before we start. If stats are enabled, we will + * check to see if they are as expected at the end. + */ + H5C_stats__reset(cache_ptr); + + + /* load a few entries with pin relationships and flush ops. + * Start by just loading the entries. + */ + + protect_entry(cache_ptr, VARIABLE_ENTRY_TYPE, 0); + unprotect_entry_with_size_change(cache_ptr, VARIABLE_ENTRY_TYPE, 0, + H5C__DIRTIED_FLAG | H5C__SIZE_CHANGED_FLAG, + (VARIABLE_ENTRY_SIZE / 2)); + + protect_entry(cache_ptr, VARIABLE_ENTRY_TYPE, 1); + unprotect_entry_with_size_change(cache_ptr, VARIABLE_ENTRY_TYPE, 1, + H5C__NO_FLAGS_SET, 0); + + protect_entry(cache_ptr, VARIABLE_ENTRY_TYPE, 2); + unprotect_entry_with_size_change(cache_ptr, VARIABLE_ENTRY_TYPE, 2, + H5C__NO_FLAGS_SET, 0); + + protect_entry(cache_ptr, VARIABLE_ENTRY_TYPE, 3); + unprotect_entry_with_size_change(cache_ptr, VARIABLE_ENTRY_TYPE, 3, + H5C__DIRTIED_FLAG | H5C__SIZE_CHANGED_FLAG, + (VARIABLE_ENTRY_SIZE / 2)); + + protect_entry(cache_ptr, VARIABLE_ENTRY_TYPE, 4); + unprotect_entry_with_size_change(cache_ptr, VARIABLE_ENTRY_TYPE, 4, + H5C__DIRTIED_FLAG | H5C__SIZE_CHANGED_FLAG, + (VARIABLE_ENTRY_SIZE / 2)); + + protect_entry(cache_ptr, VARIABLE_ENTRY_TYPE, 5); + unprotect_entry_with_size_change(cache_ptr, VARIABLE_ENTRY_TYPE, 5, + H5C__DIRTIED_FLAG | H5C__SIZE_CHANGED_FLAG, + (VARIABLE_ENTRY_SIZE / 2)); + + protect_entry(cache_ptr, VARIABLE_ENTRY_TYPE, 6); + unprotect_entry_with_size_change(cache_ptr, VARIABLE_ENTRY_TYPE, 6, + H5C__NO_FLAGS_SET, 0); + + protect_entry(cache_ptr, VARIABLE_ENTRY_TYPE, 7); + unprotect_entry_with_size_change(cache_ptr, VARIABLE_ENTRY_TYPE, 7, + H5C__NO_FLAGS_SET, 0); + + if ( ( cache_ptr->index_len != 8 ) || + ( cache_ptr->index_size != (4 * (VARIABLE_ENTRY_SIZE / 2)) + + (4 * VARIABLE_ENTRY_SIZE) ) ) { + + pass = FALSE; + failure_mssg = "unexpected size/len in flush op eviction test 1."; + } + } + + if ( pass ) { + + /* Now set up the pinning relationships: + * + * Briefly, (VET, 0) is pinned by (VET, 1), (VET, 2), and (VET, 3) + * (VET, 7) is pinned by (VET, 3), and (VET, 5) + */ + create_pinned_entry_dependency(cache_ptr, VARIABLE_ENTRY_TYPE, 1, + VARIABLE_ENTRY_TYPE, 0); + create_pinned_entry_dependency(cache_ptr, VARIABLE_ENTRY_TYPE, 2, + VARIABLE_ENTRY_TYPE, 0); + create_pinned_entry_dependency(cache_ptr, VARIABLE_ENTRY_TYPE, 3, + VARIABLE_ENTRY_TYPE, 0); + create_pinned_entry_dependency(cache_ptr, VARIABLE_ENTRY_TYPE, 3, + VARIABLE_ENTRY_TYPE, 7); + create_pinned_entry_dependency(cache_ptr, VARIABLE_ENTRY_TYPE, 5, + VARIABLE_ENTRY_TYPE, 7); + + /* Next, set up the flush operations: + * + * Briefly, (VET, 1) dirties (VET, 0) + * resizes (VET, 0) to 3/4 VARIABLE_ENTRY_SIZE + * + * (VET, 2) dirties (VET, 0) + * resizes (VET, 0) to VARIABLE_ENTRY_SIZE + * renames (VET, 0) to its alternate address + * + * (VET, 3) dirties (VET, 0) + * resizes itself to VARIABLE_ENTRY_SIZE + * + * (VET, 7) dirties (VET, 6) + */ + add_flush_op(VARIABLE_ENTRY_TYPE, 1, FLUSH_OP__DIRTY, + VARIABLE_ENTRY_TYPE, 0, FALSE, 0); + add_flush_op(VARIABLE_ENTRY_TYPE, 1, FLUSH_OP__RESIZE, + VARIABLE_ENTRY_TYPE, 0, FALSE, + 3 * VARIABLE_ENTRY_SIZE / 4); + + add_flush_op(VARIABLE_ENTRY_TYPE, 2, FLUSH_OP__DIRTY, + VARIABLE_ENTRY_TYPE, 0, FALSE, 0); + add_flush_op(VARIABLE_ENTRY_TYPE, 2, FLUSH_OP__RESIZE, + VARIABLE_ENTRY_TYPE, 0, FALSE, VARIABLE_ENTRY_SIZE); + add_flush_op(VARIABLE_ENTRY_TYPE, 2, FLUSH_OP__RENAME, + VARIABLE_ENTRY_TYPE, 0, FALSE, 0); + + add_flush_op(VARIABLE_ENTRY_TYPE, 3, FLUSH_OP__DIRTY, + VARIABLE_ENTRY_TYPE, 0, FALSE, 0); + add_flush_op(VARIABLE_ENTRY_TYPE, 3, FLUSH_OP__RESIZE, + VARIABLE_ENTRY_TYPE, 3, FALSE, VARIABLE_ENTRY_SIZE); + + add_flush_op(VARIABLE_ENTRY_TYPE, 7, FLUSH_OP__DIRTY, + VARIABLE_ENTRY_TYPE, 6, FALSE, 0); + } + + if ( pass ) { + + /* to summarize, at present the following variable size entries + * are in cache with the following characteristics: + * + * in + * entry: cache? size: dirty? pinned? pins: flush operations: + * + * (VET, 0) Y 5 KB Y Y - - + * + * (VET, 1) Y 10 KB N N 0 dirty (VET, 0), + * resize (VET, 0) to 7.5 KB + * + * (VET, 2) Y 10 KB N N 0 dirty (VET, 0) + * resize (VET, 0) to 10 KB + * rename (VET, 0) to its alternate address + * + * (VET, 3) Y 5 KB Y N 0, 7 dirty (VET, 0) + * resize (VET, 3) to 10 KB + * + * (VET, 4) Y 5 KB Y N - - + * + * (VET, 5) Y 5 KB Y N 7 - + * + * (VET, 6) Y 10 KB N N - - + * + * (VET, 7) Y 10 KB N Y - dirty (VET, 6) + * + * Recall that in this test bed, flush operations are excuted the + * first time the associated entry is flushed, and are then + * deleted. + */ + + /* Now fill up the cache with other, unrelated entries */ + for ( i = 0; i < 31; i++ ) + { + protect_entry(cache_ptr, MONSTER_ENTRY_TYPE, i); + unprotect_entry_with_size_change(cache_ptr, MONSTER_ENTRY_TYPE, i, + H5C__DIRTIED_FLAG, 0); + } + + for ( i = 0; i < 1; i++ ) + { + protect_entry(cache_ptr, LARGE_ENTRY_TYPE, i); + unprotect_entry_with_size_change(cache_ptr, LARGE_ENTRY_TYPE, i, + H5C__DIRTIED_FLAG, 0); + } + + /* The cache should now be exactly full */ + if ( ( cache_ptr->index_len != 40 ) || + ( cache_ptr->index_size != 2 * 1024 * 1024 ) || + ( cache_ptr->index_size != ((4 * VARIABLE_ENTRY_SIZE / 2) + + (4 * VARIABLE_ENTRY_SIZE) + + (31 * MONSTER_ENTRY_SIZE) + + (1 * LARGE_ENTRY_SIZE)) ) ) { + + pass = FALSE; + failure_mssg = "unexpected size/len in flush op eviction test 2."; + + } else { + + /* verify the expected status of all entries we have loaded to date: */ + num_large_entries = 1; + verify_entry_status(cache_ptr, + 0, + (num_variable_entries + num_monster_entries + num_large_entries), + expected); + } + } + + + if ( pass ) { + + /* Now load a large entry. This should result in the eviction + * of (VET,1), and the increase in the size of (VET, 0) from .5 + * VARIABLE_ENTRY_SIZE to .75 VARIABLE_ENTRY_SIZE. + * + * The following table illustrates the intended state of affairs + * after the eviction: + * + * in + * entry: cache? size: dirty? pinned? pins: flush operations: + * + * (VET, 0) Y 7.5 KB Y Y - - + * + * (VET, 1) N 10 KB N N - - + * + * (VET, 2) Y 10 KB N N 0 dirty (VET, 0) + * resize (VET, 0) to 10 KB + * rename (VET, 0) to its alternate address + * + * (VET, 3) Y 5 KB Y N 0, 7 dirty (VET, 0) + * resize (VET, 3) to 10 KB + * + * (VET, 4) Y 5 KB Y N - - + * + * (VET, 5) Y 5 KB Y N 7 - + * + * (VET, 6) Y 10 KB N N - - + * + * (VET, 7) Y 10 KB Y Y - dirty (VET, 6) + * + * Start by updating the expected table for the expected changes in entry status: + */ + expected[0].size = 3 * VARIABLE_ENTRY_SIZE / 4; + expected[1].in_cache = FALSE; + expected[1].flushed = TRUE; + expected[1].destroyed = TRUE; + + num_large_entries = 2; + + protect_entry(cache_ptr, LARGE_ENTRY_TYPE, 1); + unprotect_entry_with_size_change(cache_ptr, LARGE_ENTRY_TYPE, 1, + H5C__DIRTIED_FLAG, 0); + + if ( ( cache_ptr->index_len != 40 ) || + ( cache_ptr->index_size != (2 * 1024 * 1024) - + (VARIABLE_ENTRY_SIZE) + + (VARIABLE_ENTRY_SIZE / 4) + + (LARGE_ENTRY_SIZE) ) || + ( cache_ptr->index_size != ((1 * 3 * VARIABLE_ENTRY_SIZE / 4 ) + + (3 * VARIABLE_ENTRY_SIZE / 2 ) + + (3 * VARIABLE_ENTRY_SIZE) + + (31 * MONSTER_ENTRY_SIZE) + + (2 * LARGE_ENTRY_SIZE)) ) ) { + + pass = FALSE; + failure_mssg = "unexpected size/len in flush op eviction test 3."; + } + + /* verify entry status */ + verify_entry_status(cache_ptr, + 1, + (num_variable_entries + num_monster_entries + num_large_entries), + expected); + } + + if ( pass ) { + + /* Now load another large entry. This should result in the eviction + * of (VET, 2), the increase in the size of (VET, 0) from .75 + * VARIABLE_ENTRY_SIZE to 1.0 VARIABLE_ENTRY_SIZE, and the renaming + * of (VET, 0) to its alternate address. + * + * The following table shows the expected states of the variable + * size entries after the test. + * + * in + * entry: cache? size: dirty? pinned? pins: flush operations: + * + * (VET, 0) Y 10 KB Y Y - - + * + * (VET, 1) N 10 KB N N - - + * + * (VET, 2) N 10 KB N N - - + * + * (VET, 3) Y 5 KB Y N 0, 7 dirty (VET, 0) + * resize (VET, 3) to 10 KB + * + * (VET, 4) Y 5 KB Y N - - + * + * (VET, 5) Y 5 KB Y N 7 - + * + * (VET, 6) Y 10 KB N N - - + * + * (VET, 7) Y 10 KB Y Y - dirty (VET, 6) + * + * Start by updating the expected table for the expected changes in entry status: + */ + expected[0].size = VARIABLE_ENTRY_SIZE; + expected[0].at_main_addr = FALSE; + expected[2].in_cache = FALSE; + expected[2].flushed = TRUE; + expected[2].destroyed = TRUE; + + num_large_entries = 3; + + protect_entry(cache_ptr, LARGE_ENTRY_TYPE, 2); + unprotect_entry_with_size_change(cache_ptr, LARGE_ENTRY_TYPE, 2, + H5C__DIRTIED_FLAG, 0); + + if ( ( cache_ptr->index_len != 40 ) || + ( cache_ptr->index_size != (2 * 1024 * 1024) - + (2 * VARIABLE_ENTRY_SIZE) + + (VARIABLE_ENTRY_SIZE / 2) + + (2 * LARGE_ENTRY_SIZE) ) || + ( cache_ptr->index_size != ((3 * VARIABLE_ENTRY_SIZE / 2) + + (3 * VARIABLE_ENTRY_SIZE) + + (31 * MONSTER_ENTRY_SIZE) + + (3 * LARGE_ENTRY_SIZE)) ) ) { + + pass = FALSE; + failure_mssg = "unexpected size/len in flush op eviction test 4."; + } + + /* verify entry status */ + verify_entry_status(cache_ptr, + 2, + (num_variable_entries + num_monster_entries + num_large_entries), + expected); + } + + if ( pass ) { + + /* load two more large entries. This should result in (VET, 3) being + * flushed, and increasing its size from 1/2 VARIABLE_ENTRY_SIZE to + * VARIABLE_ENTRY_SIZE. + * + * As a result of this size increase, the cache will have to look + * for another entry to evict. After flushing (VET, 4) and (VET, 5), + * it should evict (VET, 6), yielding the needed memory. + * + * The following table shows the expected states of the variable + * size entries after the test. + * + * in + * entry: cache? size: dirty? pinned? pins: flush operations: + * + * (VET, 0) Y 10 KB Y Y - - + * + * (VET, 1) N 10 KB N N - - + * + * (VET, 2) N 10 KB N N - - + * + * (VET, 3) Y 10 KB N N 0, 7 - + * + * (VET, 4) Y 5 KB N N - - + * + * (VET, 5) Y 5 KB N N 7 - + * + * (VET, 6) N 10 KB N N - - + * + * (VET, 7) Y 10 KB Y Y - dirty (VET, 6) + * + * Start by updating the expected table for the expected changes in entry status: + */ + + expected[3].size = VARIABLE_ENTRY_SIZE; + expected[3].is_dirty = FALSE; + expected[3].flushed = TRUE; + expected[4].is_dirty = FALSE; + expected[4].flushed = TRUE; + expected[5].is_dirty = FALSE; + expected[5].flushed = TRUE; + expected[6].in_cache = FALSE; + expected[6].flushed = TRUE; + expected[6].destroyed = TRUE; + + num_large_entries = 5; + + protect_entry(cache_ptr, LARGE_ENTRY_TYPE, 3); + unprotect_entry_with_size_change(cache_ptr, LARGE_ENTRY_TYPE, 3, + H5C__DIRTIED_FLAG, 0); + + protect_entry(cache_ptr, LARGE_ENTRY_TYPE, 4); + unprotect_entry_with_size_change(cache_ptr, LARGE_ENTRY_TYPE, 4, + H5C__DIRTIED_FLAG, 0); + + /* verify cache size */ + if ( ( cache_ptr->index_len != 41 ) || + ( cache_ptr->index_size != (2 * 1024 * 1024) - + (3 * VARIABLE_ENTRY_SIZE) + + (1 * VARIABLE_ENTRY_SIZE ) + /* size increases of (VET, 0) & (VET, 3) */ + (4 * LARGE_ENTRY_SIZE) ) || + ( cache_ptr->index_size != ((2 * VARIABLE_ENTRY_SIZE / 2) + + (3 * VARIABLE_ENTRY_SIZE) + + (31 * MONSTER_ENTRY_SIZE) + + (5 * LARGE_ENTRY_SIZE)) ) ) { + + pass = FALSE; + failure_mssg = "unexpected size/len in flush op eviction test 5."; + } + + /* verify entry status */ + verify_entry_status(cache_ptr, + 3, + (num_variable_entries + num_monster_entries + num_large_entries), + expected); + } + + if ( pass ) { + + /* now touch all the non VARIABLE_ENTRY_TYPE entries in the + * cache to bring all the VARIABLE_ENTRY_TYPE entries to the + * end of the LRU list. + * + * Note that we don't have to worry about (VET, 0) and (VET, 7) + * as they are pinned and thus not in the LRU list to begin with. + */ + for ( i = 0; i < 31; i++ ) + { + protect_entry(cache_ptr, MONSTER_ENTRY_TYPE, i); + unprotect_entry_with_size_change(cache_ptr, MONSTER_ENTRY_TYPE, i, + H5C__DIRTIED_FLAG, 0); + } + + for ( i = 0; i < 5; i++ ) + { + protect_entry(cache_ptr, LARGE_ENTRY_TYPE, i); + unprotect_entry_with_size_change(cache_ptr, LARGE_ENTRY_TYPE, i, + H5C__DIRTIED_FLAG, 0); + } + + /* verify cache size */ + if ( ( cache_ptr->index_len != 41 ) || + ( cache_ptr->index_size != (2 * 1024 * 1024) - + (2 * VARIABLE_ENTRY_SIZE) + + (4 * LARGE_ENTRY_SIZE) ) ) { + + pass = FALSE; + failure_mssg = "unexpected size/len in flush op eviction test 6."; + } + + /* verify entry status */ + verify_entry_status(cache_ptr, + 4, + (num_variable_entries + num_monster_entries + num_large_entries), + expected); + } + + if ( pass ) { + + /* Now load three more large entries. This should result + * in the eviction of (VET, 3), and the unpinning of (VET, 0) + * + * The following table shows the expected states of the variable + * size entries after the test. + * + * in + * entry: cache? size: dirty? pinned? pins: flush operations: + * + * (VET, 0) Y 10 KB Y N - - + * + * (VET, 1) N 10 KB N N - - + * + * (VET, 2) N 10 KB N N - - + * + * (VET, 3) N 10 KB N N - - + * + * (VET, 4) Y 5 KB N N - - + * + * (VET, 5) Y 5 KB N N 7 - + * + * (VET, 6) N 10 KB N N - - + * + * (VET, 7) Y 10 KB Y Y - dirty (VET, 6) + * + * Start by updating the expected table for the expected changes in entry status: + */ + + expected[0].is_pinned = FALSE; + expected[3].in_cache = FALSE; + expected[3].destroyed = TRUE; + + num_large_entries = 8; + + for ( i = 5; i < 8; i++ ) + { + protect_entry(cache_ptr, LARGE_ENTRY_TYPE, i); + unprotect_entry_with_size_change(cache_ptr, LARGE_ENTRY_TYPE, i, + H5C__DIRTIED_FLAG, 0); + } + + /* verify cache size */ + if ( ( cache_ptr->index_len != 43 ) || + ( cache_ptr->index_size != (2 * 1024 * 1024) - + (3 * VARIABLE_ENTRY_SIZE) + + (7 * LARGE_ENTRY_SIZE) ) || + ( cache_ptr->index_size != ((2 * VARIABLE_ENTRY_SIZE / 2) + + (2 * VARIABLE_ENTRY_SIZE) + + (31 * MONSTER_ENTRY_SIZE) + + (8 * LARGE_ENTRY_SIZE)) ) ) { + + pass = FALSE; + failure_mssg = "unexpected size/len in flush op eviction test 7."; + } + + /* verify entry status */ + verify_entry_status(cache_ptr, + 5, + (num_variable_entries + num_monster_entries + num_large_entries), + expected); + } + + if ( pass ) { + + /* load another large entry. (VET, 4) should be evicted. + * + * The following table shows the expected states of the variable + * size entries after the test. + * + * in + * entry: cache? size: dirty? pinned? pins: flush operations: + * + * (VET, 0) Y 10 KB Y N - - + * + * (VET, 1) N 10 KB N N - - + * + * (VET, 2) N 10 KB N N - - + * + * (VET, 3) N 10 KB N N - - + * + * (VET, 4) N 5 KB N N - - + * + * (VET, 5) Y 5 KB N N 7 - + * + * (VET, 6) N 10 KB N N - - + * + * (VET, 7) Y 10 KB Y Y - dirty (VET, 6) + * + * Start by updating the expected table for the expected changes in entry status: + */ + + expected[4].in_cache = FALSE; + expected[4].destroyed = TRUE; + + num_large_entries = 9; + + for ( i = 8; i < 9; i++ ) + { + protect_entry(cache_ptr, LARGE_ENTRY_TYPE, i); + unprotect_entry_with_size_change(cache_ptr, LARGE_ENTRY_TYPE, i, + H5C__DIRTIED_FLAG, 0); + } + + /* verify cache size */ + if ( ( cache_ptr->index_len != 43 ) || + ( cache_ptr->index_size != (2 * 1024 * 1024) - + (3 * VARIABLE_ENTRY_SIZE) - + (VARIABLE_ENTRY_SIZE / 2) + + (8 * LARGE_ENTRY_SIZE) ) || + ( cache_ptr->index_size != ((1 * VARIABLE_ENTRY_SIZE / 2) + + (2 * VARIABLE_ENTRY_SIZE) + + (31 * MONSTER_ENTRY_SIZE) + + (9 * LARGE_ENTRY_SIZE)) ) ) { + + pass = FALSE; + failure_mssg = "unexpected size/len in flush op eviction test 8."; + } + + /* verify entry status */ + verify_entry_status(cache_ptr, + 6, + (num_variable_entries + num_monster_entries + num_large_entries), + expected); + } + + if ( pass ) { + + /* Load another large entry. + * + * (VET, 5) should be evicted, and (VET, 7) should be unpinned. + * + * The following table shows the expected states of the variable + * size entries after the test. + * + * in + * entry: cache? size: dirty? pinned? pins: flush operations: + * + * (VET, 0) Y 10 KB Y N - - + * + * (VET, 1) N 10 KB N N - - + * + * (VET, 2) N 10 KB N N - - + * + * (VET, 3) N 10 KB N N - - + * + * (VET, 4) N 5 KB N N - - + * + * (VET, 5) N 5 KB N N - - + * + * (VET, 6) N 10 KB N N - - + * + * (VET, 7) Y 10 KB Y N - dirty (VET, 6) + * + * Start by updating the expected table for the expected changes in entry status: + */ + + expected[5].in_cache = FALSE; + expected[5].destroyed = TRUE; + expected[7].is_pinned = FALSE; + + num_large_entries = 10; + + for ( i = 9; i < 10; i++ ) + { + protect_entry(cache_ptr, LARGE_ENTRY_TYPE, i); + unprotect_entry_with_size_change(cache_ptr, LARGE_ENTRY_TYPE, i, + H5C__DIRTIED_FLAG, 0); + } + + /* verify cache size */ + if ( ( cache_ptr->index_len != 43 ) || + ( cache_ptr->index_size != (2 * 1024 * 1024) - + (4 * VARIABLE_ENTRY_SIZE) + + (9 * LARGE_ENTRY_SIZE) ) || + ( cache_ptr->index_size != ((2 * VARIABLE_ENTRY_SIZE) + + (31 * MONSTER_ENTRY_SIZE) + + (10 * LARGE_ENTRY_SIZE)) ) ) { + + pass = FALSE; + failure_mssg = "unexpected size/len in flush op eviction test 9."; + } + + /* verify entry status */ + verify_entry_status(cache_ptr, + 7, + (num_variable_entries + num_monster_entries + num_large_entries), + expected); + } + + if ( pass ) { + + /* Again, touch all the non VARIABLE_ENTRY_TYPE entries in the + * cache to bring all the VARIABLE_ENTRY_TYPE entries to the + * end of the LRU list. + * + * Both (VET, 0) and (VET, 7) have been unpinned, so they are + * now in the LRU list. + */ + for ( i = 0; i < 31; i++ ) + { + protect_entry(cache_ptr, MONSTER_ENTRY_TYPE, i); + unprotect_entry_with_size_change(cache_ptr, MONSTER_ENTRY_TYPE, i, + H5C__DIRTIED_FLAG, 0); + } + + for ( i = 0; i < 10; i++ ) + { + protect_entry(cache_ptr, LARGE_ENTRY_TYPE, i); + unprotect_entry_with_size_change(cache_ptr, LARGE_ENTRY_TYPE, i, + H5C__DIRTIED_FLAG, 0); + } + + /* verify cache size */ + if ( ( cache_ptr->index_len != 43 ) || + ( cache_ptr->index_size != (2 * 1024 * 1024) - + (4 * VARIABLE_ENTRY_SIZE) + + (9 * LARGE_ENTRY_SIZE) ) || + ( cache_ptr->index_size != ((2 * VARIABLE_ENTRY_SIZE) + + (31 * MONSTER_ENTRY_SIZE) + + (10 * LARGE_ENTRY_SIZE)) ) ) { + + pass = FALSE; + failure_mssg = "unexpected size/len in flush op eviction test 10."; + } + + /* verify entry status */ + verify_entry_status(cache_ptr, + 8, + (num_variable_entries + num_monster_entries + num_large_entries), + expected); + } + + if ( pass ) { + + /* load two more large entries. + * + * (VET, 0) should be flushed, but not evicted initially since it is dirty. + * + * (VET, 7) should be evicted, but (VET, 7) has an eviction operation that + * dirties (VET, 6). Since (VET, 6) is not in the cache, it will be loaded. + * Since this results in no net increase in free space, the cache will + * continue to attempt to create free space. + * + * The cache will then flush all the monster and large entries, but since they + * are all dirty, they will not be evicted. + * + * Finally, it will reach (VET, 0) again, and evict it on the second pass. + * This finally makes the necessary space. + * + * The following table shows the expected states of the variable + * size entries after the test. + * + * in + * entry: cache? size: dirty? pinned? pins: flush operations: + * + * (VET, 0) N 10 KB N N - - + * + * (VET, 1) N 10 KB N N - - + * + * (VET, 2) N 10 KB N N - - + * + * (VET, 3) N 10 KB N N - - + * + * (VET, 4) N 5 KB N N - - + * + * (VET, 5) N 5 KB N N - - + * + * (VET, 6) Y 10 KB Y N - - + * + * (VET, 7) N 10 KB N N - - + * + * Start by updating the expected table for the expected changes in entry status: + * + * Note that we reset the loaded, cleared, flushed, and destroyed fields of + * (VET,6) so we can track what is happening. + */ + base_addr = entries[VARIABLE_ENTRY_TYPE]; + entry_ptr = &(base_addr[6]); + entry_ptr->loaded = FALSE; + entry_ptr->cleared = FALSE; + entry_ptr->flushed = FALSE; + entry_ptr->destroyed = FALSE; + + expected[0].in_cache = FALSE; + expected[0].is_dirty = FALSE; + expected[0].flushed = TRUE; + expected[0].destroyed = TRUE; + expected[6].in_cache = TRUE; + expected[6].is_dirty = TRUE; + expected[6].loaded = TRUE; + expected[6].flushed = FALSE; + expected[6].destroyed = FALSE; + expected[7].in_cache = FALSE; + expected[7].flushed = TRUE; + expected[7].destroyed = TRUE; + + num_large_entries = 12; + + /* a newly loaded entry is not inserted in the cache until after space has been + * made for it. Thus (LET, 11) will not be flushed. + */ + for ( i = num_variable_entries; + i < num_variable_entries + num_monster_entries + num_large_entries - 1; + i++ ) + { + expected[i].is_dirty = FALSE; + expected[i].flushed = TRUE; + } + + for ( i = 10; i < 12; i++ ) + { + protect_entry(cache_ptr, LARGE_ENTRY_TYPE, i); + unprotect_entry_with_size_change(cache_ptr, LARGE_ENTRY_TYPE, i, + H5C__DIRTIED_FLAG, 0); + } + + /* verify cache size */ + if ( ( cache_ptr->index_len != 44 ) || + ( cache_ptr->index_size != (2 * 1024 * 1024) - + (5 * VARIABLE_ENTRY_SIZE) + + (11 * LARGE_ENTRY_SIZE) ) || + ( cache_ptr->index_size != ((1 * VARIABLE_ENTRY_SIZE) + + (31 * MONSTER_ENTRY_SIZE) + + (12 * LARGE_ENTRY_SIZE)) ) ) { + + pass = FALSE; + failure_mssg = "unexpected size/len in flush op eviction test 11."; + } + + /* verify entry status */ + verify_entry_status(cache_ptr, + 9, + (num_variable_entries + num_monster_entries + num_large_entries), + expected); + } + + if ( pass ) { + + /* Again, touch all the non VARIABLE_ENTRY_TYPE entries in the + * cache to bring the last remaining VARIABLE_ENTRY_TYPE entry to the + * end of the LRU list. + */ + for ( i = 0; i < num_monster_entries; i++ ) + { + protect_entry(cache_ptr, MONSTER_ENTRY_TYPE, i); + unprotect_entry_with_size_change(cache_ptr, MONSTER_ENTRY_TYPE, i, + H5C__DIRTIED_FLAG, 0); + } + + for ( i = 0; i < num_large_entries; i++ ) + { + protect_entry(cache_ptr, LARGE_ENTRY_TYPE, i); + unprotect_entry_with_size_change(cache_ptr, LARGE_ENTRY_TYPE, i, + H5C__DIRTIED_FLAG, 0); + } + + /* update the expected array to mark all these entries dirty again. */ + for ( i = num_variable_entries; + i < num_variable_entries + num_monster_entries + num_large_entries - 1; + i++ ) + { + expected[i].is_dirty = TRUE; + } + + /* verify cache size */ + if ( ( cache_ptr->index_len != 44 ) || + ( cache_ptr->index_size != (2 * 1024 * 1024) - + (5 * VARIABLE_ENTRY_SIZE) + + (11 * LARGE_ENTRY_SIZE) ) || + ( cache_ptr->index_size != ((1 * VARIABLE_ENTRY_SIZE) + + (31 * MONSTER_ENTRY_SIZE) + + (12 * LARGE_ENTRY_SIZE)) ) ) { + + pass = FALSE; + failure_mssg = "unexpected size/len in flush op eviction test 12."; + } + + /* verify entry status */ + verify_entry_status(cache_ptr, + 10, + (num_variable_entries + num_monster_entries + num_large_entries), + expected); + } + + if ( pass ) { + + /* Load two more large entries. + * + * Since (VET, 6) is dirty, at first this will just cause (VET, 6) to be flushed. + * + * But all other entries in the cache are dirty, so the cache will flush them all, + * and then evict (VET, 6) on the second pass. + * + * The following table shows the expected states of the variable + * size entries after the test. + * + * in + * entry: cache? size: dirty? pinned? pins: flush operations: + * + * (VET, 0) N 10 KB N N - - + * + * (VET, 1) N 10 KB N N - - + * + * (VET, 2) N 10 KB N N - - + * + * (VET, 3) N 10 KB N N - - + * + * (VET, 4) N 5 KB N N - - + * + * (VET, 5) N 5 KB N N - - + * + * (VET, 6) N 10 KB N N - - + * + * (VET, 7) N 10 KB N N - - + * + * Start by updating the expected table for the expected changes in entry status: + */ + + expected[6].in_cache = FALSE; + expected[6].is_dirty = FALSE; + expected[6].flushed = TRUE; + expected[6].destroyed = TRUE; + + num_large_entries = 14; + + /* a newly loaded entry is not inserted in the cache until after space has been + * made for it. Thus (LET, 13) will not be flushed. + */ + for ( i = num_variable_entries; + i < num_variable_entries + num_monster_entries + num_large_entries - 1; + i++ ) + { + expected[i].is_dirty = FALSE; + expected[i].flushed = TRUE; + } + + for ( i = 12; i < 14; i++ ) + { + protect_entry(cache_ptr, LARGE_ENTRY_TYPE, i); + unprotect_entry_with_size_change(cache_ptr, LARGE_ENTRY_TYPE, i, + H5C__DIRTIED_FLAG, 0); + } + + /* verify cache size */ + if ( ( cache_ptr->index_len != 45 ) || + ( cache_ptr->index_size != (2 * 1024 * 1024) - + (6 * VARIABLE_ENTRY_SIZE) + + (13 * LARGE_ENTRY_SIZE) ) || + ( cache_ptr->index_size != ((31 * MONSTER_ENTRY_SIZE) + + (14 * LARGE_ENTRY_SIZE)) ) ) { + + pass = FALSE; + failure_mssg = "unexpected size/len in flush op eviction test 13."; + } + + /* verify entry status */ + verify_entry_status(cache_ptr, + 11, + (num_variable_entries + num_monster_entries + num_large_entries), + expected); + } + + /* at this point we have cycled all the variable size entries through the cache. + * + * flush the cache and end the test. + */ + + if ( pass ) { + + result = H5C_flush_cache(NULL, -1, -1, cache_ptr, + H5C__FLUSH_INVALIDATE_FLAG); + + if ( result < 0 ) { + + pass = FALSE; + failure_mssg = "Cache flush invalidate failed after flush op eviction test"; + } + else if ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) ) { + + pass = FALSE; + failure_mssg = "Unexpected cache len/size after cleanup of flush op eviction test"; + + } + } + +#if H5C_COLLECT_CACHE_STATS + /* If we are collecting stats, check to see if we get the expected + * values. + * + * Testing the stats code is fairly new, but given the extent + * to which I find myself depending on the stats, I've decided + * to start testing the stats whenever it is convenient to do + * so. + */ + if ( pass ) { + + if ( ( cache_ptr->insertions[VARIABLE_ENTRY_TYPE] != 0 ) || + ( cache_ptr->pinned_insertions[VARIABLE_ENTRY_TYPE] != 0 ) || + ( cache_ptr->clears[VARIABLE_ENTRY_TYPE] != 0 ) || + ( cache_ptr->flushes[VARIABLE_ENTRY_TYPE] != 14 ) || + ( cache_ptr->evictions[VARIABLE_ENTRY_TYPE] != 9 ) || + ( cache_ptr->renames[VARIABLE_ENTRY_TYPE] != 1 ) || + ( cache_ptr->entry_flush_renames[VARIABLE_ENTRY_TYPE] != 0 ) || + ( cache_ptr->cache_flush_renames[VARIABLE_ENTRY_TYPE] != 0 ) || + ( cache_ptr->pins[VARIABLE_ENTRY_TYPE] != 2 ) || + ( cache_ptr->unpins[VARIABLE_ENTRY_TYPE] != 2 ) || + ( cache_ptr->dirty_pins[VARIABLE_ENTRY_TYPE] != 0 ) || + ( cache_ptr->pinned_flushes[VARIABLE_ENTRY_TYPE] != 0 ) || + ( cache_ptr->pinned_clears[VARIABLE_ENTRY_TYPE] != 0 ) || + ( cache_ptr->size_increases[VARIABLE_ENTRY_TYPE] != 3 ) || + ( cache_ptr->size_decreases[VARIABLE_ENTRY_TYPE] != 4 ) || + ( cache_ptr->entry_flush_size_changes[VARIABLE_ENTRY_TYPE] != 1 ) || + ( cache_ptr->cache_flush_size_changes[VARIABLE_ENTRY_TYPE] != 0 ) ) { + + pass = FALSE; + failure_mssg = "Unexpected variable size entry stats."; + } + } + + if ( pass ) { + + if ( ( cache_ptr->insertions[LARGE_ENTRY_TYPE] != 0 ) || + ( cache_ptr->pinned_insertions[LARGE_ENTRY_TYPE] != 0 ) || + ( cache_ptr->clears[LARGE_ENTRY_TYPE] != 0 ) || + ( cache_ptr->flushes[LARGE_ENTRY_TYPE] != 38 ) || + ( cache_ptr->evictions[LARGE_ENTRY_TYPE] != 14 ) || + ( cache_ptr->renames[LARGE_ENTRY_TYPE] != 0 ) || + ( cache_ptr->entry_flush_renames[LARGE_ENTRY_TYPE] != 0 ) || + ( cache_ptr->cache_flush_renames[LARGE_ENTRY_TYPE] != 0 ) || + ( cache_ptr->pins[LARGE_ENTRY_TYPE] != 0 ) || + ( cache_ptr->unpins[LARGE_ENTRY_TYPE] != 0 ) || + ( cache_ptr->dirty_pins[LARGE_ENTRY_TYPE] != 0 ) || + ( cache_ptr->pinned_flushes[LARGE_ENTRY_TYPE] != 0 ) || + ( cache_ptr->pinned_clears[LARGE_ENTRY_TYPE] != 0 ) || + ( cache_ptr->size_increases[LARGE_ENTRY_TYPE] != 0 ) || + ( cache_ptr->size_decreases[LARGE_ENTRY_TYPE] != 0 ) || + ( cache_ptr->entry_flush_size_changes[LARGE_ENTRY_TYPE] != 0 ) || + ( cache_ptr->cache_flush_size_changes[LARGE_ENTRY_TYPE] != 0 ) ) { + + pass = FALSE; + failure_mssg = "Unexpected monster entry stats."; + } + } + + if ( pass ) { + + if ( ( cache_ptr->insertions[MONSTER_ENTRY_TYPE] != 0 ) || + ( cache_ptr->pinned_insertions[MONSTER_ENTRY_TYPE] != 0 ) || + ( cache_ptr->clears[MONSTER_ENTRY_TYPE] != 0 ) || + ( cache_ptr->flushes[MONSTER_ENTRY_TYPE] != 93 ) || + ( cache_ptr->evictions[MONSTER_ENTRY_TYPE] != 31 ) || + ( cache_ptr->renames[MONSTER_ENTRY_TYPE] != 0 ) || + ( cache_ptr->entry_flush_renames[MONSTER_ENTRY_TYPE] != 0 ) || + ( cache_ptr->cache_flush_renames[MONSTER_ENTRY_TYPE] != 0 ) || + ( cache_ptr->pins[MONSTER_ENTRY_TYPE] != 0 ) || + ( cache_ptr->unpins[MONSTER_ENTRY_TYPE] != 0 ) || + ( cache_ptr->dirty_pins[MONSTER_ENTRY_TYPE] != 0 ) || + ( cache_ptr->pinned_flushes[MONSTER_ENTRY_TYPE] != 0 ) || + ( cache_ptr->pinned_clears[MONSTER_ENTRY_TYPE] != 0 ) || + ( cache_ptr->size_increases[MONSTER_ENTRY_TYPE] != 0 ) || + ( cache_ptr->size_decreases[MONSTER_ENTRY_TYPE] != 0 ) || + ( cache_ptr->entry_flush_size_changes[MONSTER_ENTRY_TYPE] != 0 ) || + ( cache_ptr->cache_flush_size_changes[MONSTER_ENTRY_TYPE] != 0 ) ) { + + pass = FALSE; + failure_mssg = "Unexpected monster entry stats."; + } + } +#endif /* H5C_COLLECT_CACHE_STATS */ + + if ( pass ) { + + reset_entries(); + } + + return; + +} /* check_flush_cache__flush_op_eviction_test() */ + + +/*------------------------------------------------------------------------- * Function: check_flush_cache__single_entry() * * Purpose: Verify that flush_cache behaves as expected when the cache @@ -6462,6 +11880,8 @@ check_flush_cache__single_entry_test(H5C_t * cache_ptr, ( entry_ptr->flushed != expected_flushed ) || ( entry_ptr->destroyed != expected_destroyed ) ) { +#if 0 /* This is useful debugging code -- lets keep it for a while */ + HDfprintf(stdout, "loaded = %d(%d), clrd = %d(%d), flshd = %d(%d), dest = %d(%d)\n", (int)(entry_ptr->loaded), @@ -6472,7 +11892,7 @@ check_flush_cache__single_entry_test(H5C_t * cache_ptr, (int)expected_flushed, (int)(entry_ptr->destroyed), (int)expected_destroyed); - +#endif pass = FALSE; HDsnprintf(msg, (size_t)128, "Unexpected entry status after flush in single entry test #%d.", @@ -18740,6 +24160,10 @@ main(void) run_full_test = FALSE; #endif /* NDEBUG */ +#if 0 + run_full_test = TRUE; +#endif + #if 1 smoke_check_1(); smoke_check_2(); @@ -18750,7 +24174,7 @@ main(void) smoke_check_7(); smoke_check_8(); #endif -#if 1 + write_permitted_check(); check_insert_entry(); check_flush_cache(); @@ -18777,7 +24201,6 @@ main(void) check_auto_cache_resize_epoch_markers(); check_auto_cache_resize_input_errs(); check_auto_cache_resize_aux_fcns(); -#endif return(0); diff --git a/test/cache_common.c b/test/cache_common.c index 3e9b596..dc19ac2 100644 --- a/test/cache_common.c +++ b/test/cache_common.c @@ -41,6 +41,7 @@ test_entry_t medium_entries[NUM_MEDIUM_ENTRIES]; test_entry_t large_entries[NUM_LARGE_ENTRIES]; test_entry_t huge_entries[NUM_HUGE_ENTRIES]; test_entry_t monster_entries[NUM_MONSTER_ENTRIES]; +test_entry_t variable_entries[NUM_VARIABLE_ENTRIES]; test_entry_t * entries[NUMBER_OF_ENTRY_TYPES] = { @@ -52,7 +53,8 @@ test_entry_t * entries[NUMBER_OF_ENTRY_TYPES] = medium_entries, large_entries, huge_entries, - monster_entries + monster_entries, + variable_entries }; const int32_t max_indices[NUMBER_OF_ENTRY_TYPES] = @@ -65,7 +67,8 @@ const int32_t max_indices[NUMBER_OF_ENTRY_TYPES] = NUM_MEDIUM_ENTRIES - 1, NUM_LARGE_ENTRIES - 1, NUM_HUGE_ENTRIES - 1, - NUM_MONSTER_ENTRIES - 1 + NUM_MONSTER_ENTRIES - 1, + NUM_VARIABLE_ENTRIES - 1 }; const size_t entry_sizes[NUMBER_OF_ENTRY_TYPES] = @@ -78,7 +81,8 @@ const size_t entry_sizes[NUMBER_OF_ENTRY_TYPES] = MEDIUM_ENTRY_SIZE, LARGE_ENTRY_SIZE, HUGE_ENTRY_SIZE, - MONSTER_ENTRY_SIZE + MONSTER_ENTRY_SIZE, + VARIABLE_ENTRY_SIZE }; const haddr_t base_addrs[NUMBER_OF_ENTRY_TYPES] = @@ -91,7 +95,8 @@ const haddr_t base_addrs[NUMBER_OF_ENTRY_TYPES] = MEDIUM_BASE_ADDR, LARGE_BASE_ADDR, HUGE_BASE_ADDR, - MONSTER_BASE_ADDR + MONSTER_BASE_ADDR, + VARIABLE_BASE_ADDR }; const haddr_t alt_base_addrs[NUMBER_OF_ENTRY_TYPES] = @@ -104,7 +109,8 @@ const haddr_t alt_base_addrs[NUMBER_OF_ENTRY_TYPES] = MEDIUM_ALT_BASE_ADDR, LARGE_ALT_BASE_ADDR, HUGE_ALT_BASE_ADDR, - MONSTER_ALT_BASE_ADDR + MONSTER_ALT_BASE_ADDR, + VARIABLE_ALT_BASE_ADDR }; const char * entry_type_names[NUMBER_OF_ENTRY_TYPES] = @@ -117,7 +123,8 @@ const char * entry_type_names[NUMBER_OF_ENTRY_TYPES] = "medium entries -- 1 KB", "large entries -- 4 KB", "huge entries -- 16 KB", - "monster entries -- 64 KB" + "monster entries -- 64 KB", + "variable entries -- 1B - 10KB" }; @@ -196,13 +203,21 @@ const H5C_class_t types[NUMBER_OF_ENTRY_TYPES] = (H5C_dest_func_t)monster_dest, (H5C_clear_func_t)monster_clear, (H5C_size_func_t)monster_size + }, + { + VARIABLE_ENTRY_TYPE, + (H5C_load_func_t)variable_load, + (H5C_flush_func_t)variable_flush, + (H5C_dest_func_t)variable_dest, + (H5C_clear_func_t)variable_clear, + (H5C_size_func_t)variable_size } }; static herr_t clear(H5F_t * f, void * thing, hbool_t dest); static herr_t destroy(H5F_t * f, void * thing); static herr_t flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, - haddr_t addr, void *thing); + haddr_t addr, void *thing, unsigned UNUSED * flags_ptr); static void * load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1, void *udata2); static herr_t size(H5F_t * f, void * thing, size_t * size_ptr); @@ -267,18 +282,18 @@ addr_to_type_and_index(haddr_t addr, if ( addr >= PICO_ALT_BASE_ADDR ) { idx = (addr - alt_base_addrs[type]) / entry_sizes[type]; + HDassert( ( idx >= 0 ) && ( idx <= max_indices[type] ) ); HDassert( !((entries[type])[idx].at_main_addr) ); HDassert( addr == (entries[type])[idx].alt_addr ); } else { idx = (addr - base_addrs[type]) / entry_sizes[type]; + HDassert( ( idx >= 0 ) && ( idx <= max_indices[type] ) ); HDassert( (entries[type])[idx].at_main_addr ); HDassert( addr == (entries[type])[idx].main_addr ); } - HDassert( ( idx >= 0 ) && ( idx <= max_indices[type] ) ); - HDassert( addr == (entries[type])[idx].addr ); *type_ptr = type; @@ -388,6 +403,8 @@ check_write_permitted(const H5F_t UNUSED * f, * * Modifications: * + * Added variable_clear. -- JRM 8/30/06 + * *------------------------------------------------------------------------- */ @@ -410,7 +427,8 @@ clear(H5F_t * f, HDassert( entry_ptr == entry_ptr->self ); HDassert( entry_ptr->header.addr == entry_ptr->addr ); HDassert( entry_ptr->header.size == entry_ptr->size ); - HDassert( entry_ptr->size == entry_sizes[entry_ptr->type] ); + HDassert( ( entry_ptr->type == VARIABLE_ENTRY_TYPE ) || + ( entry_ptr->size == entry_sizes[entry_ptr->type] ) ); entry_ptr->header.is_dirty = FALSE; entry_ptr->is_dirty = FALSE; @@ -490,6 +508,14 @@ monster_clear(H5F_t * f, void * thing, hbool_t dest) return(clear(f, thing, dest)); } +herr_t +variable_clear(H5F_t * f, void * thing, hbool_t dest) +{ + HDassert ( ((test_entry_t *)thing)->type == VARIABLE_ENTRY_TYPE ); + return(clear(f, thing, dest)); +} + + /*------------------------------------------------------------------------- * Function: dest & friends @@ -510,6 +536,9 @@ monster_clear(H5F_t * f, void * thing, hbool_t dest) * pinned by the target entry, and to unpin those entries * if the reference count drops to zero. * + * JRM -- 8/30/06 + * Added variable_destroy(). + * *------------------------------------------------------------------------- */ @@ -534,9 +563,11 @@ destroy(H5F_t UNUSED * f, HDassert( entry_ptr == entry_ptr->self ); HDassert( entry_ptr->cache_ptr != NULL ); HDassert( entry_ptr->cache_ptr->magic == H5C__H5C_T_MAGIC ); - HDassert( entry_ptr->header.addr == entry_ptr->addr ); + HDassert( ( entry_ptr->header.destroy_in_progress ) || + ( entry_ptr->header.addr == entry_ptr->addr ) ); HDassert( entry_ptr->header.size == entry_ptr->size ); - HDassert( entry_ptr->size == entry_sizes[entry_ptr->type] ); + HDassert( ( entry_ptr->type == VARIABLE_ENTRY_TYPE ) || + ( entry_ptr->size == entry_sizes[entry_ptr->type] ) ); HDassert( !(entry_ptr->is_dirty) ); HDassert( !(entry_ptr->header.is_dirty) ); @@ -645,6 +676,13 @@ monster_dest(H5F_t * f, void * thing) return(destroy(f, thing)); } +herr_t +variable_dest(H5F_t * f, void * thing) +{ + HDassert ( ((test_entry_t *)thing)->type == VARIABLE_ENTRY_TYPE ); + return(destroy(f, thing)); +} + /*------------------------------------------------------------------------- * Function: flush & friends @@ -660,6 +698,12 @@ monster_dest(H5F_t * f, void * thing) * * Modifications: * + * JRM -- 8/30/06 + * Added variable_flush() and flags_ptr parameter. + * + * JRM -- 9/1/06 + * Added support for flush operations. + * *------------------------------------------------------------------------- */ @@ -668,8 +712,10 @@ flush(H5F_t *f, hid_t UNUSED dxpl_id, hbool_t dest, haddr_t addr, - void *thing) + void *thing, + unsigned * flags_ptr) { + int i; test_entry_t * entry_ptr; test_entry_t * base_addr; @@ -685,8 +731,26 @@ flush(H5F_t *f, HDassert( entry_ptr->header.addr == entry_ptr->addr ); HDassert( entry_ptr->addr == addr ); HDassert( entry_ptr->header.size == entry_ptr->size ); - HDassert( entry_ptr->size == entry_sizes[entry_ptr->type] ); + HDassert( ( entry_ptr->type == VARIABLE_ENTRY_TYPE ) || + ( entry_ptr->size == entry_sizes[entry_ptr->type] ) ); HDassert( entry_ptr->header.is_dirty == entry_ptr->is_dirty ); + HDassert( entry_ptr->cache_ptr != NULL ); + HDassert( entry_ptr->cache_ptr->magic == H5C__H5C_T_MAGIC ); + HDassert( entry_ptr->num_flush_ops >= 0 ); + HDassert( entry_ptr->num_flush_ops < MAX_FLUSH_OPS ); + + if ( entry_ptr->num_flush_ops > 0 ) { + + for ( i = 0; i < entry_ptr->num_flush_ops; i++ ) + { + execute_flush_op(entry_ptr->cache_ptr, + entry_ptr, + &((entry_ptr->flush_ops)[i]), + flags_ptr); + } + entry_ptr->num_flush_ops = 0; + entry_ptr->flush_op_self_resize_in_progress = FALSE; + } entry_ptr->flushed = TRUE; @@ -713,69 +777,87 @@ flush(H5F_t *f, } /* flush() */ -herr_t -pico_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, void *thing) +herr_t +pico_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, + void *thing, unsigned * flags_ptr) { HDassert ( ((test_entry_t *)thing)->type == PICO_ENTRY_TYPE ); - return(flush(f, dxpl_id, dest, addr, thing)); + return(flush(f, dxpl_id, dest, addr, thing, flags_ptr)); } herr_t -nano_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, void *thing) +nano_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, + void *thing, unsigned * flags_ptr) { HDassert ( ((test_entry_t *)thing)->type == NANO_ENTRY_TYPE ); - return(flush(f, dxpl_id, dest, addr, thing)); + return(flush(f, dxpl_id, dest, addr, thing, flags_ptr)); } herr_t -micro_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, void *thing) +micro_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, + void *thing, unsigned * flags_ptr) { HDassert ( ((test_entry_t *)thing)->type == MICRO_ENTRY_TYPE ); - return(flush(f, dxpl_id, dest, addr, thing)); + return(flush(f, dxpl_id, dest, addr, thing, flags_ptr)); } herr_t -tiny_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, void *thing) +tiny_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, + void *thing, unsigned * flags_ptr) { HDassert ( ((test_entry_t *)thing)->type == TINY_ENTRY_TYPE ); - return(flush(f, dxpl_id, dest, addr, thing)); + return(flush(f, dxpl_id, dest, addr, thing, flags_ptr)); } herr_t -small_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, void *thing) +small_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, + void *thing, unsigned * flags_ptr) { HDassert ( ((test_entry_t *)thing)->type == SMALL_ENTRY_TYPE ); - return(flush(f, dxpl_id, dest, addr, thing)); + return(flush(f, dxpl_id, dest, addr, thing, flags_ptr)); } herr_t -medium_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, void *thing) +medium_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, + void *thing, unsigned * flags_ptr) { HDassert ( ((test_entry_t *)thing)->type == MEDIUM_ENTRY_TYPE ); - return(flush(f, dxpl_id, dest, addr, thing)); + return(flush(f, dxpl_id, dest, addr, thing, flags_ptr)); } herr_t -large_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, void *thing) +large_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, + void *thing, unsigned * flags_ptr) { HDassert ( ((test_entry_t *)thing)->type == LARGE_ENTRY_TYPE ); - return(flush(f, dxpl_id, dest, addr, thing)); + return(flush(f, dxpl_id, dest, addr, thing, flags_ptr)); } herr_t -huge_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, void *thing) +huge_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, + void *thing, unsigned * flags_ptr) { HDassert ( ((test_entry_t *)thing)->type == HUGE_ENTRY_TYPE ); - return(flush(f, dxpl_id, dest, addr, thing)); + return(flush(f, dxpl_id, dest, addr, thing, flags_ptr)); } herr_t -monster_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, void *thing) +monster_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, + void *thing, unsigned * flags_ptr) { HDassert ( ((test_entry_t *)thing)->type == MONSTER_ENTRY_TYPE ); - return(flush(f, dxpl_id, dest, addr, thing)); + return(flush(f, dxpl_id, dest, addr, thing, flags_ptr)); +} + +herr_t +variable_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, + void *thing, unsigned * flags_ptr) +{ + HDassert ( ((test_entry_t *)thing)->type == VARIABLE_ENTRY_TYPE ); + return(flush(f, dxpl_id, dest, addr, thing, flags_ptr)); } + /*------------------------------------------------------------------------- * Function: load & friends @@ -791,6 +873,9 @@ monster_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, void *thing) * * Modifications: * + * JRM -- 8/30/06 + * Added variable_load(). + * *------------------------------------------------------------------------- */ @@ -819,7 +904,18 @@ load(H5F_t UNUSED *f, HDassert( entry_ptr->index <= max_indices[type] ); HDassert( entry_ptr == entry_ptr->self ); HDassert( entry_ptr->addr == addr ); - HDassert( entry_ptr->size == entry_sizes[type] ); +#if 1 /* JRM */ + if ( ! ( ( entry_ptr->type == VARIABLE_ENTRY_TYPE ) || + ( entry_ptr->size == entry_sizes[type] ) ) ) { + + HDfprintf(stdout, "entry type/index/size = %d/%d/%ld\n", + (int)(entry_ptr->type), + (int)(entry_ptr->index), + (long)(entry_ptr->size)); + } +#endif /* JRM */ + HDassert( ( entry_ptr->type == VARIABLE_ENTRY_TYPE ) || + ( entry_ptr->size == entry_sizes[type] ) ); entry_ptr->loaded = TRUE; @@ -895,6 +991,13 @@ monster_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, return(load(f, dxpl_id, addr, udata1, udata2)); } +void * +variable_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, + const void *udata1, void *udata2) +{ + return(load(f, dxpl_id, addr, udata1, udata2)); +} + /*------------------------------------------------------------------------- * Function: size & friends @@ -910,6 +1013,9 @@ monster_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, * * Modifications: * + * JRM -- 8/30/06 + * Added variable_size(). + * *------------------------------------------------------------------------- */ @@ -932,7 +1038,8 @@ size(H5F_t UNUSED * f, HDassert( entry_ptr == &(base_addr[entry_ptr->index]) ); HDassert( entry_ptr == entry_ptr->self ); HDassert( entry_ptr->header.addr == entry_ptr->addr ); - HDassert( entry_ptr->size == entry_sizes[entry_ptr->type] ); + HDassert( ( entry_ptr->type == VARIABLE_ENTRY_TYPE ) || \ + ( entry_ptr->size == entry_sizes[entry_ptr->type] ) ); *size_ptr = entry_ptr->size; @@ -1003,6 +1110,14 @@ monster_size(H5F_t * f, void * thing, size_t * size_ptr) return(size(f, thing, size_ptr)); } +herr_t +variable_size(H5F_t * f, void * thing, size_t * size_ptr) +{ + HDassert ( ((test_entry_t *)thing)->type == VARIABLE_ENTRY_TYPE ); + return(size(f, thing, size_ptr)); +} + + /**************************************************************************/ /**************************************************************************/ @@ -1011,6 +1126,72 @@ monster_size(H5F_t * f, void * thing, size_t * size_ptr) /**************************************************************************/ /*------------------------------------------------------------------------- + * Function: add_flush_op + * + * Purpose: Do noting if pass is FALSE on entry. + * + * Otherwise, add the specified flush operation to the + * target instance of test_entry_t. + * + * Return: void + * + * Programmer: John Mainzer + * 9/1/06 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +void +add_flush_op(int target_type, + int target_idx, + int op_code, + int type, + int idx, + hbool_t flag, + size_t new_size) +{ + int i; + test_entry_t * target_base_addr; + test_entry_t * target_entry_ptr; + + HDassert( ( 0 <= target_type ) && ( target_type < NUMBER_OF_ENTRY_TYPES ) ); + HDassert( ( 0 <= target_idx ) && + ( target_idx <= max_indices[target_type] ) ); + HDassert( ( 0 <= op_code ) && ( op_code <= FLUSH_OP__MAX_OP ) ); + HDassert( ( op_code != FLUSH_OP__RESIZE ) || + ( type == VARIABLE_ENTRY_TYPE ) ); + HDassert( ( 0 <= type ) && ( type < NUMBER_OF_ENTRY_TYPES ) ); + HDassert( ( 0 <= idx ) && ( idx <= max_indices[type] ) ); + HDassert( ( flag == TRUE ) || ( flag == FALSE ) ); + HDassert( new_size <= VARIABLE_ENTRY_SIZE ); + + if ( pass ) { + + target_base_addr = entries[target_type]; + target_entry_ptr = &(target_base_addr[target_idx]); + + HDassert( target_entry_ptr->index == target_idx ); + HDassert( target_entry_ptr->type == target_type ); + HDassert( target_entry_ptr == target_entry_ptr->self ); + HDassert( target_entry_ptr->num_flush_ops < MAX_FLUSH_OPS ); + + i = (target_entry_ptr->num_flush_ops)++; + (target_entry_ptr->flush_ops)[i].op_code = op_code; + (target_entry_ptr->flush_ops)[i].type = type; + (target_entry_ptr->flush_ops)[i].idx = idx; + (target_entry_ptr->flush_ops)[i].flag = flag; + (target_entry_ptr->flush_ops)[i].size = new_size; + + } + + return; + +} /* add_flush_op() */ + + +/*------------------------------------------------------------------------- * Function: create_pinned_entry_dependency * * Purpose: Do noting if pass is FALSE on entry. @@ -1093,6 +1274,194 @@ create_pinned_entry_dependency(H5C_t * cache_ptr, /*------------------------------------------------------------------------- + * Function: dirty_entry + * + * Purpose: Given a pointer to a cache, an entry type, and an index, + * dirty the target entry. + * + * If the dirty_pin parameter is true, verify that the + * target entry is in the cache and is pinned. If it + * isn't, scream and die. If it is, use the + * H5C_mark_pinned_entry_dirty() call to dirty it. + * + * Do nothing if pass is false on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 6/10/04 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +void +dirty_entry(H5C_t * cache_ptr, + int32_t type, + int32_t idx, + hbool_t dirty_pin) +{ + test_entry_t * base_addr; + test_entry_t * entry_ptr; + + HDassert( cache_ptr ); + HDassert( ( 0 <= type ) && ( type < NUMBER_OF_ENTRY_TYPES ) ); + HDassert( ( 0 <= idx ) && ( idx <= max_indices[type] ) ); + + if ( pass ) { + + if ( dirty_pin ) { + + if ( ! entry_in_cache(cache_ptr, type, idx) ) { + + pass = FALSE; + failure_mssg = "entry to be dirty pinned is not in cache."; + + } else { + + base_addr = entries[type]; + entry_ptr = &(base_addr[idx]); + + HDassert( entry_ptr->index == idx ); + HDassert( entry_ptr->type == type ); + HDassert( entry_ptr == entry_ptr->self ); + + if ( ! ( (entry_ptr->header).is_pinned ) ) { + + pass = FALSE; + failure_mssg = "entry to be dirty pinned is not pinned."; + + } else { + + mark_pinned_entry_dirty(cache_ptr, type, idx, FALSE, 0); + + } + } + } else { + + protect_entry(cache_ptr, type, idx); + unprotect_entry(cache_ptr, type, idx, TRUE, H5C__NO_FLAGS_SET); + } + } + + return; + +} /* dirty_entry() */ + + +/*------------------------------------------------------------------------- + * Function: execute_flush_op + * + * Purpose: Given a pointer to an instance of struct flush_op, execute + * it. + * + * Do nothing if pass is false on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 9/1/06 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +void +execute_flush_op(H5C_t * cache_ptr, + struct test_entry_t * entry_ptr, + struct flush_op * op_ptr, + unsigned * flags_ptr) +{ + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); + HDassert( entry_ptr != NULL ); + HDassert( entry_ptr = entry_ptr->self ); + HDassert( entry_ptr->header.addr == entry_ptr->addr ); + HDassert( ( entry_ptr->flush_op_self_resize_in_progress ) || + ( entry_ptr->header.size == entry_ptr->size ) ); + HDassert( op_ptr != NULL ); + HDassert( ( 0 <= entry_ptr->type ) && + ( entry_ptr->type < NUMBER_OF_ENTRY_TYPES ) ); + HDassert( ( 0 <= entry_ptr->index ) && + ( entry_ptr->index <= max_indices[entry_ptr->type] ) ); + HDassert( ( 0 <= op_ptr->type ) && + ( op_ptr->type < NUMBER_OF_ENTRY_TYPES ) ); + HDassert( ( 0 <= op_ptr->idx ) && + ( op_ptr->idx <= max_indices[op_ptr->type] ) ); + HDassert( ( op_ptr->flag == FALSE ) || ( op_ptr->flag == TRUE ) ); + HDassert( flags_ptr != NULL ); + + if ( pass ) { + + switch ( op_ptr->op_code ) + { + case FLUSH_OP__NO_OP: + break; + + case FLUSH_OP__DIRTY: + HDassert( ( entry_ptr->type != op_ptr->type ) || + ( entry_ptr->index != op_ptr->idx ) ); + + dirty_entry(cache_ptr, op_ptr->type, op_ptr->idx, op_ptr->flag); + break; + + case FLUSH_OP__RESIZE: + if ( ( entry_ptr->type == op_ptr->type ) && + ( entry_ptr->index == op_ptr->idx ) ) { + + /* the flush operation is acting on the entry to + * which it is attached. Handle this here: + */ + HDassert( entry_ptr->type == VARIABLE_ENTRY_TYPE ); + HDassert( op_ptr->size > 0 ); + HDassert( op_ptr->size <= VARIABLE_ENTRY_SIZE ); + + entry_ptr->size = op_ptr->size; + (*flags_ptr) |= H5C_CALLBACK__SIZE_CHANGED_FLAG; + entry_ptr->flush_op_self_resize_in_progress = TRUE; + + /* if the entry is in the process of being destroyed, + * set the header size to match the entry size so as + * to avoid a spurious failure in the destroy callback. + */ + if ( entry_ptr->header.destroy_in_progress ) { + + entry_ptr->header.size = entry_ptr->size; + } + + } else { + + /* change the size of some other entry */ + + resize_entry(cache_ptr, op_ptr->type, op_ptr->idx, + op_ptr->size, op_ptr->flag); + } + break; + + case FLUSH_OP__RENAME: + rename_entry(cache_ptr, op_ptr->type, op_ptr->idx, + op_ptr->flag); + break; + + default: + pass = FALSE; + failure_mssg = "Undefined flush op code."; + break; + } + } + + return; + +} /* execute_flush_op() */ + + +/*------------------------------------------------------------------------- * Function: entry_in_cache * * Purpose: Given a pointer to a cache, an entry type, and an index, @@ -1228,6 +1597,17 @@ reset_entries(void) base_addr[j].pin_idx[k] = -1; } + base_addr[j].num_flush_ops = 0; + for ( k = 0; k < MAX_FLUSH_OPS; k++ ) + { + base_addr[j].flush_ops[k].op_code = FLUSH_OP__NO_OP; + base_addr[j].flush_ops[k].type = -1; + base_addr[j].flush_ops[k].idx = -1; + base_addr[j].flush_ops[k].flag = FALSE; + base_addr[j].flush_ops[k].size = 0; + } + base_addr[j].flush_op_self_resize_in_progress = FALSE; + base_addr[j].loaded = FALSE; base_addr[j].cleared = FALSE; base_addr[j].flushed = FALSE; @@ -1244,6 +1624,91 @@ reset_entries(void) /*------------------------------------------------------------------------- + * Function: resize_entry + * + * Purpose: Given a pointer to a cache, an entry type, an index, and + * a size, set the size of the target entry to the size. Note + * that at present, the type of the entry must be + * VARIABLE_ENTRY_TYPE. + * + * If the resize_pin parameter is true, verify that the + * target entry is in the cache and is pinned. If it + * isn't, scream and die. If it is, use the + * H5C_mark_pinned_entry_dirty() call to resize it. + * + * Do nothing if pass is false on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 6/10/04 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +void +resize_entry(H5C_t * cache_ptr, + int32_t type, + int32_t idx, + size_t new_size, + hbool_t resize_pin) +{ + test_entry_t * base_addr; + test_entry_t * entry_ptr; + + HDassert( cache_ptr ); + HDassert( ( 0 <= type ) && ( type < NUMBER_OF_ENTRY_TYPES ) ); + HDassert( type == VARIABLE_ENTRY_TYPE ); + HDassert( ( 0 <= idx ) && ( idx <= max_indices[type] ) ); + HDassert( ( 0 < new_size ) && ( new_size <= entry_sizes[type] ) ); + + if ( pass ) { + + base_addr = entries[type]; + entry_ptr = &(base_addr[idx]); + + HDassert( entry_ptr->index == idx ); + HDassert( entry_ptr->type == type ); + HDassert( entry_ptr == entry_ptr->self ); + + if ( resize_pin ) { + + if ( ! entry_in_cache(cache_ptr, type, idx) ) { + + pass = FALSE; + failure_mssg = "entry to be resized pinned is not in cache."; + + } else { + + if ( ! ( (entry_ptr->header).is_pinned ) ) { + + pass = FALSE; + failure_mssg = "entry to be resized pinned is not pinned."; + + } else { + + mark_pinned_entry_dirty(cache_ptr, type, idx, + TRUE, new_size); + } + } + } else { + + protect_entry(cache_ptr, type, idx); + unprotect_entry_with_size_change(cache_ptr, type, idx, + H5C__SIZE_CHANGED_FLAG, new_size); + } + } + + return; + +} /* resize_entry() */ + + +/*------------------------------------------------------------------------- * Function: verify_clean * * Purpose: Verify that all cache entries are marked as clean. If any @@ -1282,7 +1747,8 @@ verify_clean(void) for ( j = 0; j <= max_index; j++ ) { - if ( ( base_addr[j].header.is_dirty ) || ( base_addr[j].is_dirty ) ) { + if ( ( base_addr[j].header.is_dirty ) || + ( base_addr[j].is_dirty ) ) { dirty_count++; } @@ -1302,6 +1768,248 @@ verify_clean(void) /*------------------------------------------------------------------------- + * Function: verify_entry_status + * + * Purpose: Verify that a list of entries have the expected status. + * If any discrepencies are found, set the failure message + * and set pass to FALSE. + * + * Do nothing if pass is FALSE on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 10/8/04 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +void +verify_entry_status(H5C_t * cache_ptr, + int tag, + int num_entries, + struct expected_entry_status expected[]) +{ + static char msg[128]; + hbool_t in_cache; + int i; + test_entry_t * entry_ptr; + test_entry_t * base_addr; + + i = 0; + while ( ( pass ) && ( i < num_entries ) ) + { + base_addr = entries[expected[i].entry_type]; + entry_ptr = &(base_addr[expected[i].entry_index]); + + if ( ( ! expected[i].in_cache ) && + ( ( expected[i].is_dirty ) || + ( expected[i].is_protected ) || + ( expected[i].is_pinned ) ) ) { + + pass = FALSE; + sprintf(msg, "Contradictory data in expected[%d].\n", i); + failure_mssg = msg; + } + + if ( pass ) { + + in_cache = entry_in_cache(cache_ptr, expected[i].entry_type, + expected[i].entry_index); + + if ( in_cache != expected[i].in_cache ) { + + pass = FALSE; + sprintf(msg, + "%d entry (%d, %d) in cache actual/expected = %d/%d.\n", + tag, + (int)expected[i].entry_type, + (int)expected[i].entry_index, + (int)in_cache, + (int)expected[i].in_cache); + failure_mssg = msg; + } + } + + if ( pass ) { + + if ( entry_ptr->size != expected[i].size ) { + + pass = FALSE; + sprintf(msg, + "%d entry (%d, %d) size actualexpected = %ld/%ld.\n", + tag, + (int)expected[i].entry_type, + (int)expected[i].entry_index, + (long)(entry_ptr->size), + (long)expected[i].size); + failure_mssg = msg; + } + } + + if ( ( pass ) && ( in_cache ) ) { + + if ( entry_ptr->header.size != expected[i].size ) { + + pass = FALSE; + sprintf(msg, + "%d entry (%d, %d) header size actual/expected = %ld/%ld.\n", + tag, + (int)expected[i].entry_type, + (int)expected[i].entry_index, + (long)(entry_ptr->header.size), + (long)expected[i].size); + failure_mssg = msg; + } + } + + if ( pass ) { + + if ( entry_ptr->at_main_addr != expected[i].at_main_addr ) { + + pass = FALSE; + sprintf(msg, + "%d entry (%d, %d) at main addr actual/expected = %d/%d.\n", + tag, + (int)expected[i].entry_type, + (int)expected[i].entry_index, + (int)(entry_ptr->at_main_addr), + (int)expected[i].at_main_addr); + failure_mssg = msg; + } + } + + if ( pass ) { + + if ( entry_ptr->is_dirty != expected[i].is_dirty ) { + + pass = FALSE; + sprintf(msg, + "%d entry (%d, %d) is_dirty actual/expected = %d/%d.\n", + tag, + (int)expected[i].entry_type, + (int)expected[i].entry_index, + (int)(entry_ptr->is_dirty), + (int)expected[i].is_dirty); + failure_mssg = msg; + } + } + + if ( ( pass ) && ( in_cache ) ) { + + if ( entry_ptr->header.is_dirty != expected[i].is_dirty ) { + + pass = FALSE; + sprintf(msg, + "%d entry (%d, %d) header is_dirty actual/expected = %d/%d.\n", + tag, + (int)expected[i].entry_type, + (int)expected[i].entry_index, + (int)(entry_ptr->header.is_dirty), + (int)expected[i].is_dirty); + failure_mssg = msg; + } + } + + if ( pass ) { + + if ( entry_ptr->is_protected != expected[i].is_protected ) { + + pass = FALSE; + sprintf(msg, + "%d entry (%d, %d) is_protected actual/expected = %d/%d.\n", + tag, + (int)expected[i].entry_type, + (int)expected[i].entry_index, + (int)(entry_ptr->is_protected), + (int)expected[i].is_protected); + failure_mssg = msg; + } + } + + if ( ( pass ) && ( in_cache ) ) { + + if ( entry_ptr->header.is_protected != expected[i].is_protected ) { + + pass = FALSE; + sprintf(msg, + "%d entry (%d, %d) header is_protected actual/expected = %d/%d.\n", + tag, + (int)expected[i].entry_type, + (int)expected[i].entry_index, + (int)(entry_ptr->header.is_protected), + (int)expected[i].is_protected); + failure_mssg = msg; + } + } + + if ( pass ) { + + if ( entry_ptr->is_pinned != expected[i].is_pinned ) { + + pass = FALSE; + sprintf(msg, + "%d entry (%d, %d) is_pinned actual/expected = %d/%d.\n", + tag, + (int)expected[i].entry_type, + (int)expected[i].entry_index, + (int)(entry_ptr->is_pinned), + (int)expected[i].is_pinned); + failure_mssg = msg; + } + } + + if ( ( pass ) && ( in_cache ) ) { + + if ( entry_ptr->header.is_pinned != expected[i].is_pinned ) { + + pass = FALSE; + sprintf(msg, + "%d entry (%d, %d) header is_pinned actual/expected = %d/%d.\n", + tag, + (int)expected[i].entry_type, + (int)expected[i].entry_index, + (int)(entry_ptr->header.is_pinned), + (int)expected[i].is_pinned); + failure_mssg = msg; + } + } + + if ( pass ) { + + if ( ( entry_ptr->loaded != expected[i].loaded ) || + ( entry_ptr->cleared != expected[i].cleared ) || + ( entry_ptr->flushed != expected[i].flushed ) || + ( entry_ptr->destroyed != expected[i].destroyed ) ) { + + pass = FALSE; + sprintf(msg, + "%d entry (%d,%d) loaded = %d(%d), clrd = %d(%d), flshd = %d(%d), dest = %d(%d)\n", + tag, + (int)expected[i].entry_type, + (int)expected[i].entry_index, + (int)(entry_ptr->loaded), + (int)(expected[i].loaded), + (int)(entry_ptr->cleared), + (int)(expected[i].cleared), + (int)(entry_ptr->flushed), + (int)(expected[i].flushed), + (int)(entry_ptr->destroyed), + (int)(expected[i].destroyed)); + failure_mssg = msg; + } + } + i++; + } /* while */ + + return; + +} /* verify_entry_status() */ + + +/*------------------------------------------------------------------------- * Function: verify_unprotected * * Purpose: Verify that no cache entries are marked as protected. If @@ -1649,8 +2357,7 @@ insert_entry(H5C_t * cache_ptr, pass = FALSE; failure_mssg = "error in H5C_insert()."; -#if 0 - /* This is useful debugging code. Lets keep it around. */ +#if 0 /* This is useful debugging code. Lets keep it around. */ HDfprintf(stdout, "result = %d\n", (int)result); HDfprintf(stdout, "entry_ptr->header.is_protected = %d\n", @@ -1934,7 +2641,9 @@ rename_entry(H5C_t * cache_ptr, if ( ! done ) { - if ( ( result < 0 ) || ( entry_ptr->header.addr != new_addr ) ) { + if ( ( result < 0 ) || + ( ( ! ( entry_ptr->header.destroy_in_progress ) ) && + ( entry_ptr->header.addr != new_addr ) ) ) { pass = FALSE; failure_mssg = "error in H5C_rename_entry()."; @@ -2241,6 +2950,130 @@ unprotect_entry(H5C_t * cache_ptr, /*------------------------------------------------------------------------- + * Function: unprotect_entry_with_size_change() + * + * Purpose: Version of unprotect_entry() that allow access to the new + * size change parameters in H5C_unprotect_entry() + * + * At present, only the sizes of VARIABLE_ENTRY_TYPE entries + * can be changed. Thus this function will scream and die + * if the H5C__SIZE_CHANGED_FLAG is set and the type is not + * VARIABLE_ENTRY_TYPE. + * + * Do nothing if pass is FALSE on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 8/31/06 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +void +unprotect_entry_with_size_change(H5C_t * cache_ptr, + int32_t type, + int32_t idx, + unsigned int flags, + size_t new_size) +{ + /* const char * fcn_name = "unprotect_entry_with_size_change()"; */ + herr_t result; + hbool_t dirty_flag_set; + hbool_t pin_flag_set; + hbool_t unpin_flag_set; + hbool_t size_changed_flag_set; + test_entry_t * base_addr; + test_entry_t * entry_ptr; + + if ( pass ) { + + HDassert( cache_ptr ); + HDassert( ( 0 <= type ) && ( type < NUMBER_OF_ENTRY_TYPES ) ); + HDassert( ( 0 <= idx ) && ( idx <= max_indices[type] ) ); + HDassert( new_size <= entry_sizes[type] ); + + base_addr = entries[type]; + entry_ptr = &(base_addr[idx]); + + HDassert( entry_ptr->index == idx ); + HDassert( entry_ptr->type == type ); + HDassert( entry_ptr == entry_ptr->self ); + HDassert( entry_ptr->cache_ptr == cache_ptr ); + HDassert( entry_ptr->header.is_protected ); + HDassert( entry_ptr->is_protected ); + + dirty_flag_set = ((flags & H5C__DIRTIED_FLAG) != 0 ); + pin_flag_set = ((flags & H5C__PIN_ENTRY_FLAG) != 0 ); + unpin_flag_set = ((flags & H5C__UNPIN_ENTRY_FLAG) != 0 ); + size_changed_flag_set = ((flags & H5C__SIZE_CHANGED_FLAG) != 0 ); + + HDassert ( ! ( pin_flag_set && unpin_flag_set ) ); + HDassert ( ( ! pin_flag_set ) || ( ! (entry_ptr->is_pinned) ) ); + HDassert ( ( ! unpin_flag_set ) || ( entry_ptr->is_pinned ) ); + HDassert ( ( ! size_changed_flag_set ) || ( new_size > 0 ) ); + HDassert ( ( ! size_changed_flag_set ) || + ( type == VARIABLE_ENTRY_TYPE ) ); + + entry_ptr->is_dirty = (entry_ptr->is_dirty || dirty_flag_set); + + if ( size_changed_flag_set ) { + + entry_ptr->is_dirty = TRUE; + entry_ptr->size = new_size; + } + + result = H5C_unprotect(NULL, -1, -1, cache_ptr, &(types[type]), + entry_ptr->addr, (void *)entry_ptr, + flags, new_size); + + if ( ( result < 0 ) || + ( entry_ptr->header.is_protected ) || + ( entry_ptr->header.type != &(types[type]) ) || + ( entry_ptr->size != entry_ptr->header.size ) || + ( entry_ptr->addr != entry_ptr->header.addr ) ) { + + pass = FALSE; + failure_mssg = "error in H5C_unprotect()."; + + } + else + { + entry_ptr->is_protected = FALSE; + + if ( pin_flag_set ) { + + HDassert ( entry_ptr->header.is_pinned ); + entry_ptr->is_pinned = TRUE; + + } else if ( unpin_flag_set ) { + + HDassert ( ! ( entry_ptr->header.is_pinned ) ); + entry_ptr->is_pinned = FALSE; + + } + } + + HDassert( ((entry_ptr->header).type)->id == type ); + + if ( ( flags & H5C__DIRTIED_FLAG ) != 0 + && ( (flags & H5C__DELETED_FLAG) == 0 ) ) { + + HDassert( entry_ptr->header.is_dirty ); + HDassert( entry_ptr->is_dirty ); + } + } + + return; + +} /* unprotect_entry_with_size_change() */ + + +/*------------------------------------------------------------------------- * Function: row_major_scan_forward() * * Purpose: Do a sequence of inserts, protects, unprotects, renames, diff --git a/test/cache_common.h b/test/cache_common.h index c6c2a32..460661a 100644 --- a/test/cache_common.h +++ b/test/cache_common.h @@ -43,8 +43,9 @@ #define LARGE_ENTRY_TYPE 6 #define HUGE_ENTRY_TYPE 7 #define MONSTER_ENTRY_TYPE 8 +#define VARIABLE_ENTRY_TYPE 9 -#define NUMBER_OF_ENTRY_TYPES 9 +#define NUMBER_OF_ENTRY_TYPES 10 #define PICO_ENTRY_SIZE (size_t)1 #define NANO_ENTRY_SIZE (size_t)4 @@ -55,6 +56,7 @@ #define LARGE_ENTRY_SIZE (size_t)(4 * 1024) #define HUGE_ENTRY_SIZE (size_t)(16 * 1024) #define MONSTER_ENTRY_SIZE (size_t)(64 * 1024) +#define VARIABLE_ENTRY_SIZE (size_t)(10 * 1024) #define NUM_PICO_ENTRIES (10 * 1024) #define NUM_NANO_ENTRIES (10 * 1024) @@ -65,6 +67,7 @@ #define NUM_LARGE_ENTRIES (10 * 1024) #define NUM_HUGE_ENTRIES (10 * 1024) #define NUM_MONSTER_ENTRIES (10 * 1024) +#define NUM_VARIABLE_ENTRIES (10 * 1024) #define MAX_ENTRIES (10 * 1024) @@ -85,9 +88,11 @@ (LARGE_ENTRY_SIZE * NUM_LARGE_ENTRIES)) #define MONSTER_BASE_ADDR (haddr_t)(HUGE_BASE_ADDR + \ (HUGE_ENTRY_SIZE * NUM_HUGE_ENTRIES)) - -#define PICO_ALT_BASE_ADDR (haddr_t)(MONSTER_BASE_ADDR + \ +#define VARIABLE_BASE_ADDR (haddr_t)(MONSTER_BASE_ADDR + \ (MONSTER_ENTRY_SIZE * NUM_MONSTER_ENTRIES)) + +#define PICO_ALT_BASE_ADDR (haddr_t)(VARIABLE_BASE_ADDR + \ + (VARIABLE_ENTRY_SIZE * NUM_VARIABLE_ENTRIES)) #define NANO_ALT_BASE_ADDR (haddr_t)(PICO_ALT_BASE_ADDR + \ (PICO_ENTRY_SIZE * NUM_PICO_ENTRIES)) #define MICRO_ALT_BASE_ADDR (haddr_t)(NANO_ALT_BASE_ADDR + \ @@ -104,10 +109,75 @@ (LARGE_ENTRY_SIZE * NUM_LARGE_ENTRIES)) #define MONSTER_ALT_BASE_ADDR (haddr_t)(HUGE_ALT_BASE_ADDR + \ (HUGE_ENTRY_SIZE * NUM_HUGE_ENTRIES)) +#define VARIABLE_ALT_BASE_ADDR (haddr_t)(MONSTER_ALT_BASE_ADDR + \ + (MONSTER_ENTRY_SIZE * NUM_MONSTER_ENTRIES)) #define MAX_PINS 8 /* Maximum number of entries that can be * directly pinned by a single entry. */ + +#define FLUSH_OP__NO_OP 0 +#define FLUSH_OP__DIRTY 1 +#define FLUSH_OP__RESIZE 2 +#define FLUSH_OP__RENAME 3 +#define FLUSH_OP__MAX_OP 3 + +#define MAX_FLUSH_OPS 10 /* Maximum number of flush operations + * that can be associated with a + * cache entry. + */ + +typedef struct flush_op +{ + int op_code; /* integer op code indicating the + * operation to be performed. At + * present it must be one of: + * + * FLUSH_OP__NO_OP + * FLUSH_OP__DIRTY + * FLUSH_OP__RESIZE + * FLUSH_OP__RENAME + */ + int type; /* type code of the cache entry that + * is the target of the operation. + * This value is passed into the + * function implementing the flush + * operation. + */ + int idx; /* index of the cache entry that + * is the target of the operation. + * This value is passed into the + * function implementing the flush + * operation. + */ + hbool_t flag; /* boolean flag passed into the + * function implementing the flush + * operation. The meaning of the + * flag is dependant upon the flush + * operation: + * + * FLUSH_OP__DIRTY: TRUE iff the + * target is pinned, and is to + * be dirtied via the + * H5C_mark_pinned_entry_dirty() + * call. + * + * FLUSH_OP__RESIZE: TRUE iff the + * target is pinned, and is to + * be resized via the + * H5C_mark_pinned_entry_dirty() + * call. + * + * FLUSH_OP__RENAME: TRUE iff the + * target is to be renamed to + * its main address. + */ + size_t size; /* New target size in the + * FLUSH_OP__RENAME operation. + * Unused elsewhere. + */ +} flush_op; + typedef struct test_entry_t { H5C_cache_entry_t header; /* entry data used by the cache @@ -172,6 +242,32 @@ typedef struct test_entry_t int pin_idx[MAX_PINS]; /* array of the indicies of * entries pinned by this entry. */ + int num_flush_ops; /* integer field containing the + * number of flush operations to + * be executed when the entry is + * flushed. This value must lie in + * the closed interval + * [0, MAX_FLUSH_OPS]. + */ + struct flush_op flush_ops[MAX_FLUSH_OPS]; /* Array of instances + * of struct flush_op detailing the + * flush operations (if any) that + * are to be executed when the entry + * is flushed from the cache. + * + * num_flush_ops contains the number + * of valid entries in this array. + */ + hbool_t flush_op_self_resize_in_progress; /* Boolean flag + * that is set to TRUE iff this + * entry is being flushed, it has + * been resized by a resize flush + * op, and the flush function has + * not yet returned, This field is + * used to turn off overactive santity + * checking code that would otherwise + * cause a false test failure. + */ hbool_t loaded; /* entry has been loaded since the * last time it was reset. */ @@ -290,6 +386,42 @@ struct pe_flush_cache_test_spec hbool_t expected_destroyed; }; +struct fo_flush_entry_check +{ + int entry_num; + int entry_type; + int entry_index; + size_t expected_size; + hbool_t in_cache; + hbool_t at_main_addr; + hbool_t is_dirty; + hbool_t is_protected; + hbool_t is_pinned; + hbool_t expected_loaded; + hbool_t expected_cleared; + hbool_t expected_flushed; + hbool_t expected_destroyed; +}; + +struct fo_flush_cache_test_spec +{ + int entry_num; + int entry_type; + int entry_index; + hbool_t insert_flag; + unsigned int flags; + size_t new_size; + int num_pins; + int pin_type[MAX_PINS]; + int pin_idx[MAX_PINS]; + int num_flush_ops; + struct flush_op flush_ops[MAX_FLUSH_OPS]; + hbool_t expected_loaded; + hbool_t expected_cleared; + hbool_t expected_flushed; + hbool_t expected_destroyed; +}; + struct rename_entry_test_spec { int entry_type; @@ -298,6 +430,22 @@ struct rename_entry_test_spec hbool_t is_pinned; }; +struct expected_entry_status +{ + int entry_type; + int entry_index; + size_t size; + hbool_t in_cache; + hbool_t at_main_addr; + hbool_t is_dirty; + hbool_t is_protected; + hbool_t is_pinned; + hbool_t loaded; + hbool_t cleared; + hbool_t flushed; + hbool_t destroyed; +}; + @@ -344,6 +492,7 @@ herr_t medium_clear(H5F_t * f, void * thing, hbool_t dest); herr_t large_clear(H5F_t * f, void * thing, hbool_t dest); herr_t huge_clear(H5F_t * f, void * thing, hbool_t dest); herr_t monster_clear(H5F_t * f, void * thing, hbool_t dest); +herr_t variable_clear(H5F_t * f, void * thing, hbool_t dest); herr_t pico_dest(H5F_t * f, void * thing); @@ -355,26 +504,29 @@ herr_t medium_dest(H5F_t * f, void * thing); herr_t large_dest(H5F_t * f, void * thing); herr_t huge_dest(H5F_t * f, void * thing); herr_t monster_dest(H5F_t * f, void * thing); +herr_t variable_dest(H5F_t * f, void * thing); herr_t pico_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, - haddr_t addr, void *thing); + haddr_t addr, void *thing, unsigned * flags_ptr); herr_t nano_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, - haddr_t addr, void *thing); + haddr_t addr, void *thing, unsigned * flags_ptr); herr_t micro_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, - haddr_t addr, void *thing); + haddr_t addr, void *thing, unsigned * flags_ptr); herr_t tiny_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, - haddr_t addr, void *thing); + haddr_t addr, void *thing, unsigned * flags_ptr); herr_t small_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, - haddr_t addr, void *thing); + haddr_t addr, void *thing, unsigned * flags_ptr); herr_t medium_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, - haddr_t addr, void *thing); + haddr_t addr, void *thing, unsigned * flags_ptr); herr_t large_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, - haddr_t addr, void *thing); + haddr_t addr, void *thing, unsigned * flags_ptr); herr_t huge_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, - haddr_t addr, void *thing); + haddr_t addr, void *thing, unsigned * flags_ptr); herr_t monster_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, - haddr_t addr, void *thing); + haddr_t addr, void *thing, unsigned * flags_ptr); +herr_t variable_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, + haddr_t addr, void *thing, unsigned * flags_ptr); void * pico_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, @@ -395,6 +547,8 @@ void * huge_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1, void *udata2); void * monster_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1, void *udata2); +void * variable_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, + const void *udata1, void *udata2); herr_t pico_size(H5F_t * f, void * thing, size_t * size_ptr); @@ -406,6 +560,7 @@ herr_t medium_size(H5F_t * f, void * thing, size_t * size_ptr); herr_t large_size(H5F_t * f, void * thing, size_t * size_ptr); herr_t huge_size(H5F_t * f, void * thing, size_t * size_ptr); herr_t monster_size(H5F_t * f, void * thing, size_t * size_ptr); +herr_t variable_size(H5F_t * f, void * thing, size_t * size_ptr); /* callback table extern */ @@ -414,6 +569,15 @@ extern const H5C_class_t types[NUMBER_OF_ENTRY_TYPES]; /* function declarations: */ +void add_flush_op(int target_type, + int target_idx, + int op_code, + int type, + int idx, + hbool_t flag, + size_t size); + + void addr_to_type_and_index(haddr_t addr, int32_t * type_ptr, int32_t * index_ptr); @@ -423,6 +587,11 @@ haddr_t type_and_index_to_addr(int32_t type, int32_t idx); #endif +void dirty_entry(H5C_t * cache_ptr, + int32_t type, + int32_t idx, + hbool_t dirty_pin); + void expunge_entry(H5C_t * cache_ptr, int32_t type, int32_t idx); @@ -462,8 +631,19 @@ void create_pinned_entry_dependency(H5C_t * cache_ptr, int pinned_type, int pinned_idx); +void execute_flush_op(H5C_t * cache_ptr, + struct test_entry_t * entry_ptr, + struct flush_op * op_ptr, + unsigned * flags_ptr); + void reset_entries(void); +void resize_entry(H5C_t * cache_ptr, + int32_t type, + int32_t idx, + size_t new_size, + hbool_t resize_pin); + H5C_t * setup_cache(size_t max_cache_size, size_t min_clean_size); void row_major_scan_forward(H5C_t * cache_ptr, @@ -571,7 +751,18 @@ void unprotect_entry(H5C_t * cache_ptr, int dirty, unsigned int flags); +void unprotect_entry_with_size_change(H5C_t * cache_ptr, + int32_t type, + int32_t idx, + unsigned int flags, + size_t new_size); + void verify_clean(void); +void verify_entry_status(H5C_t * cache_ptr, + int tag, + int num_entries, + struct expected_entry_status expected[]); + void verify_unprotected(void); |