From 0894356a3c6e17b00c7911d8199b64eefca7aa3a Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Wed, 14 Jan 2009 11:29:10 -0500 Subject: [svn-r16311] Description: Bring revisions 16280:16307 back from trunk. Tested on: FreeBSD/32 6.3 (duty) in debug mode FreeBSD/64 6.3 (liberty) w/C++ & FORTRAN, in debug mode Linux/32 2.6 (jam) w/PGI compilers, w/C++ & FORTRAN, w/threadsafe, in debug mode Linux/64-amd64 2.6 (smirom) w/Intel compilers w/default API=1.6.x, w/C++ & FORTRAN, in production mode Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN, in production mode Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in production mode Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in production mode Mac OS X/32 10.5.6 (amazon) in debug mode Mac OS X/32 10.5.6 (amazon) w/C++ & FORTRAN, w/threadsafe, in production mode --- MANIFEST | 5 +- bin/trace | 1 + configure | 2 +- fortran/src/H5Sff.f90 | 2 + release_docs/RELEASE.txt | 25 +- src/H5ACprivate.h | 4 +- src/H5C.c | 819 +++++++++++++---- src/H5Cpkg.h | 66 ++ src/H5Fprivate.h | 3 + src/H5Fpublic.h | 4 + src/H5Fquery.c | 26 + src/H5Glink.c | 1 + src/H5Gnode.c | 1 + src/H5Lexternal.c | 90 +- src/H5Lprivate.h | 14 +- src/H5Lpublic.h | 7 +- src/H5Odbg.c | 1 + src/H5Plapl.c | 185 ++++ src/H5Ppublic.h | 8 +- src/H5Tdeprec.c | 1 + src/H5public.h | 3 + test/cache.c | 1609 ++++++++++++++++++++++++++++++++- test/cache_common.c | 62 +- test/links.c | 286 ++++++ tools/h5diff/h5diff_common.c | 11 +- tools/h5diff/testfiles/h5diff_10.txt | 1 + tools/h5diff/testfiles/h5diff_600.txt | 1 + tools/h5diff/testfiles/h5diff_603.txt | 1 + tools/h5diff/testfiles/h5diff_604.txt | 1 + tools/h5diff/testfiles/h5diff_605.txt | 1 + tools/h5diff/testfiles/h5diff_606.txt | 1 + tools/h5diff/testfiles/h5diff_612.txt | 1 + tools/h5diff/testfiles/h5diff_613.txt | 1 + tools/h5diff/testfiles/h5diff_614.txt | 1 + tools/h5diff/testfiles/h5diff_615.txt | 1 + tools/h5diff/testfiles/h5diff_621.txt | 1 + tools/h5diff/testfiles/h5diff_622.txt | 1 + tools/h5diff/testfiles/h5diff_623.txt | 1 + tools/h5diff/testfiles/h5diff_624.txt | 1 + tools/h5ls/h5ls.c | 36 +- tools/h5ls/testh5ls.sh | 6 + tools/h5repack/h5repack_main.c | 2 +- tools/lib/h5diff.h | 1 + tools/lib/h5diff_array.c | 206 +++-- tools/testfiles/tdatareg.ls | 14 + tools/testfiles/tvldtypes2.ls | 22 + 46 files changed, 3187 insertions(+), 350 deletions(-) create mode 100644 tools/testfiles/tdatareg.ls create mode 100644 tools/testfiles/tvldtypes2.ls diff --git a/MANIFEST b/MANIFEST index 82a4f80..cefc645 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1307,8 +1307,6 @@ ./tools/testfiles/tfpformat.ddl ./tools/testfiles/tfpformat.h5 - - # Expected output from h5ls tests ./tools/testfiles/nosuchfile.ls ./tools/testfiles/help-1.ls @@ -1329,6 +1327,9 @@ ./tools/testfiles/tslink-1.ls ./tools/testfiles/tstr-1.ls ./tools/testfiles/tattr2.ls +./tools/testfiles/tdatareg.ls +./tools/testfiles/tvldtypes2.ls + #additional test input and output for h5dump XML ./tools/testfiles/tall.h5.xml diff --git a/bin/trace b/bin/trace index 81923fd..951d349 100755 --- a/bin/trace +++ b/bin/trace @@ -106,6 +106,7 @@ $Source = ""; "H5G_info_t" => "x", "H5I_free_t" => "x", "H5L_class_t" => "x", + "H5L_elink_traverse_t" => "x", "H5L_iterate_t" => "x", "H5MM_allocate_t" => "x", "H5MM_free_t" => "x", diff --git a/configure b/configure index 36d877b..11fcd92 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Id: configure.in 16283 2009-01-08 19:37:24Z koziol . +# From configure.in Id: configure.in 16305 2009-01-14 13:10:53Z koziol . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for HDF5 1.9.27. # diff --git a/fortran/src/H5Sff.f90 b/fortran/src/H5Sff.f90 index 6469124..e6b93f5 100644 --- a/fortran/src/H5Sff.f90 +++ b/fortran/src/H5Sff.f90 @@ -1781,6 +1781,7 @@ !DEC$ IF DEFINED(HDF5F90_WINDOWS) !DEC$ ATTRIBUTES C,reference,decorate,alias:'H5SDECODE_C'::h5sdecode_c !DEC$ ENDIF + !DEC$ATTRIBUTES reference :: buf CHARACTER(LEN=*), INTENT(IN) :: buf INTEGER(HID_T), INTENT(OUT) :: obj_id ! Object ID END FUNCTION h5sdecode_c @@ -1829,6 +1830,7 @@ !DEC$ IF DEFINED(HDF5F90_WINDOWS) !DEC$ ATTRIBUTES C,reference,decorate,alias:'H5SENCODE_C'::h5sencode_c !DEC$ ENDIF + !DEC$ATTRIBUTES reference :: buf INTEGER(HID_T), INTENT(IN) :: obj_id CHARACTER(LEN=*), INTENT(OUT) :: buf INTEGER(SIZE_T), INTENT(INOUT) :: nalloc diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index bfb30f8..51320d0 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -51,12 +51,18 @@ New Features Library: -------- + - Added H5Pset_elink_cb and H5Pget_elink_cb functions to support a + user-defined callback function for external link traversal. + (NAF - 2009/01/08) + - Added H5Pset_elink_acc_flags and H5Pget_elink_acc_flags functions to + allow the user to specify the file access flags used to open the target + file of an external link. (NAF - 2009/01/08) - Added H5Pset_chunk_cache() and H5Pget_chunk_cache() functions to allow - individual rdcc configuration for each dataset. Added - H5Dget_access_plist() function to retrieve a dataset access property - list form a dataset. (NAF - 2008/11/12) + individual rdcc configuration for each dataset. Added + H5Dget_access_plist() function to retrieve a dataset access property + list from a dataset. (NAF - 2008/11/12) - Added H5Iis_valid() function to check if an id is valid without producing - an error message. (NAF - 2008/11/5) + an error message. (NAF - 2008/11/5) - Added two new public routines: H5Pget_elink_fapl() and H5Pset_elink_fapl(). (see bug #1247) (VC - 2008/10/13) - Improved free space tracking in file to be faster. (QAK - 2008/10/06) @@ -111,7 +117,11 @@ New Features Error return code was changed to 2 from -1. (PVN - 2008/10/30) - h5import: TEXTFPE (scientific format) was deprecated. Use TEXTFP instead (PVN - 2008/10/30) - - h5repack: Define a default chunk whose size is manageable. (PVN - 2008/11/21) + - h5repack: When user doesn't specify a chunk size, h5repack now defines a default + chunk size as the same size of the size of the hyperslab used to read the chunks. + The size of the hyperslabs are defined as the size of each dimension or a + predefined constant, whatever is smaller. This assures that the chunk + read fits in the chunk cache. (PVN - 2008/11/21) @@ -190,6 +200,11 @@ Bug Fixes since HDF5-1.8.0 release (QAK - 2008/03/13) - Fixed bug in H5Aget_num_attrs() routine to handle invalid location ID correctly. (QAK - 2008/03/11) + - H5Dset_extent: when shrinking dimensions, some chunks were not deleted. + (PVN - 2009/01/8) + - Added code to maintain a min_clean_fraction in the metadata cache when + in serial mode. (MAM - 2009/01/9) + Configuration diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index 4a6f9f3..66bdf2d 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -208,8 +208,8 @@ extern hid_t H5AC_ind_dxpl_id; /* char trace_file_name[] = */ "", \ /* hbool_t evictions_enabled = */ TRUE, \ /* hbool_t set_initial_size = */ TRUE, \ - /* size_t initial_size = */ ( 1 * 1024 * 1024), \ - /* double min_clean_fraction = */ 0.5, \ + /* size_t initial_size = */ ( 2 * 1024 * 1024), \ + /* double min_clean_fraction = */ 0.3, \ /* size_t max_size = */ (16 * 1024 * 1024), \ /* size_t min_size = */ ( 1 * 1024 * 1024), \ /* long int epoch_length = */ 50000, \ diff --git a/src/H5C.c b/src/H5C.c index a6a6240..57674f2 100644 --- a/src/H5C.c +++ b/src/H5C.c @@ -584,6 +584,14 @@ if ( ( (entry_ptr) == NULL ) || \ ((cache_ptr)->size_increases[(entry_ptr)->type->id])++; \ if ( (cache_ptr)->index_size > (cache_ptr)->max_index_size ) \ (cache_ptr)->max_index_size = (cache_ptr)->index_size; \ + if ( (cache_ptr)->clean_index_size > \ + (cache_ptr)->max_clean_index_size ) \ + (cache_ptr)->max_clean_index_size = \ + (cache_ptr)->clean_index_size; \ + if ( (cache_ptr)->dirty_index_size > \ + (cache_ptr)->max_dirty_index_size ) \ + (cache_ptr)->max_dirty_index_size = \ + (cache_ptr)->dirty_index_size; \ if ( (cache_ptr)->slist_size > (cache_ptr)->max_slist_size ) \ (cache_ptr)->max_slist_size = (cache_ptr)->slist_size; \ if ( (cache_ptr)->pl_size > (cache_ptr)->max_pl_size ) \ @@ -680,6 +688,14 @@ if ( ( (entry_ptr) == NULL ) || \ (cache_ptr)->max_index_len = (cache_ptr)->index_len; \ if ( (cache_ptr)->index_size > (cache_ptr)->max_index_size ) \ (cache_ptr)->max_index_size = (cache_ptr)->index_size; \ + if ( (cache_ptr)->clean_index_size > \ + (cache_ptr)->max_clean_index_size ) \ + (cache_ptr)->max_clean_index_size = \ + (cache_ptr)->clean_index_size; \ + if ( (cache_ptr)->dirty_index_size > \ + (cache_ptr)->max_dirty_index_size ) \ + (cache_ptr)->max_dirty_index_size = \ + (cache_ptr)->dirty_index_size; \ if ( (cache_ptr)->slist_len > (cache_ptr)->max_slist_len ) \ (cache_ptr)->max_slist_len = (cache_ptr)->slist_len; \ if ( (cache_ptr)->slist_size > (cache_ptr)->max_slist_size ) \ @@ -709,6 +725,14 @@ if ( ( (entry_ptr) == NULL ) || \ (cache_ptr)->max_index_len = (cache_ptr)->index_len; \ if ( (cache_ptr)->index_size > (cache_ptr)->max_index_size ) \ (cache_ptr)->max_index_size = (cache_ptr)->index_size; \ + if ( (cache_ptr)->clean_index_size > \ + (cache_ptr)->max_clean_index_size ) \ + (cache_ptr)->max_clean_index_size = \ + (cache_ptr)->clean_index_size; \ + if ( (cache_ptr)->dirty_index_size > \ + (cache_ptr)->max_dirty_index_size ) \ + (cache_ptr)->max_dirty_index_size = \ + (cache_ptr)->dirty_index_size; \ if ( (cache_ptr)->pl_len > (cache_ptr)->max_pl_len ) \ (cache_ptr)->max_pl_len = (cache_ptr)->pl_len; \ if ( (cache_ptr)->pl_size > (cache_ptr)->max_pl_size ) \ @@ -761,6 +785,14 @@ if ( ( (entry_ptr) == NULL ) || \ (cache_ptr)->max_index_len = (cache_ptr)->index_len; \ if ( (cache_ptr)->index_size > (cache_ptr)->max_index_size ) \ (cache_ptr)->max_index_size = (cache_ptr)->index_size; \ + if ( (cache_ptr)->clean_index_size > \ + (cache_ptr)->max_clean_index_size ) \ + (cache_ptr)->max_clean_index_size = \ + (cache_ptr)->clean_index_size; \ + if ( (cache_ptr)->dirty_index_size > \ + (cache_ptr)->max_dirty_index_size ) \ + (cache_ptr)->max_dirty_index_size = \ + (cache_ptr)->dirty_index_size; \ if ( (cache_ptr)->slist_len > (cache_ptr)->max_slist_len ) \ (cache_ptr)->max_slist_len = (cache_ptr)->slist_len; \ if ( (cache_ptr)->slist_size > (cache_ptr)->max_slist_size ) \ @@ -784,6 +816,14 @@ if ( ( (entry_ptr) == NULL ) || \ if ( (cache_ptr)->index_len > (cache_ptr)->max_index_len ) \ (cache_ptr)->max_index_len = (cache_ptr)->index_len; \ if ( (cache_ptr)->index_size > (cache_ptr)->max_index_size ) \ + if ( (cache_ptr)->clean_index_size > \ + (cache_ptr)->max_clean_index_size ) \ + (cache_ptr)->max_clean_index_size = \ + (cache_ptr)->clean_index_size; \ + if ( (cache_ptr)->dirty_index_size > \ + (cache_ptr)->max_dirty_index_size ) \ + (cache_ptr)->max_dirty_index_size = \ + (cache_ptr)->dirty_index_size; \ (cache_ptr)->max_index_size = (cache_ptr)->index_size; \ if ( (cache_ptr)->pl_len > (cache_ptr)->max_pl_len ) \ (cache_ptr)->max_pl_len = (cache_ptr)->pl_len; \ @@ -830,6 +870,14 @@ if ( ( (entry_ptr) == NULL ) || \ * When modifying these macros, remember to modify the similar macros * in tst/cache.c * + * Changes: + * + * - Updated existing index macros and sanity check macros to maintain + * the clean_index_size and dirty_index_size fields of H5C_t. Also + * added macros to allow us to track entry cleans and dirties. + * + * JRM -- 11/5/08 + * ***********************************************************************/ /* H5C__HASH_TABLE_LEN is defined in H5Cpkg.h. It mut be a power of two. */ @@ -849,7 +897,11 @@ if ( ( (cache_ptr) == NULL ) || \ ( (entry_ptr)->ht_prev != NULL ) || \ ( (entry_ptr)->size <= 0 ) || \ ( (k = H5C__HASH_FCN((entry_ptr)->addr)) < 0 ) || \ - ( k >= H5C__HASH_TABLE_LEN ) ) { \ + ( k >= H5C__HASH_TABLE_LEN ) || \ + ( (cache_ptr)->index_size != \ + ((cache_ptr)->clean_index_size + \ + (cache_ptr)->dirty_index_size) ) ) { \ + HDassert(0); /* JRM */ \ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, fail_val, \ "Pre HT insert SC failed") \ } @@ -871,13 +923,19 @@ if ( ( (cache_ptr) == NULL ) || \ ( (entry_ptr)->ht_prev == NULL ) ) || \ ( ( ((cache_ptr)->index)[(H5C__HASH_FCN((entry_ptr)->addr))] == \ (entry_ptr) ) && \ - ( (entry_ptr)->ht_prev != NULL ) ) ) { \ + ( (entry_ptr)->ht_prev != NULL ) ) || \ + ( (cache_ptr)->index_size != \ + ((cache_ptr)->clean_index_size + \ + (cache_ptr)->dirty_index_size) ) ) { \ + HDassert(0); /* JRM */ \ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Pre HT remove SC failed") \ } #define H5C__PRE_HT_SEARCH_SC(cache_ptr, Addr, fail_val) \ if ( ( (cache_ptr) == NULL ) || \ ( (cache_ptr)->magic != H5C__H5C_T_MAGIC ) || \ + ( (cache_ptr)->index_size != \ + ((cache_ptr)->clean_index_size + (cache_ptr)->dirty_index_size) ) || \ ( ! H5F_addr_defined(Addr) ) || \ ( H5C__HASH_FCN(Addr) < 0 ) || \ ( H5C__HASH_FCN(Addr) >= H5C__HASH_TABLE_LEN ) ) { \ @@ -890,6 +948,8 @@ if ( ( (cache_ptr) == NULL ) || \ ( (cache_ptr)->index_len < 1 ) || \ ( (entry_ptr) == NULL ) || \ ( (cache_ptr)->index_size < (entry_ptr)->size ) || \ + ( (cache_ptr)->index_size != \ + ((cache_ptr)->clean_index_size + (cache_ptr)->dirty_index_size) ) || \ ( H5F_addr_ne((entry_ptr)->addr, (Addr)) ) || \ ( (entry_ptr)->size <= 0 ) || \ ( ((cache_ptr)->index)[k] == NULL ) || \ @@ -913,7 +973,8 @@ if ( ( (cache_ptr) == NULL ) || \ "Post HT shift to front SC failed") \ } -#define H5C__PRE_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size) \ +#define H5C__PRE_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size, \ + entry_ptr, was_clean) \ if ( ( (cache_ptr) == NULL ) || \ ( (cache_ptr)->index_len <= 0 ) || \ ( (cache_ptr)->index_size <= 0 ) || \ @@ -921,22 +982,78 @@ if ( ( (cache_ptr) == NULL ) || \ ( (old_size) > (cache_ptr)->index_size ) || \ ( (new_size) <= 0 ) || \ ( ( (cache_ptr)->index_len == 1 ) && \ - ( (cache_ptr)->index_size != (old_size) ) ) ) { \ + ( (cache_ptr)->index_size != (old_size) ) ) || \ + ( (entry_ptr) == NULL ) ) { \ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ "Pre HT entry size change SC failed") \ +} \ +HDassert( (cache_ptr)->index_size == \ + ((cache_ptr)->clean_index_size + \ + (cache_ptr)->dirty_index_size) ); \ +HDassert( (entry_ptr) != NULL ); \ +HDassert( ( ( was_clean ) && \ + ( (cache_ptr)->clean_index_size >= (old_size) ) ) || \ + ( ( ! (was_clean) ) && \ + ( (cache_ptr)->dirty_index_size >= (old_size) ) ) ); + +#define H5C__POST_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size, \ + entry_ptr) \ +if ( ( (cache_ptr) == NULL ) || \ + ( (cache_ptr)->index_len <= 0 ) || \ + ( (cache_ptr)->index_size <= 0 ) || \ + ( (new_size) > (cache_ptr)->index_size ) || \ + ( ( (cache_ptr)->index_len == 1 ) && \ + ( (cache_ptr)->index_size != (new_size) ) ) ) { \ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "Post HT entry size change SC failed") \ +} \ +HDassert( (cache_ptr)->index_size == \ + ((cache_ptr)->clean_index_size + \ + (cache_ptr)->dirty_index_size) ); \ +HDassert( ( ( (entry_ptr)->is_dirty ) && \ + ( (cache_ptr)->dirty_index_size >= (new_size) ) ) || \ + ( ( ! ((entry_ptr)->is_dirty) ) && \ + ( (cache_ptr)->clean_index_size >= (new_size) ) ) ); + +#define H5C__PRE_HT_UPDATE_FOR_ENTRY_CLEAN_SC(cache_ptr, entry_ptr) \ +{ \ + HDassert( (cache_ptr) != NULL ); \ + HDassert( (cache_ptr)->magic == H5C__H5C_T_MAGIC ); \ + HDassert( (cache_ptr)->index_len > 0 ); \ + HDassert( (entry_ptr) != NULL ); \ + HDassert( (entry_ptr)->is_dirty == FALSE ); \ + HDassert( (cache_ptr)->index_size >= (entry_ptr)->size ); \ + HDassert( (cache_ptr)->dirty_index_size >= (entry_ptr)->size ); \ + HDassert( (cache_ptr)->index_size == \ + ((cache_ptr)->clean_index_size + (cache_ptr)->dirty_index_size) ); \ +} +/* JRM */ +#define H5C__PRE_HT_UPDATE_FOR_ENTRY_DIRTY_SC(cache_ptr, entry_ptr) \ +{ \ + HDassert( (cache_ptr) != NULL ); \ + HDassert( (cache_ptr)->magic == H5C__H5C_T_MAGIC ); \ + HDassert( (cache_ptr)->index_len > 0 ); \ + HDassert( (entry_ptr) != NULL ); \ + HDassert( (entry_ptr)->is_dirty == TRUE ); \ + HDassert( (cache_ptr)->index_size >= (entry_ptr)->size ); \ + HDassert( (cache_ptr)->clean_index_size >= (entry_ptr)->size ); \ + HDassert( (cache_ptr)->index_size == \ + ((cache_ptr)->clean_index_size + (cache_ptr)->dirty_index_size) ); \ } -#define H5C__POST_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size) \ -if ( ( (cache_ptr) == NULL ) || \ - ( (cache_ptr)->index_len <= 0 ) || \ - ( (cache_ptr)->index_size <= 0 ) || \ - ( (new_size) > (cache_ptr)->index_size ) || \ - ( ( (cache_ptr)->index_len == 1 ) && \ - ( (cache_ptr)->index_size != (new_size) ) ) ) { \ - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "Post HT entry size change SC failed") \ +#define H5C__POST_HT_UPDATE_FOR_ENTRY_CLEAN_SC(cache_ptr, entry_ptr) \ +{ \ + HDassert( (cache_ptr)->index_size == \ + ((cache_ptr)->clean_index_size + (cache_ptr)->dirty_index_size) ); \ } +#define H5C__POST_HT_UPDATE_FOR_ENTRY_DIRTY_SC(cache_ptr, entry_ptr) \ +{ \ + HDassert( (cache_ptr)->index_size == \ + ((cache_ptr)->clean_index_size + (cache_ptr)->dirty_index_size) ); \ +} + + #else /* H5C_DO_SANITY_CHECKS */ #define H5C__PRE_HT_INSERT_SC(cache_ptr, entry_ptr, fail_val) @@ -944,8 +1061,14 @@ if ( ( (cache_ptr) == NULL ) || \ #define H5C__PRE_HT_SEARCH_SC(cache_ptr, Addr, fail_val) #define H5C__POST_SUC_HT_SEARCH_SC(cache_ptr, entry_ptr, Addr, k, fail_val) #define H5C__POST_HT_SHIFT_TO_FRONT(cache_ptr, entry_ptr, k, fail_val) -#define H5C__PRE_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size) -#define H5C__POST_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size) +#define H5C__PRE_HT_UPDATE_FOR_ENTRY_CLEAN_SC(cache_ptr, entry_ptr) +#define H5C__PRE_HT_UPDATE_FOR_ENTRY_DIRTY_SC(cache_ptr, entry_ptr) +#define H5C__PRE_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size, \ + entry_ptr, was_clean) +#define H5C__POST_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size, \ + entry_ptr) +#define H5C__POST_HT_UPDATE_FOR_ENTRY_CLEAN_SC(cache_ptr, entry_ptr) +#define H5C__POST_HT_UPDATE_FOR_ENTRY_DIRTY_SC(cache_ptr, entry_ptr) #endif /* H5C_DO_SANITY_CHECKS */ @@ -967,6 +1090,11 @@ if ( ( (cache_ptr) == NULL ) || \ } \ (cache_ptr)->index_len++; \ (cache_ptr)->index_size += (entry_ptr)->size; \ + if ( (entry_ptr)->is_dirty ) { \ + (cache_ptr)->dirty_index_size += (entry_ptr)->size; \ + } else { \ + (cache_ptr)->clean_index_size += (entry_ptr)->size; \ + } \ H5C__UPDATE_STATS_FOR_HT_INSERTION(cache_ptr) \ } @@ -991,6 +1119,11 @@ if ( ( (cache_ptr) == NULL ) || \ (entry_ptr)->ht_prev = NULL; \ (cache_ptr)->index_len--; \ (cache_ptr)->index_size -= (entry_ptr)->size; \ + if ( (entry_ptr)->is_dirty ) { \ + (cache_ptr)->dirty_index_size -= (entry_ptr)->size; \ + } else { \ + (cache_ptr)->clean_index_size -= (entry_ptr)->size; \ + } \ H5C__UPDATE_STATS_FOR_HT_DELETION(cache_ptr) \ } @@ -1059,12 +1192,40 @@ if ( ( (cache_ptr) == NULL ) || \ } \ } -#define H5C__UPDATE_INDEX_FOR_SIZE_CHANGE(cache_ptr, old_size, new_size) \ -{ \ - H5C__PRE_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size) \ - (cache_ptr)->index_size -= old_size; \ - (cache_ptr)->index_size += new_size; \ - H5C__POST_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size) \ +#define H5C__UPDATE_INDEX_FOR_ENTRY_CLEAN(cache_ptr, entry_ptr) \ +{ \ + H5C__PRE_HT_UPDATE_FOR_ENTRY_CLEAN_SC(cache_ptr, entry_ptr); \ + (cache_ptr)->dirty_index_size -= (entry_ptr)->size; \ + (cache_ptr)->clean_index_size += (entry_ptr)->size; \ + H5C__POST_HT_UPDATE_FOR_ENTRY_CLEAN_SC(cache_ptr, entry_ptr); \ +} + +#define H5C__UPDATE_INDEX_FOR_ENTRY_DIRTY(cache_ptr, entry_ptr) \ +{ \ + H5C__PRE_HT_UPDATE_FOR_ENTRY_DIRTY_SC(cache_ptr, entry_ptr); \ + (cache_ptr)->clean_index_size -= (entry_ptr)->size; \ + (cache_ptr)->dirty_index_size += (entry_ptr)->size; \ + H5C__POST_HT_UPDATE_FOR_ENTRY_DIRTY_SC(cache_ptr, entry_ptr); \ +} + +#define H5C__UPDATE_INDEX_FOR_SIZE_CHANGE(cache_ptr, old_size, new_size, \ + entry_ptr, was_clean) \ +{ \ + H5C__PRE_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size, \ + entry_ptr, was_clean) \ + (cache_ptr)->index_size -= (old_size); \ + (cache_ptr)->index_size += (new_size); \ + if ( was_clean ) { \ + (cache_ptr)->clean_index_size -= (old_size); \ + } else { \ + (cache_ptr)->dirty_index_size -= (old_size); \ + } \ + if ( (entry_ptr)->is_dirty ) { \ + (cache_ptr)->dirty_index_size += (new_size); \ + } else { \ + (cache_ptr)->clean_index_size += (new_size); \ + } \ + H5C__POST_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size, entry_ptr) \ } @@ -2847,6 +3008,10 @@ done: * Added initialization for the new flash cache size increase * related fields of H5C_t. * + * JRM -- 11/5/08 + * Added initialization for the new clean_index_size and + * dirty_index_size fields of H5C_t. + * *------------------------------------------------------------------------- */ @@ -2922,6 +3087,8 @@ H5C_create(size_t max_cache_size, cache_ptr->index_len = 0; cache_ptr->index_size = (size_t)0; + cache_ptr->clean_index_size = (size_t)0; + cache_ptr->dirty_index_size = (size_t)0; cache_ptr->slist_len = 0; cache_ptr->slist_size = (size_t)0; @@ -4624,6 +4791,29 @@ done: * Added initialization for the new free_file_space_on_destroy * field. * + * JRM -- 11/13/08 + * Moved test to see if we already have an entry with the + * specified address in the cache. This was necessary as + * we used to modify some fields in the entry to be inserted + * priort to this test, which got the cache confused if the + * insertion failed because the entry was already present. + * + * Also revised the function to call H5C_make_space_in_cache() + * if the min_clean_size is not met at present, not just if + * there is insufficient space in the cache for the new + * entry. + * + * The purpose of this modification is to avoid "metadata + * blizzards" in the write only case. In such instances, + * the cache was allowed to fill with dirty metadata. When + * we finally needed to evict an entry to make space, we had + * to flush out a whole cache full of metadata -- which has + * interesting performance effects. We hope to avoid (or + * perhaps more accurately hide) this effect by maintaining + * the min_clean_size, which should force us to start flushing + * entries long before we actually have to evict something + * to make space. + * *------------------------------------------------------------------------- */ @@ -4644,6 +4834,7 @@ H5C_insert_entry(H5F_t * f, hbool_t insert_pinned; hbool_t set_flush_marker; hbool_t write_permitted = TRUE; + size_t empty_space; H5C_cache_entry_t * entry_ptr; H5C_cache_entry_t * test_entry_ptr; @@ -4677,12 +4868,39 @@ H5C_insert_entry(H5F_t * f, insert_pinned = ( (flags & H5C__PIN_ENTRY_FLAG) != 0 ); entry_ptr = (H5C_cache_entry_t *)thing; + + /* verify that the new entry isn't already in the hash table -- scream + * and die if it is. + */ + + H5C__SEARCH_INDEX(cache_ptr, addr, test_entry_ptr, FAIL) + + if ( test_entry_ptr != NULL ) { + + if ( test_entry_ptr == entry_ptr ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, \ + "entry already in cache.") + + } else { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, \ + "duplicate entry in cache.") + } + } + #ifndef NDEBUG entry_ptr->magic = H5C__H5C_CACHE_ENTRY_T_MAGIC; #endif /* NDEBUG */ entry_ptr->addr = addr; entry_ptr->type = type; + entry_ptr->is_protected = FALSE; + entry_ptr->is_read_only = FALSE; + entry_ptr->ro_ref_count = 0; + + entry_ptr->is_pinned = insert_pinned; + /* newly inserted entries are assumed to be dirty */ entry_ptr->is_dirty = TRUE; @@ -4730,13 +4948,35 @@ H5C_insert_entry(H5F_t * f, } } - if ( ( cache_ptr->evictions_enabled ) && - ( (cache_ptr->index_size + entry_ptr->size) > - cache_ptr->max_cache_size ) ) { + if ( cache_ptr->index_size >= cache_ptr->max_cache_size ) { + + empty_space = 0; + + } else { + + empty_space = cache_ptr->max_cache_size - cache_ptr->index_size; + + } + + if ( ( cache_ptr->evictions_enabled ) + && + ( ( (cache_ptr->index_size + entry_ptr->size) > + cache_ptr->max_cache_size + ) + || + ( + ( ( empty_space + cache_ptr->clean_index_size ) < + cache_ptr->min_clean_size ) + ) + ) + ) { size_t space_needed; - cache_ptr->cache_full = TRUE; + if ( empty_space <= entry_ptr->size ) { + + cache_ptr->cache_full = TRUE; + } if ( cache_ptr->check_write_permitted != NULL ) { @@ -4803,38 +5043,6 @@ H5C_insert_entry(H5F_t * f, } } - /* verify that the new entry isn't already in the hash table -- scream - * and die if it is. - */ - - H5C__SEARCH_INDEX(cache_ptr, addr, test_entry_ptr, FAIL) - - if ( test_entry_ptr != NULL ) { - - if ( test_entry_ptr == entry_ptr ) { - - HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, \ - "entry already in cache.") - - } else { - - HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, \ - "duplicate entry in cache.") - } - } - - /* we don't initialize the protected field until here as it is - * possible that the entry is already in the cache, and already - * protected. If it is, we don't want to make things worse by - * marking it unprotected. - */ - - entry_ptr->is_protected = FALSE; - entry_ptr->is_read_only = FALSE; - entry_ptr->ro_ref_count = 0; - - entry_ptr->is_pinned = insert_pinned; - H5C__INSERT_IN_INDEX(cache_ptr, entry_ptr, FAIL) /* New entries are presumed to be dirty, so this if statement is @@ -5209,6 +5417,19 @@ done: * appropriate. * JRM -- 1/11/08 * + * + * Added code to update the clean_index_size and + * dirty_index_size fields of H5C_t in cases where the + * the entry was clean on protect, was marked dirty in + * this call, and did not change its size. Do this via + * a call to H5C__UPDATE_INDEX_FOR_ENTRY_DIRTY(). + * + * If the size changed, this case is already dealt with by + * by the pre-existing call to + * H5C__UPDATE_INDEX_FOR_SIZE_CHANGE(). + * + * JRM -- 11/5/08 + * *------------------------------------------------------------------------- */ herr_t @@ -5219,6 +5440,7 @@ H5C_mark_pinned_entry_dirty(H5C_t * cache_ptr, { herr_t ret_value = SUCCEED; /* Return value */ herr_t result; + hbool_t was_clean; size_t size_increase; H5C_cache_entry_t * entry_ptr; @@ -5243,6 +5465,9 @@ H5C_mark_pinned_entry_dirty(H5C_t * cache_ptr, "Entry is protected??") } + /* make note of whether the entry was dirty to begin with */ + was_clean = ! ( entry_ptr->is_dirty ); + /* mark the entry as dirty if it isn't already */ entry_ptr->is_dirty = TRUE; @@ -5278,8 +5503,8 @@ H5C_mark_pinned_entry_dirty(H5C_t * cache_ptr, (entry_ptr->size), (new_size)); /* update the hash table */ - H5C__UPDATE_INDEX_FOR_SIZE_CHANGE((cache_ptr), (entry_ptr->size),\ - (new_size)); + H5C__UPDATE_INDEX_FOR_SIZE_CHANGE((cache_ptr), (entry_ptr->size), \ + (new_size), (entry_ptr), (was_clean)); /* if the entry is in the skip list, update that too */ if ( entry_ptr->in_slist ) { @@ -5294,6 +5519,10 @@ H5C_mark_pinned_entry_dirty(H5C_t * cache_ptr, /* finally, update the entry size proper */ entry_ptr->size = new_size; + + } else if ( ( was_clean ) && ( entry_ptr->is_dirty ) ) { + + H5C__UPDATE_INDEX_FOR_ENTRY_DIRTY(cache_ptr, entry_ptr) } if ( ! (entry_ptr->in_slist) ) { @@ -5341,6 +5570,12 @@ done: * it once we deal with the problem of entries being protected * read only, and then dirtied. * + * JRM -- 11/5/08 + * Added call to H5C__UPDATE_INDEX_FOR_ENTRY_DIRTY() to + * update the new clean_index_size and dirty_index_size + * fields of H5C_t in the case that the entry was clean + * prior to this call, and is pinned and not protected. + * *------------------------------------------------------------------------- */ herr_t @@ -5348,6 +5583,7 @@ H5C_mark_pinned_or_protected_entry_dirty(H5C_t * cache_ptr, void * thing) { herr_t ret_value = SUCCEED; /* Return value */ + hbool_t was_pinned_unprotected_and_clean; H5C_cache_entry_t * entry_ptr; FUNC_ENTER_NOAPI(H5C_mark_pinned_or_protected_entry_dirty, FAIL) @@ -5367,9 +5603,15 @@ H5C_mark_pinned_or_protected_entry_dirty(H5C_t * cache_ptr, } else if ( entry_ptr->is_pinned ) { + was_pinned_unprotected_and_clean = ! ( entry_ptr->is_dirty ); + /* mark the entry as dirty if it isn't already */ entry_ptr->is_dirty = TRUE; + if ( was_pinned_unprotected_and_clean ) { + + H5C__UPDATE_INDEX_FOR_ENTRY_DIRTY(cache_ptr, entry_ptr); + } if ( ! (entry_ptr->in_slist) ) { @@ -5429,6 +5671,11 @@ done: * Note that in this case H5C_flush_single_entry() will handle * all these details for us. * + * JRM -- 11/5/08 + * On review this function looks like no change is needed to + * support the new clean_index_size and dirty_index_size + * fields of H5C_t. + * *------------------------------------------------------------------------- */ @@ -5591,7 +5838,7 @@ done: * Function: H5C_resize_pinned_entry * * Purpose: Resize a pinned entry. The target entry MUST be - * be pinned, and MUST not be unprotected. + * be pinned, and MUST be unprotected. * * Resizing an entry dirties it, so if the entry is not * already dirty, the function places the entry on the @@ -5608,6 +5855,19 @@ done: * appropriate. * JRM -- 1/11/08 * + * Added code to update the clean_index_size and + * dirty_index_size fields of H5C_t in cases where the + * the entry was clean prior to this call, was marked dirty, + * and did not change its size. Do this via a call to + * H5C__UPDATE_INDEX_FOR_ENTRY_DIRTY(). + * + * If the size changed, this case is already dealt with by + * by the pre-existing call to + * H5C__UPDATE_INDEX_FOR_SIZE_CHANGE(). + * + * JRM -- 11/5/08 + * + * *------------------------------------------------------------------------- */ herr_t @@ -5618,6 +5878,7 @@ H5C_resize_pinned_entry(H5C_t * cache_ptr, /* const char * fcn_name = "H5C_resize_pinned_entry()"; */ herr_t ret_value = SUCCEED; /* Return value */ herr_t result; + hbool_t was_clean; H5C_cache_entry_t * entry_ptr; size_t size_increase; @@ -5647,6 +5908,9 @@ H5C_resize_pinned_entry(H5C_t * cache_ptr, "Entry is protected??") } + /* make note of whether the entry was clean to begin with */ + was_clean = ! ( entry_ptr->is_dirty ); + /* resizing dirties entries -- mark the entry as dirty if it * isn't already */ @@ -5685,7 +5949,7 @@ H5C_resize_pinned_entry(H5C_t * cache_ptr, /* update the hash table */ H5C__UPDATE_INDEX_FOR_SIZE_CHANGE((cache_ptr), (entry_ptr->size),\ - (new_size)); + (new_size), (entry_ptr), (was_clean)); /* if the entry is in the skip list, update that too */ if ( entry_ptr->in_slist ) { @@ -5700,8 +5964,13 @@ H5C_resize_pinned_entry(H5C_t * cache_ptr, /* finally, update the entry size proper */ entry_ptr->size = new_size; + + } else if ( was_clean ) { + + H5C__UPDATE_INDEX_FOR_ENTRY_DIRTY(cache_ptr, entry_ptr) } + if ( ! (entry_ptr->in_slist) ) { H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL) @@ -5872,6 +6141,22 @@ done: * Added to do a flash cache size increase if appropriate * when a large entry is loaded. * + * JRM -- 11/13/08 + * Modified function to call H5C_make_space_in_cache() when + * the min_clean_size is violated, not just when there isn't + * enough space for and entry that has just been loaded. + * + * The purpose of this modification is to avoid "metadata + * blizzards" in the write only case. In such instances, + * the cache was allowed to fill with dirty metadata. When + * we finally needed to evict an entry to make space, we had + * to flush out a whole cache full of metadata -- which has + * interesting performance effects. We hope to avoid (or + * perhaps more accurately hide) this effect by maintaining + * the min_clean_size, which should force us to start flushing + * entries long before we actually have to evict something + * to make space. + * *------------------------------------------------------------------------- */ @@ -5893,6 +6178,7 @@ H5C_protect(H5F_t * f, hbool_t read_only = FALSE; hbool_t write_permitted; herr_t result; + size_t empty_space; void * thing; H5C_cache_entry_t * entry_ptr; void * ret_value; /* Return value */ @@ -5960,16 +6246,41 @@ H5C_protect(H5F_t * f, } } - /* try to free up some space if necessary and if evictions are - * permitted + if ( cache_ptr->index_size >= cache_ptr->max_cache_size ) { + + empty_space = 0; + + } else { + + empty_space = cache_ptr->max_cache_size - cache_ptr->index_size; + + } + + /* try to free up if necceary and if evictions are permitted. Note + * that if evictions are enabled, we will call H5C_make_space_in_cache() + * regardless if the min_free_space requirement is not met. */ - if ( ( cache_ptr->evictions_enabled ) && - ( (cache_ptr->index_size + entry_ptr->size) > - cache_ptr->max_cache_size ) ) { + + if ( ( cache_ptr->evictions_enabled ) + && + ( ( (cache_ptr->index_size + entry_ptr->size) > + cache_ptr->max_cache_size + ) + || + ( + ( ( empty_space + cache_ptr->clean_index_size ) < + cache_ptr->min_clean_size ) + ) + ) + ) { size_t space_needed; - cache_ptr->cache_full = TRUE; + if ( empty_space <= entry_ptr->size ) { + + cache_ptr->cache_full = TRUE; + + } if ( cache_ptr->check_write_permitted != NULL ) { @@ -6160,10 +6471,31 @@ H5C_protect(H5F_t * f, /* check to see if the cache is now oversized due to the cache * size reduction. If it is, try to evict enough entries to * bring the cache size down to the current maximum cache size. + * + * Also, if the min_clean_size requirement is not met, we + * should also call H5C_make_space_in_cache() to bring us + * into complience. */ - if ( cache_ptr->index_size > cache_ptr->max_cache_size ) { - cache_ptr->cache_full = TRUE; + if ( cache_ptr->index_size >= cache_ptr->max_cache_size ) { + + empty_space = 0; + + } else { + + empty_space = cache_ptr->max_cache_size - cache_ptr->index_size; + + } + + if ( ( cache_ptr->index_size > cache_ptr->max_cache_size ) + || + ( ( empty_space + cache_ptr->clean_index_size ) < + cache_ptr->min_clean_size) ) { + + if ( cache_ptr->index_size > cache_ptr->max_cache_size ) { + + cache_ptr->cache_full = TRUE; + } result = H5C_make_space_in_cache(f, primary_dxpl_id, secondary_dxpl_id, cache_ptr, @@ -6761,6 +7093,15 @@ done: * Added code supporting the new write_protects, * read_protects, and max_read_protects fields. * + * JRM -- 11/13/08 + * Added code displaying the max_clean_index_size and + * max_dirty_index_size. + * + * MAM -- 01/06/09 + * Added code displaying the calls_to_msic, + * total_entries_skipped_in_msic, total_entries_scanned_in_msic, + * and max_entries_skipped_in_msic fields. + * *------------------------------------------------------------------------- */ @@ -6808,6 +7149,8 @@ H5C_stats(H5C_t * cache_ptr, double hit_rate; double average_successful_search_depth = 0.0; double average_failed_search_depth = 0.0; + double average_entries_skipped_per_calls_to_msic = 0.0; + double average_entries_scanned_per_calls_to_msic = 0.0; #endif /* H5C_COLLECT_CACHE_STATS */ FUNC_ENTER_NOAPI(H5C_stats, FAIL) @@ -6927,6 +7270,14 @@ H5C_stats(H5C_t * cache_ptr, (long)(cache_ptr->max_index_len)); HDfprintf(stdout, + "%s current (max) clean/dirty idx size = %ld (%ld) / %ld (%ld)\n", + cache_ptr->prefix, + (long)(cache_ptr->clean_index_size), + (long)(cache_ptr->max_clean_index_size), + (long)(cache_ptr->dirty_index_size), + (long)(cache_ptr->max_dirty_index_size)); + + HDfprintf(stdout, "%s current (max) slist size / length = %ld (%ld) / %ld (%ld)\n", cache_ptr->prefix, (long)(cache_ptr->slist_size), @@ -7024,6 +7375,41 @@ H5C_stats(H5C_t * cache_ptr, (long)total_pinned_flushes, (long)total_pinned_clears); + HDfprintf(stdout, "%s MSIC: (make space in cache) calls = %lld\n", + cache_ptr->prefix, + (long long)(cache_ptr->calls_to_msic)); + + if (cache_ptr->calls_to_msic > 0) { + average_entries_skipped_per_calls_to_msic = + (((double)(cache_ptr->total_entries_skipped_in_msic)) / + ((double)(cache_ptr->calls_to_msic))); + } + + HDfprintf(stdout, "%s MSIC: Average/max entries skipped = %lf / %ld\n", + cache_ptr->prefix, + (float)average_entries_skipped_per_calls_to_msic, + (long)(cache_ptr->max_entries_skipped_in_msic)); + + if (cache_ptr->calls_to_msic > 0) { + average_entries_scanned_per_calls_to_msic = + (((double)(cache_ptr->total_entries_scanned_in_msic)) / + ((double)(cache_ptr->calls_to_msic))); + } + + HDfprintf(stdout, "%s MSIC: Average/max entries scanned = %lf / %ld\n", + cache_ptr->prefix, + (float)average_entries_scanned_per_calls_to_msic, + (long)(cache_ptr->max_entries_scanned_in_msic)); + + HDfprintf(stdout, "%s MSIC: Scanned to make space(evict) = %lld\n", + cache_ptr->prefix, + (long long)(cache_ptr->entries_scanned_to_make_space)); + + HDfprintf(stdout, "%s MSIC: Scanned to satisfy min_clean = %lld\n", + cache_ptr->prefix, + (long long)(cache_ptr->total_entries_scanned_in_msic - + cache_ptr->entries_scanned_to_make_space)); + #if H5C_COLLECT_CACHE_ENTRY_STATS HDfprintf(stdout, "%s aggregate max / min accesses = %d / %d\n", @@ -7192,6 +7578,15 @@ done: * Added initialization for the new write_protects, * read_protects, and max_read_protects fields. * + * JRM 11/13/08 + * Added initialization for the new max_clean_index_size and + * max_dirty_index_size fields. + * + * MAM -- 01/06/09 + * Added code to initalize the calls_to_msic, + * total_entries_skipped_in_msic, total_entries_scanned_in_msic, + * and max_entries_skipped_in_msic fields. + * *------------------------------------------------------------------------- */ @@ -7249,6 +7644,8 @@ H5C_stats__reset(H5C_t UNUSED * cache_ptr) cache_ptr->max_index_len = 0; cache_ptr->max_index_size = (size_t)0; + cache_ptr->max_clean_index_size = (size_t)0; + cache_ptr->max_dirty_index_size = (size_t)0; cache_ptr->max_slist_len = 0; cache_ptr->max_slist_size = (size_t)0; @@ -7259,6 +7656,13 @@ H5C_stats__reset(H5C_t UNUSED * cache_ptr) cache_ptr->max_pel_len = 0; cache_ptr->max_pel_size = (size_t)0; + cache_ptr->calls_to_msic = 0; + cache_ptr->total_entries_skipped_in_msic = 0; + cache_ptr->total_entries_scanned_in_msic = 0; + cache_ptr->max_entries_skipped_in_msic = 0; + cache_ptr->max_entries_scanned_in_msic = 0; + cache_ptr->entries_scanned_to_make_space = 0; + #if H5C_COLLECT_CACHE_ENTRY_STATS for ( i = 0; i <= cache_ptr->max_type_id; i++ ) @@ -7437,6 +7841,17 @@ done: * Separated "destroy entry" concept from "remove entry from * cache" concept, by adding the 'take_ownership' flag. * + * JRM -- 11/5/08 + * Added code to update the clean_index_size and + * dirty_index_size fields of H5C_t in cases where the + * the entry was clean on protect, was marked dirty on + * unprotect, and did not change its size. Do this via + * a call to H5C__UPDATE_INDEX_FOR_ENTRY_DIRTY(). + * + * If the size changed, this case is already dealt with by + * by the pre-existing call to + * H5C__UPDATE_INDEX_FOR_SIZE_CHANGE(). + * *------------------------------------------------------------------------- */ herr_t @@ -7459,6 +7874,7 @@ H5C_unprotect(H5F_t * f, hbool_t unpin_entry; hbool_t free_file_space; hbool_t take_ownership; + hbool_t was_clean; #ifdef H5_HAVE_PARALLEL hbool_t clear_entry = FALSE; #endif /* H5_HAVE_PARALLEL */ @@ -7510,6 +7926,7 @@ H5C_unprotect(H5F_t * f, * the entry. */ dirtied |= entry_ptr->dirtied; + was_clean = ! ( entry_ptr->is_dirty ); #if H5C_DO_EXTREME_SANITY_CHECKS if ( H5C_validate_lru_list(cache_ptr) < 0 ) { @@ -7646,8 +8063,9 @@ H5C_unprotect(H5F_t * f, (entry_ptr->size), (new_size)); /* update the hash table */ - H5C__UPDATE_INDEX_FOR_SIZE_CHANGE((cache_ptr), (entry_ptr->size),\ - (new_size)); + H5C__UPDATE_INDEX_FOR_SIZE_CHANGE((cache_ptr), (entry_ptr->size), \ + (new_size), (entry_ptr), \ + (was_clean)); /* if the entry is in the skip list, update that too */ if ( entry_ptr->in_slist ) { @@ -7663,7 +8081,11 @@ H5C_unprotect(H5F_t * f, /* finally, update the entry size proper */ entry_ptr->size = new_size; - } + + } else if ( ( was_clean ) && ( entry_ptr->is_dirty ) ) { + + H5C__UPDATE_INDEX_FOR_ENTRY_DIRTY(cache_ptr, entry_ptr) + } /* Pin or unpin the entry as requested. */ if ( pin_entry ) { @@ -9929,6 +10351,8 @@ H5C_flush_invalidate_cache(H5F_t * f, done = TRUE; HDassert( cache_ptr->index_size == 0 ); + HDassert( cache_ptr->clean_index_size == 0 ); + HDassert( cache_ptr->dirty_index_size == 0 ); HDassert( cache_ptr->slist_len == 0 ); HDassert( cache_ptr->slist_size == 0 ); HDassert( cache_ptr->pel_len == 0 ); @@ -10053,6 +10477,11 @@ done: * cache" concept, by adding the 'take_ownership' flag and * the "destroy_entry" variable. * + * JRM -- 11/5/08 + * Added call to H5C__UPDATE_INDEX_FOR_ENTRY_CLEAN() to + * maintain the new clean_index_size and clean_index_size + * fields of H5C_t. + * *------------------------------------------------------------------------- */ static herr_t @@ -10413,6 +10842,7 @@ H5C_flush_single_entry(H5F_t * f, HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ "unable to flush entry") } + #ifdef H5_HAVE_PARALLEL if ( flush_flags != H5C_CALLBACK__NO_FLAGS_SET ) { @@ -10455,6 +10885,12 @@ H5C_flush_single_entry(H5F_t * f, if ( ( ! destroy ) && ( entry_ptr->in_slist ) ) { H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr) + + } + + if ( ( ! destroy ) && ( was_dirty ) ) { + + H5C__UPDATE_INDEX_FOR_ENTRY_CLEAN(cache_ptr, entry_ptr); } if ( ! destroy ) { /* i.e. if the entry still exists */ @@ -10489,10 +10925,18 @@ H5C_flush_single_entry(H5F_t * f, HDassert( entry_ptr->size < H5C_MAX_ENTRY_SIZE ); - /* update the hash table for the size change*/ + /* update the hash table for the size change + * We pass TRUE as the was_clean parameter, as we + * have already updated the clean and dirty index + * size fields for the fact that the entry has + * been flushed. (See above call to + * H5C__UPDATE_INDEX_FOR_ENTRY_CLEAN()). + */ H5C__UPDATE_INDEX_FOR_SIZE_CHANGE((cache_ptr), \ (entry_ptr->size),\ - (new_size)); + (new_size), \ + (entry_ptr), \ + (TRUE)); /* The entry can't be protected since we just flushed it. * Thus we must update the replacement policy data @@ -10769,6 +11213,27 @@ done: * but one can argue that I should just scream and die if I * ever detect the condidtion. * + * JRM -- 11/13/08 + * Modified function to always observe the min_clean_size + * whether we are maintaining the clean and dirt LRU lists + * or not. To do this, we had to add the new clean_index_size + * and dirty_index_size fields to H5C_t, and supporting code + * as needed throughout the cache. + * + * The purpose of this modification is to avoid "metadata + * blizzards" in the write only case. In such instances, + * the cache was allowed to fill with dirty metadata. When + * we finally needed to evict an entry to make space, we had + * to flush out a whole cache full of metadata -- which has + * interesting performance effects. We hope to avoid (or + * perhaps more accurately hide) this effect by maintaining + * the min_clean_size, which should force us to start flushing + * entries long before we actually have to evict something + * to make space. + * + * MAM -- 01/06/09 + * Added code to maintain clean_entries_skipped and total_entries + * scanned statistics. *------------------------------------------------------------------------- */ @@ -10783,13 +11248,15 @@ H5C_make_space_in_cache(H5F_t * f, { herr_t ret_value = SUCCEED; /* Return value */ herr_t result; +#if H5C_COLLECT_CACHE_STATS + int32_t clean_entries_skipped = 0; + int32_t total_entries_scanned = 0; +#endif /* H5C_COLLECT_CACHE_STATS */ int32_t entries_examined = 0; int32_t initial_list_len; -#if H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS size_t empty_space; -#endif /* H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ hbool_t prev_is_dirty = FALSE; - hbool_t entry_is_epoch_maker = FALSE; + hbool_t didnt_flush_entry = FALSE; H5C_cache_entry_t * entry_ptr; H5C_cache_entry_t * next_ptr; H5C_cache_entry_t * prev_ptr; @@ -10800,16 +11267,36 @@ H5C_make_space_in_cache(H5F_t * f, HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); HDassert( first_flush_ptr != NULL ); HDassert( ( *first_flush_ptr == TRUE ) || ( *first_flush_ptr == FALSE ) ); + HDassert( cache_ptr->index_size == + (cache_ptr->clean_index_size + cache_ptr->dirty_index_size) ); if ( write_permitted ) { initial_list_len = cache_ptr->LRU_list_len; + entry_ptr = cache_ptr->LRU_tail_ptr; - while ( ( (cache_ptr->index_size + space_needed) - > - cache_ptr->max_cache_size - ) + if ( cache_ptr->index_size >= cache_ptr->max_cache_size ) { + + empty_space = 0; + + } else { + + empty_space = cache_ptr->max_cache_size - cache_ptr->index_size; + + } + + while ( ( ( (cache_ptr->index_size + space_needed) + > + cache_ptr->max_cache_size + ) + || + ( + ( empty_space + cache_ptr->clean_index_size ) + < + ( cache_ptr->min_clean_size ) + ) + ) && ( entries_examined <= (2 * initial_list_len) ) && @@ -10830,10 +11317,18 @@ H5C_make_space_in_cache(H5F_t * f, if ( (entry_ptr->type)->id != H5C__EPOCH_MARKER_TYPE ) { - entry_is_epoch_maker = FALSE; + didnt_flush_entry = FALSE; if ( entry_ptr->is_dirty ) { +#if H5C_COLLECT_CACHE_STATS + if ( (cache_ptr->index_size + space_needed) + > + cache_ptr->max_cache_size ) { + + cache_ptr->entries_scanned_to_make_space++; + } +#endif /* H5C_COLLECT_CACHE_STATS */ result = H5C_flush_single_entry(f, primary_dxpl_id, secondary_dxpl_id, @@ -10843,7 +11338,12 @@ H5C_make_space_in_cache(H5F_t * f, H5C__NO_FLAGS_SET, first_flush_ptr, FALSE); - } else { + } else if ( (cache_ptr->index_size + space_needed) + > + cache_ptr->max_cache_size ) { +#if H5C_COLLECT_CACHE_STATS + cache_ptr->entries_scanned_to_make_space++; +#endif /* H5C_COLLECT_CACHE_STATS */ result = H5C_flush_single_entry(f, primary_dxpl_id, @@ -10854,13 +11354,31 @@ H5C_make_space_in_cache(H5F_t * f, H5C__FLUSH_INVALIDATE_FLAG, first_flush_ptr, TRUE); + } else { + + /* We have enough space so don't flush clean entry. + * Set result to SUCCEED to avoid triggering the error + * code below. + */ +#if H5C_COLLECT_CACHE_STATS + clean_entries_skipped++; +#endif /* H5C_COLLECT_CACHE_STATS */ + didnt_flush_entry = TRUE; + result = SUCCEED; + } + +#if H5C_COLLECT_CACHE_STATS + total_entries_scanned++; +#endif /* H5C_COLLECT_CACHE_STATS */ + + } else { /* Skip epoch markers. Set result to SUCCEED to avoid * triggering the error code below. */ - entry_is_epoch_maker = TRUE; + didnt_flush_entry = TRUE; result = SUCCEED; } @@ -10882,7 +11400,7 @@ H5C_make_space_in_cache(H5F_t * f, } #endif /* NDEBUG */ - if ( entry_is_epoch_maker ) { + if ( didnt_flush_entry ) { entry_ptr = prev_ptr; @@ -10913,121 +11431,52 @@ H5C_make_space_in_cache(H5F_t * f, entries_examined++; - } - -#if H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS - - entries_examined = 0; - initial_list_len = cache_ptr->dLRU_list_len; - entry_ptr = cache_ptr->dLRU_tail_ptr; - - if ( cache_ptr->index_size < cache_ptr->max_cache_size ) { - - empty_space = cache_ptr->max_cache_size - cache_ptr->index_size; - - } else { + if ( cache_ptr->index_size >= cache_ptr->max_cache_size ) { - empty_space = 0; - } - - while ( ( (cache_ptr->cLRU_list_size + empty_space) - < cache_ptr->min_clean_size ) && - ( entries_examined <= initial_list_len ) && - ( entry_ptr != NULL ) - ) - { - HDassert( ! (entry_ptr->is_protected) ); - HDassert( ! (entry_ptr->is_read_only) ); - HDassert( (entry_ptr->ro_ref_count) == 0 ); - HDassert( entry_ptr->is_dirty ); - HDassert( entry_ptr->in_slist ); - - prev_ptr = entry_ptr->aux_prev; - - next_ptr = entry_ptr->aux_next; - - if ( prev_ptr != NULL ) { - - HDassert( prev_ptr->is_dirty ); - } - - result = H5C_flush_single_entry(f, - primary_dxpl_id, - secondary_dxpl_id, - cache_ptr, - entry_ptr->type, - entry_ptr->addr, - H5C__NO_FLAGS_SET, - first_flush_ptr, - FALSE); + empty_space = 0; - if ( result < 0 ) { + } else { - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ - "unable to flush entry") - } + empty_space = cache_ptr->max_cache_size - cache_ptr->index_size; - if ( prev_ptr != NULL ) { -#ifndef NDEBUG - if (prev_ptr->magic != H5C__H5C_CACHE_ENTRY_T_MAGIC) { + } + + HDassert( cache_ptr->index_size == + (cache_ptr->clean_index_size + + cache_ptr->dirty_index_size) ); - /* something horrible has happened to *prev_ptr -- - * scream and die. - */ + } - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "*prev_ptr corrupt 2") +#if H5C_COLLECT_CACHE_STATS + cache_ptr->calls_to_msic++; - } else -#endif /* #ifndef NDEBUG */ - if ( ( ! ( prev_ptr->is_dirty ) ) - || - ( prev_ptr->aux_next != next_ptr ) - || - ( prev_ptr->is_protected ) - || - ( prev_ptr->is_pinned ) ) { - - /* something has happened to the dirty LRU -- start over - * from the tail. - */ -#if 0 /* This debuging code may be useful in the future -- keep it for now. */ - if ( ! ( prev_ptr->is_dirty ) ) { - HDfprintf(stdout, "%s: ! prev_ptr->is_dirty\n", - fcn_name); - } - if ( prev_ptr->aux_next != next_ptr ) { - HDfprintf(stdout, "%s: prev_ptr->next != next_ptr\n", - fcn_name); - } - if ( prev_ptr->is_protected ) { - HDfprintf(stdout, "%s: prev_ptr->is_protected\n", - fcn_name); - } - if ( prev_ptr->is_pinned ) { - HDfprintf(stdout, "%s:prev_ptr->is_pinned\n", - fcn_name); - } + cache_ptr->total_entries_skipped_in_msic += clean_entries_skipped; + cache_ptr->total_entries_scanned_in_msic += total_entries_scanned; - HDfprintf(stdout, "%s: re-starting scan of dirty list\n", - fcn_name); -#endif /* JRM */ - entry_ptr = cache_ptr->dLRU_tail_ptr; + if ( clean_entries_skipped > cache_ptr->max_entries_skipped_in_msic ) { - } else { + cache_ptr->max_entries_skipped_in_msic = clean_entries_skipped; + } - entry_ptr = prev_ptr; + if ( total_entries_scanned > cache_ptr->max_entries_scanned_in_msic ) { - } - } else { + cache_ptr->max_entries_scanned_in_msic = total_entries_scanned; + } +#endif /* H5C_COLLECT_CACHE_STATS */ - entry_ptr = NULL; + HDassert( ( entries_examined > (2 * initial_list_len) ) || + ( (cache_ptr->pl_size + cache_ptr->min_clean_size) > + cache_ptr->max_cache_size ) || + ( ( cache_ptr->clean_index_size + empty_space ) + >= cache_ptr->min_clean_size ) ); - } +#if H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS - entries_examined++; - } + HDassert( ( entries_examined > (2 * initial_list_len) ) || + ( cache_ptr->cLRU_list_size <= cache_ptr->clean_index_size ) ); + HDassert( ( entries_examined > (2 * initial_list_len) ) || + ( cache_ptr->dLRU_list_size <= cache_ptr->dirty_index_size ) ); #endif /* H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ diff --git a/src/H5Cpkg.h b/src/H5Cpkg.h index bdbb25e..5e7b1a7 100644 --- a/src/H5Cpkg.h +++ b/src/H5Cpkg.h @@ -203,6 +203,38 @@ * index_size by two should yield a conservative estimate * of the cache's memory footprint. * + * clean_index_size: Number of bytes of clean entries currently stored in + * the hash table. Note that the index_size field (above) + * is also the sum of the sizes of all entries in the cache. + * Thus we should have the invarient that clean_index_size + + * dirty_index_size == index_size. + * + * WARNING: + * + * 1) The clean_index_size field is not maintained by the + * index macros, as the hash table doesn't care whether + * the entry is clean or dirty. Instead the field is + * maintained in the H5C__UPDATE_RP macros. + * + * 2) The value of the clean_index_size must not be mistaken + * for the current clean size of the cache. Rather, the + * clean size of the cache is the current value of + * clean_index_size plus the amount of empty space (if any) + * in the cache. + * + * dirty_index_size: Number of bytes of dirty entries currently stored in + * the hash table. Note that the index_size field (above) + * is also the sum of the sizes of all entries in the cache. + * Thus we should have the invarient that clean_index_size + + * dirty_index_size == index_size. + * + * WARNING: + * + * 1) The dirty_index_size field is not maintained by the + * index macros, as the hash table doesn't care whether + * the entry is clean or dirty. Instead the field is + * maintained in the H5C__UPDATE_RP macros. + * * index: Array of pointer to H5C_cache_entry_t of size * H5C__HASH_TABLE_LEN. At present, this value is a power * of two, not the usual prime number. @@ -722,6 +754,12 @@ * max_index_size: Largest value attained by the index_size field in the * current epoch. * + * max_clean_index_size: Largest value attained by the clean_index_size field + * in the current epoch. + * + * max_dirty_index_size: Largest value attained by the dirty_index_size field + * in the current epoch. + * * max_slist_len: Largest value attained by the slist_len field in the * current epoch. * @@ -740,6 +778,23 @@ * max_pel_size: Largest value attained by the pel_size field in the * current epoch. * + * calls_to_msic: Total number of calls to H5C_make_space_in_cache + * + * total_entries_skipped_in_msic: Number of clean entries skipped while + * enforcing the min_clean_fraction in H5C_make_space_in_cache(). + * + * total_entries_scanned_in_msic: Number of clean entries skipped while + * enforcing the min_clean_fraction in H5C_make_space_in_cache(). + * + * max_entries_skipped_in_msic: Maximum number of clean entries skipped + * in any one call to H5C_make_space_in_cache(). + * + * max_entries_scanned_in_msic: Maximum number of entries scanned over + * in any one call to H5C_make_space_in_cache(). + * + * entries_scanned_to_make_space: Number of entries scanned only when looking + * for entries to evict in order to make space in cache. + * The remaining stats are collected only when both H5C_COLLECT_CACHE_STATS * and H5C_COLLECT_CACHE_ENTRY_STATS are true. * @@ -830,6 +885,8 @@ struct H5C_t int32_t index_len; size_t index_size; + size_t clean_index_size; + size_t dirty_index_size; H5C_cache_entry_t * (index[H5C__HASH_TABLE_LEN]); @@ -923,6 +980,8 @@ struct H5C_t int32_t max_index_len; size_t max_index_size; + size_t max_clean_index_size; + size_t max_dirty_index_size; int32_t max_slist_len; size_t max_slist_size; @@ -933,6 +992,13 @@ struct H5C_t int32_t max_pel_len; size_t max_pel_size; + int64_t calls_to_msic; + int64_t total_entries_skipped_in_msic; + int64_t total_entries_scanned_in_msic; + int32_t max_entries_skipped_in_msic; + int32_t max_entries_scanned_in_msic; + int64_t entries_scanned_to_make_space; + #if H5C_COLLECT_CACHE_ENTRY_STATS int32_t max_accesses[H5C__MAX_NUM_TYPE_IDS + 1]; diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index fb28c4e..e717b99 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -259,6 +259,7 @@ typedef struct H5F_blk_aggr_t H5F_blk_aggr_t; #define H5F_GC_REF(F) ((F)->shared->gc_ref) #define H5F_USE_LATEST_FORMAT(F) ((F)->shared->latest_format) #define H5F_EXTPATH(F) ((F)->extpath) +#define H5F_NAME(F) ((F)->name) #define H5F_GET_FC_DEGREE(F) ((F)->shared->fc_degree) #define H5F_STORE_MSG_CRT_IDX(F) ((F)->shared->store_msg_crt_idx) #define H5F_HAS_FEATURE(F,FL) ((F)->shared->lf->feature_flags & (FL)) @@ -280,6 +281,7 @@ typedef struct H5F_blk_aggr_t H5F_blk_aggr_t; #define H5F_GC_REF(F) (H5F_gc_ref(F)) #define H5F_USE_LATEST_FORMAT(F) (H5F_use_latest_format(F)) #define H5F_EXTPATH(F) (H5F_get_extpath(F)) +#define H5F_NAME(F) (H5F_get_name(F)) #define H5F_GET_FC_DEGREE(F) (H5F_get_fc_degree(F)) #define H5F_STORE_MSG_CRT_IDX(F) (H5F_store_msg_crt_idx(F)) #define H5F_HAS_FEATURE(F,FL) (H5F_has_feature(F,FL)) @@ -466,6 +468,7 @@ H5_DLL unsigned H5F_decr_nopen_objs(H5F_t *f); H5_DLL unsigned H5F_get_intent(const H5F_t *f); H5_DLL hid_t H5F_get_access_plist(H5F_t *f, hbool_t app_ref); H5_DLL char *H5F_get_extpath(const H5F_t *f); +H5_DLL char *H5F_get_name(const H5F_t *f); H5_DLL hid_t H5F_get_id(H5F_t *file, hbool_t app_ref); H5_DLL size_t H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref); H5_DLL size_t H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *obj_id_list, hbool_t app_ref); diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h index 312d92e..287e9b5 100644 --- a/src/H5Fpublic.h +++ b/src/H5Fpublic.h @@ -50,6 +50,10 @@ #define H5F_ACC_DEBUG (H5CHECK 0x0008u) /*print debug info */ #define H5F_ACC_CREAT (H5CHECK 0x0010u) /*create non-existing files */ +/* Value passed to H5Pset_elink_acc_flags to cause flags to be taken from the + * parent file. */ +#define H5F_ACC_DEFAULT (H5CHECK 0xffffu) /*ignore setting on lapl */ + /* Flags for H5Fget_obj_count() & H5Fget_obj_ids() calls */ #define H5F_OBJ_FILE (0x0001u) /* File objects */ #define H5F_OBJ_DATASET (0x0002u) /* Dataset objects */ diff --git a/src/H5Fquery.c b/src/H5Fquery.c index 550a507..275061d 100644 --- a/src/H5Fquery.c +++ b/src/H5Fquery.c @@ -130,6 +130,32 @@ H5F_get_extpath(const H5F_t *f) /*------------------------------------------------------------------------- + * Function: H5F_get_name + * + * Purpose: Retrieve the name of a file. + * + * Return: Success: The name of the file. + * + * Failure: ? (should not happen) + * + * Programmer: Neil Fortner + * December 15 2008 + * + *------------------------------------------------------------------------- + */ +char * +H5F_get_name(const H5F_t *f) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_name) + + HDassert(f); + + FUNC_LEAVE_NOAPI(f->name) +} /* end H5F_get_name() */ + + +/*------------------------------------------------------------------------- * Function: H5F_get_fcpl * * Purpose: Retrieve the value of a file's FCPL. diff --git a/src/H5Glink.c b/src/H5Glink.c index 9527521..7051453 100644 --- a/src/H5Glink.c +++ b/src/H5Glink.c @@ -41,6 +41,7 @@ #include "H5Iprivate.h" /* IDs */ #include "H5Lprivate.h" /* Links */ #include "H5MMprivate.h" /* Memory management */ +#include "H5Ppublic.h" /* Property Lists */ /****************/ diff --git a/src/H5Gnode.c b/src/H5Gnode.c index 9468302..6b16544 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -39,6 +39,7 @@ #include "H5HLprivate.h" /* Local Heaps */ #include "H5MFprivate.h" /* File memory management */ #include "H5MMprivate.h" /* Memory management */ +#include "H5Ppublic.h" /* Property Lists */ /* Private typedefs */ diff --git a/src/H5Lexternal.c b/src/H5Lexternal.c index 46ed467..2c6b3a3 100644 --- a/src/H5Lexternal.c +++ b/src/H5Lexternal.c @@ -197,6 +197,9 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group, const char *obj_name; /* Name external link's object */ size_t fname_len; /* Length of external link file name */ unsigned intent; /* File access permissions */ + H5L_elink_cb_t cb_info; /* Callback info struct */ + const char *parent_file_name = NULL; /* Parent file name */ + const char *parent_group_name = NULL; /* Parent group name */ hid_t fapl_id = -1; /* File access property list for external link's file */ hid_t ext_obj = -1; /* ID for external link's object */ hid_t ret_value; /* Return value */ @@ -237,15 +240,68 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group, if(H5G_loc(cur_group, &loc) < 0) HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get object location") - /* get the file access mode flags for the parent file */ - intent = H5F_INTENT(loc.oloc->file); + /* get the access flags set for lapl_id if any */ + if(H5P_get(plist, H5L_ACS_ELINK_FLAGS_NAME, &intent) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get elink file access flags") - if ((fapl_id == H5P_DEFAULT) && ((fapl_id = H5F_get_access_plist(loc.oloc->file, FALSE)) < 0)) + /* get the file access mode flags for the parent file, if they were not set + * on lapl_id */ + if(intent == H5F_ACC_DEFAULT) + intent = H5F_INTENT(loc.oloc->file); + + if((fapl_id == H5P_DEFAULT) && ((fapl_id = H5F_get_access_plist(loc.oloc->file, FALSE)) < 0)) HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get parent's file access property list") - /* Set file close degree for new file to "weak" */ + /* Get callback_info */ + if(H5P_get(plist, H5L_ACS_ELINK_CB_NAME, &cb_info)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get elink callback info") + + /* Get file access property list */ if(NULL == (fa_plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Make callback if it exists */ + if(cb_info.func) { + /* Get parent file name */ + parent_file_name = H5F_NAME(loc.oloc->file); + + /* Get parent group name */ + if(loc.path->user_path_r != NULL && loc.path->obj_hidden == 0) + /* Use user_path_r if possible */ + parent_group_name = H5RS_get_str(loc.path->user_path_r); + else { + /* Otherwise use H5G_get_name */ + ssize_t group_name_len; /* Length of parent group name */ + + /* Get length of parent group name */ + if((group_name_len = H5G_get_name(cur_group, NULL, (size_t) 0, lapl_id, H5AC_ind_dxpl_id)) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to retrieve length of group name") + + /* account for null terminator */ + group_name_len++; + + /* Copy parent group name */ + if(NULL == (tempname = (char *) H5MM_malloc((size_t) group_name_len))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + if(H5G_get_name(cur_group, tempname, (size_t) group_name_len, lapl_id, H5AC_ind_dxpl_id) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to retrieve group name") + parent_group_name = tempname; + } /* end else */ + + /* Make callback */ + if((cb_info.func)(parent_file_name, parent_group_name, file_name, obj_name, + &intent, fapl_id, cb_info.user_data) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CALLBACK, FAIL, "traversal operator failed") + + /* Free tempname */ + tempname = (char *)H5MM_xfree(tempname); + + /* Check access flags */ + if((intent & H5F_ACC_TRUNC) || (intent & H5F_ACC_EXCL)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file open flags") + } /* end if */ + + /* Set file close degree for new file to "weak" */ if(H5P_set(fa_plist, H5F_ACS_CLOSE_DEGREE_NAME, &fc_degree) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file close degree") @@ -277,7 +333,8 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group, /* try searching from paths set in the environment variable */ if ((ext_file == NULL) && (env_prefix=HDgetenv("HDF5_EXT_PREFIX"))) { - tmp_env_prefix = H5MM_strdup(env_prefix); + if ((tmp_env_prefix = H5MM_strdup(env_prefix)) == NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") pp = tmp_env_prefix; while ((tmp_env_prefix) && (*tmp_env_prefix)) { @@ -290,14 +347,13 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group, ext_file = H5F_open(full_name, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY), H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id); if (full_name) - H5MM_xfree(full_name); + H5MM_free(full_name); if (ext_file != NULL) break; H5E_clear_stack(NULL); } } /* end while */ - if (pp) - H5MM_xfree(pp); + pp = (char *)H5MM_xfree(pp); } /* try searching from property list */ @@ -311,7 +367,7 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group, H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)) == NULL) H5E_clear_stack(NULL); if (full_name) - H5MM_xfree(full_name); + H5MM_free(full_name); } } @@ -323,7 +379,7 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group, H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)) == NULL) H5E_clear_stack(NULL); if (full_name) - H5MM_xfree(full_name); + H5MM_free(full_name); } /* try the relative file_name stored in tempname */ @@ -333,8 +389,7 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group, HGOTO_ERROR(H5E_LINK, H5E_CANTOPENFILE, FAIL, "unable to open external file") } - if (tempname) - H5MM_xfree(tempname); + tempname = (char *)H5MM_xfree(tempname); /* Increment the number of open objects, to hold the file open */ H5F_incr_nopen_objs(ext_file); @@ -367,9 +422,14 @@ done: if(ext_file && H5F_try_close(ext_file) < 0) HDONE_ERROR(H5E_LINK, H5E_CANTCLOSEFILE, FAIL, "problem closing external file") - /* Close object if it's open and something failed */ - if(ret_value < 0 && ext_obj >= 0 && H5I_dec_ref(ext_obj, FALSE) < 0) - HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom for external object") + if(ret_value < 0) { + H5MM_xfree(tempname); + H5MM_xfree(pp); + + /* Close object if it's open and something failed */ + if(ext_obj >= 0 && H5I_dec_ref(ext_obj, FALSE) < 0) + HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom for external object") + } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5L_extern_traverse() */ diff --git a/src/H5Lprivate.h b/src/H5Lprivate.h index cd17a87..f3079bc 100644 --- a/src/H5Lprivate.h +++ b/src/H5Lprivate.h @@ -39,15 +39,23 @@ #define H5L_CRT_INTERMEDIATE_GROUP_NAME "intermediate_group" /* Create intermediate groups flag */ /* ======== Link access property names ======== */ -#define H5L_ACS_NLINKS_NAME "max soft links" /* Number of soft links to traverse */ -#define H5L_ACS_ELINK_PREFIX_NAME "external link prefix" /* External link prefix */ -#define H5L_ACS_ELINK_FAPL_NAME "external link fapl" /* file access property list for external link access */ +#define H5L_ACS_NLINKS_NAME "max soft links" /* Number of soft links to traverse */ +#define H5L_ACS_ELINK_PREFIX_NAME "external link prefix" /* External link prefix */ +#define H5L_ACS_ELINK_FAPL_NAME "external link fapl" /* file access property list for external link access */ +#define H5L_ACS_ELINK_FLAGS_NAME "external link flags" /* file access flags for external link traversal */ +#define H5L_ACS_ELINK_CB_NAME "external link callback" /* callback function for external link traversal */ /****************************/ /* Library Private Typedefs */ /****************************/ +/* Structure for external link traversal callback property */ +typedef struct H5L_elink_cb_t { + H5L_elink_traverse_t func; + void *user_data; +} H5L_elink_cb_t; + /*****************************/ /* Library Private Variables */ diff --git a/src/H5Lpublic.h b/src/H5Lpublic.h index eba09b2..620d2e9 100644 --- a/src/H5Lpublic.h +++ b/src/H5Lpublic.h @@ -29,7 +29,6 @@ /* Public headers needed by this file */ #include "H5public.h" /* Generic Functions */ #include "H5Ipublic.h" /* IDs */ -#include "H5Ppublic.h" /* Property lists */ #include "H5Tpublic.h" /* Datatypes */ /*****************/ @@ -131,6 +130,12 @@ typedef struct { typedef herr_t (*H5L_iterate_t)(hid_t group, const char *name, const H5L_info_t *info, void *op_data); +/* Callback for external link traversal */ +typedef herr_t (*H5L_elink_traverse_t)(const char *parent_file_name, + const char *parent_group_name, const char *child_file_name, + const char *child_object_name, unsigned *acc_flags, hid_t fapl_id, + void *op_data); + /********************/ /* Public Variables */ diff --git a/src/H5Odbg.c b/src/H5Odbg.c index 7a49f75..8a8b783 100644 --- a/src/H5Odbg.c +++ b/src/H5Odbg.c @@ -37,6 +37,7 @@ #include "H5Eprivate.h" /* Error handling */ #include "H5MMprivate.h" /* Memory management */ #include "H5Opkg.h" /* Object headers */ +#include "H5Ppublic.h" /* Property Lists */ /****************/ /* Local Macros */ diff --git a/src/H5Plapl.c b/src/H5Plapl.c index e7b4381..608240f 100644 --- a/src/H5Plapl.c +++ b/src/H5Plapl.c @@ -62,6 +62,14 @@ #define H5L_ACS_ELINK_FAPL_COPY H5P_lacc_elink_fapl_copy #define H5L_ACS_ELINK_FAPL_CLOSE H5P_lacc_elink_fapl_close +/* Definitions for file access flags for external link traversal */ +#define H5L_ACS_ELINK_FLAGS_SIZE sizeof(unsigned) +#define H5L_ACS_ELINK_FLAGS_DEF H5F_ACC_DEFAULT + +/* Definitions for callback function for external link traversal */ +#define H5L_ACS_ELINK_CB_SIZE sizeof(H5L_elink_cb_t) +#define H5L_ACS_ELINK_CB_DEF {NULL,NULL} + /******************/ /* Local Typedefs */ /******************/ @@ -142,6 +150,9 @@ H5P_lacc_reg_prop(H5P_genclass_t *pclass) size_t nlinks = H5L_ACS_NLINKS_DEF; /* Default number of soft links to traverse */ char *elink_prefix = H5L_ACS_ELINK_PREFIX_DEF; /* Default external link prefix string */ hid_t def_fapl_id = H5L_ACS_ELINK_FAPL_DEF; /* Default fapl for external link access */ + unsigned elink_flags = H5L_ACS_ELINK_FLAGS_DEF; /* Default file access flags for external link traversal */ + H5L_elink_cb_t elink_cb = H5L_ACS_ELINK_CB_DEF; /* Default external link traversal callback */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5P_lacc_reg_prop) @@ -160,6 +171,16 @@ H5P_lacc_reg_prop(H5P_genclass_t *pclass) if(H5P_register(pclass, H5L_ACS_ELINK_FAPL_NAME, H5L_ACS_ELINK_FAPL_SIZE, &def_fapl_id, NULL, NULL, NULL, H5L_ACS_ELINK_FAPL_DEL, H5L_ACS_ELINK_FAPL_COPY, NULL, H5L_ACS_ELINK_FAPL_CLOSE) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + /* Register property for external link file access flags */ + if(H5P_register(pclass, H5L_ACS_ELINK_FLAGS_NAME, H5L_ACS_ELINK_FLAGS_SIZE, + &elink_flags, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + + /* Register property for external link file traversal callback */ + if(H5P_register(pclass, H5L_ACS_ELINK_CB_NAME, H5L_ACS_ELINK_CB_SIZE, + &elink_cb, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5P_lacc_reg_prop() */ @@ -634,3 +655,167 @@ done: FUNC_LEAVE_API(ret_value); } /* end H5Pget_elink_fapl() */ + +/*------------------------------------------------------------------------- + * Function: H5Pset_elink_acc_flags + * + * Purpose: Sets the file access flags to be used when traversing an + * external link. This should be either H5F_ACC_RDONLY or + * H5F_ACC_RDWR, or H5F_ACC_DEFAULT to unset the value. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * Tuesday, December 9, 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_elink_acc_flags(hid_t lapl_id, unsigned flags) +{ + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Pset_elink_acc_flags, FAIL) + H5TRACE2("e", "iIu", lapl_id, flags); + + /* Check that flags are valid */ + if((flags != H5F_ACC_RDWR) && (flags != H5F_ACC_RDONLY) && (flags != H5F_ACC_DEFAULT)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file open flags") + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(lapl_id, H5P_LINK_ACCESS))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Set flags */ + if(H5P_set(plist, H5L_ACS_ELINK_FLAGS_NAME, &flags) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set access flags") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_elink_acc_flags() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pget_elink_acc_flags + * + * Purpose: Gets the file access flags to be used when traversing an + * external link. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * Tuesday, December 9, 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_elink_acc_flags(hid_t lapl_id, unsigned *flags) +{ + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Pget_elink_acc_flags, FAIL) + H5TRACE2("e", "i*Iu", lapl_id, flags); + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(lapl_id, H5P_LINK_ACCESS))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get flags */ + if (flags) + if(H5P_get(plist, H5L_ACS_ELINK_FLAGS_NAME, flags)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, 0, "can't get access flags") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pget_elink_acc_flags() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pset_elink_cb + * + * Purpose: Sets the file access flags to be used when traversing an + * external link. This should be either H5F_ACC_RDONLY or + * H5F_ACC_RDWR. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * Tuesday, December 15, 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_elink_cb(hid_t lapl_id, H5L_elink_traverse_t func, void *op_data) +{ + H5P_genplist_t *plist; /* Property list pointer */ + H5L_elink_cb_t cb_info; /* Callback info struct */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Pset_elink_cb, FAIL) + H5TRACE3("e", "ix*x", lapl_id, func, op_data); + + /* Check if the callback function is NULL and the user data is non-NULL. + * This is almost certainly an error as the user data will not be used. */ + if(!func && op_data) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "callback is NULL while user data is not") + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(lapl_id, H5P_LINK_ACCESS))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Populate the callback info struct */ + cb_info.func = func; + cb_info.user_data = op_data; + + /* Set callback info */ + if(H5P_set(plist, H5L_ACS_ELINK_CB_NAME, &cb_info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set callback info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_elink_acc_flags() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pget_elink_cb + * + * Purpose: Gets the file access flags to be used when traversing an + * external link. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * Tuesday, December 15, 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_elink_cb(hid_t lapl_id, H5L_elink_traverse_t *func, void **op_data) +{ + H5P_genplist_t *plist; /* Property list pointer */ + H5L_elink_cb_t cb_info; /* Callback info struct */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Pget_elink_cb, FAIL) + H5TRACE3("e", "i*x**x", lapl_id, func, op_data); + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(lapl_id, H5P_LINK_ACCESS))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get callback_info */ + if(H5P_get(plist, H5L_ACS_ELINK_CB_NAME, &cb_info)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get callback info") + + if(func) + *func = cb_info.func; + + if(op_data) + *op_data = cb_info.user_data; + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pget_elink_cb() */ + diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h index 498eecc..a67ea71 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -29,6 +29,7 @@ #include "H5Fpublic.h" #include "H5FDpublic.h" #include "H5Ipublic.h" +#include "H5Lpublic.h" #include "H5MMpublic.h" #include "H5Tpublic.h" #include "H5Zpublic.h" @@ -46,9 +47,6 @@ #define H5OPEN #endif /* _H5private_H */ -/* Default value for all property list classes */ -#define H5P_DEFAULT 0 - /* * The library's property list classes */ @@ -384,6 +382,10 @@ H5_DLL herr_t H5Pset_elink_prefix(hid_t plist_id, const char *prefix); H5_DLL ssize_t H5Pget_elink_prefix(hid_t plist_id, char *prefix, size_t size); H5_DLL hid_t H5Pget_elink_fapl(hid_t lapl_id); H5_DLL herr_t H5Pset_elink_fapl(hid_t lapl_id, hid_t fapl_id); +H5_DLL herr_t H5Pset_elink_acc_flags(hid_t lapl_id, unsigned flags); +H5_DLL herr_t H5Pget_elink_acc_flags(hid_t lapl_id, unsigned *flags); +H5_DLL herr_t H5Pset_elink_cb(hid_t lapl_id, H5L_elink_traverse_t func, void *op_data); +H5_DLL herr_t H5Pget_elink_cb(hid_t lapl_id, H5L_elink_traverse_t *func, void **op_data); /* Object copy property list (OCPYPL) routines */ H5_DLL herr_t H5Pset_copy_object(hid_t plist_id, unsigned crt_intmd); diff --git a/src/H5Tdeprec.c b/src/H5Tdeprec.c index df6238c..0314a38 100644 --- a/src/H5Tdeprec.c +++ b/src/H5Tdeprec.c @@ -44,6 +44,7 @@ #include "H5Eprivate.h" /* Error handling */ #include "H5FOprivate.h" /* File objects */ #include "H5Iprivate.h" /* IDs */ +#include "H5Ppublic.h" /* Property Lists */ #include "H5Tpkg.h" /* Datatypes */ diff --git a/src/H5public.h b/src/H5public.h index e926473..cf9ff14 100644 --- a/src/H5public.h +++ b/src/H5public.h @@ -264,6 +264,9 @@ typedef signed long_long hssize_t; # error "nothing appropriate for uint64_t" #endif +/* Default value for all property list classes */ +#define H5P_DEFAULT 0 + /* Common iteration orders */ typedef enum { H5_ITER_UNKNOWN = -1, /* Unknown order */ diff --git a/test/cache.c b/test/cache.c index bc89102..24c1f6c 100644 --- a/test/cache.c +++ b/test/cache.c @@ -23,6 +23,12 @@ #include "H5Iprivate.h" #include "H5ACprivate.h" #include "cache_common.h" +#include +#include +#include +#include +#include + /* private function declarations: */ @@ -2987,6 +2993,7 @@ static void check_flush_cache(void) { const char * fcn_name = "check_flush_cache"; + hbool_t show_progress = FALSE; H5C_t * cache_ptr = NULL; TESTING("H5C_flush_cache() functionality"); @@ -3000,6 +3007,11 @@ check_flush_cache(void) if ( pass ) { + if ( show_progress ) { + + HDfprintf(stdout, "%s: reseting entries.\n", fcn_name); + } + reset_entries(); cache_ptr = setup_cache((size_t)(2 * 1024 * 1024), @@ -3012,6 +3024,12 @@ check_flush_cache(void) if ( pass ) { + if ( show_progress ) { + + HDfprintf(stdout, "%s: calling check_flush_cache__empty_cache().\n", + fcn_name); + } + check_flush_cache__empty_cache(cache_ptr); } @@ -3021,21 +3039,45 @@ check_flush_cache(void) if ( pass ) { + if ( show_progress ) { + + HDfprintf(stdout, "%s: calling check_flush_cache__single_entry().\n", + fcn_name); + } + check_flush_cache__single_entry(cache_ptr); } if ( pass ) { + if ( show_progress ) { + + HDfprintf(stdout, "%s: calling check_flush_cache__multi_entry().\n", + fcn_name); + } + check_flush_cache__multi_entry(cache_ptr); } if ( pass ) { + if ( show_progress ) { + + HDfprintf(stdout, "%s: calling check_flush_cache__flush_ops().\n", + fcn_name); + } + check_flush_cache__flush_ops(cache_ptr); } if ( pass ) { + if ( show_progress ) { + + HDfprintf(stdout, "%s: calling takedown_cache().\n", + fcn_name); + } + takedown_cache(cache_ptr, FALSE, FALSE); } @@ -9211,9 +9253,12 @@ check_flush_cache__flush_op_test(H5C_t * cache_ptr, int check_size, struct fo_flush_entry_check check[]) { - /* const char * fcn_name = "check_flush_cache__flush_op_test"; */ + const char * fcn_name = "check_flush_cache__flush_op_test"; static char msg[128]; + hbool_t show_progress = FALSE; + hbool_t verbose = FALSE; herr_t result; + int target_test = -1; int i; int j; test_entry_t * base_addr; @@ -9224,6 +9269,17 @@ check_flush_cache__flush_op_test(H5C_t * cache_ptr, test_num); #endif + if ( ( target_test > 0 ) && ( test_num != target_test ) ) { + + show_progress = FALSE; + } + + if ( show_progress ) { + + HDfprintf(stdout, "%s:%d:%d: running sanity checks on entry(1).\n", + fcn_name, test_num, (int)pass); + } + if ( cache_ptr == NULL ) { pass = FALSE; @@ -9251,6 +9307,12 @@ check_flush_cache__flush_op_test(H5C_t * cache_ptr, failure_mssg = msg; } + if ( show_progress ) { + + HDfprintf(stdout, "%s:%d:%d: running sanity checks on entry(2).\n", + fcn_name, test_num, (int)pass); + } + i = 0; while ( ( pass ) && ( i < spec_size ) ) { @@ -9273,6 +9335,12 @@ check_flush_cache__flush_op_test(H5C_t * cache_ptr, i++; } + if ( show_progress ) { + + HDfprintf(stdout, "%s:%d:%d: running sanity checks on entry(3).\n", + fcn_name, test_num, (int)pass); + } + i = 0; while ( ( pass ) && ( i < check_size ) ) { @@ -9310,18 +9378,54 @@ check_flush_cache__flush_op_test(H5C_t * cache_ptr, i++; } + if ( show_progress ) { + + HDfprintf(stdout, "%s:%d:%d: Setting up the test.\n", + fcn_name, test_num, (int)pass); + } + i = 0; while ( ( pass ) && ( i < spec_size ) ) { if ( spec[i].insert_flag ) { + if ( show_progress ) { + + HDfprintf(stdout, + "%s:%d: Inserting entry(%d,%d) with flags 0x%x.\n", + fcn_name, test_num, + (int)(spec[i].entry_type), + (int)(spec[i].entry_index), + (unsigned)spec[i].flags); + } + insert_entry(cache_ptr, spec[i].entry_type, spec[i].entry_index, TRUE, spec[i].flags); } else { + if ( show_progress ) { + + HDfprintf(stdout, + "%s:%d: Protecting entry(%d,%d).\n", + fcn_name, test_num, + (int)(spec[i].entry_type), + (int)(spec[i].entry_index)); + } + protect_entry(cache_ptr, spec[i].entry_type, spec[i].entry_index); + if ( show_progress ) { + + HDfprintf(stdout, + "%s:%d: Unprotecting entry(%d,%d) with flags 0x%x ns = %d.\n", + fcn_name, test_num, + (int)(spec[i].entry_type), + (int)(spec[i].entry_index), + (unsigned)spec[i].flags, + (int)(spec[i].new_size)); + } + unprotect_entry_with_size_change(cache_ptr, spec[i].entry_type, spec[i].entry_index, spec[i].flags, spec[i].new_size); @@ -9363,6 +9467,12 @@ check_flush_cache__flush_op_test(H5C_t * cache_ptr, } } + if ( show_progress ) { + + HDfprintf(stdout, "%s:%d:%d: Running the test.\n", + fcn_name, test_num, (int)pass); + } + if ( pass ) { result = H5C_flush_cache(NULL, -1, -1, cache_ptr, flush_flags); @@ -9377,6 +9487,11 @@ check_flush_cache__flush_op_test(H5C_t * cache_ptr, } } + if ( show_progress ) { + + HDfprintf(stdout, "%s:%d:%d: Checking test results(1).\n", + fcn_name, test_num, (int)pass); + } i = 0; while ( ( pass ) && ( i < spec_size ) ) @@ -9415,6 +9530,12 @@ check_flush_cache__flush_op_test(H5C_t * cache_ptr, i++; } + if ( show_progress ) { + + HDfprintf(stdout, "%s:%d:%d: Checking test results(2).\n", + fcn_name, test_num, (int)pass); + } + if ( pass ) { i = 0; @@ -9533,6 +9654,12 @@ check_flush_cache__flush_op_test(H5C_t * cache_ptr, } } + if ( show_progress ) { + + HDfprintf(stdout, "%s:%d:%d: Checking test results(3).\n", + fcn_name, test_num, (int)pass); + } + if ( pass ) { if ( ( ( (flush_flags & H5C__FLUSH_INVALIDATE_FLAG) == 0 ) @@ -9561,6 +9688,13 @@ check_flush_cache__flush_op_test(H5C_t * cache_ptr, } /* clean up the cache to prep for the next test */ + + if ( show_progress ) { + + HDfprintf(stdout, "%s:%d:%d: Cleaning up after test(1).\n", + fcn_name, test_num, (int)pass); + } + if ( pass ) { result = H5C_flush_cache(NULL, -1, -1, cache_ptr, @@ -9575,17 +9709,35 @@ check_flush_cache__flush_op_test(H5C_t * cache_ptr, failure_mssg = msg; } else if ( ( cache_ptr->index_len != 0 ) || - ( cache_ptr->index_size != 0 ) ) { + ( cache_ptr->index_size != 0 ) || + ( cache_ptr->clean_index_size != 0 ) || + ( cache_ptr->dirty_index_size != 0 ) ) { pass = FALSE; + + if ( verbose ) { + + HDfprintf(stdout, "%s:%d: il/is/cis/dis = %lld/%lld/%lld/%lld.\n", + fcn_name, test_num, + (long long)(cache_ptr->index_len), + (long long)(cache_ptr->index_size), + (long long)(cache_ptr->clean_index_size), + (long long)(cache_ptr->dirty_index_size)); + } HDsnprintf(msg, (size_t)128, - "Unexpected cache len/size after cleanup in flush op test #%d.", + "Unexpected cache len/size/cs/ds after cleanup in flush op test #%d.", test_num); failure_mssg = msg; } } + if ( show_progress ) { + + HDfprintf(stdout, "%s:%d:%d: Cleaning up after test(2).\n", + fcn_name, test_num, (int)pass); + } + i = 0; while ( ( pass ) && ( i < spec_size ) ) { @@ -9602,6 +9754,12 @@ check_flush_cache__flush_op_test(H5C_t * cache_ptr, i++; } + if ( show_progress ) { + + HDfprintf(stdout, "%s:%d:%d: Cleaning up after test(3).\n", + fcn_name, test_num, (int)pass); + } + i = 0; while ( ( pass ) && ( i < check_size ) ) { @@ -9618,6 +9776,11 @@ check_flush_cache__flush_op_test(H5C_t * cache_ptr, i++; } + if ( show_progress ) { + + HDfprintf(stdout, "%s:%d:%d: Done.\n", fcn_name, test_num, (int)pass); + } + return; } /* check_flush_cache__flush_op_test() */ @@ -9716,30 +9879,34 @@ check_flush_cache__flush_op_eviction_test(H5C_t * cache_ptr) { LARGE_ENTRY_TYPE, 13, LARGE_ENTRY_SIZE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE } }; - if ( cache_ptr == NULL ) { + if ( pass ) { - 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 ) ) { + if ( cache_ptr == NULL ) { - 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 = "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 = "unexpected cache config at start of flush op eviction test."; + 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 ) ) ) { - } else { + pass = FALSE; + failure_mssg = + "unexpected cache config at start of flush op eviction test."; - /* set min clean size to zero for this test as it simplifies - * computing the expected cache size after each operation. - */ + } else { - cache_ptr->min_clean_size = 0; + /* 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 ) { @@ -10793,7 +10960,8 @@ check_flush_cache__flush_op_eviction_test(H5C_t * cache_ptr) static void check_flush_cache__single_entry(H5C_t * cache_ptr) { - /* const char * fcn_name = "check_flush_cache__single_entry"; */ + const char * fcn_name = "check_flush_cache__single_entry"; + hbool_t show_progress = FALSE; if ( cache_ptr == NULL ) { @@ -10809,6 +10977,10 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 1); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -10824,10 +10996,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 2); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -10843,10 +11023,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 3); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -10862,10 +11050,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 4); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -10881,10 +11077,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 5); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -10900,10 +11104,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 6); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -10919,10 +11131,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 7); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -10938,10 +11158,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 8); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -10957,10 +11185,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 9); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -10977,10 +11213,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 10); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -10997,10 +11241,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 11); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11017,10 +11269,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 12); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11037,10 +11297,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 13); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11057,10 +11325,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 14); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11077,10 +11353,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 15); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11098,10 +11382,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 16); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11119,10 +11411,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 17); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11138,10 +11438,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 18); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11157,10 +11465,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 19); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11176,10 +11492,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 20); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11195,10 +11519,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 21); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11214,10 +11546,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 22); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11233,10 +11573,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 23); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11252,10 +11600,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 24); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11271,10 +11627,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 25); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11291,10 +11655,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 26); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11311,10 +11683,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 27); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11331,10 +11711,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 28); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11351,10 +11739,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 29); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11371,10 +11767,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 30); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11391,10 +11795,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 31); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11412,10 +11824,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 32); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11433,10 +11853,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 33); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11452,10 +11880,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 34); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11471,10 +11907,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 35); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11490,10 +11934,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 36); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11509,10 +11961,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 37); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11528,10 +11988,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 38); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11547,10 +12015,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 39); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11566,10 +12042,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 40); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11585,10 +12069,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 41); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11605,10 +12097,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 42); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11625,10 +12125,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 43); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11645,10 +12153,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 44); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11665,10 +12181,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 45); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11685,10 +12209,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 46); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11705,10 +12237,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 47); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11726,10 +12266,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 48); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11747,10 +12295,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 49); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11766,10 +12322,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 50); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11785,10 +12349,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 51); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11804,10 +12376,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 52); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11823,10 +12403,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 53); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11842,10 +12430,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 54); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11861,10 +12457,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 55); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11880,10 +12484,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 56); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11899,10 +12511,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 57); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11919,10 +12539,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 58); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11939,10 +12567,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 59); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11959,10 +12595,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 60); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11979,10 +12623,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ FALSE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 61); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -11999,10 +12651,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 62); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -12019,10 +12679,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ TRUE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 63); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -12040,10 +12708,18 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } if ( pass ) { + if ( show_progress ) { + HDfprintf(stdout, "%s: running test %d.\n", fcn_name, 64); + } + check_flush_cache__single_entry_test ( /* cache_ptr */ cache_ptr, @@ -12061,6 +12737,10 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) /* expected_flushed */ FALSE, /* expected_destroyed */ TRUE ); + + if ( show_progress ) { + HDfprintf(stdout, "%s: pass = %d.\n", fcn_name, (int)pass); + } } @@ -12409,6 +13089,11 @@ check_flush_cache__single_entry(H5C_t * cache_ptr) i = 0; while ( ( pass ) && ( i < 256 ) ) { + + if ( show_progress ) { + HDfprintf(stdout, "%s: running pinned test %d.\n", fcn_name, i); + } + check_flush_cache__pinned_single_entry_test ( /* cache_ptr */ cache_ptr, @@ -15967,7 +16652,7 @@ static void check_duplicate_insert_err(void) { const char * fcn_name = "check_duplicate_insert_err"; - herr_t result; + herr_t result = -1; H5C_t * cache_ptr = NULL; test_entry_t * base_addr; test_entry_t * entry_ptr; @@ -28154,6 +28839,878 @@ check_auto_cache_resize_aux_fcns(void) /*------------------------------------------------------------------------- + * Function: check_metadata_blizzard_absence() + * + * Purpose: Test to verify that a 'metadata blizzard' can not occur + * upon insertion into the cache. + * + * A 'metadata blizzard' in this context occurs when the cache + * gets completely filled with all dirty entries. Upon needing + * to make space in the cache, the cache then has no clean + * entries ready to evict, and must clean every dirty entry + * in the cache first, due to the second chance replacement + * policy. (i.e. after cleaning an entry, it is bumped to the + * top of the LRU to make a second pass before eviction). + * The massive amount of sequential writes to disk while + * flushing the entire cache is what constitutes a 'metadata + * blizzard'. + * + * Return: void + * + * Programmer: Mike McGreevy + * + * 12/16/08 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +static void +check_metadata_blizzard_absence(hbool_t fill_via_insertion) +{ + const char * fcn_name = "check_metadata_blizzard_absence"; + int entry_type = HUGE_ENTRY_TYPE; + size_t entry_size = HUGE_ENTRY_SIZE; /* 16 KB */ + H5C_t * cache_ptr = NULL; + hbool_t show_progress = FALSE; + int32_t checkpoint = 0; + int32_t entry_idx = 0; + int32_t i; + + /* Expected loaded status of entries depends on how they get into + * the cache. Insertions = not loaded, protect/unprotect = loaded. + */ + hbool_t loaded = !(fill_via_insertion); + + /* Set up the expected array. This is used to maintain a table of the + * expected status of every entry used in this test. + */ + struct expected_entry_status expected[150] = + { + /* entry entry in at main */ + /* type: index: size: cache: addr: dirty: prot: pinned: loaded: clrd: flshd: dest: */ + { entry_type, 0, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 1, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 2, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 3, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 4, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 5, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 6, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 7, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 8, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 9, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 10, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 11, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 12, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 13, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 14, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 15, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 16, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 17, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 18, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 19, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 20, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 21, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 22, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 23, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 24, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 25, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 26, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 27, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 28, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 29, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 30, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 31, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 32, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 33, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 34, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 35, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 36, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 37, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 38, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 39, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 40, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 41, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 42, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 43, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 44, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 45, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 46, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 47, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 48, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 49, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 50, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 51, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 52, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 53, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 54, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 55, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 56, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 57, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 58, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 59, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 60, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 61, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 62, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 63, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 64, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 65, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 66, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 67, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 68, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 69, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 70, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 71, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 72, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 73, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 74, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 75, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 76, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 77, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 78, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 79, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 80, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 81, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 82, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 83, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 84, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 85, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 86, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 87, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 88, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 89, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 90, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 91, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 92, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 93, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 94, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 95, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 96, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 97, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 98, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 99, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 100, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 101, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 102, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 103, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 104, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 105, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 106, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 107, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 108, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 109, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 110, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 111, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 112, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 113, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 114, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 115, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 116, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 117, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 118, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 119, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 120, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 121, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 122, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 123, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 124, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 125, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 126, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 127, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 128, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 129, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 130, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 131, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 132, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 133, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 134, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 135, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 136, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 137, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 138, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 139, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 140, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 141, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 142, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 143, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 144, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 145, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 146, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 147, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 148, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { entry_type, 149, entry_size, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE } + }; + + pass = TRUE; + + if (fill_via_insertion) { + + TESTING("to ensure metadata blizzard absence when inserting"); + + } else { + + TESTING("to ensure metadata blizzard absence on protect/unprotect"); + } + + if ( show_progress) /* 0 */ + HDfprintf(stdout, "\n%s: check point %d -- pass %d\n", + fcn_name, checkpoint++, pass); + + if ( pass ) { + + /* Set up the cache. + * + * The max_cache_size should have room for 50 entries. + * The min_clean_size is half of that, or 25 entries. + */ + cache_ptr = setup_cache((size_t)(50 * entry_size), /* max_cache_size */ + (size_t)(25 * entry_size)); /* min_clean_size */ + + if ( cache_ptr == NULL) { + + pass = FALSE; + failure_mssg = "bad return from cache intialization.\n"; + } + } + + if ( show_progress) /* 1 */ + HDfprintf(stdout, "%s: check point %d -- pass %d\n", + fcn_name, checkpoint++, pass); + + /* ======================================================================== + * ======================================================================== + * Phase 1: + * + * Inserting dirty entries into an empty cache, until the cache + * violates the min_clean_size requirement. The expected result is + * that none of the inserted entries during this phase will get + * flushed or evicted. + * + * This verifies that while maintaining min_clean_size, we don't go + * overboard and flush entries that we don't need to flush. + * + * ======================================================================== + * ======================================================================== + */ + + if ( pass ) { + + /* Insert 26 entries (indexes 0 through 25) into the cache. + * + * Note that we are inserting 26 entries, and not 25, because the cache + * will only try to adhere to the min_clean_size if it's currently + * being violated. Thus, on insertion of the 26th entry, since the + * min_clean_size will not be violated, it will accept the insertion + * without having to make clean space. + */ + + for (entry_idx = 0; entry_idx < 26; entry_idx++) { + + if (fill_via_insertion) { + insert_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx, /* int32_t idx */ + TRUE, /* hbool_t dirty */ + H5C__NO_FLAGS_SET); /* unsigned int flags */ + + } else { + protect_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx); /* int32-t idx */ + + unprotect_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx, /* int32_t idx */ + TRUE, /* int321_t dirty */ + H5C__NO_FLAGS_SET); /* unsigned int flags */ + } + + /* Change expected values, and verify the status of the entries + * after each insertion + */ + expected[entry_idx].in_cache = TRUE; + expected[entry_idx].is_dirty = TRUE; + expected[entry_idx].loaded = loaded; + + verify_entry_status(cache_ptr, /* H5C_t * cache_ptr */ + entry_idx, /* int tag */ + 150, /* int num_entries */ + expected); /* struct expected_entry_staus[] */ + } + } + + if ( show_progress) /* 2 */ + HDfprintf(stdout, "%s: check point %d -- pass %d\n", + fcn_name, checkpoint++, pass); + + /* ======================================================================== + * ======================================================================== + * Phase 2: + * + * Inserting entries into a cache that violates the min_clean_size, + * until the cache is full. The expected result is that each insertion + * will result in the flushing of a dirty entry in the cache. + * + * This verifies that we maintain the min_clean_size. By doing so, we + * prevent building the situation in which a 'metadata blizzard' would + * occur (i.e., the cache being completely filled with dirty entries). + * + * ======================================================================== + * ======================================================================== + */ + + if ( pass ) { + + /* Insert the 27th entry (index = 26) into the cache. + * + * This should cause the cache to flush its least recently used entry + * before the insertion because it doesn't satisfy the min_clean_size + * constraint. + */ + if (fill_via_insertion) { + insert_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx++, /* int32_t idx */ + TRUE, /* hbool_t dirty */ + H5C__NO_FLAGS_SET); /* unsigned int flags */ + } else { + protect_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx); /* int32-t idx */ + + unprotect_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx++, /* int32_t idx */ + TRUE, /* int321_t dirty */ + H5C__NO_FLAGS_SET); /* unsigned int flags */ + } + + /* Verify the status of the entries. + * + * Expected status is that there are 27 entries in the cache, and + * entry number 0 has been cleaned. + * + * Changes from last entry verification: + * - entry w/ index 0 has now been flushed and is now clean. + * - entry w/ index 26 is now in the cache and dirty. + */ + + /* entry w/ index 0 has now been flushed and is now clean. */ + expected[0].flushed = TRUE; + expected[0].is_dirty = FALSE; + + /* entry w/ index 26 is now in the cache and dirty. */ + expected[26].in_cache = TRUE; + expected[26].is_dirty = TRUE; + expected[26].loaded = loaded; + + /* verify the status */ + verify_entry_status(cache_ptr, /* H5C_t * cache_ptr */ + 26, /* int tag */ + 150, /* int num_entries */ + expected); /* expected */ + } + + if ( show_progress) /* 3 */ + HDfprintf(stdout, "%s: check point %d -- pass %d\n", + fcn_name, checkpoint++, pass); + + if ( pass ) { + + /* Insert the 28th entry (index = 27) into the cache. + * + * This should, once again, cause the cache to flush its least + * recently used entry before the insertion as it again does not + * satisfy the min_clean_size constraint. + */ + if (fill_via_insertion) { + insert_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx++, /* int32_t idx */ + TRUE, /* hbool_t dirty */ + H5C__NO_FLAGS_SET); /* unsigned int flags */ + } else { + protect_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx); /* int32-t idx */ + + unprotect_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx++, /* int32_t idx */ + TRUE, /* int321_t dirty */ + H5C__NO_FLAGS_SET); /* unsigned int flags */ + } + + /* Verify the status of the entries. + * + * Expected status is that there are 28 entries in the cache, and + * entry numbers 0 and 1 have been cleaned. + * + * Changes from last entry verification: + * - entry w/ index 1 has now been flushed and is now clean. + * - entry w/ index 27 is now in the cache and dirty. + */ + + /* entry w/ index 1 has now been flushed and is now clean. */ + expected[1].flushed = TRUE; + expected[1].is_dirty = FALSE; + + /* entry w/ index 27 is now in the cache and dirty. */ + expected[27].in_cache = TRUE; + expected[27].is_dirty = TRUE; + expected[27].loaded = loaded; + + /* verify the status */ + verify_entry_status(cache_ptr, /* H5C_t * cache_ptr */ + 27, /* int tag */ + 150, /* int num_entries */ + expected); /* expected */ + } + + if ( show_progress) /* 4 */ + HDfprintf(stdout, "%s: check point %d -- pass %d\n", + fcn_name, checkpoint++, pass); + + if ( pass ) { + + /* Fill out the rest of the cache with entries */ + /* Verify expected status of entries after each insertion */ + for (entry_idx = entry_idx; entry_idx < 50; entry_idx++) { + + if (fill_via_insertion) { + insert_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx, /* int32_t idx */ + TRUE, /* hbool_t dirty */ + H5C__NO_FLAGS_SET); /* unsigned int flags */ + } else { + protect_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx); /* int32-t idx */ + + unprotect_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx, /* int32_t idx */ + TRUE, /* int321_t dirty */ + H5C__NO_FLAGS_SET); /* unsigned int flags */ + } + + /* Expected staus is that after each insertion, the entry + * inserted 26 insertions ago has been flushed, and the + * entry currently getting inserted is now in the cache and + * dirty. + */ + expected[entry_idx - 26].flushed = TRUE; + expected[entry_idx - 26].is_dirty = FALSE; + + expected[entry_idx].in_cache = TRUE; + expected[entry_idx].is_dirty = TRUE; + expected[entry_idx].loaded = loaded; + + /* verify the status */ + verify_entry_status(cache_ptr, /* H5C_t * cache_ptr */ + entry_idx, /* int tag */ + 150, /* int num_entries */ + expected); /* expected */ + } + + /* Verify that the cache is now full */ + if ( cache_ptr->cache_full != TRUE ) { + + pass = FALSE; + failure_mssg = "cache not completely filled.\n"; + } + } + + if ( show_progress) /* 5 */ + HDfprintf(stdout, "%s: check point %d -- pass %d\n", + fcn_name, checkpoint++, pass); + + /* ======================================================================== + * ======================================================================== + * Phase 3: + * + * Inserting entries into a cache that is completely full. Insertions + * of new entries will force evictions of old entries, but since the + * min_clean_size has been maintained, doing so will not result in + * the entire cache getting flushed in order to evict a single entry, + * as a clean entry will be available to flush reasonably close to + * the bottom of the LRU. + * + * This verifies that with a maintained min_clean_size, a metadata + * blizzard does not occur on insertion. + * + * ======================================================================== + * ======================================================================== + */ + + if ( pass ) { + + /* Insert the 51st entry (index = 50) into the cache. + * + * The cache is full prior to the insertion, so it will + * have to evict in order to make room for the new entry. + */ + if (fill_via_insertion) { + insert_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx++, /* int32_t idx */ + TRUE, /* hbool_t dirty */ + H5C__NO_FLAGS_SET); /* unsigned int flags */ + } else { + protect_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx); /* int32-t idx */ + + unprotect_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx++, /* int32_t idx */ + TRUE, /* int321_t dirty */ + H5C__NO_FLAGS_SET); /* unsigned int flags */ + } + + /* Verify the status of the entries. + * + * Changes from last entry verification: + * - entry w/ index 0 has been evicted. + * - entries w/ indices 24,25 have now been flushed and are clean. + * - entry w/ index 50 is now in the cache and dirty. + */ + + /* entry w/ index 0 has been evicted. */ + expected[0].in_cache = FALSE; + expected[0].destroyed = TRUE; + + /* entries w/ indices 24,25 have now been flushed and are clean. */ + expected[24].flushed = TRUE; + expected[24].is_dirty = FALSE; + expected[25].flushed = TRUE; + expected[25].is_dirty = FALSE; + + /* entry w/ index 50 is now in the cache and dirty */ + expected[50].in_cache = TRUE; + expected[50].is_dirty = TRUE; + expected[50].loaded = loaded; + + /* verify the status */ + verify_entry_status(cache_ptr, /* H5C_t * cache_ptr */ + 50, /* int tag */ + 150, /* int num_entries */ + expected); /* expected */ + } + + if ( show_progress) /* 6 */ + HDfprintf(stdout, "%s: check point %d -- pass %d\n", + fcn_name, checkpoint++, pass); + + + if ( pass ) { + + /* Insert 49 more entries (indices 51-99) into the cache. + * + * The cache will be flushing an entry on each insertion, and + * evicting an entry on each insertion. + * + * After each insertion, verify the expected status of the + * entries in the cache. + */ + for (entry_idx = entry_idx; entry_idx < 100; entry_idx++) { + + if (fill_via_insertion) { + insert_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx, /* int32_t idx */ + TRUE, /* hbool_t dirty */ + H5C__NO_FLAGS_SET); /* unsigned int flags */ + } else { + protect_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx); /* int32-t idx */ + + unprotect_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx, /* int32_t idx */ + TRUE, /* int321_t dirty */ + H5C__NO_FLAGS_SET); /* unsigned int flags */ + } + + /* This past inserted entry is now in the cache and dirty */ + expected[entry_idx].in_cache = TRUE; + expected[entry_idx].is_dirty = TRUE; + expected[entry_idx].loaded = loaded; + + /* The entry inserted 50 insertions ago has been evicted */ + expected[entry_idx - 50].in_cache = FALSE; + expected[entry_idx - 50].destroyed = TRUE; + + /* If the newly inserted entry is among the first 24 + * insertions in this loop, then the insertion will + * have resulted in a flush of the entry inserted + * 25 insertions ago. */ + if (entry_idx < 75) { + + expected[entry_idx - 25].flushed = TRUE; + expected[entry_idx - 25].is_dirty = FALSE; + } + /* If the newly inserted entry is among the last + * 25 insertions in this loop, then the insertion will + * have resulted in a flush of the entry inserted 26 + * insertions ago. This switch is because there was two + * consecutive clean entries in the cache (due to 51/49 + * dirty/clean ratio when full), so instead of + * flush-then-evict, it switches to evict-then-flush. */ + else { + + expected[entry_idx - 26].flushed = TRUE; + expected[entry_idx - 26].is_dirty = FALSE; + } + + /* Verify this expected status */ + verify_entry_status(cache_ptr, /* H5C_t * cache_ptr */ + entry_idx, /* int tag */ + 150, /* int num_entries */ + expected); /* expected */ + } + } + + if ( show_progress) /* 7 */ + HDfprintf(stdout, "%s: check point %d -- pass %d\n", + fcn_name, checkpoint++, pass); + + /* ======================================================================== + * ======================================================================== + * Phase 4: + * + * Flushing the entire cache, and then inserting entries into a cache + * that is completely full, but all clean. + * + * Phases 1 and 2 are then repeated. Rather than inserting dirty entries + * into an empty cache, we're inserting into a full cache that's all + * clean, thus an eviction occurs before each insertion. + * + * When the cache finally hits the point of violating the + * min_clean_size, the bottom half of the LRU will be filled with + * clean entries and the top half will be filled with recently inserted + * dirty entries. We'll then verify that an insertion will only evict + * one entry and flush one entry, and no more. + * + * ======================================================================== + * ======================================================================== + */ + + if ( pass ) { + + /* Flush the cache. + * + * We're doing this so we can repeat the above insertions, but + * starting from a cache filled with clean entries as opposed + * to an empty cache. + */ + + flush_cache(cache_ptr, /* H5C_t * cache_ptr */ + FALSE, /* hbool_t destory_entries */ + FALSE, /* hbool_t dump_stats */ + FALSE); /* hbool_t dump_detailed_stats */ + + /* Verify that the cache is clean */ + verify_clean(); + + /* Verify the status of the entries. + * + * Changes from last entry verification: + * - entries w/ indices 74-99 have been flushed. + */ + + /* entries w/ indices 74-99 have been flushed. */ + for (i = 74; i < 100; i++) { + + expected[i].flushed = TRUE; + expected[i].is_dirty = FALSE; + } + verify_entry_status(cache_ptr, /* H5C_t * cache_ptr */ + 0, /* int tag */ + 150, /* int num_entries */ + expected); /* expected */ + } + + if ( show_progress) /* 8 */ + HDfprintf(stdout, "%s: check point %d -- pass %d\n", + fcn_name, checkpoint++, pass); + + if ( pass ) { + + /* Insert 26 entries (indexes 100 through 125) into the cache. + * + * The cache will evict 26 entries since it's currently full with + * all clean entries. None of the entries we're inserting now + * will get cleaned, however. + */ + + for (entry_idx = 100; entry_idx < 126; entry_idx++) { + + if (fill_via_insertion) { + insert_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx, /* int32_t idx */ + TRUE, /* hbool_t dirty */ + H5C__NO_FLAGS_SET); /* unsigned int flags */ + + } else { + protect_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx); /* int32-t idx */ + + unprotect_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx, /* int32_t idx */ + TRUE, /* int321_t dirty */ + H5C__NO_FLAGS_SET); /* unsigned int flags */ + } + + /* This past inserted entry is now in the cache and dirty */ + expected[entry_idx].in_cache = TRUE; + expected[entry_idx].is_dirty = TRUE; + expected[entry_idx].loaded = loaded; + + /* The entry with ID minus 50 will have been evicted */ + expected[entry_idx - 50].in_cache = FALSE; + expected[entry_idx - 50].destroyed = TRUE; + + /* verify the status */ + verify_entry_status(cache_ptr, /* H5C_t * cache_ptr */ + entry_idx, /* int tag */ + 150, /* int num_entries */ + expected); /* struct expected_entry_staus[] */ + } + } + + if ( show_progress) /* 9 */ + HDfprintf(stdout, "%s: check point %d -- pass %d\n", + fcn_name, checkpoint++, pass); + + if ( pass ) { + + /* Insert the 127th entry (index = 126) into the cache. */ + if (fill_via_insertion) { + insert_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx++, /* int32_t idx */ + TRUE, /* hbool_t dirty */ + H5C__NO_FLAGS_SET); /* unsigned int flags */ + } else { + protect_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx); /* int32-t idx */ + + unprotect_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx++, /* int32_t idx */ + TRUE, /* int321_t dirty */ + H5C__NO_FLAGS_SET); /* unsigned int flags */ + } + + /* Verify the status of the entries. + * + * Changes from last entry verification: + * - entry w/ index 76 is evicted. + * - entry w/ index 100 is cleaned. + * - entry w/ index 126 is now in the cache and dirty. + */ + + /* entry w/ index 76 has been evicted. */ + expected[76].in_cache = FALSE; + expected[76].destroyed = TRUE; + + /* entry w/ index 100 has now been flushed and is now clean. */ + expected[100].flushed = TRUE; + expected[100].is_dirty = FALSE; + + /* entry w/ index 26 is now in the cache and dirty. */ + expected[126].in_cache = TRUE; + expected[126].is_dirty = TRUE; + expected[126].loaded = loaded; + + /* verify the status */ + verify_entry_status(cache_ptr, /* H5C_t * cache_ptr */ + 126, /* int tag */ + 150, /* int num_entries */ + expected); /* expected */ + } + + if ( show_progress) /* 10 */ + HDfprintf(stdout, "%s: check point %d -- pass %d\n", + fcn_name, checkpoint++, pass); + + if ( pass ) { + + /* Insert entries w/ indices 127 through 149 into the cache */ + for (entry_idx = 127; entry_idx < 150; entry_idx++) { + + if (fill_via_insertion) { + insert_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx, /* int32_t idx */ + TRUE, /* hbool_t dirty */ + H5C__NO_FLAGS_SET); /* unsigned int flags */ + + } else { + protect_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx); /* int32-t idx */ + + unprotect_entry(cache_ptr, /* H5C_t * cache_ptr */ + entry_type, /* int32_t type */ + entry_idx, /* int32_t idx */ + TRUE, /* int321_t dirty */ + H5C__NO_FLAGS_SET); /* unsigned int flags */ + } + + /* This past inserted entry is now in the cache and dirty */ + expected[entry_idx].in_cache = TRUE; + expected[entry_idx].is_dirty = TRUE; + expected[entry_idx].loaded = loaded; + + /* The entry with ID minus 50 will have been evicted */ + expected[entry_idx - 50].in_cache = FALSE; + expected[entry_idx - 50].destroyed = TRUE; + + /* The entry with ID minus 26 will now be clean */ + expected[entry_idx - 26].flushed = TRUE; + expected[entry_idx - 26].is_dirty = FALSE; + + /* verify the status */ + verify_entry_status(cache_ptr, /* H5C_t * cache_ptr */ + entry_idx, /* int tag */ + 150, /* int num_entries */ + expected); /* struct expected_entry_staus[] */ + } + + } + + if ( show_progress) /* 11 */ + HDfprintf(stdout, "%s: check point %d -- pass %d\n", + fcn_name, checkpoint++, pass); + + if ( pass ) { + + /* We're done with testing. We can take down the cache. */ + takedown_cache(cache_ptr, FALSE, FALSE); + reset_entries(); + } + + if ( show_progress) /* 12 */ + HDfprintf(stdout, "%s: check point %d -- pass %d\n", + fcn_name, checkpoint++, pass); + + if ( pass ) { PASSED(); } else { H5_FAILED(); } + + return; + +} /* check_metadata_blizzard_absence() */ + + +/*------------------------------------------------------------------------- * Function: main * * Purpose: Run tests on the cache code contained in H5C.c @@ -28231,7 +29788,7 @@ main(void) check_auto_cache_resize_epoch_markers(); check_auto_cache_resize_input_errs(); check_auto_cache_resize_aux_fcns(); - + check_metadata_blizzard_absence(TRUE); + check_metadata_blizzard_absence(FALSE); return(0); - -} /* main() */ +} diff --git a/test/cache_common.c b/test/cache_common.c index c2ce274..39131bf 100644 --- a/test/cache_common.c +++ b/test/cache_common.c @@ -1133,7 +1133,7 @@ variable_size(H5F_t * f, void * thing, size_t * size_ptr) /*------------------------------------------------------------------------- * Function: add_flush_op * - * Purpose: Do noting if pass is FALSE on entry. + * Purpose: Do nothing if pass is FALSE on entry. * * Otherwise, add the specified flush operation to the * target instance of test_entry_t. @@ -1199,7 +1199,7 @@ add_flush_op(int target_type, /*------------------------------------------------------------------------- * Function: create_pinned_entry_dependency * - * Purpose: Do noting if pass is FALSE on entry. + * Purpose: Do nothing if pass is FALSE on entry. * * Otherwise, set up a pinned entry dependency so we can * test the pinned entry modifications to the flush routine. @@ -2339,7 +2339,9 @@ flush_cache(H5C_t * cache_ptr, hbool_t dump_stats, hbool_t dump_detailed_stats) { + const char * fcn_name = "flush_cache()"; herr_t result = 0; + hbool_t verbose = FALSE; HDassert(cache_ptr); @@ -2369,6 +2371,26 @@ flush_cache(H5C_t * cache_ptr, pass = FALSE; failure_mssg = "error in H5C_flush_cache()."; } + else if ( ( destroy_entries ) && + ( ( cache_ptr->index_len != 0 ) || + ( cache_ptr->index_size != 0 ) || + ( cache_ptr->clean_index_size != 0 ) || + ( cache_ptr->dirty_index_size != 0 ) ) ) { + + if ( verbose ) { + HDfprintf(stdout, + "%s: unexpected il/is/cis/dis = %lld/%lld/%lld/%lld.\n", + fcn_name, + (long long)(cache_ptr->index_len), + (long long)(cache_ptr->index_size), + (long long)(cache_ptr->clean_index_size), + (long long)(cache_ptr->dirty_index_size)); + } + pass = FALSE; + failure_mssg = + "non zero index len/sizes after H5C_flush_cache() with invalidate."; + } + return; @@ -3229,12 +3251,13 @@ unprotect_entry_with_size_change(H5C_t * cache_ptr, unsigned int flags, size_t new_size) { - /* const char * fcn_name = "unprotect_entry_with_size_change()"; */ + 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; + hbool_t verbose = FALSE; test_entry_t * base_addr; test_entry_t * entry_ptr; @@ -3285,6 +3308,39 @@ unprotect_entry_with_size_change(H5C_t * cache_ptr, ( entry_ptr->size != entry_ptr->header.size ) || ( entry_ptr->addr != entry_ptr->header.addr ) ) { + if ( verbose ) { + + if ( result < 0 ) { + HDfprintf(stdout, "%s: H5C_unprotect() failed.\n", fcn_name); + } + + if ( entry_ptr->header.is_protected ) { + HDfprintf(stdout, "%s: entry still protected?!?.\n", + fcn_name); + } + + if ( entry_ptr->header.type != &(types[type]) ) { + HDfprintf(stdout, + "%s: entry has bad type after unprotect.\n", + fcn_name); + } + + if ( entry_ptr->size != entry_ptr->header.size ) { + HDfprintf(stdout, + "%s: bad entry size after unprotect. e/a = %d/%d\n", + fcn_name, + (int)(entry_ptr->size), + (int)(entry_ptr->header.size)); + } + + if ( entry_ptr->addr != entry_ptr->header.addr ) { + HDfprintf(stdout, + "%s: bad entry addr after unprotect. e/a = 0x%llx/0x%llx\n", + fcn_name, + (long long)(entry_ptr->addr), + (long long)(entry_ptr->header.addr)); + } + } pass = FALSE; failure_mssg = "error in H5C_unprotect()."; diff --git a/test/links.c b/test/links.c index 433e9f8..d807352 100644 --- a/test/links.c +++ b/test/links.c @@ -76,6 +76,10 @@ const char *FILENAME[] = { "extlinks16A", /* 37: */ /* TESTS for H5P_set_elink_fapl */ "extlinks16B", /* 38: */ "extlinks17", /* 39: */ + "extlinks18A", /* 40: */ + "extlinks18B", /* 41: */ + "extlinks19A", /* 42: */ + "extlinks19B", /* 43: */ NULL }; @@ -112,6 +116,8 @@ const char *FILENAME[] = { #define LE_FILENAME "le_extlink1.h5" #define BE_FILENAME "be_extlink1.h5" +#define ELINK_CB_FAM_SIZE (hsize_t) 100 + #define H5L_DIM1 100 #define H5L_DIM2 100 @@ -3947,6 +3953,284 @@ external_set_elink_fapl3(hbool_t new_format) } /* end external_set_elink_fapl3() */ +/*------------------------------------------------------------------------- + * Function: external_set_elink_acc_flags + * + * Purpose: Verify functionality of H5P_set/get_elink_acc_flags + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Neil Fortner + * Jan. 5, 2009 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +external_set_elink_acc_flags(hid_t fapl, hbool_t new_format) +{ + hid_t file1, file2, group, subgroup, gapl; + char filename1[NAME_BUF_SIZE], + filename2[NAME_BUF_SIZE]; + unsigned flags; + + if(new_format) + TESTING("H5Pset/get_elink_acc_flags() (w/new group format)") + else + TESTING("H5Pset/get_elink_acc_flags()") + + /* Create parent and target files, and external link */ + h5_fixname(FILENAME[40], fapl, filename1, sizeof filename1); + h5_fixname(FILENAME[41], fapl, filename2, sizeof filename2); + if ((file1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR + if ((file2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR + if (H5Lcreate_external(filename2, "/", file1, "ext_link", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + + /* Close file2, leave file1 open (should be read-write) */ + if (H5Fclose(file2) < 0) TEST_ERROR + + /* Create new gapl, and set elink access flags to be H5F_ACC_RDONLY */ + if ((gapl = H5Pcreate(H5P_GROUP_ACCESS)) < 0) TEST_ERROR + if (H5Pset_elink_acc_flags(gapl, H5F_ACC_RDONLY) < 0) TEST_ERROR + + /* Verify "get" routine functionality */ + if (H5Pget_elink_acc_flags(gapl, &flags) < 0) TEST_ERROR + if (flags != H5F_ACC_RDONLY) TEST_ERROR + + /* Attempt to create a group through the external link using gapl (should fail) */ + H5E_BEGIN_TRY { + group = H5Gcreate2(file1, "/ext_link/group", H5P_DEFAULT, H5P_DEFAULT, gapl); + } H5E_END_TRY; + if (group != FAIL) TEST_ERROR + + /* Close file1 and reopen with read only access */ + if (H5Fclose(file1) < 0) TEST_ERROR + if ((file1 = H5Fopen(filename1, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR + + /* Set elink access flags on gapl to be H5F_ACC_RDWR */ + if (H5Pset_elink_acc_flags(gapl, H5F_ACC_RDWR) < 0) TEST_ERROR + + /* Create a group through the external link using gapl (should succeed) */ + if ((group = H5Gcreate2(file1, "/ext_link/group", H5P_DEFAULT, H5P_DEFAULT, gapl)) < 0) TEST_ERROR + + /* Unset elink access flags on gapl */ + if (H5Pset_elink_acc_flags(gapl, H5F_ACC_DEFAULT) < 0) TEST_ERROR + + /* Attempt to create a group through the external link using gapl (should fail) */ + H5E_BEGIN_TRY { + subgroup = H5Gcreate2(file1, "/ext_link/group/subgroup", H5P_DEFAULT, H5P_DEFAULT, gapl); + } H5E_END_TRY; + if (subgroup != FAIL) TEST_ERROR + + /* Close file1 and group */ + if (H5Gclose(group) < 0) TEST_ERROR + if (H5Fclose(file1) < 0) TEST_ERROR + + /* Verify that H5Fcreate and H5Fopen reject H5F_ACC_DEFAULT */ + H5E_BEGIN_TRY { + file1 = H5Fcreate(filename1, H5F_ACC_DEFAULT, H5P_DEFAULT, fapl); + } H5E_END_TRY; + if (file1 != FAIL) TEST_ERROR + H5E_BEGIN_TRY { + file1 = H5Fcreate(filename1, H5F_ACC_TRUNC | H5F_ACC_DEFAULT, H5P_DEFAULT, fapl); + } H5E_END_TRY; + if (file1 != FAIL) TEST_ERROR + H5E_BEGIN_TRY { + file1 = H5Fopen(filename1, H5F_ACC_DEFAULT, fapl); + } H5E_END_TRY; + if (file1 != FAIL) TEST_ERROR + H5E_BEGIN_TRY { + file1 = H5Fopen(filename1, H5F_ACC_RDWR | H5F_ACC_DEFAULT, fapl); + } H5E_END_TRY; + if (file1 != FAIL) TEST_ERROR + + /* Close gapl */ + if (H5Pclose(gapl) < 0) TEST_ERROR + + PASSED(); + return 0; + + error: + H5E_BEGIN_TRY { + H5Gclose(group); + H5Gclose(subgroup); + H5Fclose(file1); + H5Fclose(file2); + H5Pclose(gapl); + } H5E_END_TRY; + return -1; +} /* end external_set_elink_acc_flags() */ + + +/*------------------------------------------------------------------------- + * Function: external_set_elink_cb + * + * Purpose: Verify functionality of H5P_set/get_elink_cb + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Neil Fortner + * Jan. 5, 2009 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + /* User data structure for callback function */ +typedef struct { + const char *parent_file; /* Expected parent file name */ + const char *target_file; /* Expected target file name */ + hid_t base_fapl; /* Base fapl for family driver */ + hsize_t fam_size; /* Size of family files */ + int code; /* Code to control the actions taken by the callback */ +} set_elink_cb_t; + +/* Callback function */ +static herr_t +external_set_elink_cb_cb(const char *parent_file, const char *parent_group, + const char *target_file, const char *target_obj, unsigned *flags, + hid_t fapl, void *_op_data) +{ + set_elink_cb_t *op_data = (set_elink_cb_t *)_op_data; + + /* Verify file and object names are correct */ + if (HDstrcmp(parent_file, op_data->parent_file)) return FAIL; + if (HDstrcmp(parent_group, "/group1")) return FAIL; + if (HDstrcmp(target_file, op_data->target_file)) return FAIL; + if (HDstrcmp(target_obj, "/")) return FAIL; + + /* Set flags to be read-write */ + *flags = (*flags & ~H5F_ACC_RDONLY) | H5F_ACC_RDWR; + + /* Set family file driver on fapl */ + if (H5Pset_fapl_family(fapl, op_data->fam_size, op_data->base_fapl) < 0) return FAIL; + + /* Codes to cause an invalid condition (and verify that an error is issued */ + if (op_data->code == 1) + return FAIL; + if (op_data->code == 2) + *flags = H5F_ACC_DEFAULT; + + return 0; +} + +/* Main test function */ +static int +external_set_elink_cb(hid_t fapl, hbool_t new_format) +{ + hid_t file1, file2, group, gapl, fam_fapl, ret_fapl, base_driver; + set_elink_cb_t op_data, + *op_data_p; + H5L_elink_traverse_t cb; + char filename1[NAME_BUF_SIZE], + filename2[NAME_BUF_SIZE]; + unsigned flags; + + if(new_format) + TESTING("H5Pset/get_elink_cb() (w/new group format)") + else + TESTING("H5Pset/get_elink_cb()") + + /* Build user data for callback */ + op_data.parent_file = filename1; + op_data.target_file = filename2; + /* Core file driver has issues when used as the member file driver for a family file */ + /* Family file driver cannot be used with family or multi drivers for member files */ + /* Also disable parellel member drivers, because IS_H5FD_MPI whould report FALSE, causing problems */ + base_driver = H5Pget_driver(fapl); + op_data.base_fapl = (base_driver == H5FD_FAMILY || base_driver == H5FD_MULTI + || base_driver == H5FD_MPIO || base_driver == H5FD_MPIPOSIX + || base_driver == H5FD_CORE) ? H5P_DEFAULT : fapl; + op_data.fam_size = ELINK_CB_FAM_SIZE; + op_data.code = 0; + + /* Create family fapl */ + if ((fam_fapl = H5Pcopy(fapl)) < 0) TEST_ERROR + if (H5Pset_fapl_family(fam_fapl, op_data.fam_size, op_data.base_fapl) < 0) TEST_ERROR + + /* Create parent and target files, group, and external link */ + h5_fixname(FILENAME[40], fapl, filename1, sizeof filename1); + h5_fixname(FILENAME[41], fam_fapl, filename2, sizeof filename2); + if ((file1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR + if ((file2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, fam_fapl)) < 0) TEST_ERROR + if ((group = H5Gcreate2(file1, "group1",H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + if (H5Lcreate_external(filename2, "/", group, "ext_link", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + + /* Close files and group */ + if (H5Fclose(file1) < 0) TEST_ERROR + if (H5Fclose(file2) < 0) TEST_ERROR + if (H5Gclose(group) < 0) TEST_ERROR + + /* Create new gapl, and set elink callback */ + if ((gapl = H5Pcreate(H5P_GROUP_ACCESS)) < 0) TEST_ERROR + if (H5Pset_elink_cb(gapl, external_set_elink_cb_cb, &op_data) < 0) TEST_ERROR + + /* Verify "get" routine functionality */ + if (H5Pget_elink_cb(gapl, &cb, (void **) &op_data_p) < 0) TEST_ERROR + if (cb != external_set_elink_cb_cb) TEST_ERROR + if (op_data_p != &op_data) TEST_ERROR + + /* Open file1 with read only access */ + if ((file1 = H5Fopen(filename1, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR + + /* Create a group through the external link using gapl */ + if ((group = H5Gcreate2(file1, "/group1/ext_link/group2", H5P_DEFAULT, H5P_DEFAULT, gapl)) < 0) TEST_ERROR + + /* Verify that the correct parameters have been set on file2 (somewhat + * redundant as the library would be unable to create the group otherwise) + */ + if ((file2 = H5Iget_file_id(group)) < 0) TEST_ERROR + if (H5Fget_intent(file2, &flags) < 0) TEST_ERROR + if (!(flags & H5F_ACC_RDWR)) TEST_ERROR + if ((ret_fapl = H5Fget_access_plist(file2)) < 0) TEST_ERROR + if (H5FD_FAMILY != H5Pget_driver(ret_fapl)) TEST_ERROR + + if (H5Gclose(group) < 0) TEST_ERROR + if (H5Fclose(file2) < 0) TEST_ERROR + if (H5Pclose(ret_fapl) < 0) TEST_ERROR + if (H5Pclose(fam_fapl) < 0) TEST_ERROR + + /* Modify the user data structure to cause the callback to fail next time */ + op_data.code = 1; + + /* Attempt to reopen group2 (should fail) */ + H5E_BEGIN_TRY { + group = H5Gopen2(file1, "/group1/ext_link/group2", gapl); + } H5E_END_TRY; + if (group != FAIL) TEST_ERROR + + /* Modify the user data structure to cause the callback to return invalid flags */ + op_data.code = 2; + + /* Attempt to reopen group2 (should fail) */ + H5E_BEGIN_TRY { + group = H5Gopen2(file1, "/group1/ext_link/group2", gapl); + } H5E_END_TRY; + if (group != FAIL) TEST_ERROR + + /* Close */ + if (H5Fclose(file1) < 0) TEST_ERROR + if (H5Pclose(gapl) < 0) TEST_ERROR + + PASSED(); + return 0; + + error: + H5E_BEGIN_TRY { + H5Gclose(group); + H5Fclose(file1); + H5Fclose(file2); + H5Pclose(gapl); + H5Pclose(ret_fapl); + H5Pclose(fam_fapl); + } H5E_END_TRY; + return -1; +} /* end external_set_elink_cb() */ + + #ifdef H5_HAVE_WINDOW_PATH /*------------------------------------------------------------------------- @@ -12342,6 +12626,8 @@ main(void) nerrors += external_set_elink_fapl1(my_fapl, new_format) < 0 ? 1 : 0; nerrors += external_set_elink_fapl2(my_fapl, new_format) < 0 ? 1 : 0; nerrors += external_set_elink_fapl3(new_format) < 0 ? 1 : 0; + nerrors += external_set_elink_acc_flags(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_set_elink_cb(my_fapl, new_format) < 0 ? 1 : 0; #ifdef H5_HAVE_WINDOW_PATH nerrors += external_link_win1(my_fapl, new_format) < 0 ? 1 : 0; diff --git a/tools/h5diff/h5diff_common.c b/tools/h5diff/h5diff_common.c index 5a59215..8a49fa0 100644 --- a/tools/h5diff/h5diff_common.c +++ b/tools/h5diff/h5diff_common.c @@ -31,7 +31,7 @@ const char *progname = "h5diff"; * Command-line options: The user can specify short or long-named * parameters. */ -static const char *s_opts = "hVrvqn:d:p:"; +static const char *s_opts = "hVrvqn:d:p:N"; static struct long_options l_opts[] = { { "help", no_arg, 'h' }, { "version", no_arg, 'V' }, @@ -41,6 +41,7 @@ static struct long_options l_opts[] = { { "count", require_arg, 'n' }, { "delta", require_arg, 'd' }, { "relative", require_arg, 'p' }, + { "nan", no_arg, 'N' }, { NULL, 0, '\0' } }; @@ -70,6 +71,9 @@ void parse_command_line(int argc, /* assume equal contents initially */ options->contents = 1; + /* NaNs are handled by default */ + options->do_nans = 1; + /* parse command line options */ while ((opt = get_option(argc, argv, s_opts, l_opts)) != EOF) { @@ -130,6 +134,10 @@ void parse_command_line(int argc, options->count = atol( opt_arg ); break; + + case 'N': + options->do_nans = 0; + break; } } @@ -323,6 +331,7 @@ void usage(void) printf(" -r, --report Report mode. Print differences\n"); printf(" -v, --verbose Verbose mode. Print differences, list of objects\n"); printf(" -q, --quiet Quiet mode. Do not do output\n"); + printf(" -N, --nan Avoid NaNs detection\n"); printf(" -n C, --count=C Print differences up to C number\n"); printf(" -d D, --delta=D Print difference when greater than limit D\n"); diff --git a/tools/h5diff/testfiles/h5diff_10.txt b/tools/h5diff/testfiles/h5diff_10.txt index a74a37c..5480df1 100644 --- a/tools/h5diff/testfiles/h5diff_10.txt +++ b/tools/h5diff/testfiles/h5diff_10.txt @@ -9,6 +9,7 @@ usage: h5diff [OPTIONS] file1 file2 [obj1[obj2]] -r, --report Report mode. Print differences -v, --verbose Verbose mode. Print differences, list of objects -q, --quiet Quiet mode. Do not do output + -N, --nan Avoid NaNs detection -n C, --count=C Print differences up to C number -d D, --delta=D Print difference when greater than limit D -p R, --relative=R Print difference when greater than relative limit R diff --git a/tools/h5diff/testfiles/h5diff_600.txt b/tools/h5diff/testfiles/h5diff_600.txt index dcf14f7..22a3155 100644 --- a/tools/h5diff/testfiles/h5diff_600.txt +++ b/tools/h5diff/testfiles/h5diff_600.txt @@ -9,6 +9,7 @@ usage: h5diff [OPTIONS] file1 file2 [obj1[obj2]] -r, --report Report mode. Print differences -v, --verbose Verbose mode. Print differences, list of objects -q, --quiet Quiet mode. Do not do output + -N, --nan Avoid NaNs detection -n C, --count=C Print differences up to C number -d D, --delta=D Print difference when greater than limit D -p R, --relative=R Print difference when greater than relative limit R diff --git a/tools/h5diff/testfiles/h5diff_603.txt b/tools/h5diff/testfiles/h5diff_603.txt index e274d88..80ee102 100644 --- a/tools/h5diff/testfiles/h5diff_603.txt +++ b/tools/h5diff/testfiles/h5diff_603.txt @@ -10,6 +10,7 @@ usage: h5diff [OPTIONS] file1 file2 [obj1[obj2]] -r, --report Report mode. Print differences -v, --verbose Verbose mode. Print differences, list of objects -q, --quiet Quiet mode. Do not do output + -N, --nan Avoid NaNs detection -n C, --count=C Print differences up to C number -d D, --delta=D Print difference when greater than limit D -p R, --relative=R Print difference when greater than relative limit R diff --git a/tools/h5diff/testfiles/h5diff_604.txt b/tools/h5diff/testfiles/h5diff_604.txt index 8232c38..acb12b9 100644 --- a/tools/h5diff/testfiles/h5diff_604.txt +++ b/tools/h5diff/testfiles/h5diff_604.txt @@ -10,6 +10,7 @@ usage: h5diff [OPTIONS] file1 file2 [obj1[obj2]] -r, --report Report mode. Print differences -v, --verbose Verbose mode. Print differences, list of objects -q, --quiet Quiet mode. Do not do output + -N, --nan Avoid NaNs detection -n C, --count=C Print differences up to C number -d D, --delta=D Print difference when greater than limit D -p R, --relative=R Print difference when greater than relative limit R diff --git a/tools/h5diff/testfiles/h5diff_605.txt b/tools/h5diff/testfiles/h5diff_605.txt index bce2118..94f016d 100644 --- a/tools/h5diff/testfiles/h5diff_605.txt +++ b/tools/h5diff/testfiles/h5diff_605.txt @@ -10,6 +10,7 @@ usage: h5diff [OPTIONS] file1 file2 [obj1[obj2]] -r, --report Report mode. Print differences -v, --verbose Verbose mode. Print differences, list of objects -q, --quiet Quiet mode. Do not do output + -N, --nan Avoid NaNs detection -n C, --count=C Print differences up to C number -d D, --delta=D Print difference when greater than limit D -p R, --relative=R Print difference when greater than relative limit R diff --git a/tools/h5diff/testfiles/h5diff_606.txt b/tools/h5diff/testfiles/h5diff_606.txt index 9a0a8cd..f181030 100644 --- a/tools/h5diff/testfiles/h5diff_606.txt +++ b/tools/h5diff/testfiles/h5diff_606.txt @@ -10,6 +10,7 @@ usage: h5diff [OPTIONS] file1 file2 [obj1[obj2]] -r, --report Report mode. Print differences -v, --verbose Verbose mode. Print differences, list of objects -q, --quiet Quiet mode. Do not do output + -N, --nan Avoid NaNs detection -n C, --count=C Print differences up to C number -d D, --delta=D Print difference when greater than limit D -p R, --relative=R Print difference when greater than relative limit R diff --git a/tools/h5diff/testfiles/h5diff_612.txt b/tools/h5diff/testfiles/h5diff_612.txt index 16baa7c..840058d 100644 --- a/tools/h5diff/testfiles/h5diff_612.txt +++ b/tools/h5diff/testfiles/h5diff_612.txt @@ -10,6 +10,7 @@ usage: h5diff [OPTIONS] file1 file2 [obj1[obj2]] -r, --report Report mode. Print differences -v, --verbose Verbose mode. Print differences, list of objects -q, --quiet Quiet mode. Do not do output + -N, --nan Avoid NaNs detection -n C, --count=C Print differences up to C number -d D, --delta=D Print difference when greater than limit D -p R, --relative=R Print difference when greater than relative limit R diff --git a/tools/h5diff/testfiles/h5diff_613.txt b/tools/h5diff/testfiles/h5diff_613.txt index e57c320..5c18686 100644 --- a/tools/h5diff/testfiles/h5diff_613.txt +++ b/tools/h5diff/testfiles/h5diff_613.txt @@ -10,6 +10,7 @@ usage: h5diff [OPTIONS] file1 file2 [obj1[obj2]] -r, --report Report mode. Print differences -v, --verbose Verbose mode. Print differences, list of objects -q, --quiet Quiet mode. Do not do output + -N, --nan Avoid NaNs detection -n C, --count=C Print differences up to C number -d D, --delta=D Print difference when greater than limit D -p R, --relative=R Print difference when greater than relative limit R diff --git a/tools/h5diff/testfiles/h5diff_614.txt b/tools/h5diff/testfiles/h5diff_614.txt index 828d250..a630e02 100644 --- a/tools/h5diff/testfiles/h5diff_614.txt +++ b/tools/h5diff/testfiles/h5diff_614.txt @@ -10,6 +10,7 @@ usage: h5diff [OPTIONS] file1 file2 [obj1[obj2]] -r, --report Report mode. Print differences -v, --verbose Verbose mode. Print differences, list of objects -q, --quiet Quiet mode. Do not do output + -N, --nan Avoid NaNs detection -n C, --count=C Print differences up to C number -d D, --delta=D Print difference when greater than limit D -p R, --relative=R Print difference when greater than relative limit R diff --git a/tools/h5diff/testfiles/h5diff_615.txt b/tools/h5diff/testfiles/h5diff_615.txt index 654a743..8fdc0ce 100644 --- a/tools/h5diff/testfiles/h5diff_615.txt +++ b/tools/h5diff/testfiles/h5diff_615.txt @@ -10,6 +10,7 @@ usage: h5diff [OPTIONS] file1 file2 [obj1[obj2]] -r, --report Report mode. Print differences -v, --verbose Verbose mode. Print differences, list of objects -q, --quiet Quiet mode. Do not do output + -N, --nan Avoid NaNs detection -n C, --count=C Print differences up to C number -d D, --delta=D Print difference when greater than limit D -p R, --relative=R Print difference when greater than relative limit R diff --git a/tools/h5diff/testfiles/h5diff_621.txt b/tools/h5diff/testfiles/h5diff_621.txt index 18acda6..746977e 100644 --- a/tools/h5diff/testfiles/h5diff_621.txt +++ b/tools/h5diff/testfiles/h5diff_621.txt @@ -10,6 +10,7 @@ usage: h5diff [OPTIONS] file1 file2 [obj1[obj2]] -r, --report Report mode. Print differences -v, --verbose Verbose mode. Print differences, list of objects -q, --quiet Quiet mode. Do not do output + -N, --nan Avoid NaNs detection -n C, --count=C Print differences up to C number -d D, --delta=D Print difference when greater than limit D -p R, --relative=R Print difference when greater than relative limit R diff --git a/tools/h5diff/testfiles/h5diff_622.txt b/tools/h5diff/testfiles/h5diff_622.txt index 7740b0a..4ead1fb 100644 --- a/tools/h5diff/testfiles/h5diff_622.txt +++ b/tools/h5diff/testfiles/h5diff_622.txt @@ -10,6 +10,7 @@ usage: h5diff [OPTIONS] file1 file2 [obj1[obj2]] -r, --report Report mode. Print differences -v, --verbose Verbose mode. Print differences, list of objects -q, --quiet Quiet mode. Do not do output + -N, --nan Avoid NaNs detection -n C, --count=C Print differences up to C number -d D, --delta=D Print difference when greater than limit D -p R, --relative=R Print difference when greater than relative limit R diff --git a/tools/h5diff/testfiles/h5diff_623.txt b/tools/h5diff/testfiles/h5diff_623.txt index e238a6b..fb94e0d 100644 --- a/tools/h5diff/testfiles/h5diff_623.txt +++ b/tools/h5diff/testfiles/h5diff_623.txt @@ -10,6 +10,7 @@ usage: h5diff [OPTIONS] file1 file2 [obj1[obj2]] -r, --report Report mode. Print differences -v, --verbose Verbose mode. Print differences, list of objects -q, --quiet Quiet mode. Do not do output + -N, --nan Avoid NaNs detection -n C, --count=C Print differences up to C number -d D, --delta=D Print difference when greater than limit D -p R, --relative=R Print difference when greater than relative limit R diff --git a/tools/h5diff/testfiles/h5diff_624.txt b/tools/h5diff/testfiles/h5diff_624.txt index 7100555..bb4b133 100644 --- a/tools/h5diff/testfiles/h5diff_624.txt +++ b/tools/h5diff/testfiles/h5diff_624.txt @@ -10,6 +10,7 @@ usage: h5diff [OPTIONS] file1 file2 [obj1[obj2]] -r, --report Report mode. Print differences -v, --verbose Verbose mode. Print differences, list of objects -q, --quiet Quiet mode. Do not do output + -N, --nan Avoid NaNs detection -n C, --count=C Print differences up to C number -d D, --delta=D Print difference when greater than limit D -p R, --relative=R Print difference when greater than relative limit R diff --git a/tools/h5ls/h5ls.c b/tools/h5ls/h5ls.c index eec1fcd..d0af4bb 100644 --- a/tools/h5ls/h5ls.c +++ b/tools/h5ls/h5ls.c @@ -1515,7 +1515,8 @@ dataset_list2(hid_t dset, const char UNUSED *name) int ndims; /* dimensionality */ int n, max_len; /* max extern file name length */ double utilization; /* percent utilization of storage */ - int i; + H5T_class_t tclass; /* datatype class identifier */ + int i; if(verbose_g > 0) { dcpl = H5Dget_create_plist(dset); @@ -1539,14 +1540,35 @@ dataset_list2(hid_t dset, const char UNUSED *name) /* Print total raw storage size */ total = H5Sget_simple_extent_npoints(space) * H5Tget_size(type); used = H5Dget_storage_size(dset); + tclass = H5Tget_class(type); printf(" %-10s ", "Storage:"); - printf("%lu logical byte%s, %lu allocated byte%s", - (unsigned long)total, 1==total?"":"s", - (unsigned long)used, 1==used?"":"s"); - if (used>0) { - utilization = (total*100.0)/used; - printf(", %1.2f%% utilization", utilization); + switch (tclass) + { + + case H5T_VLEN: + printf("information not available"); + break; + + case H5T_REFERENCE: + if ( H5Tequal(type, H5T_STD_REF_DSETREG)) + { + printf("information not available"); + } + break; + + default: + printf("%lu logical byte%s, %lu allocated byte%s", + (unsigned long)total, 1==total?"":"s", + (unsigned long)used, 1==used?"":"s"); + if (used>0) + { + utilization = (total*100.0)/used; + printf(", %1.2f%% utilization", utilization); + } + } + + putchar('\n'); /* Print information about external strorage */ diff --git a/tools/h5ls/testh5ls.sh b/tools/h5ls/testh5ls.sh index 0bae60b..8194bfb 100755 --- a/tools/h5ls/testh5ls.sh +++ b/tools/h5ls/testh5ls.sh @@ -173,6 +173,12 @@ TOOLTEST tattr2.ls 0 -w80 -v -S tattr2.h5 # test for non-existing file TOOLTEST nosuchfile.ls 0 nosuchfile.h5 +# test for variable length data types in verbose mode +TOOLTEST tvldtypes2.ls 0 -v tvldtypes1.h5 + +# test for dataset region references data types in verbose mode +TOOLTEST tdatareg.ls 0 -v tdatareg.h5 + if test $nerrors -eq 0 ; then echo "All h5ls tests passed." fi diff --git a/tools/h5repack/h5repack_main.c b/tools/h5repack/h5repack_main.c index 8fd2046..f55bd2e 100644 --- a/tools/h5repack/h5repack_main.c +++ b/tools/h5repack/h5repack_main.c @@ -183,7 +183,7 @@ static void usage(const char *prog) printf("\n"); - printf(" M - is an integer greater than 1, size of dataset in bytes \n"); + printf(" M - is an integer greater than 1, size of dataset in bytes (default is 1024) \n"); printf(" E - is a filename.\n"); printf(" S - is an integer\n"); printf(" U - is a filename.\n"); diff --git a/tools/lib/h5diff.h b/tools/lib/h5diff.h index c013ba5..57d06a5 100644 --- a/tools/lib/h5diff.h +++ b/tools/lib/h5diff.h @@ -38,6 +38,7 @@ typedef struct { int cmn_objs; /* do we have comparable objects */ int not_cmp; /* are the objects comparable */ int contents; /* equal contents */ + int do_nans; /* consider Nans while diffing floats */ } diff_opt_t; diff --git a/tools/lib/h5diff_array.c b/tools/lib/h5diff_array.c index 5d187cd..e5f065c 100644 --- a/tools/lib/h5diff_array.c +++ b/tools/lib/h5diff_array.c @@ -141,10 +141,10 @@ static hbool_t all_zero(const void *_mem, size_t size); static int ull2float(unsigned long_long ull_value, float *f_value); static hsize_t character_compare(unsigned char *mem1,unsigned char *mem2,hsize_t i,unsigned u,int rank,hsize_t *dims,hsize_t *acc,hsize_t *pos,diff_opt_t *options,const char *obj1,const char *obj2,int *ph); static hsize_t character_compare_opt(unsigned char *mem1,unsigned char *mem2,hsize_t i,int rank,hsize_t *dims,hsize_t *acc,hsize_t *pos,diff_opt_t *options,const char *obj1,const char *obj2,int *ph); -static hbool_t equal_float(float value, float expected); -static hbool_t equal_double(double value, double expected); +static hbool_t equal_float(float value, float expected, diff_opt_t *options); +static hbool_t equal_double(double value, double expected, diff_opt_t *options); #if H5_SIZEOF_LONG_DOUBLE !=0 -static hbool_t equal_ldouble(long double value, long double expected); +static hbool_t equal_ldouble(long double value, long double expected, diff_opt_t *options); #endif static int print_data(diff_opt_t *options); static void print_pos(int *ph,int pp,hsize_t curr_pos,hsize_t *acc,hsize_t *pos,int rank,hsize_t *dims,const char *obj1,const char *obj2 ); @@ -1970,7 +1970,7 @@ hsize_t diff_datum(void *_mem1, * no -d and -p *------------------------------------------------------------------------- */ - else if (equal_float(temp1_float,temp2_float)==FALSE) + else if (equal_float(temp1_float,temp2_float,options)==FALSE) { if ( print_data(options) ) @@ -2139,7 +2139,7 @@ hsize_t diff_datum(void *_mem1, * no -d and -p *------------------------------------------------------------------------- */ - else if (equal_double(temp1_double,temp2_double)==FALSE) + else if (equal_double(temp1_double,temp2_double,options)==FALSE) { if ( print_data(options) ) { @@ -2310,7 +2310,7 @@ hsize_t diff_datum(void *_mem1, * no -d and -p *------------------------------------------------------------------------- */ - else if (equal_ldouble(temp1_double,temp2_double)==FALSE) + else if (equal_ldouble(temp1_double,temp2_double,options)==FALSE) { if ( print_data(options) ) { @@ -2931,7 +2931,7 @@ hsize_t diff_float(unsigned char *mem1, memcpy(&temp2_float, mem2, sizeof(float)); - if (equal_float(temp1_float,temp2_float)==FALSE) + if (equal_float(temp1_float,temp2_float,options)==FALSE) { if ( print_data(options) ) { @@ -3114,7 +3114,7 @@ hsize_t diff_double(unsigned char *mem1, memcpy(&temp1_double, mem1, sizeof(double)); memcpy(&temp2_double, mem2, sizeof(double)); - if (equal_double(temp1_double,temp2_double)==FALSE) + if (equal_double(temp1_double,temp2_double,options)==FALSE) { if ( print_data(options) ) { @@ -3293,7 +3293,7 @@ hsize_t diff_ldouble(unsigned char *mem1, memcpy(&temp1_double, mem1, sizeof(long double)); memcpy(&temp2_double, mem2, sizeof(long double)); - if (equal_ldouble(temp1_double,temp2_double)==FALSE) + if (equal_ldouble(temp1_double,temp2_double,options)==FALSE) { if ( print_data(options) ) { @@ -5183,48 +5183,53 @@ error: *------------------------------------------------------------------------- */ static -hbool_t equal_double(double value, double expected) +hbool_t equal_double(double value, double expected, diff_opt_t *options) { int both_zero; int is_zero; -/*------------------------------------------------------------------------- - * detect NaNs - *------------------------------------------------------------------------- - */ - int isnan1 = my_isnan(FLT_DOUBLE,&value); - int isnan2 = my_isnan(FLT_DOUBLE,&expected); - - /*------------------------------------------------------------------------- - * we consider NaN == NaN to be true - *------------------------------------------------------------------------- - */ - if ( isnan1 && isnan2 ) - { - return TRUE; - } - /*------------------------------------------------------------------------- - * one is a NaN, do not compare but assume difference - *------------------------------------------------------------------------- - */ - if ( (isnan1 && !isnan2) || ( !isnan1 && isnan2 ) ) + if ( options->do_nans ) { - return FALSE; + + /*------------------------------------------------------------------------- + * detect NaNs + *------------------------------------------------------------------------- + */ + int isnan1 = my_isnan(FLT_DOUBLE,&value); + int isnan2 = my_isnan(FLT_DOUBLE,&expected); + + /*------------------------------------------------------------------------- + * we consider NaN == NaN to be true + *------------------------------------------------------------------------- + */ + if ( isnan1 && isnan2 ) + { + return TRUE; + } + + /*------------------------------------------------------------------------- + * one is a NaN, do not compare but assume difference + *------------------------------------------------------------------------- + */ + if ( (isnan1 && !isnan2) || ( !isnan1 && isnan2 ) ) + { + return FALSE; + } + + /*------------------------------------------------------------------------- + * both are not NaNs, compare + *------------------------------------------------------------------------- + */ } - /*------------------------------------------------------------------------- - * both are not NaNs, compare - *------------------------------------------------------------------------- - */ - BOTH_ZERO(value,expected) if (both_zero) return TRUE; IS_ZERO(expected) if (is_zero) - return(equal_double(expected,value)); + return(equal_double(expected,value,options)); if ( ABS( (value-expected) / expected) < H5DIFF_DBL_EPSILON) return TRUE; @@ -5244,48 +5249,54 @@ hbool_t equal_double(double value, double expected) #if H5_SIZEOF_LONG_DOUBLE !=0 static -hbool_t equal_ldouble(long double value, long double expected) +hbool_t equal_ldouble(long double value, long double expected, diff_opt_t *options) { int both_zero; int is_zero; -/*------------------------------------------------------------------------- - * detect NaNs - *------------------------------------------------------------------------- - */ - int isnan1 = my_isnan(FLT_LDOUBLE,&value); - int isnan2 = my_isnan(FLT_LDOUBLE,&expected); - - /*------------------------------------------------------------------------- - * we consider NaN == NaN to be true - *------------------------------------------------------------------------- - */ - if ( isnan1 && isnan2 ) - { - return TRUE; - } - - /*------------------------------------------------------------------------- - * one is a NaN, do not compare but assume difference - *------------------------------------------------------------------------- - */ - if ( (isnan1 && !isnan2) || ( !isnan1 && isnan2 ) ) + + if ( options->do_nans ) { - return FALSE; + + /*------------------------------------------------------------------------- + * detect NaNs + *------------------------------------------------------------------------- + */ + int isnan1 = my_isnan(FLT_LDOUBLE,&value); + int isnan2 = my_isnan(FLT_LDOUBLE,&expected); + + /*------------------------------------------------------------------------- + * we consider NaN == NaN to be true + *------------------------------------------------------------------------- + */ + if ( isnan1 && isnan2 ) + { + return TRUE; + } + + /*------------------------------------------------------------------------- + * one is a NaN, do not compare but assume difference + *------------------------------------------------------------------------- + */ + if ( (isnan1 && !isnan2) || ( !isnan1 && isnan2 ) ) + { + return FALSE; + } + + /*------------------------------------------------------------------------- + * both are not NaNs, compare + *------------------------------------------------------------------------- + */ + } - /*------------------------------------------------------------------------- - * both are not NaNs, compare - *------------------------------------------------------------------------- - */ - BOTH_ZERO(value,expected) if (both_zero) return TRUE; IS_ZERO(expected) if (is_zero) - return(equal_ldouble(expected,value)); + return(equal_ldouble(expected,value,options)); if ( ABS( (value-expected) / expected) < H5DIFF_DBL_EPSILON) return TRUE; @@ -5309,48 +5320,53 @@ hbool_t equal_ldouble(long double value, long double expected) *------------------------------------------------------------------------- */ static -hbool_t equal_float(float value, float expected) +hbool_t equal_float(float value, float expected, diff_opt_t *options) { int both_zero; int is_zero; -/*------------------------------------------------------------------------- - * detect NaNs - *------------------------------------------------------------------------- - */ - int isnan1 = my_isnan(FLT_FLOAT,&value); - int isnan2 = my_isnan(FLT_FLOAT,&expected); - - /*------------------------------------------------------------------------- - * we consider NaN == NaN to be true - *------------------------------------------------------------------------- - */ - if ( isnan1 && isnan2 ) + if ( options->do_nans ) { - return TRUE; - } - - /*------------------------------------------------------------------------- - * one is a NaN, do not compare but assume difference - *------------------------------------------------------------------------- - */ - if ( (isnan1 && !isnan2) || ( !isnan1 && isnan2 ) ) - { - return FALSE; + + /*------------------------------------------------------------------------- + * detect NaNs + *------------------------------------------------------------------------- + */ + int isnan1 = my_isnan(FLT_FLOAT,&value); + int isnan2 = my_isnan(FLT_FLOAT,&expected); + + /*------------------------------------------------------------------------- + * we consider NaN == NaN to be true + *------------------------------------------------------------------------- + */ + if ( isnan1 && isnan2 ) + { + return TRUE; + } + + /*------------------------------------------------------------------------- + * one is a NaN, do not compare but assume difference + *------------------------------------------------------------------------- + */ + if ( (isnan1 && !isnan2) || ( !isnan1 && isnan2 ) ) + { + return FALSE; + } + + /*------------------------------------------------------------------------- + * both are not NaNs, compare + *------------------------------------------------------------------------- + */ + } - /*------------------------------------------------------------------------- - * both are not NaNs, compare - *------------------------------------------------------------------------- - */ - BOTH_ZERO(value,expected) if (both_zero) return TRUE; IS_ZERO(expected) if (is_zero) - return(equal_float(expected,value)); + return(equal_float(expected,value,options)); if ( ABS( (value-expected) / expected) < H5DIFF_FLT_EPSILON) return TRUE; diff --git a/tools/testfiles/tdatareg.ls b/tools/testfiles/tdatareg.ls new file mode 100644 index 0000000..b07b274 --- /dev/null +++ b/tools/testfiles/tdatareg.ls @@ -0,0 +1,14 @@ +############################# + output for 'h5ls -v tdatareg.h5' +############################# +Opened "tdatareg.h5" with sec2 driver. +Dataset1 Dataset {4/4} + Location: 1:1284 + Links: 1 + Storage: information not available + Type: dataset region reference +Dataset2 Dataset {10/10, 10/10} + Location: 1:744 + Links: 1 + Storage: 100 logical bytes, 100 allocated bytes, 100.00% utilization + Type: 8-bit unsigned integer diff --git a/tools/testfiles/tvldtypes2.ls b/tools/testfiles/tvldtypes2.ls new file mode 100644 index 0000000..62dfa61 --- /dev/null +++ b/tools/testfiles/tvldtypes2.ls @@ -0,0 +1,22 @@ +############################# + output for 'h5ls -v tvldtypes1.h5' +############################# +Opened "tvldtypes1.h5" with sec2 driver. +Dataset1.0 Dataset {4/4} + Location: 1:976 + Links: 1 + Storage: information not available + Type: variable length of + native int +Dataset2.0 Dataset {4/4} + Location: 1:1576 + Links: 1 + Storage: information not available + Type: variable length of + native float +Dataset3.0 Dataset {SCALAR} + Location: 1:6272 + Links: 1 + Storage: information not available + Type: variable length of + native int -- cgit v0.12