diff options
author | John Mainzer <mainzer@hdfgroup.org> | 2006-04-28 13:27:54 (GMT) |
---|---|---|
committer | John Mainzer <mainzer@hdfgroup.org> | 2006-04-28 13:27:54 (GMT) |
commit | 8a7b9b3221f192ed0e64b00c3a90d5e6a1fb9e19 (patch) | |
tree | 2a4a38cc7b359149409ba55d919031ce9d25e932 /testpar | |
parent | 6a77572c26b354541cafed74bf583e0de0ddfe9a (diff) | |
download | hdf5-8a7b9b3221f192ed0e64b00c3a90d5e6a1fb9e19.zip hdf5-8a7b9b3221f192ed0e64b00c3a90d5e6a1fb9e19.tar.gz hdf5-8a7b9b3221f192ed0e64b00c3a90d5e6a1fb9e19.tar.bz2 |
[svn-r12311] Purpose:
Add pinned entry capability to cache.
Description:
For frequently accessed cache entries, the protect/unprotect overhead
is sometimes a bottleneck.
Solution:
Allow entries to be pinned in the cache. Pinned entries can't be
evicted, but can be flushed or modified.
Platforms tested:
h5committested -- minus one small typo in test/cache.c whose fix was
tested on copper and heping only.
Misc. update:
Diffstat (limited to 'testpar')
-rw-r--r-- | testpar/t_cache.c | 1178 |
1 files changed, 1046 insertions, 132 deletions
diff --git a/testpar/t_cache.c b/testpar/t_cache.c index 95b3e4b..f80f4b3 100644 --- a/testpar/t_cache.c +++ b/testpar/t_cache.c @@ -26,6 +26,10 @@ #include "H5Cpkg.h" +#define H5AC_PACKAGE /*suppress error about including H5Cpkg */ + +#include "H5ACpkg.h" + #define H5F_PACKAGE /*suppress error about including H5Fpkg */ #include "H5Fpkg.h" @@ -57,6 +61,21 @@ int file_mpi_rank = -1; MPI_Comm file_mpi_comm = MPI_COMM_NULL; +/* the following globals are used to maintain rudementary statistics + * to check the validity of the statistics maintained by H5C.c + */ + +long datum_clears = 0; +long datum_pinned_clears = 0; +long datum_destroys = 0; +long datum_flushes = 0; +long datum_pinned_flushes = 0; +long datum_loads = 0; +long global_pins = 0; +long global_dirty_pins = 0; +long local_pins = 0; + + /***************************************************************************** * struct datum * @@ -91,6 +110,17 @@ MPI_Comm file_mpi_comm = MPI_COMM_NULL; * locked: Boolean flag that is set to true iff the entry is in * the cache and locked. * + * global_pinned: Boolean flag that is set to true iff the entry has + * been pinned collectively in all caches. Since writes must + * be collective across all processes, only entries pinned + * in this fashion may be marked dirty. + * + * local_pinned: Boolean flag that is set to true iff the entry + * has been pinned in the local cache, but probably not all + * caches. Such pins will typically not be consistant across + * processes, and thus cannot be marked as dirty unless they + * happen to overlap some collective operation. + * * index: Index of this instance of datum in the data_index[] array * discussed below. * @@ -105,6 +135,8 @@ struct datum hbool_t dirty; hbool_t valid; hbool_t locked; + hbool_t global_pinned; + hbool_t local_pinned; int index; }; @@ -124,15 +156,44 @@ struct datum *****************************************************************************/ #ifndef H5_HAVE_MPE + +#if 1 /* JRM */ #define NUM_DATA_ENTRIES 100000 -#else - /* Use a smaller test size to avoid creating huge MPE logfiles. */ +#else /* JRM */ +#define NUM_DATA_ENTRIES 10000 +#endif /* JRM */ + +#else /* H5_HAVE_MPE */ + +/* Use a smaller test size to avoid creating huge MPE logfiles. */ #define NUM_DATA_ENTRIES 1000 -#endif + +#endif /* H5_HAVE_MPE */ struct datum data[NUM_DATA_ENTRIES]; +/* Many tests use the size of data array as the size of test loops. + * On some machines, this results in unacceptably long test runs. + * + * To deal with this issue, I have introduced the virt_num_data_entries + * global, which can be set to a lower value to throtle the length of + * tests. + * + * Note that this value must always be divisible by 40, and must be an + * even divisor of NUM_DATA_ENTRIES. So far, all tests have been with + * powers of 10 that meet these criteria. + * + * Further, this value must be consistant across all processes. + */ + +#define STD_VIRT_NUM_DATA_ENTRIES NUM_DATA_ENTRIES +#define EXPRESS_VIRT_NUM_DATA_ENTRIES (NUM_DATA_ENTRIES / 10) +#define MPE_VIRT_NUM_DATA_ENTIES (NUM_DATA_ENTRIES / 100) + +int virt_num_data_entries = NUM_DATA_ENTRIES; + + /***************************************************************************** * data_index array * @@ -202,6 +263,11 @@ MPI_Datatype mpi_mssg_t; /* for MPI derived type created from mssg */ /************************** function declarations ****************************/ /*****************************************************************************/ +/* stats functions */ + +void print_stats(void); +void reset_stats(void); + /* MPI setup functions */ hbool_t set_up_file_communicator(void); @@ -213,9 +279,14 @@ int addr_to_datum_index(haddr_t base_addr); void init_data(void); -/* mssg xfer related functions */ +/* test coodination related functions */ +int do_express_test(void); int get_max_nerrors(void); + + +/* mssg xfer related functions */ + hbool_t recv_mssg(struct mssg_t *mssg_ptr); hbool_t send_mssg(struct mssg_t *mssg_ptr); hbool_t setup_derived_types(void); @@ -260,12 +331,25 @@ const H5C_class_t types[NUMBER_OF_ENTRY_TYPES] = void insert_entry(H5C_t * cache_ptr, H5F_t * file_ptr, int32_t idx, unsigned int flags); +void local_pin_and_unpin_random_entries(H5C_t * cache_ptr, H5F_t * file_ptr, + int min_idx, int max_idx, + int min_count, int max_count); +void local_pin_random_entry(H5C_t * cache_ptr, H5F_t * file_ptr, + int min_idx, int max_idx); +void local_unpin_all_entries(H5C_t * cache_ptr, H5F_t * file_ptr, + hbool_t via_unprotect); +int local_unpin_next_pinned_entry(H5C_t * cache_ptr, H5F_t * file_ptr, + int start_idx, hbool_t via_unprotect); void lock_and_unlock_random_entries(H5C_t * cache_ptr, H5F_t * file_ptr, int min_idx, int max_idx, int min_count, int max_count); void lock_and_unlock_random_entry(H5C_t * cache_ptr, H5F_t * file_ptr, int min_idx, int max_idx); void lock_entry(H5C_t * cache_ptr, H5F_t * file_ptr, int32_t idx); +void mark_pinned_entry_dirty(H5C_t * cache_ptr, int32_t idx, + hbool_t size_changed, size_t new_size); +void pin_entry(H5C_t * cache_ptr, H5F_t * file_ptr, int32_t idx, + hbool_t global, hbool_t dirty); void rename_entry(H5C_t * cache_ptr, H5F_t * file_ptr, int32_t old_idx, int32_t new_idx); hbool_t setup_cache_for_test(hid_t * fid_ptr, H5F_t ** file_ptr_ptr, @@ -274,6 +358,8 @@ void setup_rand(void); hbool_t take_down_cache(hid_t fid); void unlock_entry(H5C_t * cache_ptr, H5F_t * file_ptr, int32_t type, unsigned int flags); +void unpin_entry(H5C_t * cache_ptr, H5F_t * file_ptr, int32_t idx, + hbool_t global, hbool_t dirty, hbool_t via_unprotect); /* test functions */ @@ -286,6 +372,83 @@ hbool_t smoke_check_4(void); /*****************************************************************************/ +/****************************** stats functions ******************************/ +/*****************************************************************************/ + +/***************************************************************************** + * + * Function: print_stats() + * + * Purpose: Print the rudementary stats maintained by t_cache. + * + * This is a debugging function, which will not normally + * be run as part of t_cache. + * + * Return: void + * + * Programmer: JRM -- 4/17/06 + * + * Modifications: + * + * None. + * + *****************************************************************************/ + +void +print_stats(void) +{ + HDfprintf(stdout, + "%d: datum clears / pinned clears / destroys = %ld / %ld / %ld\n", + world_mpi_rank, datum_clears, datum_pinned_clears, + datum_destroys ); + HDfprintf(stdout, + "%d: datum flushes / pinned flushes / loads = %ld / %ld / %ld\n", + world_mpi_rank, datum_flushes, datum_pinned_flushes, + datum_loads ); + HDfprintf(stdout, + "%d: pins: global / global dirty / local = %ld / %ld / %ld\n", + world_mpi_rank, global_pins, global_dirty_pins, local_pins); + HDfflush(stdout); + + return; + +} /* print_stats() */ + +/***************************************************************************** + * + * Function: reset_stats() + * + * Purpose: Reset the rudementary stats maintained by t_cache. + * + * Return: void + * + * Programmer: JRM -- 4/17/06 + * + * Modifications: + * + * None. + * + *****************************************************************************/ + +void +reset_stats(void) +{ + datum_clears = 0; + datum_pinned_clears = 0; + datum_destroys = 0; + datum_flushes = 0; + datum_pinned_flushes = 0; + datum_loads = 0; + global_pins = 0; + global_dirty_pins = 0; + local_pins = 0; + + return; + +} /* reset_stats() */ + + +/*****************************************************************************/ /**************************** MPI setup functions ****************************/ /*****************************************************************************/ @@ -433,14 +596,6 @@ set_up_file_communicator(void) } } -#if 0 /* Useful debuggging code -- lets keep it around for a while */ - if ( success ) { - - fprintf(stdout, "%d:%s: file mpi size = %d, file mpi rank = %d.\n", - world_mpi_rank, fcn_name, file_mpi_size, file_mpi_rank); - } -#endif /* JRM */ - return(success); } /* set_up_file_communicator() */ @@ -544,18 +699,21 @@ init_data(void) /* this must hold so renames don't change entry size. */ HDassert( (NUM_DATA_ENTRIES / 2) % 20 == 0 ); + HDassert( (virt_num_data_entries / 2) % 20 == 0 ); for ( i = 0; i < NUM_DATA_ENTRIES; i++ ) { - data[i].base_addr = addr; - data[i].len = (size_t)(addr_offsets[j]); - data[i].ver = 0; - data[i].dirty = FALSE; - data[i].valid = FALSE; - data[i].locked = FALSE; - data[i].index = i; - - data_index[i] = i; + data[i].base_addr = addr; + data[i].len = (size_t)(addr_offsets[j]); + data[i].ver = 0; + data[i].dirty = FALSE; + data[i].valid = FALSE; + data[i].locked = FALSE; + data[i].global_pinned = FALSE; + data[i].local_pinned = FALSE; + data[i].index = i; + + data_index[i] = i; addr += addr_offsets[j]; HDassert( addr > data[i].base_addr ); @@ -569,11 +727,68 @@ init_data(void) /*****************************************************************************/ -/************************ mssg xfer related functions ************************/ +/******************** test coodination related functions *********************/ /*****************************************************************************/ /***************************************************************************** * + * Function: do_express_test() + * + * Purpose: Do an MPI_Allreduce to obtain the maximum value returned + * by GetTestExpress() across all processes. Return this + * value. + * + * Envirmoment variables can be different across different + * processes. This function ensures that all processes agree + * on whether to do an express test. + * + * Return: Success: Maximum of the values returned by + * GetTestExpress() across all processes. + * + * Failure: -1 + * + * Programmer: JRM -- 4/25/06 + * + * Modifications: + * + * None. + * + *****************************************************************************/ + +int +do_express_test(void) +{ + const char * fcn_name = "do_express_test()"; + int express_test; + int max_express_test; + int result; + + express_test = GetTestExpress(); + + result = MPI_Allreduce((void *)&express_test, + (void *)&max_express_test, + 1, + MPI_INT, + MPI_MAX, + world_mpi_comm); + + if ( result != MPI_SUCCESS ) { + + nerrors++; + max_express_test = -1; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: MPI_Allreduce() failed.\n", + world_mpi_rank, fcn_name ); + } + } + + return(max_express_test); + +} /* do_express_test() */ + + +/***************************************************************************** + * * Function: get_max_nerrors() * * Purpose: Do an MPI_Allreduce to obtain the maximum value of nerrors @@ -621,6 +836,10 @@ get_max_nerrors(void) } /* get_max_nerrors() */ +/*****************************************************************************/ +/************************ mssg xfer related functions ************************/ +/*****************************************************************************/ + /***************************************************************************** * * Function: recv_mssg() @@ -648,7 +867,6 @@ recv_mssg(struct mssg_t *mssg_ptr) const char * fcn_name = "recv_mssg()"; hbool_t success = TRUE; int result; - static long mssg_num = 0; MPI_Status status; if ( mssg_ptr == NULL ) { @@ -794,9 +1012,9 @@ setup_derived_types(void) hbool_t success = TRUE; int i; int result; - MPI_Datatype types[8] = {MPI_INT, MPI_INT, MPI_INT, MPI_LONG, - HADDR_AS_MPI_TYPE, MPI_INT, MPI_INT, - MPI_UNSIGNED}; + MPI_Datatype mpi_types[8] = {MPI_INT, MPI_INT, MPI_INT, MPI_LONG, + HADDR_AS_MPI_TYPE, MPI_INT, MPI_INT, + MPI_UNSIGNED}; int block_len[8] = {1, 1, 1, 1, 1, 1, 1, 1}; MPI_Aint displs[8]; struct mssg_t sample; /* used to compute displacements */ @@ -829,7 +1047,7 @@ setup_derived_types(void) if ( success ) { - result = MPI_Type_struct(8, block_len, displs, types, &mpi_mssg_t); + result = MPI_Type_struct(8, block_len, displs, mpi_types, &mpi_mssg_t); if ( result != MPI_SUCCESS ) { @@ -886,7 +1104,6 @@ takedown_derived_types(void) { const char * fcn_name = "takedown_derived_types()"; hbool_t success = TRUE; - int i; int result; result = MPI_Type_free(&mpi_mssg_t); @@ -1225,18 +1442,19 @@ clear_datum(H5F_t * f, void * thing, hbool_t dest) { - int index; + int idx; struct datum * entry_ptr; HDassert( thing ); entry_ptr = (struct datum *)thing; - index = addr_to_datum_index(entry_ptr->base_addr); + idx = addr_to_datum_index(entry_ptr->base_addr); - HDassert( index >= 0 ); - HDassert( index < NUM_DATA_ENTRIES ); - HDassert( &(data[index]) == entry_ptr ); + HDassert( idx >= 0 ); + HDassert( idx < NUM_DATA_ENTRIES ); + HDassert( idx < virt_num_data_entries ); + HDassert( &(data[idx]) == entry_ptr ); HDassert( entry_ptr->header.addr == entry_ptr->base_addr ); HDassert( entry_ptr->header.size == entry_ptr->len ); @@ -1250,6 +1468,14 @@ clear_datum(H5F_t * f, } + datum_clears++; + + if ( entry_ptr->header.is_pinned ) { + + datum_pinned_clears++; + HDassert( entry_ptr->global_pinned || entry_ptr->local_pinned ); + } + return(SUCCEED); } /* clear_datum() */ @@ -1275,24 +1501,30 @@ herr_t destroy_datum(H5F_t UNUSED * f, void * thing) { - int index; + int idx; struct datum * entry_ptr; HDassert( thing ); entry_ptr = (struct datum *)thing; - index = addr_to_datum_index(entry_ptr->base_addr); + idx = addr_to_datum_index(entry_ptr->base_addr); - HDassert( index >= 0 ); - HDassert( index < NUM_DATA_ENTRIES ); - HDassert( &(data[index]) == entry_ptr ); + HDassert( idx >= 0 ); + HDassert( idx < NUM_DATA_ENTRIES ); + HDassert( idx < virt_num_data_entries ); + HDassert( &(data[idx]) == entry_ptr ); HDassert( entry_ptr->header.addr == entry_ptr->base_addr ); HDassert( entry_ptr->header.size == entry_ptr->len ); HDassert( !(entry_ptr->dirty) ); HDassert( !(entry_ptr->header.is_dirty) ); + HDassert( !(entry_ptr->global_pinned) ); + HDassert( !(entry_ptr->local_pinned) ); + HDassert( !(entry_ptr->header.is_pinned) ); + + datum_destroys++; return(SUCCEED); @@ -1318,12 +1550,12 @@ herr_t flush_datum(H5F_t *f, hid_t UNUSED dxpl_id, hbool_t dest, - haddr_t addr, + haddr_t UNUSED addr, void *thing) { const char * fcn_name = "flush_datum()"; herr_t ret_value = SUCCEED; - int index; + int idx; struct datum * entry_ptr; struct mssg_t mssg; @@ -1331,11 +1563,12 @@ flush_datum(H5F_t *f, entry_ptr = (struct datum *)thing; - index = addr_to_datum_index(entry_ptr->base_addr); + idx = addr_to_datum_index(entry_ptr->base_addr); - HDassert( index >= 0 ); - HDassert( index < NUM_DATA_ENTRIES ); - HDassert( &(data[index]) == entry_ptr ); + HDassert( idx >= 0 ); + HDassert( idx < NUM_DATA_ENTRIES ); + HDassert( idx < virt_num_data_entries ); + HDassert( &(data[idx]) == entry_ptr ); HDassert( entry_ptr->header.addr == entry_ptr->base_addr ); HDassert( entry_ptr->header.size == entry_ptr->len ); @@ -1389,6 +1622,14 @@ flush_datum(H5F_t *f, } } + datum_flushes++; + + if ( entry_ptr->header.is_pinned ) { + + datum_pinned_flushes++; + HDassert( entry_ptr->global_pinned || entry_ptr->local_pinned ); + } + return(ret_value); } /* flush_datum() */ @@ -1418,18 +1659,21 @@ load_datum(H5F_t UNUSED *f, { const char * fcn_name = "load_datum()"; hbool_t success = TRUE; - int index; + int idx; struct datum * entry_ptr = NULL; struct mssg_t mssg; - index = addr_to_datum_index(addr); + idx = addr_to_datum_index(addr); - HDassert( index >= 0 ); - HDassert( index < NUM_DATA_ENTRIES ); + HDassert( idx >= 0 ); + HDassert( idx < NUM_DATA_ENTRIES ); + HDassert( idx < virt_num_data_entries ); - entry_ptr = &(data[index]); + entry_ptr = &(data[idx]); HDassert( addr == entry_ptr->base_addr ); + HDassert( ! entry_ptr->global_pinned ); + HDassert( ! entry_ptr->local_pinned ); /* compose the read message */ mssg.req = READ_REQ_CODE; @@ -1494,6 +1738,8 @@ load_datum(H5F_t UNUSED *f, } + datum_loads++; + return(entry_ptr); } /* load_datum() */ @@ -1519,7 +1765,7 @@ size_datum(H5F_t UNUSED * f, void * thing, size_t * size_ptr) { - int index; + int idx; struct datum * entry_ptr; HDassert( thing ); @@ -1527,11 +1773,12 @@ size_datum(H5F_t UNUSED * f, entry_ptr = (struct datum *)thing; - index = addr_to_datum_index(entry_ptr->base_addr); + idx = addr_to_datum_index(entry_ptr->base_addr); - HDassert( index >= 0 ); - HDassert( index < NUM_DATA_ENTRIES ); - HDassert( &(data[index]) == entry_ptr ); + HDassert( idx >= 0 ); + HDassert( idx < NUM_DATA_ENTRIES ); + HDassert( idx < virt_num_data_entries ); + HDassert( &(data[idx]) == entry_ptr ); HDassert( entry_ptr->header.addr == entry_ptr->base_addr ); @@ -1578,6 +1825,7 @@ insert_entry(H5C_t * cache_ptr, HDassert( cache_ptr ); HDassert( file_ptr ); HDassert( ( 0 <= idx ) && ( idx < NUM_DATA_ENTRIES ) ); + HDassert( idx < virt_num_data_entries ); entry_ptr = &(data[idx]); @@ -1605,11 +1853,26 @@ insert_entry(H5C_t * cache_ptr, if ( ! (entry_ptr->header.is_dirty) ) { - nerrors++; - if ( verbose ) { - HDfprintf(stdout, "%d:%s: data[%d].header.is_dirty = %d.\n", - world_mpi_rank, fcn_name, idx, - (int)(data[idx].header.is_dirty)); + /* it is possible that we just exceeded the dirty bytes + * threshold, triggering a write of the newly inserted + * entry. Test for this, and only flag an error if this + * is not the case. + */ + + struct H5AC_aux_t * aux_ptr; + + aux_ptr = ((H5AC_aux_t *)(cache_ptr->aux_ptr)); + + if ( ! ( ( aux_ptr != NULL ) && + ( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ) && + ( aux_ptr->dirty_bytes == 0 ) ) ) { + + nerrors++; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: data[%d].header.is_dirty = %d.\n", + world_mpi_rank, fcn_name, idx, + (int)(data[idx].header.is_dirty)); + } } } @@ -1623,6 +1886,242 @@ insert_entry(H5C_t * cache_ptr, /***************************************************************************** + * Function: local_pin_and_unpin_random_entries() + * + * Purpose: Pin a random number of randomly selected entries in cache, and + * then unpin a random number of entries. + * + * Do nothing if nerrors is non-zero on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 4/12/06 + * + * Modifications: + * + *****************************************************************************/ + +void +local_pin_and_unpin_random_entries(H5C_t * cache_ptr, + H5F_t * file_ptr, + int min_idx, + int max_idx, + int min_count, + int max_count) +{ + const char * fcn_name = "local_pin_and_unpin_random_entries()"; + + if ( nerrors == 0 ) { + + hbool_t via_unprotect; + int count; + int i; + int idx; + + HDassert( cache_ptr ); + HDassert( file_ptr ); + HDassert( 0 <= min_idx ); + HDassert( min_idx < max_idx ); + HDassert( max_idx < NUM_DATA_ENTRIES ); + HDassert( max_idx < virt_num_data_entries ); + HDassert( 0 <= min_count ); + HDassert( min_count < max_count ); + + count = (HDrand() % (max_count - min_count)) + min_count; + + HDassert( min_count <= count ); + HDassert( count <= max_count ); + + for ( i = 0; i < count; i++ ) + { + local_pin_random_entry(cache_ptr, file_ptr, min_idx, max_idx); + } + + count = (HDrand() % (max_count - min_count)) + min_count; + + HDassert( min_count <= count ); + HDassert( count <= max_count ); + + i = 0; + idx = 0; + + while ( ( i < count ) && ( idx >= 0 ) ) + { + via_unprotect = ( (((unsigned)i) & 0x0001) == 0 ); + idx = local_unpin_next_pinned_entry(cache_ptr, file_ptr, + idx, via_unprotect); + i++; + } + } + + return; + +} /* local_pin_and_unpin_random_entries() */ + + +/***************************************************************************** + * Function: local_pin_random_entry() + * + * Purpose: Pin a randomly selected entry in cache, and mark the entry + * as being locally pinned. Since this entry will not in + * general be pinned in any other cache, we can't mark it + * dirty. + * + * Do nothing if nerrors is non-zero on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 4/12/06 + * + * Modifications: + * + *****************************************************************************/ + +void +local_pin_random_entry(H5C_t * cache_ptr, + H5F_t * file_ptr, + int min_idx, + int max_idx) +{ + const char * fcn_name = "local_pin_random_entry()"; + int idx; + + if ( nerrors == 0 ) { + + HDassert( cache_ptr ); + HDassert( file_ptr ); + HDassert( 0 <= min_idx ); + HDassert( min_idx < max_idx ); + HDassert( max_idx < NUM_DATA_ENTRIES ); + HDassert( max_idx < virt_num_data_entries ); + + do + { + idx = (HDrand() % (max_idx - min_idx)) + min_idx; + HDassert( min_idx <= idx ); + HDassert( idx <= max_idx ); + } + while ( data[idx].global_pinned || data[idx].local_pinned ); + + pin_entry(cache_ptr, file_ptr, idx, FALSE, FALSE); + } + + return; + +} /* local_pin_random_entry() */ + + +/***************************************************************************** + * Function: local_unpin_all_entries() + * + * Purpose: Unpin all local pinned entries. + * + * Do nothing if nerrors is non-zero on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 4/12/06 + * + * Modifications: + * + *****************************************************************************/ + +void +local_unpin_all_entries(H5C_t * cache_ptr, + H5F_t * file_ptr, + hbool_t via_unprotect) +{ + const char * fcn_name = "local_unpin_all_entries()"; + + if ( nerrors == 0 ) { + + int idx; + + HDassert( cache_ptr ); + HDassert( file_ptr ); + + idx = 0; + + while ( idx >= 0 ) + { + idx = local_unpin_next_pinned_entry(cache_ptr, file_ptr, + idx, via_unprotect); + } + } + + return; + +} /* local_unpin_all_entries() */ + + +/***************************************************************************** + * Function: local_unpin_next_pinned_entry() + * + * Purpose: Find the next locally pinned entry after the specified + * starting point, and unpin it. + * + * Do nothing if nerrors is non-zero on entry. + * + * Return: Index of the unpinned entry if there is one, or -1 if + * nerrors is non-zero on entry, or if there is no locally + * pinned entry. + * + * Programmer: John Mainzer + * 4/12/06 + * + * Modifications: + * + *****************************************************************************/ + +int +local_unpin_next_pinned_entry(H5C_t * cache_ptr, + H5F_t * file_ptr, + int start_idx, + hbool_t via_unprotect) +{ + const char * fcn_name = "local_unpin_next_pinned_entry()"; + int i = 0; + int idx = -1; + + if ( nerrors == 0 ) { + + HDassert( cache_ptr ); + HDassert( file_ptr ); + HDassert( 0 <= start_idx ); + HDassert( start_idx < NUM_DATA_ENTRIES ); + HDassert( start_idx < virt_num_data_entries ); + + idx = start_idx; + + while ( ( i < virt_num_data_entries ) && + ( ! ( data[idx].local_pinned ) ) ) + { + i++; + idx++; + if ( idx >= virt_num_data_entries ) { + idx = 0; + } + } + + if ( data[idx].local_pinned ) { + + unpin_entry(cache_ptr, file_ptr, idx, FALSE, FALSE, via_unprotect); + + } else { + + idx = -1; + } + } + + return(idx); + +} /* local_unpin_next_pinned_entry() */ + + +/***************************************************************************** * Function: lock_and_unlock_random_entries() * * Purpose: Obtain a random number in the closed interval [min_count, @@ -1699,7 +2198,7 @@ lock_and_unlock_random_entry(H5C_t * cache_ptr, int max_idx) { const char * fcn_name = "lock_and_unlock_random_entry()"; - int index; + int idx; if ( nerrors == 0 ) { @@ -1708,14 +2207,15 @@ lock_and_unlock_random_entry(H5C_t * cache_ptr, HDassert( 0 <= min_idx ); HDassert( min_idx < max_idx ); HDassert( max_idx < NUM_DATA_ENTRIES ); + HDassert( max_idx < virt_num_data_entries ); - index = (HDrand() % (max_idx - min_idx)) + min_idx; + idx = (HDrand() % (max_idx - min_idx)) + min_idx; - HDassert( min_idx <= index ); - HDassert( index <= max_idx ); + HDassert( min_idx <= idx ); + HDassert( idx <= max_idx ); - lock_entry(cache_ptr, file_ptr, index); - unlock_entry(cache_ptr, file_ptr, index, H5AC__NO_FLAGS_SET); + lock_entry(cache_ptr, file_ptr, idx); + unlock_entry(cache_ptr, file_ptr, idx, H5AC__NO_FLAGS_SET); } return; @@ -1752,6 +2252,7 @@ lock_entry(H5C_t * cache_ptr, HDassert( cache_ptr ); HDassert( ( 0 <= idx ) && ( idx < NUM_DATA_ENTRIES ) ); + HDassert( idx < virt_num_data_entries ); entry_ptr = &(data[idx]); @@ -1780,6 +2281,142 @@ lock_entry(H5C_t * cache_ptr, /***************************************************************************** + * Function: mark_pinned_entry_dirty() + * + * Purpose: Mark dirty the entry indicated by the index, + * + * Do nothing if nerrors is non-zero on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 4/14/06 + * + * Modifications: + * + *****************************************************************************/ + +void +mark_pinned_entry_dirty(H5C_t * cache_ptr, + int32_t idx, + hbool_t size_changed, + size_t new_size) +{ + const char * fcn_name = "mark_pinned_entry_dirty()"; + herr_t result; + struct datum * entry_ptr; + + if ( nerrors == 0 ) { + + HDassert( cache_ptr ); + HDassert( ( 0 <= idx ) && ( idx < NUM_DATA_ENTRIES ) ); + HDassert( idx < virt_num_data_entries ); + + entry_ptr = &(data[idx]); + + HDassert ( entry_ptr->global_pinned ); + HDassert ( ! (entry_ptr->local_pinned) ); + + (entry_ptr->ver)++; + entry_ptr->dirty = TRUE; + + result = H5AC_mark_pinned_entry_dirty(cache_ptr, + (void *)entry_ptr, + size_changed, + new_size); + + if ( result < 0 ) { + + nerrors++; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: error in H5AC_unpin_entry().\n", + world_mpi_rank, fcn_name); + } + } + else + { + global_dirty_pins++; + } + } + + return; + +} /* mark_pinned_entry_dirty() */ + + +/***************************************************************************** + * Function: pin_entry() + * + * Purpose: Pin the entry indicated by the index. + * + * Do nothing if nerrors is non-zero on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 4/11/06 + * + * Modifications: + * + *****************************************************************************/ + +void +pin_entry(H5C_t * cache_ptr, + H5F_t * file_ptr, + int32_t idx, + hbool_t global, + hbool_t dirty) +{ + const char * fcn_name = "pin_entry()"; + unsigned int flags = H5AC__PIN_ENTRY_FLAG; + struct datum * entry_ptr; + + if ( nerrors == 0 ) { + + HDassert( cache_ptr ); + HDassert( file_ptr ); + HDassert( ( 0 <= idx ) && ( idx < NUM_DATA_ENTRIES ) ); + HDassert( idx < virt_num_data_entries ); + + entry_ptr = &(data[idx]); + + HDassert ( ! (entry_ptr->global_pinned) ); + HDassert ( ! (entry_ptr->local_pinned) ); + HDassert ( ! ( dirty && ( ! global ) ) ); + + lock_entry(cache_ptr, file_ptr, idx); + + if ( dirty ) { + + flags |= H5AC__DIRTIED_FLAG; + } + + unlock_entry(cache_ptr, file_ptr, idx, flags); + + HDassert( (entry_ptr->header).is_pinned ); + HDassert( ( ! dirty ) || ( (entry_ptr->header).is_dirty ) ); + + if ( global ) { + + entry_ptr->global_pinned = TRUE; + + global_pins++; + + } else { + + entry_ptr->local_pinned = TRUE; + + local_pins++; + + } + } + + return; + +} /* pin_entry() */ + + +/***************************************************************************** * Function: rename_entry() * * Purpose: Rename the entry indicated old_idx to the entry indicated @@ -1809,7 +2446,6 @@ rename_entry(H5C_t * cache_ptr, const char * fcn_name = "rename_entry()"; herr_t result; int tmp; - hbool_t done = TRUE; /* will set to FALSE if we have work to do */ haddr_t old_addr = HADDR_UNDEF; haddr_t new_addr = HADDR_UNDEF; struct datum * old_entry_ptr; @@ -1820,7 +2456,9 @@ rename_entry(H5C_t * cache_ptr, HDassert( cache_ptr ); HDassert( file_ptr ); HDassert( ( 0 <= old_idx ) && ( old_idx < NUM_DATA_ENTRIES ) ); + HDassert( old_idx < virt_num_data_entries ); HDassert( ( 0 <= new_idx ) && ( new_idx < NUM_DATA_ENTRIES ) ); + HDassert( new_idx < virt_num_data_entries ); old_entry_ptr = &(data[old_idx]); new_entry_ptr = &(data[new_idx]); @@ -2159,6 +2797,7 @@ setup_rand(void) seed = (unsigned)tv.tv_usec; HDfprintf(stdout, "%d:%s: seed = %d.\n", world_mpi_rank, fcn_name, seed); + fflush(stdout); HDsrand(seed); } @@ -2258,6 +2897,7 @@ unlock_entry(H5C_t * cache_ptr, HDassert( cache_ptr ); HDassert( file_ptr ); HDassert( ( 0 <= idx ) && ( idx < NUM_DATA_ENTRIES ) ); + HDassert( idx < virt_num_data_entries ); entry_ptr = &(data[idx]); @@ -2269,7 +2909,8 @@ unlock_entry(H5C_t * cache_ptr, entry_ptr->dirty = TRUE; } - result = H5AC_unprotect(file_ptr, -1, &(types[0]), entry_ptr->base_addr, + result = H5AC_unprotect(file_ptr, -1, &(types[0]), + entry_ptr->base_addr, (void *)(&(entry_ptr->header)), flags); if ( ( result < 0 ) || @@ -2299,6 +2940,98 @@ unlock_entry(H5C_t * cache_ptr, } /* unlock_entry() */ +/***************************************************************************** + * Function: unpin_entry() + * + * Purpose: Unpin the entry indicated by the index. + * + * Do nothing if nerrors is non-zero on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 4/12/06 + * + * Modifications: + * + *****************************************************************************/ + +void +unpin_entry(H5C_t * cache_ptr, + H5F_t * file_ptr, + int32_t idx, + hbool_t global, + hbool_t dirty, + hbool_t via_unprotect) +{ + const char * fcn_name = "unpin_entry()"; + herr_t result; + unsigned int flags = H5AC__UNPIN_ENTRY_FLAG; + struct datum * entry_ptr; + + if ( nerrors == 0 ) { + + HDassert( cache_ptr ); + HDassert( file_ptr ); + HDassert( ( 0 <= idx ) && ( idx < NUM_DATA_ENTRIES ) ); + HDassert( idx < virt_num_data_entries ); + + entry_ptr = &(data[idx]); + + HDassert ( ! ( entry_ptr->global_pinned && entry_ptr->local_pinned) ); + HDassert ( ( global && entry_ptr->global_pinned ) || + ( ! global && entry_ptr->local_pinned ) ); + HDassert ( ! ( dirty && ( ! global ) ) ); + + if ( via_unprotect ) { + + lock_entry(cache_ptr, file_ptr, idx); + + if ( dirty ) { + + flags |= H5AC__DIRTIED_FLAG; + } + + unlock_entry(cache_ptr, file_ptr, idx, flags); + + } else { + + if ( dirty ) { + + mark_pinned_entry_dirty(cache_ptr, idx, FALSE, (size_t)0); + + } + + result = H5AC_unpin_entry(cache_ptr, (void *)entry_ptr); + + if ( result < 0 ) { + + nerrors++; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: error in H5AC_unpin_entry().\n", + world_mpi_rank, fcn_name); + } + } + } + + HDassert( ! ((entry_ptr->header).is_pinned) ); + + if ( global ) { + + entry_ptr->global_pinned = FALSE; + + } else { + + entry_ptr->local_pinned = FALSE; + + } + } + + return; + +} /* unpin_entry() */ + + /*****************************************************************************/ /****************************** test functions *******************************/ /*****************************************************************************/ @@ -2336,6 +3069,7 @@ server_smoke_check(void) nerrors = 0; init_data(); + reset_stats(); if ( world_mpi_rank == world_server_mpi_rank ) { @@ -2512,6 +3246,7 @@ smoke_check_1(void) nerrors = 0; init_data(); + reset_stats(); if ( world_mpi_rank == world_server_mpi_rank ) { @@ -2538,31 +3273,33 @@ smoke_check_1(void) } } - for ( i = 0; i < (NUM_DATA_ENTRIES / 2); i++ ) + for ( i = 0; i < (virt_num_data_entries / 2); i++ ) { insert_entry(cache_ptr, file_ptr, i, H5AC__NO_FLAGS_SET); } - for ( i = (NUM_DATA_ENTRIES / 2) - 1; i >= 0; i-- ) + for ( i = (virt_num_data_entries / 2) - 1; i >= 0; i-- ) { lock_entry(cache_ptr, file_ptr, i); unlock_entry(cache_ptr, file_ptr, i, H5AC__NO_FLAGS_SET); } /* rename the first half of the entries... */ - for ( i = 0; i < (NUM_DATA_ENTRIES / 2); i++ ) + for ( i = 0; i < (virt_num_data_entries / 2); i++ ) { lock_entry(cache_ptr, file_ptr, i); unlock_entry(cache_ptr, file_ptr, i, H5AC__NO_FLAGS_SET); - rename_entry(cache_ptr, file_ptr, i, (i + (NUM_DATA_ENTRIES / 2))); + rename_entry(cache_ptr, file_ptr, i, + (i + (virt_num_data_entries / 2))); } /* ...and then rename them back. */ - for ( i = (NUM_DATA_ENTRIES / 2) - 1; i >= 0; i-- ) + for ( i = (virt_num_data_entries / 2) - 1; i >= 0; i-- ) { lock_entry(cache_ptr, file_ptr, i); unlock_entry(cache_ptr, file_ptr, i, H5AC__NO_FLAGS_SET); - rename_entry(cache_ptr, file_ptr, i, (i + (NUM_DATA_ENTRIES / 2))); + rename_entry(cache_ptr, file_ptr, i, + (i + (virt_num_data_entries / 2))); } if ( fid >= 0 ) { @@ -2599,7 +3336,6 @@ smoke_check_1(void) if ( success ) { - success = send_mssg(&mssg); if ( ! success ) { @@ -2652,7 +3388,11 @@ smoke_check_1(void) * * Modifications: * - * None. + * JRM -- 4/13/06 + * Added pinned entry tests. + * + * JRM -- 4/28/06 + * Modified test to rename pinned entries. * *****************************************************************************/ @@ -2675,6 +3415,7 @@ smoke_check_2(void) nerrors = 0; init_data(); + reset_stats(); if ( world_mpi_rank == world_server_mpi_rank ) { @@ -2701,7 +3442,7 @@ smoke_check_2(void) } } - for ( i = 0; i < (NUM_DATA_ENTRIES / 2); i++ ) + for ( i = 0; i < (virt_num_data_entries / 2); i++ ) { insert_entry(cache_ptr, file_ptr, i, H5AC__NO_FLAGS_SET); @@ -2712,43 +3453,72 @@ smoke_check_2(void) } } - for ( i = (NUM_DATA_ENTRIES / 2) - 1; i >= 0; i-=2 ) + for ( i = 0; i < (virt_num_data_entries / 2); i+=61 ) + { + /* Make sure we don't step on any locally pinned entries */ + if ( data[i].local_pinned ) { + unpin_entry(cache_ptr, file_ptr, i, FALSE, FALSE, FALSE); + } + + pin_entry(cache_ptr, file_ptr, i, TRUE, FALSE); + } + + for ( i = (virt_num_data_entries / 2) - 1; i >= 0; i-=2 ) { lock_entry(cache_ptr, file_ptr, i); unlock_entry(cache_ptr, file_ptr, i, H5AC__NO_FLAGS_SET); - lock_and_unlock_random_entries(cache_ptr, file_ptr, - 0, (NUM_DATA_ENTRIES / 20), 0, 100); + lock_and_unlock_random_entries(cache_ptr, file_ptr, 0, + (virt_num_data_entries / 20), + 0, 100); + local_pin_and_unpin_random_entries(cache_ptr, file_ptr, 0, + (virt_num_data_entries / 4), + 0, 3); } - for ( i = 0; i < (NUM_DATA_ENTRIES / 2); i+=2 ) + for ( i = 0; i < (virt_num_data_entries / 2); i+=2 ) { lock_entry(cache_ptr, file_ptr, i); unlock_entry(cache_ptr, file_ptr, i, H5AC__DIRTIED_FLAG); - lock_and_unlock_random_entries(cache_ptr, file_ptr, - 0, (NUM_DATA_ENTRIES / 10), 0, 100); + lock_and_unlock_random_entries(cache_ptr, file_ptr, 0, + (virt_num_data_entries / 10), + 0, 100); } + /* we can't rename pinned entries, so release any local pins now. */ + local_unpin_all_entries(cache_ptr, file_ptr, FALSE); + /* rename the first half of the entries... */ - for ( i = 0; i < (NUM_DATA_ENTRIES / 2); i++ ) + for ( i = 0; i < (virt_num_data_entries / 2); i++ ) { lock_entry(cache_ptr, file_ptr, i); unlock_entry(cache_ptr, file_ptr, i, H5AC__NO_FLAGS_SET); - rename_entry(cache_ptr, file_ptr, i, (i + (NUM_DATA_ENTRIES / 2))); - lock_and_unlock_random_entries(cache_ptr, file_ptr, - 0, ((NUM_DATA_ENTRIES / 50) - 1), + rename_entry(cache_ptr, file_ptr, i, + (i + (virt_num_data_entries / 2))); + lock_and_unlock_random_entries(cache_ptr, file_ptr, 0, + ((virt_num_data_entries / 50) - 1), 0, 100); } /* ...and then rename them back. */ - for ( i = (NUM_DATA_ENTRIES / 2) - 1; i >= 0; i-- ) + for ( i = (virt_num_data_entries / 2) - 1; i >= 0; i-- ) { lock_entry(cache_ptr, file_ptr, i); unlock_entry(cache_ptr, file_ptr, i, H5AC__DIRTIED_FLAG); - rename_entry(cache_ptr, file_ptr, i, (i + (NUM_DATA_ENTRIES / 2))); - lock_and_unlock_random_entries(cache_ptr, file_ptr, - 0, (NUM_DATA_ENTRIES / 100), 0, 100); + rename_entry(cache_ptr, file_ptr, i, + (i + (virt_num_data_entries / 2))); + lock_and_unlock_random_entries(cache_ptr, file_ptr, 0, + (virt_num_data_entries / 100), + 0, 100); } + for ( i = 0; i < (virt_num_data_entries / 2); i+=61 ) + { + hbool_t via_unprotect = ( (((unsigned)i) & 0x01) == 0 ); + hbool_t dirty = ( (((unsigned)i) & 0x02) == 0 ); + + unpin_entry(cache_ptr, file_ptr, i, TRUE, dirty, via_unprotect); + } + if ( fid >= 0 ) { if ( ! take_down_cache(fid) ) { @@ -2783,7 +3553,6 @@ smoke_check_2(void) if ( success ) { - success = send_mssg(&mssg); if ( ! success ) { @@ -2842,6 +3611,8 @@ smoke_check_2(void) * Added code intended to ensure correct operation with large * numbers of processors. * JRM - 1/31/06 + * + * Added pinned entry tests. JRM - 4/14/06 * *****************************************************************************/ @@ -2868,6 +3639,7 @@ smoke_check_3(void) nerrors = 0; init_data(); + reset_stats(); if ( world_mpi_rank == world_server_mpi_rank ) { @@ -2894,11 +3666,10 @@ smoke_check_3(void) } } - min_count = 100 / ((file_mpi_rank + 1) * (file_mpi_rank + 1)); max_count = min_count + 50; - for ( i = 0; i < (NUM_DATA_ENTRIES / 4); i++ ) + for ( i = 0; i < (virt_num_data_entries / 4); i++ ) { insert_entry(cache_ptr, file_ptr, i, H5AC__NO_FLAGS_SET); @@ -2910,46 +3681,101 @@ smoke_check_3(void) } } + min_count = 100 / ((file_mpi_rank + 2) * (file_mpi_rank + 2)); max_count = min_count + 50; - for ( i = (NUM_DATA_ENTRIES / 4); i < (NUM_DATA_ENTRIES / 2); i++ ) + for ( i = (virt_num_data_entries / 4); + i < (virt_num_data_entries / 2); + i++ ) { + insert_entry(cache_ptr, file_ptr, i, H5AC__NO_FLAGS_SET); + if ( i % 59 == 0 ) { + + hbool_t dirty = ( (i % 2) == 0); + + if ( data[i].local_pinned ) { + unpin_entry(cache_ptr, file_ptr, i, FALSE, FALSE, FALSE); + } + + pin_entry(cache_ptr, file_ptr, i, TRUE, dirty); + + HDassert( !dirty || data[i].header.is_dirty ); + HDassert( data[i].header.is_pinned ); + HDassert( data[i].global_pinned ); + HDassert( ! data[i].local_pinned ); + } + if ( i > 100 ) { lock_and_unlock_random_entries(cache_ptr, file_ptr, (i - 100), i, min_count, max_count); } + + local_pin_and_unpin_random_entries(cache_ptr, file_ptr, + 0, virt_num_data_entries / 4, + 0, (file_mpi_rank + 2)); + + } + + + /* flush the file to be sure that we have no problems flushing + * pinned entries + */ + if ( H5Fflush(fid, H5F_SCOPE_GLOBAL) < 0 ) { + nerrors++; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: H5Fflush() failed.\n", + world_mpi_rank, fcn_name); + } } + min_idx = 0; - max_idx = ((NUM_DATA_ENTRIES / 10) / + max_idx = ((virt_num_data_entries / 10) / ((file_mpi_rank + 1) * (file_mpi_rank + 1))) - 1; if ( max_idx <= min_idx ) { max_idx = min_idx + 10; } - for ( i = (NUM_DATA_ENTRIES / 2) - 1; i >= 0; i-=2 ) + for ( i = (virt_num_data_entries / 2) - 1; i >= 0; i-- ) { - lock_entry(cache_ptr, file_ptr, i); - unlock_entry(cache_ptr, file_ptr, i, H5AC__NO_FLAGS_SET); - lock_and_unlock_random_entries(cache_ptr, file_ptr, - min_idx, max_idx, 0, 100); + if ( ( i >= (virt_num_data_entries / 4) ) && ( i % 59 == 0 ) ) { + + hbool_t via_unprotect = ( (((unsigned)i) & 0x02) == 0 ); + hbool_t dirty = ( (((unsigned)i) & 0x04) == 0 ); + + HDassert( data[i].global_pinned ); + HDassert( ! data[i].local_pinned ); + + unpin_entry(cache_ptr, file_ptr, i, TRUE, dirty, + via_unprotect); + } + if ( i % 2 == 0 ) { + + lock_entry(cache_ptr, file_ptr, i); + unlock_entry(cache_ptr, file_ptr, i, H5AC__NO_FLAGS_SET); + local_pin_and_unpin_random_entries(cache_ptr, file_ptr, 0, + virt_num_data_entries / 2, + 0, 2); + lock_and_unlock_random_entries(cache_ptr, file_ptr, + min_idx, max_idx, 0, 100); + } } min_idx = 0; - max_idx = ((NUM_DATA_ENTRIES / 10) / + max_idx = ((virt_num_data_entries / 10) / ((file_mpi_rank + 3) * (file_mpi_rank + 3))) - 1; if ( max_idx <= min_idx ) { max_idx = min_idx + 10; } - for ( i = 0; i < (NUM_DATA_ENTRIES / 2); i+=2 ) + for ( i = 0; i < (virt_num_data_entries / 2); i+=2 ) { lock_entry(cache_ptr, file_ptr, i); unlock_entry(cache_ptr, file_ptr, i, H5AC__DIRTIED_FLAG); @@ -2957,28 +3783,33 @@ smoke_check_3(void) min_idx, max_idx, 0, 100); } + /* we can't rename pinned entries, so release any local pins now. */ + local_unpin_all_entries(cache_ptr, file_ptr, FALSE); + min_count = 10 / (file_mpi_rank + 1); max_count = min_count + 100; /* rename the first half of the entries... */ - for ( i = 0; i < (NUM_DATA_ENTRIES / 2); i++ ) + for ( i = 0; i < (virt_num_data_entries / 2); i++ ) { lock_entry(cache_ptr, file_ptr, i); unlock_entry(cache_ptr, file_ptr, i, H5AC__NO_FLAGS_SET); - rename_entry(cache_ptr, file_ptr, i, (i + (NUM_DATA_ENTRIES / 2))); - lock_and_unlock_random_entries(cache_ptr, file_ptr, - 0, (NUM_DATA_ENTRIES / 20), + rename_entry(cache_ptr, file_ptr, i, + (i + (virt_num_data_entries / 2))); + lock_and_unlock_random_entries(cache_ptr, file_ptr, 0, + (virt_num_data_entries / 20), min_count, max_count); } /* ...and then rename them back. */ - for ( i = (NUM_DATA_ENTRIES / 2) - 1; i >= 0; i-- ) + for ( i = (virt_num_data_entries / 2) - 1; i >= 0; i-- ) { lock_entry(cache_ptr, file_ptr, i); unlock_entry(cache_ptr, file_ptr, i, H5AC__DIRTIED_FLAG); - rename_entry(cache_ptr, file_ptr, i, (i + (NUM_DATA_ENTRIES / 2))); - lock_and_unlock_random_entries(cache_ptr, file_ptr, - 0, (NUM_DATA_ENTRIES / 40), + rename_entry(cache_ptr, file_ptr, i, + (i + (virt_num_data_entries / 2))); + lock_and_unlock_random_entries(cache_ptr, file_ptr, 0, + (virt_num_data_entries / 40), min_count, max_count); } @@ -2988,8 +3819,12 @@ smoke_check_3(void) min_count = 200 / ((file_mpi_rank + 1) * (file_mpi_rank + 1)); max_count = min_count + 100; - for ( i = 0; i < (NUM_DATA_ENTRIES / 2); i+=2 ) + for ( i = 0; i < (virt_num_data_entries / 2); i+=2 ) { + local_pin_and_unpin_random_entries(cache_ptr, file_ptr, 0, + (virt_num_data_entries / 2), + 0, 5); + lock_entry(cache_ptr, file_ptr, i); unlock_entry(cache_ptr, file_ptr, i, H5AC__DIRTIED_FLAG); @@ -3001,6 +3836,9 @@ smoke_check_3(void) } } + /* release any local pins before we take down the cache. */ + local_unpin_all_entries(cache_ptr, file_ptr, FALSE); + if ( fid >= 0 ) { if ( ! take_down_cache(fid) ) { @@ -3120,6 +3958,7 @@ smoke_check_4(void) nerrors = 0; init_data(); + reset_stats(); if ( world_mpi_rank == world_server_mpi_rank ) { @@ -3150,7 +3989,7 @@ smoke_check_4(void) min_count = 100 * (file_mpi_rank % 4); max_count = min_count + 50; - for ( i = 0; i < (NUM_DATA_ENTRIES / 4); i++ ) + for ( i = 0; i < (virt_num_data_entries / 4); i++ ) { insert_entry(cache_ptr, file_ptr, i, H5AC__NO_FLAGS_SET); @@ -3165,35 +4004,84 @@ smoke_check_4(void) min_count = 10 * (file_mpi_rank % 4); max_count = min_count + 100; - for ( i = (NUM_DATA_ENTRIES / 4); i < (NUM_DATA_ENTRIES / 2); i++ ) + for ( i = (virt_num_data_entries / 4); + i < (virt_num_data_entries / 2); + i++ ) { insert_entry(cache_ptr, file_ptr, i, H5AC__NO_FLAGS_SET); + if ( i % 59 == 0 ) { + + hbool_t dirty = ( (i % 2) == 0); + + if ( data[i].local_pinned ) { + unpin_entry(cache_ptr, file_ptr, i, FALSE, FALSE, FALSE); + } + + pin_entry(cache_ptr, file_ptr, i, TRUE, dirty); + + HDassert( !dirty || data[i].header.is_dirty ); + HDassert( data[i].header.is_pinned ); + HDassert( data[i].global_pinned ); + HDassert( ! data[i].local_pinned ); + } + if ( i > 100 ) { lock_and_unlock_random_entries(cache_ptr, file_ptr, (i - 100), i, min_count, max_count); } + + local_pin_and_unpin_random_entries(cache_ptr, file_ptr, 0, + (virt_num_data_entries / 4), + 0, (file_mpi_rank + 2)); } + + /* flush the file to be sure that we have no problems flushing + * pinned entries + */ + if ( H5Fflush(fid, H5F_SCOPE_GLOBAL) < 0 ) { + nerrors++; + if ( verbose ) { + HDfprintf(stdout, "%d:%s: H5Fflush() failed.\n", + world_mpi_rank, fcn_name); + } + } + + min_idx = 0; - max_idx = (((NUM_DATA_ENTRIES / 10) / 4) * + max_idx = (((virt_num_data_entries / 10) / 4) * ((file_mpi_rank % 4) + 1)) - 1; - for ( i = (NUM_DATA_ENTRIES / 2) - 1; i >= 0; i-=2 ) + for ( i = (virt_num_data_entries / 2) - 1; i >= 0; i-- ) { - lock_entry(cache_ptr, file_ptr, i); - unlock_entry(cache_ptr, file_ptr, i, H5AC__NO_FLAGS_SET); - lock_and_unlock_random_entries(cache_ptr, file_ptr, - min_idx, max_idx, 0, 100); + if ( ( i >= (virt_num_data_entries / 4) ) && ( i % 59 == 0 ) ) { + + hbool_t via_unprotect = ( (((unsigned)i) & 0x02) == 0 ); + hbool_t dirty = ( (((unsigned)i) & 0x04) == 0 ); + + HDassert( data[i].global_pinned ); + HDassert( ! data[i].local_pinned ); + + unpin_entry(cache_ptr, file_ptr, i, TRUE, dirty, via_unprotect); + } + + if ( i % 2 == 0 ) { + + lock_entry(cache_ptr, file_ptr, i); + unlock_entry(cache_ptr, file_ptr, i, H5AC__NO_FLAGS_SET); + lock_and_unlock_random_entries(cache_ptr, file_ptr, + min_idx, max_idx, 0, 100); + } } min_idx = 0; - max_idx = (((NUM_DATA_ENTRIES / 10) / 8) * + max_idx = (((virt_num_data_entries / 10) / 8) * ((file_mpi_rank % 4) + 1)) - 1; - for ( i = 0; i < (NUM_DATA_ENTRIES / 2); i+=2 ) + for ( i = 0; i < (virt_num_data_entries / 2); i+=2 ) { lock_entry(cache_ptr, file_ptr, i); unlock_entry(cache_ptr, file_ptr, i, H5AC__DIRTIED_FLAG); @@ -3201,28 +4089,33 @@ smoke_check_4(void) min_idx, max_idx, 0, 100); } + /* we can't rename pinned entries, so release any local pins now. */ + local_unpin_all_entries(cache_ptr, file_ptr, FALSE); + min_count = 10 * (file_mpi_rank % 4); max_count = min_count + 100; /* rename the first half of the entries... */ - for ( i = 0; i < (NUM_DATA_ENTRIES / 2); i++ ) + for ( i = 0; i < (virt_num_data_entries / 2); i++ ) { lock_entry(cache_ptr, file_ptr, i); unlock_entry(cache_ptr, file_ptr, i, H5AC__NO_FLAGS_SET); - rename_entry(cache_ptr, file_ptr, i, (i + (NUM_DATA_ENTRIES / 2))); - lock_and_unlock_random_entries(cache_ptr, file_ptr, - 0, (NUM_DATA_ENTRIES / 20), + rename_entry(cache_ptr, file_ptr, i, + (i + (virt_num_data_entries / 2))); + lock_and_unlock_random_entries(cache_ptr, file_ptr, 0, + (virt_num_data_entries / 20), min_count, max_count); } /* ...and then rename them back. */ - for ( i = (NUM_DATA_ENTRIES / 2) - 1; i >= 0; i-- ) + for ( i = (virt_num_data_entries / 2) - 1; i >= 0; i-- ) { lock_entry(cache_ptr, file_ptr, i); unlock_entry(cache_ptr, file_ptr, i, H5AC__DIRTIED_FLAG); - rename_entry(cache_ptr, file_ptr, i, (i + (NUM_DATA_ENTRIES / 2))); - lock_and_unlock_random_entries(cache_ptr, file_ptr, - 0, (NUM_DATA_ENTRIES / 40), + rename_entry(cache_ptr, file_ptr, i, + (i + (virt_num_data_entries / 2))); + lock_and_unlock_random_entries(cache_ptr, file_ptr, 0, + (virt_num_data_entries / 40), min_count, max_count); } @@ -3232,7 +4125,7 @@ smoke_check_4(void) min_count = 100 * (file_mpi_rank % 4); max_count = min_count + 100; - for ( i = 0; i < (NUM_DATA_ENTRIES / 2); i+=2 ) + for ( i = 0; i < (virt_num_data_entries / 2); i+=2 ) { lock_entry(cache_ptr, file_ptr, i); unlock_entry(cache_ptr, file_ptr, i, H5AC__DIRTIED_FLAG); @@ -3337,10 +4230,10 @@ int main(int argc, char **argv) { const char * fcn_name = "main()"; + int express_test; int i; int mpi_size; int mpi_rank; - int ret_code; int max_nerrors; MPI_Init(&argc, &argv); @@ -3354,10 +4247,29 @@ main(int argc, char **argv) H5open(); + if ( express_test = do_express_test() ) { + +#if 0 /* I'll want this from time to time */ + HDfprintf(stdout, "%d:%s: Express test.\n", world_mpi_rank, fcn_name); +#endif + virt_num_data_entries = EXPRESS_VIRT_NUM_DATA_ENTRIES; + + } else { + + virt_num_data_entries = STD_VIRT_NUM_DATA_ENTRIES; + } + +#ifdef H5_HAVE_MPE + if ( MAINPROCESS ) { printf(" Tests compiled for MPE.\n"); } + virt_num_data_entries = MPE_VIRT_NUM_DATA_ENTIES; +#endif /* H5_HAVE_MPE */ + + if (MAINPROCESS){ printf("===================================\n"); printf("Parallel metadata cache tests\n"); - printf(" mpi_size = %d\n", mpi_size); + printf(" mpi_size = %d\n", mpi_size); + printf(" express_test = %d\n", express_test); printf("===================================\n"); } @@ -3463,6 +4375,8 @@ main(int argc, char **argv) /* run the tests */ #if 1 server_smoke_check(); +#endif +#if 1 smoke_check_1(); #endif #if 1 |