diff options
author | John Mainzer <mainzer@hdfgroup.org> | 2006-10-18 10:51:26 (GMT) |
---|---|---|
committer | John Mainzer <mainzer@hdfgroup.org> | 2006-10-18 10:51:26 (GMT) |
commit | 2d6bb5932951242d23ccef420a328a033f3b4efa (patch) | |
tree | 3650df339b604f381873f55dcb24af501a83bd0b /src | |
parent | ce30ee9b28e9b68de817845aa5bc965d35ca8967 (diff) | |
download | hdf5-2d6bb5932951242d23ccef420a328a033f3b4efa.zip hdf5-2d6bb5932951242d23ccef420a328a033f3b4efa.tar.gz hdf5-2d6bb5932951242d23ccef420a328a033f3b4efa.tar.bz2 |
[svn-r12774] Modified flush code in the metadata cache to allow it to
handle flush callbacks which can dirty other entries, and
resize and/or rename the target entry.
This feature is needed by the fractal heap code.
Also added associated test code.
H5Commit tested. Test failed on heping, but the
error appears to be a syntax error in an un-related
file.
Tests on copper & sol passed, along with tests on
phoenix.
Diffstat (limited to 'src')
-rw-r--r-- | src/H5ACprivate.h | 4 | ||||
-rw-r--r-- | src/H5B2cache.c | 29 | ||||
-rw-r--r-- | src/H5Bcache.c | 10 | ||||
-rw-r--r-- | src/H5C.c | 961 | ||||
-rw-r--r-- | src/H5Cpkg.h | 61 | ||||
-rw-r--r-- | src/H5Cprivate.h | 18 | ||||
-rw-r--r-- | src/H5FScache.c | 20 | ||||
-rw-r--r-- | src/H5Gnode.c | 10 | ||||
-rw-r--r-- | src/H5HFcache.c | 29 | ||||
-rw-r--r-- | src/H5HG.c | 11 | ||||
-rw-r--r-- | src/H5HL.c | 10 | ||||
-rw-r--r-- | src/H5Ocache.c | 10 |
12 files changed, 995 insertions, 178 deletions
diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index fd6a073..dab3cf2 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -114,6 +114,10 @@ typedef enum { * Note that the space allocated on disk may not be contiguous. */ +#define H5AC_CALLBACK__NO_FLAGS_SET H5C_CALLBACK__NO_FLAGS_SET +#define H5AC_CALLBACK__SIZE_CHANGED_FLAG H5C_CALLBACK__SIZE_CHANGED_FLAG +#define H5AC_CALLBACK__RENAMED_FLAG H5C_CALLBACK__RENAMED_FLAG + typedef H5C_load_func_t H5AC_load_func_t; typedef H5C_flush_func_t H5AC_flush_func_t; typedef H5C_dest_func_t H5AC_dest_func_t; diff --git a/src/H5B2cache.c b/src/H5B2cache.c index 9019765..e484529 100644 --- a/src/H5B2cache.c +++ b/src/H5B2cache.c @@ -62,15 +62,15 @@ /* Metadata cache callbacks */ static H5B2_t *H5B2_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, void *udata); -static herr_t H5B2_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_t *b); +static herr_t H5B2_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_t *b, unsigned UNUSED * flags_ptr); static herr_t H5B2_cache_hdr_clear(H5F_t *f, H5B2_t *b, hbool_t destroy); static herr_t H5B2_cache_hdr_size(const H5F_t *f, const H5B2_t *bt, size_t *size_ptr); static H5B2_internal_t *H5B2_cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrec, void *_shared); -static herr_t H5B2_cache_internal_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_internal_t *i); +static herr_t H5B2_cache_internal_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_internal_t *i, unsigned UNUSED * flags_ptr); static herr_t H5B2_cache_internal_clear(H5F_t *f, H5B2_internal_t *i, hbool_t destroy); static herr_t H5B2_cache_internal_size(const H5F_t *f, const H5B2_internal_t *i, size_t *size_ptr); static H5B2_leaf_t *H5B2_cache_leaf_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrec, void *_shared); -static herr_t H5B2_cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_leaf_t *l); +static herr_t H5B2_cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_leaf_t *l, unsigned UNUSED * flags_ptr); static herr_t H5B2_cache_leaf_clear(H5F_t *f, H5B2_leaf_t *l, hbool_t destroy); static herr_t H5B2_cache_leaf_size(const H5F_t *f, const H5B2_leaf_t *l, size_t *size_ptr); @@ -248,11 +248,16 @@ done: * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu * Feb 1 2005 + * Changes: JRM -- 8/21/06 + * Added the flags_ptr parameter. This parameter exists to + * allow the flush routine to report to the cache if the + * entry is resized or renamed as a result of the flush. + * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry. * *------------------------------------------------------------------------- */ static herr_t -H5B2_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_t *bt2) +H5B2_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_t *bt2, unsigned UNUSED * flags_ptr) { herr_t ret_value = SUCCEED; /* Return value */ @@ -579,11 +584,16 @@ done: * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu * Feb 3 2005 + * Changes: JRM -- 8/21/06 + * Added the flags_ptr parameter. This parameter exists to + * allow the flush routine to report to the cache if the + * entry is resized or renamed as a result of the flush. + * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry. * *------------------------------------------------------------------------- */ static herr_t -H5B2_cache_internal_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_internal_t *internal) +H5B2_cache_internal_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_internal_t *internal, unsigned UNUSED * flags_ptr) { herr_t ret_value = SUCCEED; /* Return value */ @@ -909,10 +919,17 @@ done: * koziol@ncsa.uiuc.edu * Feb 2 2005 * + * Changes: JRM -- 8/21/06 + * Added the flags_ptr parameter. This parameter exists to + * allow the flush routine to report to the cache if the + * entry is resized or renamed as a result of the flush. + * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry. + * + * *------------------------------------------------------------------------- */ static herr_t -H5B2_cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_leaf_t *leaf) +H5B2_cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_leaf_t *leaf, unsigned UNUSED * flags_ptr) { herr_t ret_value = SUCCEED; /* Return value */ diff --git a/src/H5Bcache.c b/src/H5Bcache.c index 6f8e259..554ec11 100644 --- a/src/H5Bcache.c +++ b/src/H5Bcache.c @@ -54,7 +54,7 @@ static herr_t H5B_serialize(const H5F_t *f, const H5B_t *bt); /* Metadata cache callbacks */ static H5B_t *H5B_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, void *udata); -static herr_t H5B_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B_t *b); +static herr_t H5B_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B_t *b, unsigned UNUSED * flags_ptr); static herr_t H5B_clear(H5F_t *f, H5B_t *b, hbool_t destroy); static herr_t H5B_compute_size(const H5F_t *f, const H5B_t *bt, size_t *size_ptr); @@ -258,10 +258,16 @@ done: * matzke@llnl.gov * Jun 23 1997 * + * Changes: JRM -- 8/21/06 + * Added the flags_ptr parameter. This parameter exists to + * allow the flush routine to report to the cache if the + * entry is resized or renamed as a result of the flush. + * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry. + * *------------------------------------------------------------------------- */ static herr_t -H5B_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B_t *bt) +H5B_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B_t *bt, unsigned UNUSED * flags_ptr) { H5B_shared_t *shared; /* Pointer to shared B-tree info */ herr_t ret_value = SUCCEED; /* Return value */ @@ -559,10 +559,22 @@ if ( ( (entry_ptr) == NULL ) || \ if ( (cache_ptr)->pel_size > (cache_ptr)->max_pel_size ) \ (cache_ptr)->max_pel_size = (cache_ptr)->pel_size; -#define H5C__UPDATE_STATS_FOR_RENAME(cache_ptr, entry_ptr) \ +#define H5C__UPDATE_STATS_FOR_RENAME(cache_ptr, entry_ptr) \ + if ( cache_ptr->flush_in_progress ) { \ + ((cache_ptr)->cache_flush_renames[(entry_ptr)->type->id])++; \ + } \ + if ( entry_ptr->flush_in_progress ) { \ + ((cache_ptr)->entry_flush_renames[(entry_ptr)->type->id])++; \ + } \ (((cache_ptr)->renames)[(entry_ptr)->type->id])++; #define H5C__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE(cache_ptr, entry_ptr, new_size)\ + if ( cache_ptr->flush_in_progress ) { \ + ((cache_ptr)->cache_flush_size_changes[(entry_ptr)->type->id])++; \ + } \ + if ( entry_ptr->flush_in_progress ) { \ + ((cache_ptr)->entry_flush_size_changes[(entry_ptr)->type->id])++; \ + } \ if ( (entry_ptr)->size < (new_size) ) { \ ((cache_ptr)->size_increases[(entry_ptr)->type->id])++; \ if ( (cache_ptr)->index_size > (cache_ptr)->max_index_size ) \ @@ -571,7 +583,7 @@ if ( ( (entry_ptr) == NULL ) || \ (cache_ptr)->max_slist_size = (cache_ptr)->slist_size; \ if ( (cache_ptr)->pl_size > (cache_ptr)->max_pl_size ) \ (cache_ptr)->max_pl_size = (cache_ptr)->pl_size; \ - } else { \ + } else if ( (entry_ptr)->size > (new_size) ) { \ ((cache_ptr)->size_decreases[(entry_ptr)->type->id])++; \ } @@ -1077,9 +1089,49 @@ if ( ( (cache_ptr) == NULL ) || \ * JRM -- 6/27/06 * Added fail_val parameter. * + * JRM -- 8/25/06 + * Added the H5C_DO_SANITY_CHECKS version of the macro. + * + * This version maintains the slist_len_increase and + * slist_size_increase fields that are used in sanity + * checks in the flush routines. + * + * All this is needed as the fractal heap needs to be + * able to dirty, resize and/or rename entries during the + * flush. + * *------------------------------------------------------------------------- */ +#if H5C_DO_SANITY_CHECKS + +#define H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C__H5C_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( (entry_ptr)->size > 0 ); \ + HDassert( H5F_addr_defined((entry_ptr)->addr) ); \ + HDassert( !((entry_ptr)->in_slist) ); \ + \ + if ( H5SL_insert((cache_ptr)->slist_ptr, entry_ptr, &(entry_ptr)->addr) \ + < 0 ) \ + HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, (fail_val), \ + "Can't insert entry in skip list") \ + \ + (entry_ptr)->in_slist = TRUE; \ + (cache_ptr)->slist_len++; \ + (cache_ptr)->slist_size += (entry_ptr)->size; \ + (cache_ptr)->slist_len_increase++; \ + (cache_ptr)->slist_size_increase += (entry_ptr)->size; \ + \ + HDassert( (cache_ptr)->slist_len > 0 ); \ + HDassert( (cache_ptr)->slist_size > 0 ); \ + \ +} /* H5C__INSERT_ENTRY_IN_SLIST */ + +#else /* H5C_DO_SANITY_CHECKS */ + #define H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, fail_val) \ { \ HDassert( (cache_ptr) ); \ @@ -1103,6 +1155,8 @@ if ( ( (cache_ptr) == NULL ) || \ \ } /* H5C__INSERT_ENTRY_IN_SLIST */ +#endif /* H5C_DO_SANITY_CHECKS */ + /*------------------------------------------------------------------------- * @@ -1169,11 +1223,21 @@ if ( ( (cache_ptr) == NULL ) || \ * * Modifications: * - * None. + * JRM -- 8/27/06 + * Added the H5C_DO_SANITY_CHECKS version of the macro. + * + * This version maintains the slist_size_increase field + * that are used in sanity checks in the flush routines. + * + * All this is needed as the fractal heap needs to be + * able to dirty, resize and/or rename entries during the + * flush. * *------------------------------------------------------------------------- */ +#if H5C_DO_SANITY_CHECKS + #define H5C__UPDATE_SLIST_FOR_SIZE_CHANGE(cache_ptr, old_size, new_size) \ { \ HDassert( (cache_ptr) ); \ @@ -1188,11 +1252,37 @@ if ( ( (cache_ptr) == NULL ) || \ (cache_ptr)->slist_size -= (old_size); \ (cache_ptr)->slist_size += (new_size); \ \ + (cache_ptr)->slist_size_increase -= (int64_t)(old_size); \ + (cache_ptr)->slist_size_increase += (int64_t)(new_size); \ + \ HDassert( (new_size) <= (cache_ptr)->slist_size ); \ HDassert( ( (cache_ptr)->slist_len > 1 ) || \ ( (cache_ptr)->slist_size == (new_size) ) ); \ } /* H5C__REMOVE_ENTRY_FROM_SLIST */ +#else /* H5C_DO_SANITY_CHECKS */ + +#define H5C__UPDATE_SLIST_FOR_SIZE_CHANGE(cache_ptr, old_size, new_size) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C__H5C_T_MAGIC ); \ + HDassert( (old_size) > 0 ); \ + HDassert( (new_size) > 0 ); \ + HDassert( (old_size) <= (cache_ptr)->slist_size ); \ + HDassert( (cache_ptr)->slist_len > 0 ); \ + HDassert( ((cache_ptr)->slist_len > 1) || \ + ( (cache_ptr)->slist_size == (old_size) ) ); \ + \ + (cache_ptr)->slist_size -= (old_size); \ + (cache_ptr)->slist_size += (new_size); \ + \ + HDassert( (new_size) <= (cache_ptr)->slist_size ); \ + HDassert( ( (cache_ptr)->slist_len > 1 ) || \ + ( (cache_ptr)->slist_size == (new_size) ) ); \ +} /* H5C__REMOVE_ENTRY_FROM_SLIST */ + +#endif /* H5C_DO_SANITY_CHECKS */ + /************************************************************************** * @@ -1997,6 +2087,127 @@ if ( ( (cache_ptr) == NULL ) || \ /*------------------------------------------------------------------------- * + * Macro: H5C__UPDATE_RP_FOR_SIZE_CHANGE + * + * Purpose: Update the replacement policy data structures for a + * size change of the specified cache entry. + * + * To do this, determine if the entry is pinned. If it is, + * update the size of the pinned entry list. + * + * If it isn't pinned, the entry must handled by the + * replacement policy. Update the appropriate replacement + * policy data structures. + * + * At present, we only support the modified LRU policy, so + * this function deals with that case unconditionally. If + * we ever support other replacement policies, the function + * should switch on the current policy and act accordingly. + * + * Return: N/A + * + * Programmer: John Mainzer, 8/23/06 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +#if H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS + +#define H5C__UPDATE_RP_FOR_SIZE_CHANGE(cache_ptr, entry_ptr, new_size) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C__H5C_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( (entry_ptr)->size > 0 ); \ + HDassert( new_size > 0 ); \ + \ + if ( (entry_ptr)->is_pinned ) { \ + \ + H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->pel_len, \ + (cache_ptr)->pel_size, \ + (entry_ptr)->size, \ + (new_size)); \ + \ + } else { \ + \ + /* modified LRU specific code */ \ + \ + /* Update the size of the LRU list */ \ + \ + H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, \ + (entry_ptr)->size, \ + (new_size)); \ + \ + /* Similarly, update the size of the clean or dirty LRU list as \ + * appropriate. At present, the entry must be clean, but that \ + * could change. \ + */ \ + \ + if ( (entry_ptr)->is_dirty ) { \ + \ + H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->dLRU_list_len, \ + (cache_ptr)->dLRU_list_size, \ + (entry_ptr)->size, \ + (new_size)); \ + \ + } else { \ + \ + H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->cLRU_list_len, \ + (cache_ptr)->cLRU_list_size, \ + (entry_ptr)->size, \ + (new_size)); \ + } \ + \ + /* End modified LRU specific code. */ \ + } \ + \ +} /* H5C__UPDATE_RP_FOR_SIZE_CHANGE */ + +#else /* H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + +#define H5C__UPDATE_RP_FOR_SIZE_CHANGE(cache_ptr, entry_ptr, new_size) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C__H5C_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( (entry_ptr)->size > 0 ); \ + HDassert( new_size > 0 ); \ + \ + if ( (entry_ptr)->is_pinned ) { \ + \ + H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->pel_len, \ + (cache_ptr)->pel_size, \ + (entry_ptr)->size, \ + (new_size)); \ + \ + } else { \ + \ + /* modified LRU specific code */ \ + \ + /* Update the size of the LRU list */ \ + \ + H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, \ + (entry_ptr)->size, \ + (new_size)); \ + \ + /* End modified LRU specific code. */ \ + } \ + \ +} /* H5C__UPDATE_RP_FOR_SIZE_CHANGE */ + +#endif /* H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + + +/*------------------------------------------------------------------------- + * * Macro: H5C__UPDATE_RP_FOR_UNPIN * * Purpose: Update the replacement policy data structures for an @@ -2352,7 +2563,8 @@ static herr_t H5C_verify_not_in_index(H5C_t * cache_ptr, static void *H5C_epoch_marker_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1, void *udata2); static herr_t H5C_epoch_marker_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, - haddr_t addr, void *thing); + haddr_t addr, void *thing, + unsigned *flags_ptr); static herr_t H5C_epoch_marker_dest(H5F_t *f, void *thing); static herr_t H5C_epoch_marker_clear(H5F_t *f, void *thing, hbool_t dest); static herr_t H5C_epoch_marker_size(const H5F_t *f, const void *thing, size_t *size_ptr); @@ -2377,11 +2589,11 @@ const H5C_class_t epoch_marker_class = ***************************************************************************/ static void * -H5C_epoch_marker_load(UNUSED H5F_t *f, - UNUSED hid_t dxpl_id, - UNUSED haddr_t addr, - UNUSED const void *udata1, - UNUSED void *udata2) +H5C_epoch_marker_load(H5F_t UNUSED * f, + hid_t UNUSED dxpl_id, + haddr_t UNUSED addr, + const void UNUSED * udata1, + void UNUSED * udata2) { void * ret_value = NULL; /* Return value */ @@ -2395,11 +2607,12 @@ done: } static herr_t -H5C_epoch_marker_flush(UNUSED H5F_t *f, - UNUSED hid_t dxpl_id, - UNUSED hbool_t dest, - UNUSED haddr_t addr, - UNUSED void *thing) +H5C_epoch_marker_flush(H5F_t UNUSED *f, + hid_t UNUSED dxpl_id, + hbool_t UNUSED dest, + haddr_t UNUSED addr, + void UNUSED *thing, + unsigned UNUSED * flags_ptr) { herr_t ret_value = FAIL; /* Return value */ @@ -2413,8 +2626,8 @@ done: } static herr_t -H5C_epoch_marker_dest(UNUSED H5F_t *f, - UNUSED void *thing) +H5C_epoch_marker_dest(H5F_t UNUSED * f, + void UNUSED * thing) { herr_t ret_value = FAIL; /* Return value */ @@ -2428,9 +2641,9 @@ done: } static herr_t -H5C_epoch_marker_clear(UNUSED H5F_t *f, - UNUSED void *thing, - UNUSED hbool_t dest) +H5C_epoch_marker_clear(H5F_t UNUSED * f, + void UNUSED * thing, + hbool_t UNUSED dest) { herr_t ret_value = FAIL; /* Return value */ @@ -2444,9 +2657,9 @@ done: } static herr_t -H5C_epoch_marker_size(UNUSED const H5F_t *f, - UNUSED const void *thing, - UNUSED size_t *size_ptr) +H5C_epoch_marker_size(const H5F_t UNUSED * f, + const void UNUSED * thing, + size_t UNUSED * size_ptr) { herr_t ret_value = FAIL; /* Return value */ @@ -2518,6 +2731,15 @@ done: * JRM -- 5/31/06 * Added initialization for the trace_file_ptr field. * + * JRM -- 8/19/06 + * Added initialization for the flush_in_progress field. + * + * JRM -- 8/25/06 + * Added initialization for the slist_len_increase and + * slist_size_increase fields. These fields are used + * for sanity checking in the flush process, and are not + * compiled in unless H5C_DO_SANITY_CHECKS is TRUE. + * *------------------------------------------------------------------------- */ @@ -2572,6 +2794,8 @@ H5C_create(size_t max_cache_size, cache_ptr->magic = H5C__H5C_T_MAGIC; + cache_ptr->flush_in_progress = FALSE; + cache_ptr->trace_file_ptr = NULL; cache_ptr->aux_ptr = aux_ptr; @@ -2593,6 +2817,11 @@ H5C_create(size_t max_cache_size, cache_ptr->slist_len = 0; cache_ptr->slist_size = (size_t)0; +#if H5C_DO_SANITY_CHECKS + cache_ptr->slist_len_increase = 0; + cache_ptr->slist_size_increase = 0; +#endif /* H5C_DO_SANITY_CHECKS */ + for ( i = 0; i < H5C__HASH_TABLE_LEN; i++ ) { (cache_ptr->index)[i] = NULL; @@ -2754,7 +2983,7 @@ H5C_def_auto_resize_rpt_fcn(H5C_t * cache_ptr, #ifndef NDEBUG int32_t version, #else /* NDEBUG */ - UNUSED int32_t version, + int32_t UNUSED version, #endif /* NDEBUG */ double hit_rate, enum H5C_resize_status status, @@ -3193,9 +3422,18 @@ done: * Note that even with this flag set, it is still an error * to try to flush a protected entry. * - * JRM -- 3/25/065 + * JRM -- 3/25/06 * Updated function to handle pinned entries. * + * JRM -- 8/19/06 + * Added code managing the new flush_in_progress field of + * H5C_t. + * + * Also reworked function to allow for the possibility that + * entries will be dirtied, resized, or renamed during flush + * callbacks. As a result, we may have to make multiple + * passes through the skip list before the cache is flushed. + * *------------------------------------------------------------------------- */ herr_t @@ -3208,18 +3446,20 @@ H5C_flush_cache(H5F_t * f, herr_t status; herr_t ret_value = SUCCEED; hbool_t destroy; + hbool_t flushed_entries_last_pass; hbool_t flush_marked_entries; hbool_t first_flush = TRUE; hbool_t ignore_protected; hbool_t tried_to_flush_protected_entry = FALSE; + int32_t passes = 0; int32_t protected_entries = 0; H5SL_node_t * node_ptr = NULL; H5C_cache_entry_t * entry_ptr = NULL; #if H5C_DO_SANITY_CHECKS - int32_t actual_slist_len = 0; - int32_t initial_slist_len = 0; - size_t actual_slist_size = 0; - size_t initial_slist_size = 0; + int64_t flushed_entries_count; + size_t flushed_entries_size; + int64_t initial_slist_len; + size_t initial_slist_size; #endif /* H5C_DO_SANITY_CHECKS */ FUNC_ENTER_NOAPI(H5C_flush_cache, FAIL) @@ -3241,6 +3481,10 @@ H5C_flush_cache(H5F_t * f, HDassert( ! ( destroy && ignore_protected ) ); + HDassert( ! ( cache_ptr->flush_in_progress ) ); + + cache_ptr->flush_in_progress = TRUE; + if ( destroy ) { status = H5C_flush_invalidate_cache(f, @@ -3258,103 +3502,160 @@ H5C_flush_cache(H5F_t * f, "flush invalidate failed.") } } else { - - if ( cache_ptr->slist_len == 0 ) { - - node_ptr = NULL; - HDassert( cache_ptr->slist_size == 0 ); - - } else { - + /* When we are only flushing marked entries, the slist will usually + * still contain entries when we have flushed everything we should. + * Thus we track whether we have flushed any entries in the last + * pass, and terminate if we haven't. + */ + + flushed_entries_last_pass = TRUE; + + while ( ( passes < H5C__MAX_PASSES_ON_FLUSH ) && + ( cache_ptr->slist_len != 0 ) && + ( protected_entries == 0 ) && + ( flushed_entries_last_pass ) ) + { + flushed_entries_last_pass = FALSE; node_ptr = H5SL_first(cache_ptr->slist_ptr); + + HDassert( node_ptr != NULL ); #if H5C_DO_SANITY_CHECKS - /* H5C_flush_single_entry() now removes dirty entries from the - * slist as it flushes them. Thus for sanity checks we must - * make note of the initial slist length and size before we - * do any flushes. - */ + /* For sanity checking, try to verify that the skip list has + * the expected size and number of entries at the end of each + * internal while loop (see below). + * + * Doing this get a bit tricky, as depending on flags, we may + * or may not flush all the entries in the slist. + * + * To make things more entertaining, with the advent of the + * fractal heap, the entry flush callback can cause entries + * to be dirtied, resized, and/or renamed. + * + * To deal with this, we first make note of the initial + * skip list length and size: + */ initial_slist_len = cache_ptr->slist_len; initial_slist_size = cache_ptr->slist_size; -#endif /* H5C_DO_SANITY_CHECKS */ - - } - - while ( node_ptr != NULL ) - { - entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr); - - /* increment node pointer now, before we delete its target - * from the slist. - */ - node_ptr = H5SL_next(node_ptr); - - HDassert( entry_ptr != NULL ); - HDassert( entry_ptr->in_slist ); -#if H5C_DO_SANITY_CHECKS - actual_slist_len++; - actual_slist_size += entry_ptr->size; + /* We then zero counters that we use to track the number + * and total size of entries flushed: + */ + flushed_entries_count = 0; + flushed_entries_size = 0; + + /* As mentioned above, there is the possibility that + * entries will be dirtied, resized, and/or flushed during + * our pass through the skip list. To capture the number + * of entries added, and the skip list size delta, + * zero the slist_len_increase and slist_size_increase of + * the cache's instance of H5C_t. These fields will be + * updated elsewhere to account for slist insertions and/or + * dirty entry size changes. + */ + cache_ptr->slist_len_increase = 0; + cache_ptr->slist_size_increase = 0; + + /* at the end of the loop, use these values to compute the + * expected slist length and size and compare this with the + * value recorded in the cache's instance of H5C_t. + */ #endif /* H5C_DO_SANITY_CHECKS */ - if ( ( ! flush_marked_entries ) || ( entry_ptr->flush_marker ) ) { + while ( node_ptr != NULL ) + { + entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr); - if ( entry_ptr->is_protected ) { + /* increment node pointer now, before we delete its target + * from the slist. + */ + node_ptr = H5SL_next(node_ptr); - /* we probably have major problems -- but lets flush - * everything we can before we decide whether to flag - * an error. - */ - tried_to_flush_protected_entry = TRUE; - protected_entries++; + HDassert( entry_ptr != NULL ); + HDassert( entry_ptr->in_slist ); - } else { + if ( ( ! flush_marked_entries ) || + ( entry_ptr->flush_marker ) ) { - status = H5C_flush_single_entry(f, - primary_dxpl_id, - secondary_dxpl_id, - cache_ptr, - NULL, - entry_ptr->addr, - flags, - &first_flush, - FALSE); - if ( status < 0 ) { + if ( entry_ptr->is_protected ) { - /* This shouldn't happen -- if it does, we are toast so - * just scream and die. + /* we probably have major problems -- but lets flush + * everything we can before we decide whether to flag + * an error. */ - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ - "Can't flush entry.") + tried_to_flush_protected_entry = TRUE; + protected_entries++; + + } else { +#if H5C_DO_SANITY_CHECKS + flushed_entries_count++; + flushed_entries_size += entry_ptr->size; +#endif /* H5C_DO_SANITY_CHECKS */ + status = H5C_flush_single_entry(f, + primary_dxpl_id, + secondary_dxpl_id, + cache_ptr, + NULL, + entry_ptr->addr, + flags, + &first_flush, + FALSE); + if ( status < 0 ) { + + /* This shouldn't happen -- if it does, we are + * toast so just scream and die. + */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "Can't flush entry.") + } + flushed_entries_last_pass = TRUE; } } - } - } /* while */ + } /* while ( node_ptr != NULL ) */ #if H5C_DO_SANITY_CHECKS - HDassert( actual_slist_len == initial_slist_len ); - HDassert( actual_slist_size == initial_slist_size ); - - if ( ! flush_marked_entries ) { + /* Verify that the slist size and length are as expected. */ - HDassert( cache_ptr->slist_len == 0 ); - HDassert( cache_ptr->slist_size == 0 ); - } + HDassert( (initial_slist_len + cache_ptr->slist_len_increase - + flushed_entries_count) == cache_ptr->slist_len ); + HDassert( (initial_slist_size + cache_ptr->slist_size_increase - + flushed_entries_size) == cache_ptr->slist_size ); #endif /* H5C_DO_SANITY_CHECKS */ + passes++; + + } /* while */ + HDassert( protected_entries <= cache_ptr->pl_len ); if ( ( ( cache_ptr->pl_len > 0 ) && ( !ignore_protected ) ) || ( tried_to_flush_protected_entry ) ) { - HGOTO_ERROR(H5E_CACHE, H5E_PROTECT, FAIL, \ + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ "cache has protected items") } - } + + if ( ( cache_ptr->slist_len != 0 ) && + ( passes >= H5C__MAX_PASSES_ON_FLUSH ) ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "flush pass limit exceeded.") + } + +#if H5C_DO_SANITY_CHECKS + if ( ! flush_marked_entries ) { + + HDassert( cache_ptr->slist_len == 0 ); + HDassert( cache_ptr->slist_size == 0 ); + } +#endif /* H5C_DO_SANITY_CHECKS */ + + } done: + cache_ptr->flush_in_progress = FALSE; FUNC_LEAVE_NOAPI(ret_value) @@ -3964,6 +4265,10 @@ done: * JRM -- 8/9/06 * Added code supporting insertion of pinned entries. * + * JRM -- 8/21/06 + * Added initialization for the new flush_in_progress and + * destroy_in_progress fields. + * *------------------------------------------------------------------------- */ @@ -4040,6 +4345,9 @@ H5C_insert_entry(H5F_t * f, entry_ptr->clear_on_unprotect = FALSE; #endif /* H5_HAVE_PARALLEL */ + entry_ptr->flush_in_progress = FALSE; + entry_ptr->destroy_in_progress = FALSE; + entry_ptr->ht_next = NULL; entry_ptr->ht_prev = NULL; @@ -4702,6 +5010,15 @@ done: * JRM -- 4/27/06 * Updated function to support renaming of pinned entries. * + * JRM -- 8/24/06 + * Updated function to refrain from alterning the index, the + * replacement policy data structures, and skip list when + * the function is called within the flush callback for the + * target entry and the target entry is being destroyed. + * + * Note that in this case H5C_flush_single_entry() will handle + * all these details for us. + * *------------------------------------------------------------------------- */ @@ -4715,6 +5032,9 @@ H5C_rename_entry(H5C_t * cache_ptr, hbool_t was_dirty; H5C_cache_entry_t * entry_ptr = NULL; H5C_cache_entry_t * test_entry_ptr = NULL; +#if H5C_DO_SANITY_CHECKS + hbool_t removed_entry_from_slist = FALSE; +#endif /* H5C_DO_SANITY_CHECKS */ FUNC_ENTER_NOAPI(H5C_rename_entry, FAIL) @@ -4733,7 +5053,6 @@ H5C_rename_entry(H5C_t * cache_ptr, } #endif /* H5C_DO_EXTREME_SANITY_CHECKS */ - H5C__SEARCH_INDEX(cache_ptr, old_addr, entry_ptr, FAIL) if ( ( entry_ptr == NULL ) || ( entry_ptr->type != type ) ) { @@ -4768,7 +5087,7 @@ H5C_rename_entry(H5C_t * cache_ptr, } } - /* If we get this far, we have work to do. Remove *entry_ptr from + /* If we get this far we have work to do. Remove *entry_ptr from * the hash table (and skip list if necessary), change its address to the * new address, mark it as dirty (if it isn't already) and then re-insert. * @@ -4777,26 +5096,69 @@ H5C_rename_entry(H5C_t * cache_ptr, * * Note that we do not check the size of the cache, or evict anything. * Since this is a simple re-name, cache size should be unaffected. + * + * Check to see if the target entry is in the process of being destroyed + * before we delete from the index, etc. If it is, all we do is + * change the addr. If the entry is only in the process of being flushed, + * don't mark it as dirty either, lest we confuse the flush call back. */ - H5C__DELETE_FROM_INDEX(cache_ptr, entry_ptr) + if ( ! ( entry_ptr->destroy_in_progress ) ) { + + H5C__DELETE_FROM_INDEX(cache_ptr, entry_ptr) - if ( entry_ptr->in_slist ) { + if ( entry_ptr->in_slist ) { + + HDassert( cache_ptr->slist_ptr ); + + H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr) + +#if H5C_DO_SANITY_CHECKS - HDassert( cache_ptr->slist_ptr ); + removed_entry_from_slist = TRUE; - H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr) +#endif /* H5C_DO_SANITY_CHECKS */ + } } entry_ptr->addr = new_addr; - was_dirty = entry_ptr->is_dirty; - entry_ptr->is_dirty = TRUE; - H5C__INSERT_IN_INDEX(cache_ptr, entry_ptr, FAIL) + if ( ! ( entry_ptr->destroy_in_progress ) ) { + + was_dirty = entry_ptr->is_dirty; - H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL) + if ( ! ( entry_ptr->flush_in_progress ) ) { - H5C__UPDATE_RP_FOR_RENAME(cache_ptr, entry_ptr, was_dirty, FAIL) + entry_ptr->is_dirty = TRUE; + } + + H5C__INSERT_IN_INDEX(cache_ptr, entry_ptr, FAIL) + + if ( ! ( entry_ptr->flush_in_progress ) ) { + + H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL) + +#if H5C_DO_SANITY_CHECKS + + if ( removed_entry_from_slist ) { + + /* we just removed the entry from the slist. Thus we + * must touch up cache_ptr->slist_len_increase and + * cache_ptr->slist_size_increase to keep from skewing + * the sanity checks. + */ + HDassert( cache_ptr->slist_len_increase > 1 ); + HDassert( cache_ptr->slist_size_increase > entry_ptr->size ); + + cache_ptr->slist_len_increase -= 1; + cache_ptr->slist_size_increase -= entry_ptr->size; + } + +#endif /* H5C_DO_SANITY_CHECKS */ + + H5C__UPDATE_RP_FOR_RENAME(cache_ptr, entry_ptr, was_dirty, FAIL) + } + } H5C__UPDATE_STATS_FOR_RENAME(cache_ptr, entry_ptr) @@ -5773,6 +6135,9 @@ done: * JRM -- 8/9/06 * More code supporting pinned entry related stats. * + * JRM -- 8/23/06 + * Added code supporting new flush related statistics. + * *------------------------------------------------------------------------- */ @@ -5797,8 +6162,12 @@ H5C_stats(H5C_t * cache_ptr, int64_t total_flushes = 0; int64_t total_evictions = 0; int64_t total_renames = 0; + int64_t total_entry_flush_renames = 0; + int64_t total_cache_flush_renames = 0; int64_t total_size_increases = 0; int64_t total_size_decreases = 0; + int64_t total_entry_flush_size_changes = 0; + int64_t total_cache_flush_size_changes = 0; int64_t total_pins = 0; int64_t total_unpins = 0; int64_t total_dirty_pins = 0; @@ -5839,8 +6208,16 @@ H5C_stats(H5C_t * cache_ptr, total_flushes += cache_ptr->flushes[i]; total_evictions += cache_ptr->evictions[i]; total_renames += cache_ptr->renames[i]; + total_entry_flush_renames + += cache_ptr->entry_flush_renames[i]; + total_cache_flush_renames + += cache_ptr->cache_flush_renames[i]; total_size_increases += cache_ptr->size_increases[i]; total_size_decreases += cache_ptr->size_decreases[i]; + total_entry_flush_size_changes + += cache_ptr->entry_flush_size_changes[i]; + total_cache_flush_size_changes + += cache_ptr->cache_flush_size_changes[i]; total_pins += cache_ptr->pins[i]; total_unpins += cache_ptr->unpins[i]; total_dirty_pins += cache_ptr->dirty_pins[i]; @@ -5981,11 +6358,22 @@ H5C_stats(H5C_t * cache_ptr, (long)total_pinned_insertions, (long)total_renames); + HDfprintf(stdout, + "%s Total entry / cache flush renames = %ld / %ld\n", + cache_ptr->prefix, + (long)total_entry_flush_renames, + (long)total_cache_flush_renames); + HDfprintf(stdout, "%s Total entry size incrs / decrs = %ld / %ld\n", cache_ptr->prefix, (long)total_size_increases, (long)total_size_decreases); + HDfprintf(stdout, "%s Ttl entry/cache flush size changes = %ld / %ld\n", + cache_ptr->prefix, + (long)total_entry_flush_size_changes, + (long)total_cache_flush_size_changes); + HDfprintf(stdout, "%s Total entry pins (dirty) / unpins = %ld (%ld) / %ld\n", cache_ptr->prefix, @@ -6058,12 +6446,25 @@ H5C_stats(H5C_t * cache_ptr, (long)(cache_ptr->renames[i])); HDfprintf(stdout, + "%s entry / cache flush renames = %ld / %ld\n", + cache_ptr->prefix, + (long)(cache_ptr->entry_flush_renames[i]), + (long)(cache_ptr->cache_flush_renames[i])); + + HDfprintf(stdout, "%s size increases / decreases = %ld / %ld\n", cache_ptr->prefix, (long)(cache_ptr->size_increases[i]), (long)(cache_ptr->size_decreases[i])); HDfprintf(stdout, + "%s entry/cache flush size changes = %ld / %ld\n", + cache_ptr->prefix, + (long)(cache_ptr->entry_flush_size_changes[i]), + (long)(cache_ptr->cache_flush_size_changes[i])); + + + HDfprintf(stdout, "%s entry pins / unpins = %ld / %ld\n", cache_ptr->prefix, (long)(cache_ptr->pins[i]), @@ -6135,6 +6536,9 @@ done: * JRM - 8/9/06 * Further updates for pin related statistics. * + * JRM 8/23/08 + * Added initialization code for new flush related statistics. + * *------------------------------------------------------------------------- */ @@ -6159,6 +6563,8 @@ H5C_stats__reset(H5C_t * cache_ptr) cache_ptr->flushes[i] = 0; cache_ptr->evictions[i] = 0; cache_ptr->renames[i] = 0; + cache_ptr->entry_flush_renames[i] = 0; + cache_ptr->cache_flush_renames[i] = 0; cache_ptr->pins[i] = 0; cache_ptr->unpins[i] = 0; cache_ptr->dirty_pins[i] = 0; @@ -6166,6 +6572,8 @@ H5C_stats__reset(H5C_t * cache_ptr) cache_ptr->pinned_clears[i] = 0; cache_ptr->size_increases[i] = 0; cache_ptr->size_decreases[i] = 0; + cache_ptr->entry_flush_size_changes[i] = 0; + cache_ptr->cache_flush_size_changes[i] = 0; } cache_ptr->total_ht_insertions = 0; @@ -7971,7 +8379,11 @@ done: * * Modifications: * - * None. + * To support the fractal heap, the cache must now deal with + * entries being dirtied, resized, and/or renamed inside + * flush callbacks. Updated function to support this. + * + * -- JRM 8/27/06 * *------------------------------------------------------------------------- */ @@ -7984,6 +8396,7 @@ H5C_flush_invalidate_cache(H5F_t * f, { herr_t status; herr_t ret_value = SUCCEED; + hbool_t done = FALSE; hbool_t first_flush = TRUE; hbool_t first_pass = TRUE; hbool_t have_pinned_entries; @@ -7991,13 +8404,14 @@ H5C_flush_invalidate_cache(H5F_t * f, int32_t i; int32_t cur_pel_len; int32_t old_pel_len; + int32_t passes = 0; unsigned cooked_flags; H5SL_node_t * node_ptr = NULL; H5C_cache_entry_t * entry_ptr = NULL; H5C_cache_entry_t * next_entry_ptr = NULL; #if H5C_DO_SANITY_CHECKS - int32_t actual_slist_len = 0; - int32_t initial_slist_len = 0; + int64_t actual_slist_len = 0; + int64_t initial_slist_len = 0; size_t actual_slist_size = 0; size_t initial_slist_size = 0; #endif /* H5C_DO_SANITY_CHECKS */ @@ -8026,15 +8440,51 @@ H5C_flush_invalidate_cache(H5F_t * f, } } + /* The flush proceedure here is a bit strange. + * + * In the outer while loop we make at least one pass through the + * cache, and then repeat until either all the pinned entries + * unpin themselves, or until the number of pinned entries stops + * declining. In this later case, we scream and die. + * + * Since the fractal heap can dirty, resize, and/or rename entries + * in is flush callback, it is possible that the cache will still + * contain dirty entries at this point. If so, we must make up to + * H5C__MAX_PASSES_ON_FLUSH more passes through the skip list + * to allow it to empty. If is is not empty at this point, we again + * scream and die. + * + * Further, since clean entries can be dirtied, resized, and/or renamed + * as the result of a flush call back (either the entries own, or that + * for some other cache entry), we can no longer promise to flush + * the cache entries in increasing address order. + * + * Instead, we just do the best we can -- making a pass through + * the skip list, and then a pass through the "clean" entries, and + * then repeating as needed. Thus it is quite possible that an + * entry will be evicted from the cache only to be re-loaded later + * in the flush process (From what Quincey tells me, the pin + * mechanism makes this impossible, but even it it is true now, + * we shouldn't count on it in the future.) + * + * The bottom line is that entries will probably be flushed in close + * to increasing address order, but there are no guarantees. + */ + cur_pel_len = cache_ptr->pel_len; old_pel_len = cache_ptr->pel_len; - while ( ( first_pass ) || - ( ( cur_pel_len < old_pel_len ) && ( protected_entries == 0 ) ) ) + while ( ! done ) { + first_pass = FALSE; + have_pinned_entries = ( cur_pel_len > 0 ); - /* first, try to flush-destroy any dirty entries */ + /* first, try to flush-destroy any dirty entries. Do this by + * making a scan through the slist. Note that new dirty entries + * may be created by the flush call backs. Thus it is possible + * that the slist will not be empty after we finish the scan. + */ if ( cache_ptr->slist_len == 0 ) { @@ -8045,18 +8495,36 @@ H5C_flush_invalidate_cache(H5F_t * f, node_ptr = H5SL_first(cache_ptr->slist_ptr); + } #if H5C_DO_SANITY_CHECKS - /* Depending on circumstances, H5C_flush_single_entry() will - * remove dirty entries from the slist as it flushes them. - * Thus for sanity checks we must make note of the initial - * slist length and size before we do any flushes. - */ - initial_slist_len = cache_ptr->slist_len; - initial_slist_size = cache_ptr->slist_size; + /* Depending on circumstances, H5C_flush_single_entry() will + * remove dirty entries from the slist as it flushes them. + * Thus for sanity checks we must make note of the initial + * slist length and size before we do any flushes. + */ + initial_slist_len = cache_ptr->slist_len; + initial_slist_size = cache_ptr->slist_size; + + /* There is also the possibility that entries will be + * dirtied, resized, and/or renamed as the result of + * calls to the flush callbacks. We use the slist_len_increase + * and slist_size_increase increase fields in struct H5C_t + * to track these changes for purpose of sanity checking. + * To this end, we must zero these fields before we start + * the pass through the slist. + */ + cache_ptr->slist_len_increase = 0; + cache_ptr->slist_size_increase = 0; + + /* Finally, reset the actual_slist_len and actual_slist_size + * fields to zero, as these fields are used to accumulate + * the slist lenght and size that we see as we scan through + * the slist. + */ + actual_slist_len = 0; + actual_slist_size = 0; #endif /* H5C_DO_SANITY_CHECKS */ - } - while ( node_ptr != NULL ) { /* Note that we now remove nodes from the slist as we flush @@ -8064,14 +8532,10 @@ H5C_flush_invalidate_cache(H5F_t * f, * until we are done, and then destroying all nodes in * the slist. * - * While this optimization is still easy if everything works, - * the addition of pinned entries and multiple passes - * through the cache to allow entries to unpin themselves - * complicates error recover greatly. - * - * Given these complications, I've decided to ommit this - * this optimization for now. It can be re-implemented - * later if needed. + * While this optimization used to be easy, with the possibility + * of new entries being added to the slist in the midst of the + * flush, we must keep the slist in cannonical form at all + * times. */ entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr); @@ -8085,6 +8549,16 @@ H5C_flush_invalidate_cache(H5F_t * f, HDassert( entry_ptr->in_slist ); #if H5C_DO_SANITY_CHECKS + /* update actual_slist_len & actual_slist_size before + * the flush. Note that the entry will be removed + * from the slist after the flush, and thus may be + * resized by the flush callback. This is OK, as + * we will catch the size delta in + * cache_ptr->slist_size_increase. + * + * Note that we include pinned entries in this count, even + * though we will not actually flush them. + */ actual_slist_len++; actual_slist_size += entry_ptr->size; #endif /* H5C_DO_SANITY_CHECKS */ @@ -8103,8 +8577,11 @@ H5C_flush_invalidate_cache(H5F_t * f, * H5C_flush_single_entry() to destroy the entry * as pinned entries can't be evicted. */ - if ( TRUE ) { /* insert test here */ /* JRM */ - + if ( TRUE ) { /* When we get to multithreaded cache, + * we will need either locking code, and/or + * a test to see if the entry is in flushable + * condition here. + */ status = H5C_flush_single_entry(f, primary_dxpl_id, @@ -8114,12 +8591,13 @@ H5C_flush_invalidate_cache(H5F_t * f, entry_ptr->addr, H5C__NO_FLAGS_SET, &first_flush, - TRUE); + FALSE); if ( status < 0 ) { /* This shouldn't happen -- if it does, we are toast * so just scream and die. */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ "dirty pinned entry flush failed.") } @@ -8141,6 +8619,7 @@ H5C_flush_invalidate_cache(H5F_t * f, /* This shouldn't happen -- if it does, we are toast so * just scream and die. */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ "dirty entry flush destroy failed.") } @@ -8148,14 +8627,27 @@ H5C_flush_invalidate_cache(H5F_t * f, } /* end while loop scanning skip list */ #if H5C_DO_SANITY_CHECKS - HDassert( actual_slist_len == initial_slist_len ); - HDassert( actual_slist_size == initial_slist_size ); + /* It is possible that entries were added to the slist during + * the scan, either before or after scan pointer. The following + * asserts take this into account. + */ + + HDassert( (actual_slist_len + cache_ptr->slist_len) == + (initial_slist_len + cache_ptr->slist_len_increase) ); + HDassert( (actual_slist_size + cache_ptr->slist_size) == + (initial_slist_size + cache_ptr->slist_size_increase) ); #endif /* H5C_DO_SANITY_CHECKS */ /* Since we are doing a destroy, we must make a pass through * the hash table and try to flush - destroy all entries that - * remain. Note that all remaining entries entries must be - * clean, so this will not result in any writes to disk. + * remain. + * + * It used to be that all entries remaining in the cache at + * this point had to be clean, but with the fractal heap mods + * this may not be the case. If so, we will flush entries out + * of increasing address order. + * + * Writes to disk are possible here. */ for ( i = 0; i < H5C__HASH_TABLE_LEN; i++ ) { @@ -8171,17 +8663,14 @@ H5C_flush_invalidate_cache(H5F_t * f, /* we have major problems -- but lets flush and destroy * everything we can before we flag an error. */ + protected_entries++; if ( ! entry_ptr->in_slist ) { - protected_entries++; HDassert( !(entry_ptr->is_dirty) ); } } else if ( ! ( entry_ptr->is_pinned ) ) { - HDassert( !(entry_ptr->is_dirty) ); - HDassert( !(entry_ptr->in_slist) ); - status = H5C_flush_single_entry(f, primary_dxpl_id, secondary_dxpl_id, @@ -8197,8 +8686,9 @@ H5C_flush_invalidate_cache(H5F_t * f, /* This shouldn't happen -- if it does, we are toast so * just scream and die. */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ - "Clean entry flush destroy failed.") + "Entry flush destroy failed.") } } /* We can't do anything if the entry is pinned. The @@ -8212,15 +8702,50 @@ H5C_flush_invalidate_cache(H5F_t * f, } /* end while loop scanning hash table bin */ } /* end for loop scanning hash table */ - HDassert( protected_entries == cache_ptr->pl_len ); - old_pel_len = cur_pel_len; cur_pel_len = cache_ptr->pel_len; - first_pass = FALSE; + if ( ( cur_pel_len > 0 ) && ( cur_pel_len >= old_pel_len ) ) { + + /* The number of pinned entries is positive, and it is not + * declining. Scream and die. + */ + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "Can't unpin all pinned entries 1.") + + } else if ( ( cur_pel_len == 0 ) && ( old_pel_len == 0 ) ) { + + /* increment the pass count */ + passes++; + } + + if ( passes >= H5C__MAX_PASSES_ON_FLUSH ) { + + /* we have exceeded the maximum number of passes through the + * cache to flush and destroy all entries. Scream and die. + */ + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "Maximum passes on flush exceeded.") + } + if ( cache_ptr->index_len <= 0 ) { + + done = TRUE; + HDassert( cache_ptr->index_size == 0 ); + HDassert( cache_ptr->slist_len == 0 ); + HDassert( cache_ptr->slist_size == 0 ); + HDassert( cache_ptr->pel_len == 0 ); + HDassert( cache_ptr->pel_size == 0 ); + HDassert( cache_ptr->pl_len == 0 ); + HDassert( cache_ptr->pl_size == 0 ); + HDassert( cache_ptr->LRU_list_len == 0 ); + HDassert( cache_ptr->LRU_list_size == 0 ); + } } /* main while loop */ + HDassert( protected_entries <= cache_ptr->pl_len ); if ( protected_entries > 0 ) { @@ -8231,7 +8756,7 @@ H5C_flush_invalidate_cache(H5F_t * f, } else if ( cur_pel_len > 0 ) { HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ - "Can't unpin all pinned entries.") + "Can't unpin all pinned entries 2.") } @@ -8313,6 +8838,17 @@ done: * is not called if the H5C__FLUSH_CLEAR_ONLY_FLAG is set, * as there is no write to file in this case. * + * JRM -- 8/21/06 + * Added code maintaining the flush_in_progress and + * destroy_in_progress fields in H5C_cache_entry_t. + * + * Also added flush_flags parameter to the call to + * type_ptr->flush() so that the flush routine can report + * whether the entry has been resized or renamed. Added + * code using the flush_flags variable to detect the case + * in which the target entry is resized during flush, and + * update the caches data structures accordingly. + * *------------------------------------------------------------------------- */ static herr_t @@ -8332,10 +8868,12 @@ H5C_flush_single_entry(H5F_t * f, herr_t ret_value = SUCCEED; /* Return value */ herr_t status; int type_id; + unsigned flush_flags = H5C_CALLBACK__NO_FLAGS_SET; H5C_cache_entry_t * entry_ptr = NULL; FUNC_ENTER_NOAPI_NOINIT(H5C_flush_single_entry) + HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); HDassert( cache_ptr->skip_file_checks || f ); @@ -8351,6 +8889,8 @@ H5C_flush_single_entry(H5F_t * f, #if H5C_DO_SANITY_CHECKS if ( entry_ptr != NULL ) { + HDassert( ! ( ( destroy ) && ( entry_ptr->is_pinned ) ) ); + if ( entry_ptr->in_slist ) { if ( ( ( entry_ptr->flush_marker ) && ( ! entry_ptr->is_dirty ) ) || @@ -8396,6 +8936,11 @@ H5C_flush_single_entry(H5F_t * f, { /* we have work to do */ + /* We will set flush_in_progress back to FALSE at the end if the + * entry still exists at that point. + */ + entry_ptr->flush_in_progress = TRUE; + #ifdef H5_HAVE_PARALLEL #ifndef NDEBUG @@ -8456,13 +9001,21 @@ H5C_flush_single_entry(H5F_t * f, /* Always remove the entry from the hash table on a destroy. On a * flush with destroy, it is cheaper to discard the skip list all at * once rather than remove the entries one by one, so we only delete - * from the list if requested. + * from the slist only if requested. * * We must do deletions now as the callback routines will free the * entry if destroy is true. + * + * Note that it is possible that the entry will be renamed during + * its call to flush. This will upset H5C_rename_entry() if we + * don't tell it that it doesn't have to worry about updating the + * index and SLIST. Use the destroy_in_progress field for this + * purpose. */ if ( destroy ) { + entry_ptr->destroy_in_progress = TRUE; + H5C__DELETE_FROM_INDEX(cache_ptr, entry_ptr) if ( ( entry_ptr->in_slist ) && @@ -8606,14 +9159,15 @@ H5C_flush_single_entry(H5F_t * f, if ( *first_flush_ptr && entry_ptr->is_dirty ) { status = (entry_ptr->type->flush)(f, primary_dxpl_id, destroy, - entry_ptr->addr, entry_ptr); + entry_ptr->addr, entry_ptr, + &flush_flags); *first_flush_ptr = FALSE; } else { status = (entry_ptr->type->flush)(f, secondary_dxpl_id, destroy, entry_ptr->addr, - entry_ptr); + entry_ptr, &flush_flags); } if ( status < 0 ) { @@ -8621,6 +9175,43 @@ 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 ) { + + /* In the parallel case, flush operations can + * cause problems. If they occur, scream and + * die. + * + * At present, in the parallel case, the aux_ptr + * will only be set if there is more than one + * process. Thus we can use this to detect + * the parallel case. + * + * This works for now, but if we start using the + * aux_ptr for other purposes, we will have to + * change this test accordingly. + * + * NB: While this test detects entryies that attempt + * to resize or rename themselves during a flush + * in the parallel case, it will not detect an + * entry that dirties, resizes, and/or renames + * other entries during its flush. + * + * From what Quincey tells me, this test is + * sufficient for now, as any flush routine that + * does the latter will also do the former. + * + * If that ceases to be the case, further + * tests will be necessary. + */ + if ( cache_ptr->aux_ptr != NULL ) { + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "Flush operation occured in the parallel case.") + + } + } +#endif /* H5_HAVE_PARALLEL */ } if ( ( ! destroy ) && ( entry_ptr->in_slist ) ) { @@ -8628,11 +9219,79 @@ H5C_flush_single_entry(H5F_t * f, H5C__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr) } - if ( ! destroy ) { + if ( ! destroy ) { /* i.e. if the entry still exists */ HDassert( !(entry_ptr->is_dirty) ); HDassert( !(entry_ptr->flush_marker) ); HDassert( !(entry_ptr->in_slist) ); + HDassert( !(entry_ptr->is_protected) ); + + if ( (flush_flags & H5C_CALLBACK__SIZE_CHANGED_FLAG) != 0 ) { + + /* The entry size changed as a result of the flush. + * + * Most likely, the entry was compressed, and the + * new version is of a different size than the old. + * + * In any case, we must update entry and cache size + * accordingly. + */ + size_t new_size; + + if ( (entry_ptr->type->size)(f, (void *)entry_ptr, &new_size) + < 0 ) { + + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGETSIZE, FAIL, \ + "Can't get entry size after flush") + } + + if ( new_size != entry_ptr->size ) { + + HDassert( entry_ptr->size < H5C_MAX_ENTRY_SIZE ); + + /* update the hash table for the size change*/ + H5C__UPDATE_INDEX_FOR_SIZE_CHANGE((cache_ptr), \ + (entry_ptr->size),\ + (new_size)); + + /* The entry can't be protected since we just flushed it. + * Thus we must update the replacement policy data + * structures for the size change. The macro deals + * with the pinned case. + */ + H5C__UPDATE_RP_FOR_SIZE_CHANGE(cache_ptr, entry_ptr, \ + new_size) + + /* The entry can't be in the slist, so no need to update + * the slist for the size change. + */ + + /* update stats for the size change */ + H5C__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE(cache_ptr, \ + entry_ptr, \ + new_size) + + /* finally, update the entry size proper */ + entry_ptr->size = new_size; + } + } + + if ( (flush_flags & H5C_CALLBACK__RENAMED_FLAG) != 0 ) { + + /* The entry was renamed as the result of the flush. + * + * Most likely, the entry was compressed, and the + * new version is larger than the old and thus had + * to be relocated. + * + * At preset, all processing for this case is + * handled elsewhere. But lets keep the if statement + * around just in case. + */ + + } + + entry_ptr->flush_in_progress = FALSE; } if ( cache_ptr->log_flush ) { @@ -8682,6 +9341,10 @@ done: * the case, as our code will attempt to repair errors * on load. * + * JRM - 8/21/06 + * Added initialization for the new flush_in_progress and + * destroy in progress fields. + * *------------------------------------------------------------------------- */ @@ -8695,7 +9358,7 @@ H5C_load_entry(H5F_t * f, #ifndef NDEBUG hbool_t skip_file_checks) #else /* NDEBUG */ - UNUSED hbool_t skip_file_checks) + hbool_t UNUSED skip_file_checks) #endif /* NDEBUG */ { void * thing = NULL; @@ -8751,6 +9414,8 @@ H5C_load_entry(H5F_t * f, #ifdef H5_HAVE_PARALLEL entry_ptr->clear_on_unprotect = FALSE; #endif /* H5_HAVE_PARALLEL */ + entry_ptr->flush_in_progress = FALSE; + entry_ptr->destroy_in_progress = FALSE; if ( (type->size)(f, thing, &(entry_ptr->size)) < 0 ) { diff --git a/src/H5Cpkg.h b/src/H5Cpkg.h index 7895315..4dd3547 100644 --- a/src/H5Cpkg.h +++ b/src/H5Cpkg.h @@ -42,6 +42,17 @@ /* Get needed headers */ #include "H5SLprivate.h" /* Skip lists */ +/* With the introduction of the fractal heap, it is now possible for + * entries to be dirtied, resized, and/or renamed in the flush callbacks. + * As a result, on flushes, it may be necessary to make multiple passes + * through the slist before it is empty. The H5C__MAX_PASSES_ON_FLUSH + * #define is used to set an upper limit on the number of passes. + * The current value was obtained via personal communication with + * Quincey. I have applied a fudge factor of 2. + */ + +#define H5C__MAX_PASSES_ON_FLUSH 4 + #define H5C__HASH_TABLE_LEN (64 * 1024) /* must be a power of 2 */ @@ -87,6 +98,9 @@ * magic: Unsigned 32 bit integer always set to H5C__H5C_T_MAGIC. This * field is used to validate pointers to instances of H5C_t. * + * flush_in_progress: Boolean flag indicating whether a flush is in + * progress. + * * trace_file_ptr: File pointer pointing to the trace file, which is used * to record cache operations for use in simulations and design * studies. This field will usually be NULL, indicating that @@ -222,6 +236,19 @@ * don't use this at present, I hope that this will allow * some optimizations when I get to it. * + * With the addition of the fractal heap, the cache must now deal with + * the case in which entries may be dirtied, renamed, or have their sizes + * changed during a flush. To allow sanity checks in this situation, the + * following two fields have been added. They are only compiled in when + * H5C_DO_SANITY_CHECKS is TRUE. + * + * slist_len_increase: Number of entries that have been added to the + * slist since the last time this field was set to zero. + * + * slist_size_increase: Total size of all entries that have been added + * to the slist since the last time this field was set to + * zero. + * * * When a cache entry is protected, it must be removed from the LRU * list(s) as it cannot be either flushed or evicted until it is unprotected. @@ -570,6 +597,16 @@ * id equal to the array index has been renamed in the current * epoch. * + * entry_flush_renames: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1. + * The cells are used to record the number of times an entry + * with type id equal to the array index has been renamed + * during its flush callback in the current epoch. + * + * cache_flush_renames: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1. + * The cells are used to record the number of times an entry + * with type id equal to the array index has been renamed + * during a cache flush in the current epoch. + * * pins: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1. The cells * are used to record the number of times an entry with type * id equal to the array index has been pinned in the current @@ -595,7 +632,6 @@ * with type id equal to the array index has been cleared while * pinned in the current epoch. * - * * size_increases: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1. * The cells are used to record the number of times an entry * with type id equal to the array index has increased in @@ -606,6 +642,16 @@ * with type id equal to the array index has decreased in * size in the current epoch. * + * entry_flush_size_changes: Array of int64 of length + * H5C__MAX_NUM_TYPE_IDS + 1. The cells are used to record + * the number of times an entry with type id equal to the + * array index has changed size while in its flush callback. + * + * cache_flush_size_changes: Array of int64 of length + * H5C__MAX_NUM_TYPE_IDS + 1. The cells are used to record + * the number of times an entry with type id equal to the + * array index has changed size during a cache flush + * * total_ht_insertions: Number of times entries have been inserted into the * hash table in the current epoch. * @@ -719,6 +765,8 @@ struct H5C_t { uint32_t magic; + hbool_t flush_in_progress; + FILE * trace_file_ptr; void * aux_ptr; @@ -742,7 +790,10 @@ struct H5C_t int32_t slist_len; size_t slist_size; H5SL_t * slist_ptr; - +#if H5C_DO_SANITY_CHECKS + int64_t slist_len_increase; + int64_t slist_size_increase; +#endif /* H5C_DO_SANITY_CHECKS */ int32_t pl_len; size_t pl_size; @@ -798,6 +849,8 @@ struct H5C_t int64_t flushes[H5C__MAX_NUM_TYPE_IDS + 1]; int64_t evictions[H5C__MAX_NUM_TYPE_IDS + 1]; int64_t renames[H5C__MAX_NUM_TYPE_IDS + 1]; + int64_t entry_flush_renames[H5C__MAX_NUM_TYPE_IDS + 1]; + int64_t cache_flush_renames[H5C__MAX_NUM_TYPE_IDS + 1]; int64_t pins[H5C__MAX_NUM_TYPE_IDS + 1]; int64_t unpins[H5C__MAX_NUM_TYPE_IDS + 1]; int64_t dirty_pins[H5C__MAX_NUM_TYPE_IDS + 1]; @@ -805,6 +858,10 @@ struct H5C_t int64_t pinned_clears[H5C__MAX_NUM_TYPE_IDS + 1]; int64_t size_increases[H5C__MAX_NUM_TYPE_IDS + 1]; int64_t size_decreases[H5C__MAX_NUM_TYPE_IDS + 1]; + int64_t entry_flush_size_changes + [H5C__MAX_NUM_TYPE_IDS + 1]; + int64_t cache_flush_size_changes + [H5C__MAX_NUM_TYPE_IDS + 1]; int64_t total_ht_insertions; int64_t total_ht_deletions; diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h index 63393ec..2c97853 100644 --- a/src/H5Cprivate.h +++ b/src/H5Cprivate.h @@ -60,7 +60,7 @@ */ #if H5C_COLLECT_CACHE_STATS -#define H5C_COLLECT_CACHE_ENTRY_STATS 0 +#define H5C_COLLECT_CACHE_ENTRY_STATS 1 #else @@ -116,6 +116,10 @@ typedef struct H5C_t H5C_t; * Note that the space allocated on disk may not be contiguous. */ +#define H5C_CALLBACK__NO_FLAGS_SET 0x0 +#define H5C_CALLBACK__SIZE_CHANGED_FLAG 0x1 +#define H5C_CALLBACK__RENAMED_FLAG 0x2 + typedef void *(*H5C_load_func_t)(H5F_t *f, hid_t dxpl_id, haddr_t addr, @@ -125,7 +129,8 @@ typedef herr_t (*H5C_flush_func_t)(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, - void *thing); + void *thing, + unsigned * flags_ptr); typedef herr_t (*H5C_dest_func_t)(H5F_t *f, void *thing); typedef herr_t (*H5C_clear_func_t)(H5F_t *f, @@ -312,6 +317,13 @@ typedef herr_t (*H5C_log_flush_func_t)(H5C_t * cache_ptr, * the unprotect, the entry's is_dirty flag is reset by flushing * it with the H5C__FLUSH_CLEAR_ONLY_FLAG. * + * flush_in_progress: Boolean flag that is set to true iff the entry + * is in the process of being flushed. This allows the cache + * to detect when a call is the result of a flush callback. + * + * destroy_in_progress: Boolean flag that is set to true iff the entry + * is in the process of being flushed and destroyed. + * * * Fields supporting the hash table: * @@ -425,6 +437,8 @@ typedef struct H5C_cache_entry_t #ifdef H5_HAVE_PARALLEL hbool_t clear_on_unprotect; #endif /* H5_HAVE_PARALLEL */ + hbool_t flush_in_progress; + hbool_t destroy_in_progress; /* fields supporting the hash table: */ diff --git a/src/H5FScache.c b/src/H5FScache.c index fdf54e8..73341f2 100644 --- a/src/H5FScache.c +++ b/src/H5FScache.c @@ -75,11 +75,11 @@ static herr_t H5FS_sinfo_serialize_node_cb(void *_item, void UNUSED *key, void * /* Metadata cache callbacks */ static H5FS_t *H5FS_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata, void *udata2); -static herr_t H5FS_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5FS_t *fspace); +static herr_t H5FS_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5FS_t *fspace, unsigned UNUSED * flags_ptr); static herr_t H5FS_cache_hdr_clear(H5F_t *f, H5FS_t *fspace, hbool_t destroy); static herr_t H5FS_cache_hdr_size(const H5F_t *f, const H5FS_t *fspace, size_t *size_ptr); static H5FS_sinfo_t *H5FS_cache_sinfo_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata, void *udata2); -static herr_t H5FS_cache_sinfo_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5FS_sinfo_t *sinfo); +static herr_t H5FS_cache_sinfo_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5FS_sinfo_t *sinfo, unsigned UNUSED * flags_ptr); static herr_t H5FS_cache_sinfo_clear(H5F_t *f, H5FS_sinfo_t *sinfo, hbool_t destroy); static herr_t H5FS_cache_sinfo_size(const H5F_t *f, const H5FS_sinfo_t *sinfo, size_t *size_ptr); @@ -271,10 +271,17 @@ done: * koziol@ncsa.uiuc.edu * May 2 2006 * + * Changes: JRM -- 8/21/06 + * Added the flags_ptr parameter. This parameter exists to + * allow the flush routine to report to the cache if the + * entry is resized or renamed as a result of the flush. + * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry. + * + * *------------------------------------------------------------------------- */ static herr_t -H5FS_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5FS_t *fspace) +H5FS_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5FS_t *fspace, unsigned UNUSED * flags_ptr) { herr_t ret_value = SUCCEED; /* Return value */ @@ -823,10 +830,15 @@ done: * koziol@ncsa.uiuc.edu * July 31 2006 * + * Changes: JRM -- 8/21/06 + * Added the flags_ptr parameter. This parameter exists to + * allow the flush routine to report to the cache if the + * entry is resized or renamed as a result of the flush. + * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry. *------------------------------------------------------------------------- */ static herr_t -H5FS_cache_sinfo_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5FS_sinfo_t *sinfo) +H5FS_cache_sinfo_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5FS_sinfo_t *sinfo, unsigned UNUSED * flags_ptr) { herr_t ret_value = SUCCEED; /* Return value */ diff --git a/src/H5Gnode.c b/src/H5Gnode.c index cbbfeae..8d534a8 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -75,7 +75,7 @@ static herr_t H5G_node_shared_free(void *shared); static H5G_node_t *H5G_node_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_udata1, void *_udata2); static herr_t H5G_node_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, - H5G_node_t *sym); + H5G_node_t *sym, unsigned UNUSED * flags_ptr); static herr_t H5G_node_dest(H5F_t *f, H5G_node_t *sym); static herr_t H5G_node_clear(H5F_t *f, H5G_node_t *sym, hbool_t destroy); static herr_t H5G_compute_size(const H5F_t *f, const H5G_node_t *sym, size_t *size_ptr); @@ -446,10 +446,16 @@ done: * Pedro Vicente, <pvn@ncsa.uiuc.edu> 18 Sep 2002 * Added `id to name' support. * + * JRM -- 8/21/06 + * Added the flags_ptr parameter. This parameter exists to + * allow the flush routine to report to the cache if the + * entry is resized or renamed as a result of the flush. + * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry. + * *------------------------------------------------------------------------- */ static herr_t -H5G_node_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5G_node_t *sym) +H5G_node_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5G_node_t *sym, unsigned UNUSED * flags_ptr) { uint8_t *buf = NULL; size_t size; diff --git a/src/H5HFcache.c b/src/H5HFcache.c index c1df3c7..41e79e6 100644 --- a/src/H5HFcache.c +++ b/src/H5HFcache.c @@ -68,15 +68,15 @@ static herr_t H5HF_dtable_decode(H5F_t *f, const uint8_t **pp, H5HF_dtable_t *dt /* Metadata cache (H5AC) callbacks */ static H5HF_hdr_t *H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata, void *udata2); -static herr_t H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_hdr_t *hdr); +static herr_t H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_hdr_t *hdr, unsigned UNUSED * flags_ptr); static herr_t H5HF_cache_hdr_clear(H5F_t *f, H5HF_hdr_t *hdr, hbool_t destroy); static herr_t H5HF_cache_hdr_size(const H5F_t *f, const H5HF_hdr_t *hdr, size_t *size_ptr); static H5HF_indirect_t *H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata, void *udata2); -static herr_t H5HF_cache_iblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_indirect_t *iblock); +static herr_t H5HF_cache_iblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_indirect_t *iblock, unsigned UNUSED * flags_ptr); static herr_t H5HF_cache_iblock_clear(H5F_t *f, H5HF_indirect_t *iblock, hbool_t destroy); static herr_t H5HF_cache_iblock_size(const H5F_t *f, const H5HF_indirect_t *iblock, size_t *size_ptr); static H5HF_direct_t *H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata, void *udata2); -static herr_t H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_direct_t *dblock); +static herr_t H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_direct_t *dblock, unsigned UNUSED * flags_ptr); static herr_t H5HF_cache_dblock_clear(H5F_t *f, H5HF_direct_t *dblock, hbool_t destroy); static herr_t H5HF_cache_dblock_size(const H5F_t *f, const H5HF_direct_t *dblock, size_t *size_ptr); @@ -432,11 +432,16 @@ done: * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu * Feb 24 2006 + * Changes: JRM -- 8/21/06 + * Added the flags_ptr parameter. This parameter exists to + * allow the flush routine to report to the cache if the + * entry is resized or renamed as a result of the flush. + * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry. * *------------------------------------------------------------------------- */ static herr_t -H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_hdr_t *hdr) +H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_hdr_t *hdr, unsigned UNUSED * flags_ptr) { herr_t ret_value = SUCCEED; /* Return value */ @@ -878,10 +883,16 @@ done: * koziol@ncsa.uiuc.edu * Mar 6 2006 * + * Changes: JRM -- 8/21/06 + * Added the flags_ptr parameter. This parameter exists to + * allow the flush routine to report to the cache if the + * entry is resized or renamed as a result of the flush. + * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry. + * *------------------------------------------------------------------------- */ static herr_t -H5HF_cache_iblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_indirect_t *iblock) +H5HF_cache_iblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_indirect_t *iblock, unsigned UNUSED * flags_ptr) { herr_t ret_value = SUCCEED; /* Return value */ @@ -1282,10 +1293,16 @@ done: * koziol@ncsa.uiuc.edu * Feb 27 2006 * + * Changes: JRM -- 8/21/06 + * Added the flags_ptr parameter. This parameter exists to + * allow the flush routine to report to the cache if the + * entry is resized or renamed as a result of the flush. + * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry. + * *------------------------------------------------------------------------- */ static herr_t -H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_direct_t *dblock) +H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_direct_t *dblock, unsigned UNUSED * flags_ptr) { herr_t ret_value = SUCCEED; /* Return value */ @@ -126,7 +126,7 @@ static void *H5HG_peek(H5F_t *f, hid_t dxpl_id, H5HG_t *hobj); static H5HG_heap_t *H5HG_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1, void *udata2); static herr_t H5HG_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, - H5HG_heap_t *heap); + H5HG_heap_t *heap, unsigned UNUSED * flags_ptr); static herr_t H5HG_dest(H5F_t *f, H5HG_heap_t *heap); static herr_t H5HG_clear(H5F_t *f, H5HG_heap_t *heap, hbool_t destroy); static herr_t H5HG_compute_size(const H5F_t *f, const H5HG_heap_t *heap, size_t *size_ptr); @@ -506,10 +506,17 @@ done: * Quincey Koziol, 2002-7-180 * Added dxpl parameter to allow more control over I/O from metadata * cache. + * + * JRM -- 8/21/06 + * Added the flags_ptr parameter. This parameter exists to + * allow the flush routine to report to the cache if the + * entry is resized or renamed as a result of the flush. + * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry. + * *------------------------------------------------------------------------- */ static herr_t -H5HG_flush (H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HG_heap_t *heap) +H5HG_flush (H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HG_heap_t *heap, unsigned UNUSED * flags_ptr) { herr_t ret_value=SUCCEED; /* Return value */ @@ -66,7 +66,7 @@ static herr_t H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap); /* Metadata cache callbacks */ static H5HL_t *H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1, void *udata2); -static herr_t H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, H5HL_t *heap); +static herr_t H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr); static herr_t H5HL_dest(H5F_t *f, H5HL_t *heap); static herr_t H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy); static herr_t H5HL_compute_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr); @@ -550,10 +550,16 @@ H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf) * Instead, disk space allocation/deallocation is now done at * insert/remove time. * + * John Mainzer, 2006-08-21 + * Added the flags_ptr parameter. This parameter exists to + * allow the flush routine to report to the cache if the + * entry is resized or renamed as a result of the flush. + * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry. + * *------------------------------------------------------------------------- */ static herr_t -H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap) +H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr) { herr_t ret_value = SUCCEED; /* Return value */ diff --git a/src/H5Ocache.c b/src/H5Ocache.c index d0f479d..1ac9550 100644 --- a/src/H5Ocache.c +++ b/src/H5Ocache.c @@ -63,7 +63,7 @@ /* Metadata cache callbacks */ static H5O_t *H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_udata1, void *_udata2); -static herr_t H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh); +static herr_t H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh, unsigned UNUSED * flags_ptr); static herr_t H5O_clear(H5F_t *f, H5O_t *oh, hbool_t destroy); static herr_t H5O_size(const H5F_t *f, const H5O_t *oh, size_t *size_ptr); @@ -518,10 +518,16 @@ done: * matzke@llnl.gov * Aug 5 1997 * + * Changes: JRM -- 8/21/06 + * Added the flags_ptr parameter. This parameter exists to + * allow the flush routine to report to the cache if the + * entry is resized or renamed as a result of the flush. + * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry. + * *------------------------------------------------------------------------- */ static herr_t -H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t UNUSED addr, H5O_t *oh) +H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t UNUSED addr, H5O_t *oh, unsigned UNUSED * flags_ptr) { herr_t ret_value = SUCCEED; /* Return value */ |