From 2c84019fcaca9a1cb2a415564d8b88e3dd88479d Mon Sep 17 00:00:00 2001 From: John Mainzer Date: Fri, 25 Apr 2008 09:55:20 -0500 Subject: [svn-r14863] Checking in code supporting metadata journaling in the serial case. While this code doesn't break any of the existing tests, it HAS NOT been tested beyond that. Also mods needed to integrate the journaling code with Quincey's latest mods, and to adapt existing test code to slight changes caused by the addition of journaling. Finally, fixed an undefined variable bug in the HL code exposed by the journaling mods. Tested serial under Linux (Phoenix) and parallel under Linux (Kagiso). --- hl/src/H5PT.c | 11 + src/H5A.c | 19 +- src/H5AC2.c | 425 +++++- src/H5AC2private.h | 40 +- src/H5AC2public.h | 66 +- src/H5ACprivate.h | 12 +- src/H5ACpublic.h | 20 + src/H5Adeprec.c | 3 +- src/H5C2.c | 2780 ++++-------------------------------- src/H5C2journal.c | 1025 +++++++++++++- src/H5C2pkg.h | 3271 ++++++++++++++++++++++++++++++++++++++++++- src/H5C2private.h | 118 +- src/H5D.c | 9 +- src/H5Ddeprec.c | 5 +- src/H5Dio.c | 3 +- src/H5F.c | 38 +- src/H5FDpublic.h | 15 +- src/H5Fmount.c | 15 +- src/H5G.c | 8 +- src/H5Gdeprec.c | 15 +- src/H5I.c | 5 +- src/H5L.c | 15 +- src/H5Lexternal.c | 5 +- src/H5O.c | 16 +- src/H5Ocopy.c | 4 +- src/H5R.c | 3 +- src/H5T.c | 3 +- src/H5Tcommit.c | 5 +- src/H5Tdeprec.c | 3 +- src/H5private.h | 25 +- test/cache2.c | 34 +- test/cache2_common.c | 76 +- test/cache2_common.h | 50 +- test/cache2_journal.c | 144 +- test/testfiles/err_compat_1 | 5 +- test/testfiles/error_test_1 | 10 +- test/testhdf5.c | 1 + testpar/t_cache2.c | 18 +- 38 files changed, 5540 insertions(+), 2780 deletions(-) diff --git a/hl/src/H5PT.c b/hl/src/H5PT.c index f337360..2119cca 100644 --- a/hl/src/H5PT.c +++ b/hl/src/H5PT.c @@ -214,6 +214,11 @@ out: * * Modifications: * + * John Mainzer -- 4/23/08 + * Added error check on malloc of table, initialized fields + * in table to keep lower level code from choking on bogus + * data in error cases. + * *------------------------------------------------------------------------- */ hid_t H5PTopen( hid_t loc_id, @@ -232,6 +237,12 @@ hid_t H5PTopen( hid_t loc_id, table = (htbl_t *)malloc(sizeof(htbl_t)); + if ( table == NULL ) { + goto out; + } + table->dset_id = H5I_BADID; + table->type_id = H5I_BADID; + /* Open the dataset */ if((table->dset_id = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0) goto out; diff --git a/src/H5A.c b/src/H5A.c index 29aa2a2..955c809 100644 --- a/src/H5A.c +++ b/src/H5A.c @@ -36,6 +36,7 @@ #include "H5MMprivate.h" /* Memory management */ #include "H5Sprivate.h" /* Dataspace functions */ #include "H5SMprivate.h" /* Shared Object Header Messages */ +#include "H5AC2private.h" /* Metadata cache */ /****************/ /* Local Macros */ @@ -222,7 +223,7 @@ H5Acreate2(hid_t loc_id, const char *attr_name, hid_t type_id, hid_t space_id, H5S_t *space; /* Dataspace to use for attribute */ hid_t ret_value; /* Return value */ - FUNC_ENTER_API_META(H5Acreate2, FAIL) + FUNC_ENTER_API_META(H5Acreate2, loc_id, FAIL) H5TRACE6("i", "i*siiii", loc_id, attr_name, type_id, space_id, acpl_id, aapl_id); /* check arguments */ @@ -293,7 +294,7 @@ H5Acreate_by_name(hid_t loc_id, const char *obj_name, const char *attr_name, H5S_t *space; /* Dataspace to use for attribute */ hid_t ret_value; /* Return value */ - FUNC_ENTER_API_META(H5Acreate_by_name, FAIL) + FUNC_ENTER_API_META(H5Acreate_by_name, loc_id, FAIL) H5TRACE8("i", "i*s*siiiii", loc_id, obj_name, attr_name, type_id, space_id, acpl_id, aapl_id, lapl_id); @@ -904,7 +905,7 @@ H5Awrite(hid_t attr_id, hid_t dtype_id, const void *buf) const H5T_t *mem_type = NULL; herr_t ret_value; - FUNC_ENTER_API_META(H5Awrite, FAIL) + FUNC_ENTER_API_META(H5Awrite, attr_id, FAIL) H5TRACE3("e", "ii*x", attr_id, dtype_id, buf); /* check arguments */ @@ -1724,7 +1725,7 @@ H5Arename(hid_t loc_id, const char *old_name, const char *new_name) H5G_loc_t loc; /* Object location */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Arename, FAIL) + FUNC_ENTER_API_META(H5Arename, loc_id, FAIL) H5TRACE3("e", "i*s*s", loc_id, old_name, new_name); /* check arguments */ @@ -1770,7 +1771,7 @@ H5Arename_by_name(hid_t loc_id, const char *obj_name, const char *old_attr_name, hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Arename_by_name, FAIL) + FUNC_ENTER_API_META(H5Arename_by_name, loc_id, FAIL) H5TRACE5("e", "i*s*s*si", loc_id, obj_name, old_attr_name, new_attr_name, lapl_id); @@ -2036,7 +2037,7 @@ H5Adelete(hid_t loc_id, const char *name) H5G_loc_t loc; /* Object location */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Adelete, FAIL) + FUNC_ENTER_API_META(H5Adelete, loc_id, FAIL) H5TRACE2("e", "i*s", loc_id, name); /* check arguments */ @@ -2083,7 +2084,7 @@ H5Adelete_by_name(hid_t loc_id, const char *obj_name, const char *attr_name, hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Adelete_by_name, FAIL) + FUNC_ENTER_API_META(H5Adelete_by_name, loc_id, FAIL) H5TRACE4("e", "i*s*si", loc_id, obj_name, attr_name, lapl_id); /* check arguments */ @@ -2159,7 +2160,7 @@ H5Adelete_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type, hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Adelete_by_idx, FAIL) + FUNC_ENTER_API_META(H5Adelete_by_idx, loc_id, FAIL) H5TRACE6("e", "i*sIiIohi", loc_id, obj_name, idx_type, order, n, lapl_id); /* check arguments */ @@ -2222,7 +2223,7 @@ H5Aclose(hid_t attr_id) { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Aclose, FAIL) + FUNC_ENTER_API_META(H5Aclose, attr_id, FAIL) H5TRACE1("e", "i", attr_id); /* check arguments */ diff --git a/src/H5AC2.c b/src/H5AC2.c index 4a63c7c..adda9b1 100644 --- a/src/H5AC2.c +++ b/src/H5AC2.c @@ -481,6 +481,10 @@ H5AC2_term_interface(void) * API. * JRM - 10/18/07 * + * Added the dxpl_id parameter, and updated for parameter + * list changes in H5C2_create(). + * JRM - 3/26/08 + * *------------------------------------------------------------------------- */ @@ -505,8 +509,9 @@ static const char * H5AC2_entry_type_names[H5AC2_NTYPES] = }; herr_t -H5AC2_create(const H5F_t *f, - H5AC2_cache_config_t *config_ptr) +H5AC2_create(H5F_t * f, + hid_t dxpl_id, + H5AC2_cache_config_t *config_ptr) { herr_t ret_value = SUCCEED; /* Return value */ herr_t result; @@ -617,18 +622,23 @@ H5AC2_create(const H5F_t *f, if ( aux_ptr->mpi_rank == 0 ) { - f->shared->cache2 = H5C2_create(H5AC2__DEFAULT_MAX_CACHE_SIZE, + f->shared->cache2 = H5C2_create(f, + dxpl_id, + H5AC2__DEFAULT_MAX_CACHE_SIZE, H5AC2__DEFAULT_MIN_CLEAN_SIZE, (H5AC2_NTYPES - 1), (const char **)H5AC2_entry_type_names, H5AC2_check_if_write_permitted, TRUE, H5AC2_log_flushed_entry, - (void *)aux_ptr); + (void *)aux_ptr, + config_ptr->journal_recovered); } else { - f->shared->cache2 = H5C2_create(H5AC2__DEFAULT_MAX_CACHE_SIZE, + f->shared->cache2 = H5C2_create(f, + dxpl_id, + H5AC2__DEFAULT_MAX_CACHE_SIZE, H5AC2__DEFAULT_MIN_CLEAN_SIZE, (H5AC2_NTYPES - 1), (const char **)H5AC2_entry_type_names, @@ -639,19 +649,23 @@ H5AC2_create(const H5F_t *f, #else /* JRM */ NULL, #endif /* JRM */ - (void *)aux_ptr); + (void *)aux_ptr, + config_ptr->journal_recovered); } } else { - f->shared->cache2 = H5C2_create(H5AC2__DEFAULT_MAX_CACHE_SIZE, + f->shared->cache2 = H5C2_create(f, + dxpl_id, + H5AC2__DEFAULT_MAX_CACHE_SIZE, H5AC2__DEFAULT_MIN_CLEAN_SIZE, (H5AC2_NTYPES - 1), (const char **)H5AC2_entry_type_names, H5AC2_check_if_write_permitted, TRUE, NULL, - NULL); + NULL, + config_ptr->journal_recovered); } } else { #endif /* H5_HAVE_PARALLEL */ @@ -660,14 +674,17 @@ H5AC2_create(const H5F_t *f, * -- JRM */ - f->shared->cache2 = H5C2_create(H5AC2__DEFAULT_MAX_CACHE_SIZE, + f->shared->cache2 = H5C2_create(f, + dxpl_id, + H5AC2__DEFAULT_MAX_CACHE_SIZE, H5AC2__DEFAULT_MIN_CLEAN_SIZE, (H5AC2_NTYPES - 1), (const char **)H5AC2_entry_type_names, H5AC2_check_if_write_permitted, TRUE, NULL, - NULL); + NULL, + config_ptr->journal_recovered); #ifdef H5_HAVE_PARALLEL } #endif /* H5_HAVE_PARALLEL */ @@ -690,7 +707,9 @@ H5AC2_create(const H5F_t *f, } #endif /* H5_HAVE_PARALLEL */ - result = H5AC2_set_cache_auto_resize_config(f, config_ptr); + result = H5AC2_set_cache_auto_resize_config(f, + dxpl_id, + config_ptr); if ( result != SUCCEED ) { @@ -833,6 +852,258 @@ done: /*------------------------------------------------------------------------- + * Function: H5AC2_begin_transaction() + * + * Purpose: Mark the beginning of a transaction. + * + * This function is just a wrapper for H5C2_begin_transaction(). + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: John Mainzer + * 4/12/08 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +herr_t +H5AC2_begin_transaction(hid_t id, + hbool_t * do_transaction_ptr, + H5O_loc_t * id_oloc_ptr, + hbool_t * id_oloc_open_ptr, + hbool_t * transaction_begun_ptr, + uint64_t * trans_num_ptr, + const char * api_call_name) +{ + herr_t result; + H5G_loc_t id_loc; + H5F_t * f = NULL; + H5AC2_t * cache_ptr = NULL; + herr_t ret_value = SUCCEED; /* Return value */ +#if H5AC2__TRACE_FILE_ENABLED + char trace[256] = ""; + FILE * trace_file_ptr = NULL; +#endif /* H5AC2__TRACE_FILE_ENABLED */ + + FUNC_ENTER_NOAPI(H5AC2_begin_transaction, FAIL) + + HDassert( do_transaction_ptr != NULL ); + HDassert( id_oloc_ptr != NULL ); + HDassert( id_oloc_open_ptr != NULL ); + HDassert( transaction_begun_ptr != NULL ); + HDassert( trans_num_ptr != NULL ); + HDassert( api_call_name != NULL ); + +#if H5AC2__TRACE_FILE_ENABLED + /* For the begin transaction call, only the transaction number and the + * api call name. Write the return value to catch occult errors. + */ + if ( ( cache_ptr != NULL ) && + ( H5C2_get_trace_file_ptr(cache_ptr, &trace_file_ptr) >= 0 ) && + ( trace_file_ptr != NULL ) ) { + + sprintf(trace, "H5AC2_begin_transaction %s", api_call_name); + } +#endif /* H5AC2__TRACE_FILE_ENABLED */ + + *id_oloc_open_ptr = FALSE; + *transaction_begun_ptr = FALSE; + + switch ( H5I_get_type(id) ) + { + case H5I_DATASPACE: + case H5I_ERROR_CLASS: + case H5I_ERROR_MSG: + case H5I_ERROR_STACK: + case H5I_GENPROP_CLS: + case H5I_GENPROP_LST: + *do_transaction_ptr = FALSE; + break; + + case H5I_DATATYPE: + { + H5T_t *dt = H5I_object(id); + if( ( dt == NULL ) || ( ! H5T_committed(dt) ) ) { + *do_transaction_ptr = FALSE; + } + } + break; + + case H5I_BADID: + *do_transaction_ptr = FALSE; + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, \ + "H5I_get_type() reports bad id") + break; + + default: + *do_transaction_ptr = TRUE; + } + + if ( *do_transaction_ptr ) { + + if ((H5G_loc((id), &id_loc) < 0) || (id_loc.oloc == NULL)) { + + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "H5G_loc() failed"); + } + + *id_oloc_ptr = *(id_loc.oloc); + + if ( H5O_open(id_oloc_ptr) < 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, "H5O_open() failed."); + } + + *id_oloc_open_ptr = TRUE; + + f = id_oloc_ptr->file; + + if ( ( f == NULL ) || + ( f->shared == NULL ) || + ( f->shared->cache2 == NULL ) ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, "can't get cache_ptr."); + } + + cache_ptr = f->shared->cache2; + + result = H5C2_begin_transaction(cache_ptr, trans_num_ptr, api_call_name); + + if ( result < 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_begin_transaction() failed.") + } + + *transaction_begun_ptr = TRUE; + } + +done: + + *trans_num_ptr = 1; + +#if H5AC2__TRACE_FILE_ENABLED + if ( trace_file_ptr != NULL ) { + + HDfprintf(trace_file_ptr, "%s %llu %d\n", trace, + *trans_num_ptr, (int)ret_value); + } +#endif /* H5AC2__TRACE_FILE_ENABLED */ + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5AC2_begin_transaction() */ + + +/*------------------------------------------------------------------------- + * Function: H5AC2_end_transaction() + * + * Purpose: Mark the end of a transaction. + * + * This function is just a wrapper for H5C2_end_transaction(). + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: John Mainzer + * 4/12/08 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +herr_t +H5AC2_end_transaction(hbool_t do_transaction, + H5O_loc_t * id_oloc_ptr, + hbool_t id_oloc_open, + hbool_t transaction_begun, + uint64_t trans_num, + const char * api_call_name) +{ + herr_t result; + herr_t ret_value=SUCCEED; /* Return value */ + H5F_t * f = NULL; + H5AC2_t * cache_ptr = NULL; +#if H5AC2__TRACE_FILE_ENABLED + char trace[256] = ""; + FILE * trace_file_ptr = NULL; +#endif /* H5AC2__TRACE_FILE_ENABLED */ + + FUNC_ENTER_NOAPI(H5AC2_end_transaction, FAIL) + + HDassert( id_oloc_ptr != NULL ); + HDassert( api_call_name != NULL ); + +#if H5AC2__TRACE_FILE_ENABLED + /* For the end transaction call, only the transaction number and the + * api call name are really needed. Write the return value to catch + * occult errors. + */ + if ( ( cache_ptr != NULL ) && + ( H5C2_get_trace_file_ptr(cache_ptr, &trace_file_ptr) >= 0 ) && + ( trace_file_ptr != NULL ) ) { + + sprintf(trace, "H5AC2_end_transaction %s %llu", api_call_name, trans_num); + } +#endif /* H5AC2__TRACE_FILE_ENABLED */ + + if ( do_transaction ) { + + if ( transaction_begun ) { + + f = id_oloc_ptr->file; + + if ( ( f == NULL ) || + ( f->shared == NULL ) || + ( f->shared->cache2 == NULL ) ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "can't get cache_ptr."); + } + + cache_ptr = f->shared->cache2; + + result = H5C2_end_transaction(f, cache_ptr, trans_num, api_call_name); + + if ( result < 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_end_transaction() failed.") + } + } + + if ( id_oloc_open ) { + + result = H5O_close(id_oloc_ptr); + + if ( result < 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5O_close() failed."); + } + } + } + +done: + +#if H5AC2__TRACE_FILE_ENABLED + if ( trace_file_ptr != NULL ) { + + HDfprintf(trace_file_ptr, "%s %d\n", trace, (int)ret_value); + } +#endif /* H5AC2__TRACE_FILE_ENABLED */ + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5AC2_end_transaction() */ + + +/*------------------------------------------------------------------------- * Function: H5AC2_expunge_entry * * Purpose: Expunge the target entry from the cache without writing it @@ -1013,6 +1284,7 @@ H5AC2_flush(H5F_t *f, hid_t dxpl_id, unsigned flags) FUNC_ENTER_NOAPI(H5AC2_flush, FAIL) HDassert(f); + HDassert(f->shared); HDassert(f->shared->cache2); #if H5AC2__TRACE_FILE_ENABLED @@ -1164,7 +1436,9 @@ H5AC2_get_entry_status(H5F_t * f, FUNC_ENTER_NOAPI(H5AC2_get_entry_status, FAIL) - if ( ( f->shared->cache2 == NULL ) || + if ( ( f == NULL ) || + ( f->shared == NULL ) || + ( f->shared->cache2 == NULL ) || ( f->shared->cache2->magic != H5C2__H5C2_T_MAGIC ) || ( ! H5F_addr_defined(addr) ) || ( status_ptr == NULL ) ) { @@ -1290,6 +1564,7 @@ H5AC2_set(H5F_t *f, hid_t dxpl_id, const H5AC2_class_t *type, haddr_t addr, size FUNC_ENTER_NOAPI(H5AC2_set, FAIL) HDassert(f); + HDassert(f->shared); HDassert(f->shared->cache2); HDassert(type); HDassert(type->serialize); @@ -1426,7 +1701,7 @@ H5AC2_mark_pinned_entry_dirty(H5F_t * f, size_t new_size) { #ifdef H5_HAVE_PARALLEL - H5C2_t *cache_ptr = f->shared->cache2; + H5C2_t *cache_ptr; #endif /* H5_HAVE_PARALLEL */ herr_t result; herr_t ret_value = SUCCEED; /* Return value */ @@ -1437,6 +1712,10 @@ H5AC2_mark_pinned_entry_dirty(H5F_t * f, FUNC_ENTER_NOAPI(H5AC2_mark_pinned_entry_dirty, FAIL) + HDassert( f ); + HDassert( f->shared ); + HDassert( f->shared->cache2 ); + #if H5AC2__TRACE_FILE_ENABLED /* For the mark pinned entry dirty call, only the addr, size_changed, * and new_size are really necessary in the trace file. Write the result @@ -1457,6 +1736,8 @@ H5AC2_mark_pinned_entry_dirty(H5F_t * f, #ifdef H5_HAVE_PARALLEL + cache_ptr = f->shared->cache2; + HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); HDassert( thing ); @@ -1549,7 +1830,7 @@ H5AC2_mark_pinned_or_protected_entry_dirty(H5F_t * f, void * thing) { #ifdef H5_HAVE_PARALLEL - H5C2_t * cache_ptr = f->shared->cache2; + H5C2_t * cache_ptr; H5AC2_info_t * info_ptr; #endif /* H5_HAVE_PARALLEL */ herr_t result; @@ -1560,6 +1841,10 @@ H5AC2_mark_pinned_or_protected_entry_dirty(H5F_t * f, #endif /* H5AC2__TRACE_FILE_ENABLED */ FUNC_ENTER_NOAPI(H5AC2_mark_pinned_or_protected_entry_dirty, FAIL) + + HDassert( f ); + HDassert( f->shared ); + HDassert( f->shared->cache2 ); #if H5AC2__TRACE_FILE_ENABLED /* For the mark pinned or protected entry dirty call, only the addr @@ -1579,6 +1864,8 @@ H5AC2_mark_pinned_or_protected_entry_dirty(H5F_t * f, #ifdef H5_HAVE_PARALLEL + cache_ptr = f->shared->cache2; + HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); HDassert( thing ); @@ -2054,7 +2341,7 @@ H5AC2_resize_pinned_entry(H5F_t * f, size_t new_size) { #ifdef H5_HAVE_PARALLEL - H5C2_t *cache_ptr = f->shared->cache2; + H5C2_t *cache_ptr; #endif /* H5_HAVE_PARALLEL */ herr_t result; herr_t ret_value = SUCCEED; /* Return value */ @@ -2065,6 +2352,10 @@ H5AC2_resize_pinned_entry(H5F_t * f, FUNC_ENTER_NOAPI(H5AC2_resize_pinned_entry, FAIL) + HDassert( f ); + HDassert( f->shared ); + HDassert( f->shared->cache2 ); + #if H5AC2__TRACE_FILE_ENABLED /* For the resize pinned entry call, only the addr, and new_size are * really necessary in the trace file. Write the result to catch @@ -2084,6 +2375,8 @@ H5AC2_resize_pinned_entry(H5F_t * f, #ifdef H5_HAVE_PARALLEL + cache_ptr = f->shared->cache2; + HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); HDassert( thing ); @@ -2334,6 +2627,7 @@ H5AC2_unprotect(H5F_t *f, hid_t dxpl_id, const H5AC2_class_t *type, FUNC_ENTER_NOAPI(H5AC2_unprotect, FAIL) HDassert(f); + HDassert(f->shared); HDassert(f->shared->cache2); HDassert(type); HDassert(type->deserialize); @@ -2536,6 +2830,7 @@ H5AC2_stats(const H5F_t *f) FUNC_ENTER_NOAPI(H5AC2_stats, FAIL) HDassert(f); + HDassert(f->shared); HDassert(f->shared->cache2); /* at present, this can't fail */ @@ -2586,6 +2881,9 @@ done: * Added support for the new flash cache increment related * fields. * + * JRM -- 4/12/08 + * Added support for the new journaling control fields. + * *------------------------------------------------------------------------- */ @@ -2692,6 +2990,32 @@ H5AC2_get_cache_auto_resize_config(H5AC2_t * cache_ptr, } #endif /* H5_HAVE_PARALLEL */ + /* get the current journal configuration. Start by setting defaults, + * which may be changed shortly. + */ + + config_ptr->enable_journaling = FALSE; + config_ptr->journal_file_path[0] = '\0'; + config_ptr->journal_recovered = FALSE; + config_ptr->jbrb_buf_size = 4096; + config_ptr->jbrb_num_bufs = 1; + config_ptr->jbrb_use_aio = FALSE; + config_ptr->jbrb_human_readable = FALSE; + + result = H5C2_get_journal_config(cache_ptr, + &(config_ptr->enable_journaling), + &(config_ptr->journal_file_path[0]), + &(config_ptr->jbrb_buf_size), + &(config_ptr->jbrb_num_bufs), + &(config_ptr->jbrb_use_aio), + &(config_ptr->jbrb_human_readable)); + + if ( result < 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "H5C2_get_journal_config() failed.") + } + done: FUNC_LEAVE_NOAPI(ret_value) @@ -2874,17 +3198,23 @@ done: * Updated trace file code to record the new flash cache * size increase related fields. * + * John Mainzer -- 4/13/08 + * Added code to allow control of metadata journaling. + * This required the addition of the dxpl_id parameter. + * *------------------------------------------------------------------------- */ herr_t H5AC2_set_cache_auto_resize_config(const H5F_t * f, + hid_t dxpl_id, H5AC2_cache_config_t *config_ptr) { /* const char * fcn_name = "H5AC2_set_cache_auto_resize_config"; */ - H5AC2_t * cache_ptr = (H5AC2_t *)f->shared->cache2; + H5AC2_t * cache_ptr; herr_t result; herr_t ret_value = SUCCEED; /* Return value */ + hbool_t mdj_enabled = FALSE; H5C2_auto_size_ctl_t internal_config; #if H5AC2__TRACE_FILE_ENABLED H5AC2_cache_config_t trace_config = H5AC2__DEFAULT_CACHE_CONFIG; @@ -2893,6 +3223,12 @@ H5AC2_set_cache_auto_resize_config(const H5F_t * f, FUNC_ENTER_NOAPI(H5AC2_set_cache_auto_resize_config, FAIL) + HDassert( f ); + HDassert( f->shared ); + HDassert( f->shared->cache2 ); + + cache_ptr = (H5AC2_t *)f->shared->cache2; + #if H5AC2__TRACE_FILE_ENABLED /* Make note of the new configuration. Don't look up the trace file * pointer, as that may change before we use it. @@ -3008,6 +3344,47 @@ H5AC2_set_cache_auto_resize_config(const H5F_t * f, "H5C2_set_evictions_enabled() failed.") } + result = H5C2_get_journal_config((H5C2_t *)cache_ptr, &mdj_enabled, + NULL, NULL, NULL, NULL, NULL); + + if ( result < 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "H5C2_get_journal_config() failed.") + } + + if ( config_ptr->enable_journaling != mdj_enabled ) { + + /* we have work to do -- start or stop journaling as requested */ + + if ( config_ptr->enable_journaling ) { + + result = H5C2_begin_journaling(f, + dxpl_id, + cache_ptr, + &(config_ptr->journal_file_path[0]), + config_ptr->jbrb_buf_size, + config_ptr->jbrb_num_bufs, + config_ptr->jbrb_use_aio, + config_ptr->jbrb_human_readable); + if ( result < 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_begin_journaling() failed.") + } + } else { + + result = H5C2_end_journaling(f, dxpl_id, cache_ptr); + + if ( result < 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_end_journaling() failed.") + } + } + } + + #ifdef H5_HAVE_PARALLEL if ( cache_ptr->aux_ptr != NULL ) { @@ -3028,7 +3405,7 @@ done: ( trace_file_ptr != NULL ) ) { HDfprintf(trace_file_ptr, - "%s %d %d %d %d \"%s\" %d %d %d %f %d %d %ld %d %f %f %d %d %d %f %f %d %f %f %d %d %d %d %f %d %d\n", + "%s %d %d %d %d \"%s\" %d %d %d %f %d %d %ld %d %f %f %d %d %d %f %f %d %f %f %d %d %d %d %f %d %d \"%s\" %d %d %d %d %d %d\n", "H5AC2_set_cache_auto_resize_config", trace_config.version, (int)(trace_config.rpt_fcn_enabled), @@ -3059,6 +3436,13 @@ done: (int)(trace_config.apply_empty_reserve), trace_config.empty_reserve, trace_config.dirty_bytes_threshold, + (int)(config_ptr->enable_journaling), + config_ptr->journal_file_path, + (int)(config_ptr->journal_recovered), + (int)(config_ptr->jbrb_buf_size), + config_ptr->jbrb_num_bufs, + (int)(config_ptr->jbrb_use_aio), + (int)(config_ptr->jbrb_human_readable), (int)ret_value); } #endif /* H5AC2__TRACE_FILE_ENABLED */ @@ -4334,7 +4718,7 @@ H5AC2_log_renamed_entry(H5F_t * f, haddr_t new_addr) { herr_t ret_value = SUCCEED; /* Return value */ - H5AC2_t * cache_ptr = (H5AC2_t *)f->shared->cache2; + H5AC2_t * cache_ptr; hbool_t entry_in_cache; hbool_t entry_dirty; size_t entry_size; @@ -4343,6 +4727,11 @@ H5AC2_log_renamed_entry(H5F_t * f, FUNC_ENTER_NOAPI(H5AC2_log_renamed_entry, FAIL) + HDassert( f != NULL ); + HDassert( f->shared != NULL ); + + cache_ptr = (H5AC2_t *)f->shared->cache2; + HDassert( cache_ptr != NULL ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); diff --git a/src/H5AC2private.h b/src/H5AC2private.h index 6676d7e..520900b 100644 --- a/src/H5AC2private.h +++ b/src/H5AC2private.h @@ -41,6 +41,7 @@ /* Pivate headers needed by this header */ #include "H5private.h" /* Generic Functions */ +#include "H5Oprivate.h" /* Object headers */ #include "H5Fprivate.h" /* File access */ #include "H5C2private.h" /* cache */ @@ -215,7 +216,14 @@ extern hid_t H5AC2_ind_dxpl_id; /* int epochs_before_eviction = */ 3, \ /* hbool_t apply_empty_reserve = */ TRUE, \ /* double empty_reserve = */ 0.1, \ - /* int dirty_bytes_threshold = */ (256 * 1024) \ + /* int dirty_bytes_threshold = */ (256 * 1024), \ + /* hbool_t enable_journaling = */ FALSE, \ + /* char journal_file_path[] = */ "", \ + /* hbool_t journal_recovered = */ FALSE, \ + /* size_t jbrb_buf_size = */ (8 * 1024), \ + /* int jbrb_num_bufs = */ 2, \ + /* hbool_t jbrb_use_aio = */ FALSE, \ + /* hbool_t jbrb_human_readable = */ TRUE \ } @@ -254,7 +262,32 @@ extern hid_t H5AC2_ind_dxpl_id; /* external function declarations: */ H5_DLL herr_t H5AC2_init(void); -H5_DLL herr_t H5AC2_create(const H5F_t *f, H5AC2_cache_config_t *config_ptr); +H5_DLL herr_t H5AC2_create(H5F_t *f, + hid_t dxpl_id, + H5AC2_cache_config_t *config_ptr); +#if 1 /* new version */ +H5_DLL herr_t H5AC2_begin_transaction(hid_t id, + hbool_t * do_transaction_ptr, + H5O_loc_t * id_oloc_ptr, + hbool_t * id_oloc_open_ptr, + hbool_t * transaction_begun_ptr, + uint64_t * trans_num_ptr, + const char * api_call_name); + +H5_DLL herr_t H5AC2_end_transaction(hbool_t do_transaction, + H5O_loc_t * id_oloc_ptr, + hbool_t id_oloc_open, + hbool_t transaction_begun, + uint64_t trans_num, + const char * api_call_name); +#else /* old version */ +H5_DLL herr_t H5AC2_begin_transaction(H5F_t * f, + uint64_t * trans_num_ptr, + const char * api_call_name); +H5_DLL herr_t H5AC2_end_transaction(H5F_t * f, + uint64_t trans_num, + const char * api_call_name); +#endif /* old version */ H5_DLL herr_t H5AC2_get_entry_status(H5F_t * f, haddr_t addr, unsigned * status_ptr); H5_DLL herr_t H5AC2_set(H5F_t *f, hid_t dxpl_id, const H5AC2_class_t *type, @@ -306,7 +339,8 @@ H5_DLL herr_t H5AC2_get_cache_hit_rate(H5AC2_t * cache_ptr, H5_DLL herr_t H5AC2_reset_cache_hit_rate_stats(H5AC2_t * cache_ptr); H5_DLL herr_t H5AC2_set_cache_auto_resize_config(const H5F_t * f, - H5AC2_cache_config_t *config_ptr); + hid_t dxpl_id, + H5AC2_cache_config_t *config_ptr); H5_DLL herr_t H5AC2_validate_config(H5AC2_cache_config_t * config_ptr); diff --git a/src/H5AC2public.h b/src/H5AC2public.h index a16ad2a..57c65b9 100644 --- a/src/H5AC2public.h +++ b/src/H5AC2public.h @@ -36,7 +36,8 @@ extern "C" { #endif -#define H5AC2__MAX_TRACE_FILE_NAME_LEN 1024 +#define H5AC2__MAX_TRACE_FILE_NAME_LEN 1024 +#define H5AC2__MAX_JOURNAL_FILE_NAME_LEN 1024 /**************************************************************************** * @@ -380,6 +381,58 @@ extern "C" { * file. This field is ignored unless HDF5 has been compiled for * parallel. * + * + * Journal Configuration Fields: + * + * The journaling fields allow enabling of metadata journaling, specification + * of the journal file, and marking a file as recovered. + * + * Note that the fields with the "jbrb_" prefix are used to configure the + * journal buffer ring buffer -- a ring buffer of buffers used to buffer + * output of journal messages. + * + * At least to begin with, these fields may only be used at file open/create + * time -- i.e. in the FAPL. + * + * enable_journaling: Boolean flag that is set to TRUE if journaling is + * to be enabled, and to FALSE otherwise. + * + * When the cache configuration is reported, this field is TRUE iff + * journaling is enabled. + * + * journal_file_path: Full path of the file to be used to store the + * metadata journal. This field is only defined if enable_journaling + * is TRUE. + * + * At present, the length of the journal file path is restricted to + * no more than H5AC2__MAX_JOURNAL_FILE_NAME_LEN. + * + * journal_recovered: Boolean flag use to indicate that we are opening + * a journaled file that was not closed correctly, and on which the + * journal recovery tool has been run. + * + * Unless you are the writer of a new journal recovery tool, you + * should always set this field to FALSE. + * + * jbrb_buf_size: size_t containing the size of each individual buffer + * in the journal buffer ring buffer. This size should be chosen + * to be some multiple of the block size used by the file system + * on which the journal file will be written. + * + * jbrb_num_bufs: Integer containing the number of buffers in the journal + * buffer ring buffer. If synchronous I/O is used, one or two buffers + * is sufficient. If asynchronous I/O is used, the number of buffers + * should be sufficiently large that a write on buffer is likely to + * complete before that buffer is needed again. + * + * jbrb_use_aio: Boolean flag indicating whether we should use + * asynchronous I/O for journal entry writes. + * + * jbrb_human_readable: Boolean flag which determines whether the journal + * file will be written in human readable form. In general, this + * field should be set to false, as the human readable journal + * file is at least twice a large as the machine readable version. + * ****************************************************************************/ #define H5AC2__CURR_CACHE_CONFIG_VERSION 1 @@ -442,6 +495,17 @@ typedef struct H5AC2_cache_config_t /* parallel configuration fields: */ int dirty_bytes_threshold; + + /* metadata journaling configuration fields: */ + hbool_t enable_journaling; + char journal_file_path[ + H5AC2__MAX_JOURNAL_FILE_NAME_LEN]; + hbool_t journal_recovered; + size_t jbrb_buf_size; + int jbrb_num_bufs; + hbool_t jbrb_use_aio; + hbool_t jbrb_human_readable; + } H5AC2_cache_config_t; diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index bbbcf11..40ab9ab 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -225,7 +225,17 @@ extern hid_t H5AC_ind_dxpl_id; /* int epochs_before_eviction = */ 3, \ /* hbool_t apply_empty_reserve = */ TRUE, \ /* double empty_reserve = */ 0.1, \ - /* int dirty_bytes_threshold = */ (256 * 1024) \ + /* int dirty_bytes_threshold = */ (256 * 1024), \ + /* The following fields are not used by H5AC or H5C -- they exist here */ \ + /* because they are used by H5AC2 and H5C2, and including them here */ \ + /* us to avoid duplicating the user level cache configuration code. */ \ + /* hbool_t enable_journaling = */ FALSE, \ + /* char journal_file_path[] = */ "", \ + /* hbool_t journal_recovered = */ FALSE, \ + /* size_t jbrb_buf_size = */ (8 * 1024), \ + /* int jbrb_num_bufs = */ 2, \ + /* hbool_t jbrb_use_aio = */ FALSE, \ + /* hbool_t jbrb_human_readable = */ TRUE \ } diff --git a/src/H5ACpublic.h b/src/H5ACpublic.h index 0e75117..6539a64 100644 --- a/src/H5ACpublic.h +++ b/src/H5ACpublic.h @@ -37,6 +37,7 @@ extern "C" { #endif #define H5AC__MAX_TRACE_FILE_NAME_LEN 1024 +#define H5AC__MAX_JOURNAL_FILE_NAME_LEN 1024 /**************************************************************************** * @@ -443,6 +444,25 @@ typedef struct H5AC_cache_config_t /* parallel configuration fields: */ int dirty_bytes_threshold; + /* The following fields are not used in H5AC or H5C. They are + * added because they are used in H5AC2 and H5C2, and putting + * them here allows us to avoid duplicating the functions involved + * in metadata cache configuration at the user API level. + * + * The old H5AC and H5C code simply ignores them. + * + * -- JRM + */ + /* metadata journaling configuration fields: */ + hbool_t enable_journaling; + char journal_file_path[ + H5AC__MAX_JOURNAL_FILE_NAME_LEN]; + hbool_t journal_recovered; + size_t jbrb_buf_size; + int jbrb_num_bufs; + hbool_t jbrb_use_aio; + hbool_t jbrb_human_readable; + } H5AC_cache_config_t; diff --git a/src/H5Adeprec.c b/src/H5Adeprec.c index 1e22493..f2c63e9 100644 --- a/src/H5Adeprec.c +++ b/src/H5Adeprec.c @@ -47,6 +47,7 @@ #include "H5Eprivate.h" /* Error handling */ #include "H5Iprivate.h" /* IDs */ #include "H5Opkg.h" /* Object headers */ +#include "H5AC2private.h" /* Metadata cache */ /****************/ @@ -143,7 +144,7 @@ H5Acreate1(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, H5S_t *space; /* Dataspace to use for attribute */ hid_t ret_value; /* Return value */ - FUNC_ENTER_API_META(H5Acreate1, FAIL) + FUNC_ENTER_API_META(H5Acreate1, loc_id, FAIL) H5TRACE5("i", "i*siii", loc_id, name, type_id, space_id, plist_id); /* check arguments */ diff --git a/src/H5C2.c b/src/H5C2.c index b885751..02b2a1d 100644 --- a/src/H5C2.c +++ b/src/H5C2.c @@ -112,2447 +112,6 @@ #include "H5SLprivate.h" /* Skip lists */ -/**************************************************************************** - * - * We maintain doubly linked lists of instances of H5C2_cache_entry_t for a - * variety of reasons -- protected list, LRU list, and the clean and dirty - * LRU lists at present. The following macros support linking and unlinking - * of instances of H5C2_cache_entry_t by both their regular and auxilary next - * and previous pointers. - * - * The size and length fields are also maintained. - * - * Note that the relevant pair of prev and next pointers are presumed to be - * NULL on entry in the insertion macros. - * - * Finally, observe that the sanity checking macros evaluate to the empty - * string when H5C2_DO_SANITY_CHECKS is FALSE. They also contain calls - * to the HGOTO_ERROR macro, which may not be appropriate in all cases. - * If so, we will need versions of the insertion and deletion macros which - * do not reference the sanity checking macros. - * JRM - 5/5/04 - * - * Changes: - * - * - Removed the line: - * - * ( ( (Size) == (entry_ptr)->size ) && ( (len) != 1 ) ) || - * - * from the H5C2__DLL_PRE_REMOVE_SC macro. With the addition of the - * epoch markers used in the age out based cache size reduction algorithm, - * this invarient need not hold, as the epoch markers are of size 0. - * - * One could argue that I should have given the epoch markers a positive - * size, but this would break the index_size = LRU_list_size + pl_size - * + pel_size invarient. - * - * Alternatively, I could pass the current decr_mode in to the macro, - * and just skip the check whenever epoch markers may be in use. - * - * However, any size errors should be caught when the cache is flushed - * and destroyed. Until we are tracking such an error, this should be - * good enough. - * JRM - 12/9/04 - * - * - * - In the H5C2__DLL_PRE_INSERT_SC macro, replaced the lines: - * - * ( ( (len) == 1 ) && - * ( ( (head_ptr) != (tail_ptr) ) || ( (Size) <= 0 ) || - * ( (head_ptr) == NULL ) || ( (head_ptr)->size != (Size) ) - * ) - * ) || - * - * with: - * - * ( ( (len) == 1 ) && - * ( ( (head_ptr) != (tail_ptr) ) || - * ( (head_ptr) == NULL ) || ( (head_ptr)->size != (Size) ) - * ) - * ) || - * - * Epoch markers have size 0, so we can now have a non-empty list with - * zero size. Hence the "( (Size) <= 0 )" clause cause false failures - * in the sanity check. Since "Size" is typically a size_t, it can't - * take on negative values, and thus the revised clause "( (Size) < 0 )" - * caused compiler warnings. - * JRM - 12/22/04 - * - * - In the H5C2__DLL_SC macro, replaced the lines: - * - * ( ( (len) == 1 ) && - * ( ( (head_ptr) != (tail_ptr) ) || ( (cache_ptr)->size <= 0 ) || - * ( (head_ptr) == NULL ) || ( (head_ptr)->size != (Size) ) - * ) - * ) || - * - * with - * - * ( ( (len) == 1 ) && - * ( ( (head_ptr) != (tail_ptr) ) || - * ( (head_ptr) == NULL ) || ( (head_ptr)->size != (Size) ) - * ) - * ) || - * - * Epoch markers have size 0, so we can now have a non-empty list with - * zero size. Hence the "( (Size) <= 0 )" clause cause false failures - * in the sanity check. Since "Size" is typically a size_t, it can't - * take on negative values, and thus the revised clause "( (Size) < 0 )" - * caused compiler warnings. - * JRM - 1/10/05 - * - * - Added the H5C2__DLL_UPDATE_FOR_SIZE_CHANGE macro and the associated - * sanity checking macros. These macro are used to update the size of - * a DLL when one of its entries changes size. - * - * JRM - 9/8/05 - * - ****************************************************************************/ - -#if H5C2_DO_SANITY_CHECKS - -#define H5C2__DLL_PRE_REMOVE_SC(entry_ptr, head_ptr, tail_ptr, len, Size, fv) \ -if ( ( (head_ptr) == NULL ) || \ - ( (tail_ptr) == NULL ) || \ - ( (entry_ptr) == NULL ) || \ - ( (len) <= 0 ) || \ - ( (Size) < (entry_ptr)->size ) || \ - ( ( (entry_ptr)->prev == NULL ) && ( (head_ptr) != (entry_ptr) ) ) || \ - ( ( (entry_ptr)->next == NULL ) && ( (tail_ptr) != (entry_ptr) ) ) || \ - ( ( (len) == 1 ) && \ - ( ! ( ( (head_ptr) == (entry_ptr) ) && \ - ( (tail_ptr) == (entry_ptr) ) && \ - ( (entry_ptr)->next == NULL ) && \ - ( (entry_ptr)->prev == NULL ) && \ - ( (Size) == (entry_ptr)->size ) \ - ) \ - ) \ - ) \ - ) { \ - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (fv), "DLL pre remove SC failed") \ -} - -#define H5C2__DLL_SC(head_ptr, tail_ptr, len, Size, fv) \ -if ( ( ( ( (head_ptr) == NULL ) || ( (tail_ptr) == NULL ) ) && \ - ( (head_ptr) != (tail_ptr) ) \ - ) || \ - ( (len) < 0 ) || \ - ( (Size) < 0 ) || \ - ( ( (len) == 1 ) && \ - ( ( (head_ptr) != (tail_ptr) ) || \ - ( (head_ptr) == NULL ) || ( (head_ptr)->size != (Size) ) \ - ) \ - ) || \ - ( ( (len) >= 1 ) && \ - ( ( (head_ptr) == NULL ) || ( (head_ptr)->prev != NULL ) || \ - ( (tail_ptr) == NULL ) || ( (tail_ptr)->next != NULL ) \ - ) \ - ) \ - ) { \ - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (fv), "DLL sanity check failed") \ -} - -#define H5C2__DLL_PRE_INSERT_SC(entry_ptr, head_ptr, tail_ptr, len, Size, fv) \ -if ( ( (entry_ptr) == NULL ) || \ - ( (entry_ptr)->next != NULL ) || \ - ( (entry_ptr)->prev != NULL ) || \ - ( ( ( (head_ptr) == NULL ) || ( (tail_ptr) == NULL ) ) && \ - ( (head_ptr) != (tail_ptr) ) \ - ) || \ - ( (len) < 0 ) || \ - ( ( (len) == 1 ) && \ - ( ( (head_ptr) != (tail_ptr) ) || \ - ( (head_ptr) == NULL ) || ( (head_ptr)->size != (Size) ) \ - ) \ - ) || \ - ( ( (len) >= 1 ) && \ - ( ( (head_ptr) == NULL ) || ( (head_ptr)->prev != NULL ) || \ - ( (tail_ptr) == NULL ) || ( (tail_ptr)->next != NULL ) \ - ) \ - ) \ - ) { \ - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (fv), "DLL pre insert SC failed") \ -} - -#define H5C2__DLL_PRE_SIZE_UPDATE_SC(dll_len, dll_size, old_size, new_size) \ -if ( ( (dll_len) <= 0 ) || \ - ( (dll_size) <= 0 ) || \ - ( (old_size) <= 0 ) || \ - ( (old_size) > (dll_size) ) || \ - ( (new_size) <= 0 ) || \ - ( ( (dll_len) == 1 ) && ( (old_size) != (dll_size) ) ) ) { \ - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "DLL pre size update SC failed") \ -} - -#define H5C2__DLL_POST_SIZE_UPDATE_SC(dll_len, dll_size, old_size, new_size) \ -if ( ( (new_size) > (dll_size) ) || \ - ( ( (dll_len) == 1 ) && ( (new_size) != (dll_size) ) ) ) { \ - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "DLL post size update SC failed") \ -} - -#else /* H5C2_DO_SANITY_CHECKS */ - -#define H5C2__DLL_PRE_REMOVE_SC(entry_ptr, head_ptr, tail_ptr, len, Size, fv) -#define H5C2__DLL_SC(head_ptr, tail_ptr, len, Size, fv) -#define H5C2__DLL_PRE_INSERT_SC(entry_ptr, head_ptr, tail_ptr, len, Size, fv) -#define H5C2__DLL_PRE_SIZE_UPDATE_SC(dll_len, dll_size, old_size, new_size) -#define H5C2__DLL_POST_SIZE_UPDATE_SC(dll_len, dll_size, old_size, new_size) - -#endif /* H5C2_DO_SANITY_CHECKS */ - - -#define H5C2__DLL_APPEND(entry_ptr, head_ptr, tail_ptr, len, Size, fail_val) \ - H5C2__DLL_PRE_INSERT_SC(entry_ptr, head_ptr, tail_ptr, len, Size, \ - fail_val) \ - if ( (head_ptr) == NULL ) \ - { \ - (head_ptr) = (entry_ptr); \ - (tail_ptr) = (entry_ptr); \ - } \ - else \ - { \ - (tail_ptr)->next = (entry_ptr); \ - (entry_ptr)->prev = (tail_ptr); \ - (tail_ptr) = (entry_ptr); \ - } \ - (len)++; \ - (Size) += (entry_ptr)->size; - -#define H5C2__DLL_PREPEND(entry_ptr, head_ptr, tail_ptr, len, Size, fail_val) \ - H5C2__DLL_PRE_INSERT_SC(entry_ptr, head_ptr, tail_ptr, len, Size, \ - fail_val) \ - if ( (head_ptr) == NULL ) \ - { \ - (head_ptr) = (entry_ptr); \ - (tail_ptr) = (entry_ptr); \ - } \ - else \ - { \ - (head_ptr)->prev = (entry_ptr); \ - (entry_ptr)->next = (head_ptr); \ - (head_ptr) = (entry_ptr); \ - } \ - (len)++; \ - (Size) += entry_ptr->size; - -#define H5C2__DLL_REMOVE(entry_ptr, head_ptr, tail_ptr, len, Size, fail_val) \ - H5C2__DLL_PRE_REMOVE_SC(entry_ptr, head_ptr, tail_ptr, len, Size, \ - fail_val) \ - { \ - if ( (head_ptr) == (entry_ptr) ) \ - { \ - (head_ptr) = (entry_ptr)->next; \ - if ( (head_ptr) != NULL ) \ - { \ - (head_ptr)->prev = NULL; \ - } \ - } \ - else \ - { \ - (entry_ptr)->prev->next = (entry_ptr)->next; \ - } \ - if ( (tail_ptr) == (entry_ptr) ) \ - { \ - (tail_ptr) = (entry_ptr)->prev; \ - if ( (tail_ptr) != NULL ) \ - { \ - (tail_ptr)->next = NULL; \ - } \ - } \ - else \ - { \ - (entry_ptr)->next->prev = (entry_ptr)->prev; \ - } \ - entry_ptr->next = NULL; \ - entry_ptr->prev = NULL; \ - (len)--; \ - (Size) -= entry_ptr->size; \ - } - -#define H5C2__DLL_UPDATE_FOR_SIZE_CHANGE(dll_len, dll_size, old_size, new_size) \ - H5C2__DLL_PRE_SIZE_UPDATE_SC(dll_len, dll_size, old_size, new_size) \ - (dll_size) -= (old_size); \ - (dll_size) += (new_size); \ - H5C2__DLL_POST_SIZE_UPDATE_SC(dll_len, dll_size, old_size, new_size) - -#if H5C2_DO_SANITY_CHECKS - -#define H5C2__AUX_DLL_PRE_REMOVE_SC(entry_ptr, hd_ptr, tail_ptr, len, Size, fv) \ -if ( ( (hd_ptr) == NULL ) || \ - ( (tail_ptr) == NULL ) || \ - ( (entry_ptr) == NULL ) || \ - ( (len) <= 0 ) || \ - ( (Size) < (entry_ptr)->size ) || \ - ( ( (Size) == (entry_ptr)->size ) && ( ! ( (len) == 1 ) ) ) || \ - ( ( (entry_ptr)->aux_prev == NULL ) && ( (hd_ptr) != (entry_ptr) ) ) || \ - ( ( (entry_ptr)->aux_next == NULL ) && ( (tail_ptr) != (entry_ptr) ) ) || \ - ( ( (len) == 1 ) && \ - ( ! ( ( (hd_ptr) == (entry_ptr) ) && ( (tail_ptr) == (entry_ptr) ) && \ - ( (entry_ptr)->aux_next == NULL ) && \ - ( (entry_ptr)->aux_prev == NULL ) && \ - ( (Size) == (entry_ptr)->size ) \ - ) \ - ) \ - ) \ - ) { \ - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (fv), "aux DLL pre remove SC failed") \ -} - -#define H5C2__AUX_DLL_SC(head_ptr, tail_ptr, len, Size, fv) \ -if ( ( ( ( (head_ptr) == NULL ) || ( (tail_ptr) == NULL ) ) && \ - ( (head_ptr) != (tail_ptr) ) \ - ) || \ - ( (len) < 0 ) || \ - ( (Size) < 0 ) || \ - ( ( (len) == 1 ) && \ - ( ( (head_ptr) != (tail_ptr) ) || ( (Size) <= 0 ) || \ - ( (head_ptr) == NULL ) || ( (head_ptr)->size != (Size) ) \ - ) \ - ) || \ - ( ( (len) >= 1 ) && \ - ( ( (head_ptr) == NULL ) || ( (head_ptr)->aux_prev != NULL ) || \ - ( (tail_ptr) == NULL ) || ( (tail_ptr)->aux_next != NULL ) \ - ) \ - ) \ - ) { \ - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (fv), "AUX DLL sanity check failed") \ -} - -#define H5C2__AUX_DLL_PRE_INSERT_SC(entry_ptr, hd_ptr, tail_ptr, len, Size, fv) \ -if ( ( (entry_ptr) == NULL ) || \ - ( (entry_ptr)->aux_next != NULL ) || \ - ( (entry_ptr)->aux_prev != NULL ) || \ - ( ( ( (hd_ptr) == NULL ) || ( (tail_ptr) == NULL ) ) && \ - ( (hd_ptr) != (tail_ptr) ) \ - ) || \ - ( (len) < 0 ) || \ - ( ( (len) == 1 ) && \ - ( ( (hd_ptr) != (tail_ptr) ) || ( (Size) <= 0 ) || \ - ( (hd_ptr) == NULL ) || ( (hd_ptr)->size != (Size) ) \ - ) \ - ) || \ - ( ( (len) >= 1 ) && \ - ( ( (hd_ptr) == NULL ) || ( (hd_ptr)->aux_prev != NULL ) || \ - ( (tail_ptr) == NULL ) || ( (tail_ptr)->aux_next != NULL ) \ - ) \ - ) \ - ) { \ - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (fv), "AUX DLL pre insert SC failed") \ -} - -#else /* H5C2_DO_SANITY_CHECKS */ - -#define H5C2__AUX_DLL_PRE_REMOVE_SC(entry_ptr, hd_ptr, tail_ptr, len, Size, fv) -#define H5C2__AUX_DLL_SC(head_ptr, tail_ptr, len, Size, fv) -#define H5C2__AUX_DLL_PRE_INSERT_SC(entry_ptr, hd_ptr, tail_ptr, len, Size, fv) - -#endif /* H5C2_DO_SANITY_CHECKS */ - - -#define H5C2__AUX_DLL_APPEND(entry_ptr, head_ptr, tail_ptr, len, Size, fail_val)\ - H5C2__AUX_DLL_PRE_INSERT_SC(entry_ptr, head_ptr, tail_ptr, len, Size, \ - fail_val) \ - if ( (head_ptr) == NULL ) \ - { \ - (head_ptr) = (entry_ptr); \ - (tail_ptr) = (entry_ptr); \ - } \ - else \ - { \ - (tail_ptr)->aux_next = (entry_ptr); \ - (entry_ptr)->aux_prev = (tail_ptr); \ - (tail_ptr) = (entry_ptr); \ - } \ - (len)++; \ - (Size) += entry_ptr->size; - -#define H5C2__AUX_DLL_PREPEND(entry_ptr, head_ptr, tail_ptr, len, Size, fv) \ - H5C2__AUX_DLL_PRE_INSERT_SC(entry_ptr, head_ptr, tail_ptr, len, Size, \ - fv) \ - if ( (head_ptr) == NULL ) \ - { \ - (head_ptr) = (entry_ptr); \ - (tail_ptr) = (entry_ptr); \ - } \ - else \ - { \ - (head_ptr)->aux_prev = (entry_ptr); \ - (entry_ptr)->aux_next = (head_ptr); \ - (head_ptr) = (entry_ptr); \ - } \ - (len)++; \ - (Size) += entry_ptr->size; - -#define H5C2__AUX_DLL_REMOVE(entry_ptr, head_ptr, tail_ptr, len, Size, fv) \ - H5C2__AUX_DLL_PRE_REMOVE_SC(entry_ptr, head_ptr, tail_ptr, len, Size, \ - fv) \ - { \ - if ( (head_ptr) == (entry_ptr) ) \ - { \ - (head_ptr) = (entry_ptr)->aux_next; \ - if ( (head_ptr) != NULL ) \ - { \ - (head_ptr)->aux_prev = NULL; \ - } \ - } \ - else \ - { \ - (entry_ptr)->aux_prev->aux_next = (entry_ptr)->aux_next; \ - } \ - if ( (tail_ptr) == (entry_ptr) ) \ - { \ - (tail_ptr) = (entry_ptr)->aux_prev; \ - if ( (tail_ptr) != NULL ) \ - { \ - (tail_ptr)->aux_next = NULL; \ - } \ - } \ - else \ - { \ - (entry_ptr)->aux_next->aux_prev = (entry_ptr)->aux_prev; \ - } \ - entry_ptr->aux_next = NULL; \ - entry_ptr->aux_prev = NULL; \ - (len)--; \ - (Size) -= entry_ptr->size; \ - } - - -/*********************************************************************** - * - * Stats collection macros - * - * The following macros must handle stats collection when this collection - * is enabled, and evaluate to the empty string when it is not. - * - * The sole exception to this rule is - * H5C2__UPDATE_CACHE_HIT_RATE_STATS(), which is always active as - * the cache hit rate stats are always collected and available. - * - * Changes: - * - * JRM -- 3/21/06 - * Added / updated macros for pinned entry related stats. - * - * JRM -- 8/9/06 - * More pinned entry stats related updates. - * - * JRM -- 3/31/07 - * Updated H5C2__UPDATE_STATS_FOR_PROTECT() to keep stats on - * read and write protects. - * - ***********************************************************************/ - -#define H5C2__UPDATE_CACHE_HIT_RATE_STATS(cache_ptr, hit) \ - (cache_ptr->cache_accesses)++; \ - if ( hit ) { \ - (cache_ptr->cache_hits)++; \ - } \ - -#if H5C2_COLLECT_CACHE_STATS - -#define H5C2__UPDATE_STATS_FOR_DIRTY_PIN(cache_ptr, entry_ptr) \ - (((cache_ptr)->dirty_pins)[(entry_ptr)->type->id])++; - -#define H5C2__UPDATE_STATS_FOR_UNPROTECT(cache_ptr) \ - 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 ) \ - (cache_ptr)->max_slist_size = (cache_ptr)->slist_size; \ - if ( (cache_ptr)->pel_len > (cache_ptr)->max_pel_len ) \ - (cache_ptr)->max_pel_len = (cache_ptr)->pel_len; \ - if ( (cache_ptr)->pel_size > (cache_ptr)->max_pel_size ) \ - (cache_ptr)->max_pel_size = (cache_ptr)->pel_size; - -#define H5C2__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 H5C2__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 ) \ - (cache_ptr)->max_index_size = (cache_ptr)->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 ) \ - (cache_ptr)->max_pl_size = (cache_ptr)->pl_size; \ - } else if ( (entry_ptr)->size > (new_size) ) { \ - ((cache_ptr)->size_decreases[(entry_ptr)->type->id])++; \ - } - -#define H5C2__UPDATE_STATS_FOR_HT_INSERTION(cache_ptr) \ - (cache_ptr)->total_ht_insertions++; - -#define H5C2__UPDATE_STATS_FOR_HT_DELETION(cache_ptr) \ - (cache_ptr)->total_ht_deletions++; - -#define H5C2__UPDATE_STATS_FOR_HT_SEARCH(cache_ptr, success, depth) \ - if ( success ) { \ - (cache_ptr)->successful_ht_searches++; \ - (cache_ptr)->total_successful_ht_search_depth += depth; \ - } else { \ - (cache_ptr)->failed_ht_searches++; \ - (cache_ptr)->total_failed_ht_search_depth += depth; \ - } - -#define H5C2__UPDATE_STATS_FOR_UNPIN(cache_ptr, entry_ptr) \ - ((cache_ptr)->unpins)[(entry_ptr)->type->id]++; - -#if H5C2_COLLECT_CACHE_ENTRY_STATS - -#define H5C2__RESET_CACHE_ENTRY_STATS(entry_ptr) \ - (entry_ptr)->accesses = 0; \ - (entry_ptr)->clears = 0; \ - (entry_ptr)->flushes = 0; \ - (entry_ptr)->pins = 0; - -#define H5C2__UPDATE_STATS_FOR_CLEAR(cache_ptr, entry_ptr) \ - (((cache_ptr)->clears)[(entry_ptr)->type->id])++; \ - if ( (entry_ptr)->is_pinned ) { \ - (((cache_ptr)->pinned_clears)[(entry_ptr)->type->id])++; \ - } \ - ((entry_ptr)->clears)++; - -#define H5C2__UPDATE_STATS_FOR_FLUSH(cache_ptr, entry_ptr) \ - (((cache_ptr)->flushes)[(entry_ptr)->type->id])++; \ - if ( (entry_ptr)->is_pinned ) { \ - (((cache_ptr)->pinned_flushes)[(entry_ptr)->type->id])++; \ - } \ - ((entry_ptr)->flushes)++; - -#define H5C2__UPDATE_STATS_FOR_EVICTION(cache_ptr, entry_ptr) \ - (((cache_ptr)->evictions)[(entry_ptr)->type->id])++; \ - if ( (entry_ptr)->accesses > \ - ((cache_ptr)->max_accesses)[(entry_ptr)->type->id] ) { \ - ((cache_ptr)->max_accesses)[(entry_ptr)->type->id] \ - = (entry_ptr)->accesses; \ - } \ - if ( (entry_ptr)->accesses < \ - ((cache_ptr)->min_accesses)[(entry_ptr)->type->id] ) { \ - ((cache_ptr)->min_accesses)[(entry_ptr)->type->id] \ - = (entry_ptr)->accesses; \ - } \ - if ( (entry_ptr)->clears > \ - ((cache_ptr)->max_clears)[(entry_ptr)->type->id] ) { \ - ((cache_ptr)->max_clears)[(entry_ptr)->type->id] \ - = (entry_ptr)->clears; \ - } \ - if ( (entry_ptr)->flushes > \ - ((cache_ptr)->max_flushes)[(entry_ptr)->type->id] ) { \ - ((cache_ptr)->max_flushes)[(entry_ptr)->type->id] \ - = (entry_ptr)->flushes; \ - } \ - if ( (entry_ptr)->size > \ - ((cache_ptr)->max_size)[(entry_ptr)->type->id] ) { \ - ((cache_ptr)->max_size)[(entry_ptr)->type->id] \ - = (entry_ptr)->size; \ - } \ - if ( (entry_ptr)->pins > \ - ((cache_ptr)->max_pins)[(entry_ptr)->type->id] ) { \ - ((cache_ptr)->max_pins)[(entry_ptr)->type->id] \ - = (entry_ptr)->pins; \ - } - -#define H5C2__UPDATE_STATS_FOR_INSERTION(cache_ptr, entry_ptr) \ - (((cache_ptr)->insertions)[(entry_ptr)->type->id])++; \ - if ( (entry_ptr)->is_pinned ) { \ - (((cache_ptr)->pinned_insertions)[(entry_ptr)->type->id])++; \ - ((cache_ptr)->pins)[(entry_ptr)->type->id]++; \ - (entry_ptr)->pins++; \ - if ( (cache_ptr)->pel_len > (cache_ptr)->max_pel_len ) \ - (cache_ptr)->max_pel_len = (cache_ptr)->pel_len; \ - if ( (cache_ptr)->pel_size > (cache_ptr)->max_pel_size ) \ - (cache_ptr)->max_pel_size = (cache_ptr)->pel_size; \ - } \ - 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 ) \ - (cache_ptr)->max_index_size = (cache_ptr)->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 ) \ - (cache_ptr)->max_slist_size = (cache_ptr)->slist_size; \ - if ( (entry_ptr)->size > \ - ((cache_ptr)->max_size)[(entry_ptr)->type->id] ) { \ - ((cache_ptr)->max_size)[(entry_ptr)->type->id] \ - = (entry_ptr)->size; \ - } - -#define H5C2__UPDATE_STATS_FOR_PROTECT(cache_ptr, entry_ptr, hit) \ - if ( hit ) \ - ((cache_ptr)->hits)[(entry_ptr)->type->id]++; \ - else \ - ((cache_ptr)->misses)[(entry_ptr)->type->id]++; \ - if ( ! ((entry_ptr)->is_read_only) ) { \ - ((cache_ptr)->write_protects)[(entry_ptr)->type->id]++; \ - } else { \ - ((cache_ptr)->read_protects)[(entry_ptr)->type->id]++; \ - if ( ((entry_ptr)->ro_ref_count) > \ - ((cache_ptr)->max_read_protects)[(entry_ptr)->type->id] ) { \ - ((cache_ptr)->max_read_protects)[(entry_ptr)->type->id] = \ - ((entry_ptr)->ro_ref_count); \ - } \ - } \ - 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 ) \ - (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; \ - if ( (cache_ptr)->pl_size > (cache_ptr)->max_pl_size ) \ - (cache_ptr)->max_pl_size = (cache_ptr)->pl_size; \ - if ( (entry_ptr)->size > \ - ((cache_ptr)->max_size)[(entry_ptr)->type->id] ) { \ - ((cache_ptr)->max_size)[(entry_ptr)->type->id] \ - = (entry_ptr)->size; \ - } \ - ((entry_ptr)->accesses)++; - -#define H5C2__UPDATE_STATS_FOR_PIN(cache_ptr, entry_ptr) \ - ((cache_ptr)->pins)[(entry_ptr)->type->id]++; \ - (entry_ptr)->pins++; \ - if ( (cache_ptr)->pel_len > (cache_ptr)->max_pel_len ) \ - (cache_ptr)->max_pel_len = (cache_ptr)->pel_len; \ - if ( (cache_ptr)->pel_size > (cache_ptr)->max_pel_size ) \ - (cache_ptr)->max_pel_size = (cache_ptr)->pel_size; - -#else /* H5C2_COLLECT_CACHE_ENTRY_STATS */ - -#define H5C2__RESET_CACHE_ENTRY_STATS(entry_ptr) - -#define H5C2__UPDATE_STATS_FOR_CLEAR(cache_ptr, entry_ptr) \ - if ( (entry_ptr)->is_pinned ) { \ - (((cache_ptr)->pinned_clears)[(entry_ptr)->type->id])++; \ - } \ - (((cache_ptr)->clears)[(entry_ptr)->type->id])++; - -#define H5C2__UPDATE_STATS_FOR_FLUSH(cache_ptr, entry_ptr) \ - (((cache_ptr)->flushes)[(entry_ptr)->type->id])++; \ - if ( (entry_ptr)->is_pinned ) { \ - (((cache_ptr)->pinned_flushes)[(entry_ptr)->type->id])++; \ - } - -#define H5C2__UPDATE_STATS_FOR_EVICTION(cache_ptr, entry_ptr) \ - (((cache_ptr)->evictions)[(entry_ptr)->type->id])++; - -#define H5C2__UPDATE_STATS_FOR_INSERTION(cache_ptr, entry_ptr) \ - (((cache_ptr)->insertions)[(entry_ptr)->type->id])++; \ - if ( (entry_ptr)->is_pinned ) { \ - (((cache_ptr)->pinned_insertions)[(entry_ptr)->type->id])++; \ - ((cache_ptr)->pins)[(entry_ptr)->type->id]++; \ - if ( (cache_ptr)->pel_len > (cache_ptr)->max_pel_len ) \ - (cache_ptr)->max_pel_len = (cache_ptr)->pel_len; \ - if ( (cache_ptr)->pel_size > (cache_ptr)->max_pel_size ) \ - (cache_ptr)->max_pel_size = (cache_ptr)->pel_size; \ - } \ - 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 ) \ - (cache_ptr)->max_index_size = (cache_ptr)->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 ) \ - (cache_ptr)->max_slist_size = (cache_ptr)->slist_size; - -#define H5C2__UPDATE_STATS_FOR_PROTECT(cache_ptr, entry_ptr, hit) \ - if ( hit ) \ - ((cache_ptr)->hits)[(entry_ptr)->type->id]++; \ - else \ - ((cache_ptr)->misses)[(entry_ptr)->type->id]++; \ - if ( ! ((entry_ptr)->is_read_only) ) { \ - ((cache_ptr)->write_protects)[(entry_ptr)->type->id]++; \ - } else { \ - ((cache_ptr)->read_protects)[(entry_ptr)->type->id]++; \ - if ( ((entry_ptr)->ro_ref_count) > \ - ((cache_ptr)->max_read_protects)[(entry_ptr)->type->id] ) { \ - ((cache_ptr)->max_read_protects)[(entry_ptr)->type->id] = \ - ((entry_ptr)->ro_ref_count); \ - } \ - } \ - 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 ) \ - (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; \ - if ( (cache_ptr)->pl_size > (cache_ptr)->max_pl_size ) \ - (cache_ptr)->max_pl_size = (cache_ptr)->pl_size; - -#define H5C2__UPDATE_STATS_FOR_PIN(cache_ptr, entry_ptr) \ - ((cache_ptr)->pins)[(entry_ptr)->type->id]++; \ - if ( (cache_ptr)->pel_len > (cache_ptr)->max_pel_len ) \ - (cache_ptr)->max_pel_len = (cache_ptr)->pel_len; \ - if ( (cache_ptr)->pel_size > (cache_ptr)->max_pel_size ) \ - (cache_ptr)->max_pel_size = (cache_ptr)->pel_size; - -#endif /* H5C2_COLLECT_CACHE_ENTRY_STATS */ - -#else /* H5C2_COLLECT_CACHE_STATS */ - -#define H5C2__RESET_CACHE_ENTRY_STATS(entry_ptr) -#define H5C2__UPDATE_STATS_FOR_DIRTY_PIN(cache_ptr, entry_ptr) -#define H5C2__UPDATE_STATS_FOR_UNPROTECT(cache_ptr) -#define H5C2__UPDATE_STATS_FOR_RENAME(cache_ptr, entry_ptr) -#define H5C2__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE(cache_ptr, entry_ptr, new_size) -#define H5C2__UPDATE_STATS_FOR_HT_INSERTION(cache_ptr) -#define H5C2__UPDATE_STATS_FOR_HT_DELETION(cache_ptr) -#define H5C2__UPDATE_STATS_FOR_HT_SEARCH(cache_ptr, success, depth) -#define H5C2__UPDATE_STATS_FOR_INSERTION(cache_ptr, entry_ptr) -#define H5C2__UPDATE_STATS_FOR_CLEAR(cache_ptr, entry_ptr) -#define H5C2__UPDATE_STATS_FOR_FLUSH(cache_ptr, entry_ptr) -#define H5C2__UPDATE_STATS_FOR_EVICTION(cache_ptr, entry_ptr) -#define H5C2__UPDATE_STATS_FOR_PROTECT(cache_ptr, entry_ptr, hit) -#define H5C2__UPDATE_STATS_FOR_PIN(cache_ptr, entry_ptr) -#define H5C2__UPDATE_STATS_FOR_UNPIN(cache_ptr, entry_ptr) - -#endif /* H5C2_COLLECT_CACHE_STATS */ - - -/*********************************************************************** - * - * Hash table access and manipulation macros: - * - * The following macros handle searches, insertions, and deletion in - * the hash table. - * - * When modifying these macros, remember to modify the similar macros - * in tst/cache.c - * - ***********************************************************************/ - -/* H5C2__HASH_TABLE_LEN is defined in H5C2pkg.h. It mut be a power of two. */ - -#define H5C2__HASH_MASK ((size_t)(H5C2__HASH_TABLE_LEN - 1) << 3) - -#define H5C2__HASH_FCN(x) (int)(((x) & H5C2__HASH_MASK) >> 3) - -#if H5C2_DO_SANITY_CHECKS - -#define H5C2__PRE_HT_INSERT_SC(cache_ptr, entry_ptr, fail_val) \ -if ( ( (cache_ptr) == NULL ) || \ - ( (cache_ptr)->magic != H5C2__H5C2_T_MAGIC ) || \ - ( (entry_ptr) == NULL ) || \ - ( ! H5F_addr_defined((entry_ptr)->addr) ) || \ - ( (entry_ptr)->ht_next != NULL ) || \ - ( (entry_ptr)->ht_prev != NULL ) || \ - ( (entry_ptr)->size <= 0 ) || \ - ( (k = H5C2__HASH_FCN((entry_ptr)->addr)) < 0 ) || \ - ( k >= H5C2__HASH_TABLE_LEN ) ) { \ - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, fail_val, \ - "Pre HT insert SC failed") \ -} - -#define H5C2__PRE_HT_REMOVE_SC(cache_ptr, entry_ptr) \ -if ( ( (cache_ptr) == NULL ) || \ - ( (cache_ptr)->magic != H5C2__H5C2_T_MAGIC ) || \ - ( (cache_ptr)->index_len < 1 ) || \ - ( (entry_ptr) == NULL ) || \ - ( (cache_ptr)->index_size < (entry_ptr)->size ) || \ - ( ! H5F_addr_defined((entry_ptr)->addr) ) || \ - ( (entry_ptr)->size <= 0 ) || \ - ( H5C2__HASH_FCN((entry_ptr)->addr) < 0 ) || \ - ( H5C2__HASH_FCN((entry_ptr)->addr) >= H5C2__HASH_TABLE_LEN ) || \ - ( ((cache_ptr)->index)[(H5C2__HASH_FCN((entry_ptr)->addr))] \ - == NULL ) || \ - ( ( ((cache_ptr)->index)[(H5C2__HASH_FCN((entry_ptr)->addr))] \ - != (entry_ptr) ) && \ - ( (entry_ptr)->ht_prev == NULL ) ) || \ - ( ( ((cache_ptr)->index)[(H5C2__HASH_FCN((entry_ptr)->addr))] == \ - (entry_ptr) ) && \ - ( (entry_ptr)->ht_prev != NULL ) ) ) { \ - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Pre HT remove SC failed") \ -} - -#define H5C2__PRE_HT_SEARCH_SC(cache_ptr, Addr, fail_val) \ -if ( ( (cache_ptr) == NULL ) || \ - ( (cache_ptr)->magic != H5C2__H5C2_T_MAGIC ) || \ - ( ! H5F_addr_defined(Addr) ) || \ - ( H5C2__HASH_FCN(Addr) < 0 ) || \ - ( H5C2__HASH_FCN(Addr) >= H5C2__HASH_TABLE_LEN ) ) { \ - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, fail_val, "Pre HT search SC failed") \ -} - -#define H5C2__POST_SUC_HT_SEARCH_SC(cache_ptr, entry_ptr, Addr, k, fail_val) \ -if ( ( (cache_ptr) == NULL ) || \ - ( (cache_ptr)->magic != H5C2__H5C2_T_MAGIC ) || \ - ( (cache_ptr)->index_len < 1 ) || \ - ( (entry_ptr) == NULL ) || \ - ( (cache_ptr)->index_size < (entry_ptr)->size ) || \ - ( H5F_addr_ne((entry_ptr)->addr, (Addr)) ) || \ - ( (entry_ptr)->size <= 0 ) || \ - ( ((cache_ptr)->index)[k] == NULL ) || \ - ( ( ((cache_ptr)->index)[k] != (entry_ptr) ) && \ - ( (entry_ptr)->ht_prev == NULL ) ) || \ - ( ( ((cache_ptr)->index)[k] == (entry_ptr) ) && \ - ( (entry_ptr)->ht_prev != NULL ) ) || \ - ( ( (entry_ptr)->ht_prev != NULL ) && \ - ( (entry_ptr)->ht_prev->ht_next != (entry_ptr) ) ) || \ - ( ( (entry_ptr)->ht_next != NULL ) && \ - ( (entry_ptr)->ht_next->ht_prev != (entry_ptr) ) ) ) { \ - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, fail_val, \ - "Post successful HT search SC failed") \ -} - -#define H5C2__POST_HT_SHIFT_TO_FRONT(cache_ptr, entry_ptr, k, fail_val) \ -if ( ( (cache_ptr) == NULL ) || \ - ( ((cache_ptr)->index)[k] != (entry_ptr) ) || \ - ( (entry_ptr)->ht_prev != NULL ) ) { \ - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, fail_val, \ - "Post HT shift to front SC failed") \ -} - -#define H5C2__PRE_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) <= 0 ) || \ - ( (old_size) > (cache_ptr)->index_size ) || \ - ( (new_size) <= 0 ) || \ - ( ( (cache_ptr)->index_len == 1 ) && \ - ( (cache_ptr)->index_size != (old_size) ) ) ) { \ - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "Pre HT entry size change SC failed") \ -} - -#define H5C2__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") \ -} - -#else /* H5C2_DO_SANITY_CHECKS */ - -#define H5C2__PRE_HT_INSERT_SC(cache_ptr, entry_ptr, fail_val) -#define H5C2__PRE_HT_REMOVE_SC(cache_ptr, entry_ptr) -#define H5C2__PRE_HT_SEARCH_SC(cache_ptr, Addr, fail_val) -#define H5C2__POST_SUC_HT_SEARCH_SC(cache_ptr, entry_ptr, Addr, k, fail_val) -#define H5C2__POST_HT_SHIFT_TO_FRONT(cache_ptr, entry_ptr, k, fail_val) -#define H5C2__PRE_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size) -#define H5C2__POST_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size) - -#endif /* H5C2_DO_SANITY_CHECKS */ - - -#define H5C2__INSERT_IN_INDEX(cache_ptr, entry_ptr, fail_val) \ -{ \ - int k; \ - H5C2__PRE_HT_INSERT_SC(cache_ptr, entry_ptr, fail_val) \ - k = H5C2__HASH_FCN((entry_ptr)->addr); \ - if ( ((cache_ptr)->index)[k] == NULL ) \ - { \ - ((cache_ptr)->index)[k] = (entry_ptr); \ - } \ - else \ - { \ - (entry_ptr)->ht_next = ((cache_ptr)->index)[k]; \ - (entry_ptr)->ht_next->ht_prev = (entry_ptr); \ - ((cache_ptr)->index)[k] = (entry_ptr); \ - } \ - (cache_ptr)->index_len++; \ - (cache_ptr)->index_size += (entry_ptr)->size; \ - H5C2__UPDATE_STATS_FOR_HT_INSERTION(cache_ptr) \ -} - -#define H5C2__DELETE_FROM_INDEX(cache_ptr, entry_ptr) \ -{ \ - int k; \ - H5C2__PRE_HT_REMOVE_SC(cache_ptr, entry_ptr) \ - k = H5C2__HASH_FCN((entry_ptr)->addr); \ - if ( (entry_ptr)->ht_next ) \ - { \ - (entry_ptr)->ht_next->ht_prev = (entry_ptr)->ht_prev; \ - } \ - if ( (entry_ptr)->ht_prev ) \ - { \ - (entry_ptr)->ht_prev->ht_next = (entry_ptr)->ht_next; \ - } \ - if ( ((cache_ptr)->index)[k] == (entry_ptr) ) \ - { \ - ((cache_ptr)->index)[k] = (entry_ptr)->ht_next; \ - } \ - (entry_ptr)->ht_next = NULL; \ - (entry_ptr)->ht_prev = NULL; \ - (cache_ptr)->index_len--; \ - (cache_ptr)->index_size -= (entry_ptr)->size; \ - H5C2__UPDATE_STATS_FOR_HT_DELETION(cache_ptr) \ -} - -#define H5C2__SEARCH_INDEX(cache_ptr, Addr, entry_ptr, fail_val) \ -{ \ - int k; \ - int depth = 0; \ - H5C2__PRE_HT_SEARCH_SC(cache_ptr, Addr, fail_val) \ - k = H5C2__HASH_FCN(Addr); \ - entry_ptr = ((cache_ptr)->index)[k]; \ - while ( ( entry_ptr ) && ( H5F_addr_ne(Addr, (entry_ptr)->addr) ) ) \ - { \ - (entry_ptr) = (entry_ptr)->ht_next; \ - (depth)++; \ - } \ - if ( entry_ptr ) \ - { \ - H5C2__POST_SUC_HT_SEARCH_SC(cache_ptr, entry_ptr, Addr, k, fail_val) \ - if ( entry_ptr != ((cache_ptr)->index)[k] ) \ - { \ - if ( (entry_ptr)->ht_next ) \ - { \ - (entry_ptr)->ht_next->ht_prev = (entry_ptr)->ht_prev; \ - } \ - HDassert( (entry_ptr)->ht_prev != NULL ); \ - (entry_ptr)->ht_prev->ht_next = (entry_ptr)->ht_next; \ - ((cache_ptr)->index)[k]->ht_prev = (entry_ptr); \ - (entry_ptr)->ht_next = ((cache_ptr)->index)[k]; \ - (entry_ptr)->ht_prev = NULL; \ - ((cache_ptr)->index)[k] = (entry_ptr); \ - H5C2__POST_HT_SHIFT_TO_FRONT(cache_ptr, entry_ptr, k, fail_val) \ - } \ - } \ - H5C2__UPDATE_STATS_FOR_HT_SEARCH(cache_ptr, (entry_ptr != NULL), depth) \ -} - -#define H5C2__SEARCH_INDEX_NO_STATS(cache_ptr, Addr, entry_ptr, fail_val) \ -{ \ - int k; \ - int depth = 0; \ - H5C2__PRE_HT_SEARCH_SC(cache_ptr, Addr, fail_val) \ - k = H5C2__HASH_FCN(Addr); \ - entry_ptr = ((cache_ptr)->index)[k]; \ - while ( ( entry_ptr ) && ( H5F_addr_ne(Addr, (entry_ptr)->addr) ) ) \ - { \ - (entry_ptr) = (entry_ptr)->ht_next; \ - (depth)++; \ - } \ - if ( entry_ptr ) \ - { \ - H5C2__POST_SUC_HT_SEARCH_SC(cache_ptr, entry_ptr, Addr, k, fail_val) \ - if ( entry_ptr != ((cache_ptr)->index)[k] ) \ - { \ - if ( (entry_ptr)->ht_next ) \ - { \ - (entry_ptr)->ht_next->ht_prev = (entry_ptr)->ht_prev; \ - } \ - HDassert( (entry_ptr)->ht_prev != NULL ); \ - (entry_ptr)->ht_prev->ht_next = (entry_ptr)->ht_next; \ - ((cache_ptr)->index)[k]->ht_prev = (entry_ptr); \ - (entry_ptr)->ht_next = ((cache_ptr)->index)[k]; \ - (entry_ptr)->ht_prev = NULL; \ - ((cache_ptr)->index)[k] = (entry_ptr); \ - H5C2__POST_HT_SHIFT_TO_FRONT(cache_ptr, entry_ptr, k, fail_val) \ - } \ - } \ -} - -#define H5C2__UPDATE_INDEX_FOR_SIZE_CHANGE(cache_ptr, old_size, new_size) \ -{ \ - H5C2__PRE_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size) \ - (cache_ptr)->index_size -= old_size; \ - (cache_ptr)->index_size += new_size; \ - H5C2__POST_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size) \ -} - - -/************************************************************************** - * - * Skip list insertion and deletion macros: - * - * These used to be functions, but I converted them to macros to avoid some - * function call overhead. - * - **************************************************************************/ - -/*------------------------------------------------------------------------- - * - * Macro: H5C2__INSERT_ENTRY_IN_SLIST - * - * Purpose: Insert the specified instance of H5C2_cache_entry_t into - * the skip list in the specified instance of H5C2_t. Update - * the associated length and size fields. - * - * Return: N/A - * - * Programmer: John Mainzer, 5/10/04 - * - * Modifications: - * - * JRM -- 7/21/04 - * Updated function to set the in_tree flag when inserting - * an entry into the tree. Also modified the function to - * update the tree size and len fields instead of the similar - * index fields. - * - * All of this is part of the modifications to support the - * hash table. - * - * JRM -- 7/27/04 - * Converted the function H5C2_insert_entry_in_tree() into - * the macro H5C2__INSERT_ENTRY_IN_TREE in the hopes of - * wringing a little more speed out of the cache. - * - * Note that we don't bother to check if the entry is already - * in the tree -- if it is, H5SL_insert() will fail. - * - * QAK -- 11/27/04 - * Switched over to using skip list routines. - * - * JRM -- 6/27/06 - * Added fail_val parameter. - * - * JRM -- 8/25/06 - * Added the H5C2_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 H5C2_DO_SANITY_CHECKS - -#define H5C2__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, fail_val) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_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 ); \ - \ -} /* H5C2__INSERT_ENTRY_IN_SLIST */ - -#else /* H5C2_DO_SANITY_CHECKS */ - -#define H5C2__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, fail_val) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_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; \ - \ - HDassert( (cache_ptr)->slist_len > 0 ); \ - HDassert( (cache_ptr)->slist_size > 0 ); \ - \ -} /* H5C2__INSERT_ENTRY_IN_SLIST */ - -#endif /* H5C2_DO_SANITY_CHECKS */ - - -/*------------------------------------------------------------------------- - * - * Function: H5C2__REMOVE_ENTRY_FROM_SLIST - * - * Purpose: Remove the specified instance of H5C2_cache_entry_t from the - * index skip list in the specified instance of H5C2_t. Update - * the associated length and size fields. - * - * Return: N/A - * - * Programmer: John Mainzer, 5/10/04 - * - * Modifications: - * - * JRM -- 7/21/04 - * Updated function for the addition of the hash table. - * - * JRM - 7/27/04 - * Converted from the function H5C2_remove_entry_from_tree() - * to the macro H5C2__REMOVE_ENTRY_FROM_TREE in the hopes of - * wringing a little more performance out of the cache. - * - * QAK -- 11/27/04 - * Switched over to using skip list routines. - * - * JRM -- 3/28/07 - * Updated sanity checks for the new is_read_only and - * ro_ref_count fields in H5C2_cache_entry_t. - * - *------------------------------------------------------------------------- - */ - -#define H5C2__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( !((entry_ptr)->is_protected) ); \ - HDassert( !((entry_ptr)->is_read_only) ); \ - HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ - HDassert( (entry_ptr)->size > 0 ); \ - HDassert( (entry_ptr)->in_slist ); \ - HDassert( (cache_ptr)->slist_ptr ); \ - \ - if ( H5SL_remove((cache_ptr)->slist_ptr, &(entry_ptr)->addr) \ - != (entry_ptr) ) \ - \ - HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, \ - "Can't delete entry from skip list.") \ - \ - HDassert( (cache_ptr)->slist_len > 0 ); \ - (cache_ptr)->slist_len--; \ - HDassert( (cache_ptr)->slist_size >= (entry_ptr)->size ); \ - (cache_ptr)->slist_size -= (entry_ptr)->size; \ - (entry_ptr)->in_slist = FALSE; \ -} /* H5C2__REMOVE_ENTRY_FROM_SLIST */ - - -/*------------------------------------------------------------------------- - * - * Function: H5C2__UPDATE_SLIST_FOR_SIZE_CHANGE - * - * Purpose: Update cache_ptr->slist_size for a change in the size of - * and entry in the slist. - * - * Return: N/A - * - * Programmer: John Mainzer, 9/07/05 - * - * Modifications: - * - * JRM -- 8/27/06 - * Added the H5C2_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 H5C2_DO_SANITY_CHECKS - -#define H5C2__UPDATE_SLIST_FOR_SIZE_CHANGE(cache_ptr, old_size, new_size) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_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); \ - \ - (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) ) ); \ -} /* H5C2__REMOVE_ENTRY_FROM_SLIST */ - -#else /* H5C2_DO_SANITY_CHECKS */ - -#define H5C2__UPDATE_SLIST_FOR_SIZE_CHANGE(cache_ptr, old_size, new_size) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_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) ) ); \ -} /* H5C2__REMOVE_ENTRY_FROM_SLIST */ - -#endif /* H5C2_DO_SANITY_CHECKS */ - - -/************************************************************************** - * - * Replacement policy update macros: - * - * These used to be functions, but I converted them to macros to avoid some - * function call overhead. - * - **************************************************************************/ - -/*------------------------------------------------------------------------- - * - * Macro: H5C2__FAKE_RP_FOR_MOST_RECENT_ACCESS - * - * Purpose: For efficiency, we sometimes change the order of flushes -- - * but doing so can confuse the replacement policy. This - * macro exists to allow us to specify an entry as the - * most recently touched so we can repair any such - * confusion. - * - * 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 macro - * should switch on the current policy and act accordingly. - * - * Return: N/A - * - * Programmer: John Mainzer, 10/13/05 - * - * Modifications: - * - * JRM -- 3/20/06 - * Modified macro to ignore pinned entries. Pinned entries - * do not appear in the data structures maintained by the - * replacement policy code, and thus this macro has nothing - * to do if called for such an entry. - * - * JRM -- 3/28/07 - * Added sanity checks using the new is_read_only and - * ro_ref_count fields of struct H5C2_cache_entry_t. - * - *------------------------------------------------------------------------- - */ - -#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS - -#define H5C2__FAKE_RP_FOR_MOST_RECENT_ACCESS(cache_ptr, entry_ptr, fail_val) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( !((entry_ptr)->is_protected) ); \ - HDassert( !((entry_ptr)->is_read_only) ); \ - HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ - HDassert( (entry_ptr)->size > 0 ); \ - \ - if ( ! ((entry_ptr)->is_pinned) ) { \ - \ - /* modified LRU specific code */ \ - \ - /* remove the entry from the LRU list, and re-insert it at the head.\ - */ \ - \ - H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - /* Use the dirty flag to infer whether the entry is on the clean or \ - * dirty LRU list, and remove it. Then insert it at the head of \ - * the same LRU list. \ - * \ - * At least initially, all entries should be clean. That may \ - * change, so we may as well deal with both cases now. \ - */ \ - \ - if ( (entry_ptr)->is_dirty ) { \ - H5C2__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ - (cache_ptr)->dLRU_tail_ptr, \ - (cache_ptr)->dLRU_list_len, \ - (cache_ptr)->dLRU_list_size, (fail_val)) \ - \ - H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ - (cache_ptr)->dLRU_tail_ptr, \ - (cache_ptr)->dLRU_list_len, \ - (cache_ptr)->dLRU_list_size, (fail_val)) \ - } else { \ - H5C2__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ - (cache_ptr)->cLRU_tail_ptr, \ - (cache_ptr)->cLRU_list_len, \ - (cache_ptr)->cLRU_list_size, (fail_val)) \ - \ - H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ - (cache_ptr)->cLRU_tail_ptr, \ - (cache_ptr)->cLRU_list_len, \ - (cache_ptr)->cLRU_list_size, (fail_val)) \ - } \ - \ - /* End modified LRU specific code. */ \ - } \ -} /* H5C2__FAKE_RP_FOR_MOST_RECENT_ACCESS */ - -#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ - -#define H5C2__FAKE_RP_FOR_MOST_RECENT_ACCESS(cache_ptr, entry_ptr, fail_val) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( !((entry_ptr)->is_protected) ); \ - HDassert( !((entry_ptr)->is_read_only) ); \ - HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ - HDassert( (entry_ptr)->size > 0 ); \ - \ - if ( ! ((entry_ptr)->is_pinned) ) { \ - \ - /* modified LRU specific code */ \ - \ - /* remove the entry from the LRU list, and re-insert it at the head \ - */ \ - \ - H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - /* End modified LRU specific code. */ \ - } \ -} /* H5C2__FAKE_RP_FOR_MOST_RECENT_ACCESS */ - -#endif /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ - - -/*------------------------------------------------------------------------- - * - * Macro: H5C2__UPDATE_RP_FOR_EVICTION - * - * Purpose: Update the replacement policy data structures for an - * eviction of the specified cache entry. - * - * 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: Non-negative on success/Negative on failure. - * - * Programmer: John Mainzer, 5/10/04 - * - * Modifications: - * - * JRM - 7/27/04 - * Converted the function H5C2_update_rp_for_eviction() to the - * macro H5C2__UPDATE_RP_FOR_EVICTION in an effort to squeeze - * a bit more performance out of the cache. - * - * At least for the first cut, I am leaving the comments and - * white space in the macro. If they cause dificulties with - * the pre-processor, I'll have to remove them. - * - * JRM - 7/28/04 - * Split macro into two version, one supporting the clean and - * dirty LRU lists, and the other not. Yet another attempt - * at optimization. - * - * JRM - 3/20/06 - * Pinned entries can't be evicted, so this entry should never - * be called on a pinned entry. Added assert to verify this. - * - * JRM -- 3/28/07 - * Added sanity checks for the new is_read_only and - * ro_ref_count fields of struct H5C2_cache_entry_t. - * - *------------------------------------------------------------------------- - */ - -#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS - -#define H5C2__UPDATE_RP_FOR_EVICTION(cache_ptr, entry_ptr, fail_val) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( !((entry_ptr)->is_protected) ); \ - HDassert( !((entry_ptr)->is_read_only) ); \ - HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ - HDassert( !((entry_ptr)->is_pinned) ); \ - HDassert( (entry_ptr)->size > 0 ); \ - \ - /* modified LRU specific code */ \ - \ - /* remove the entry from the LRU list. */ \ - \ - H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - /* If the entry is clean when it is evicted, it should be on the \ - * clean LRU list, if it was dirty, it should be on the dirty LRU list. \ - * Remove it from the appropriate list according to the value of the \ - * dirty flag. \ - */ \ - \ - if ( (entry_ptr)->is_dirty ) { \ - \ - H5C2__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ - (cache_ptr)->dLRU_tail_ptr, \ - (cache_ptr)->dLRU_list_len, \ - (cache_ptr)->dLRU_list_size, (fail_val)) \ - } else { \ - H5C2__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ - (cache_ptr)->cLRU_tail_ptr, \ - (cache_ptr)->cLRU_list_len, \ - (cache_ptr)->cLRU_list_size, (fail_val)) \ - } \ - \ -} /* H5C2__UPDATE_RP_FOR_EVICTION */ - -#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ - -#define H5C2__UPDATE_RP_FOR_EVICTION(cache_ptr, entry_ptr, fail_val) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( !((entry_ptr)->is_protected) ); \ - HDassert( !((entry_ptr)->is_read_only) ); \ - HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ - HDassert( !((entry_ptr)->is_pinned) ); \ - HDassert( (entry_ptr)->size > 0 ); \ - \ - /* modified LRU specific code */ \ - \ - /* remove the entry from the LRU list. */ \ - \ - H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ -} /* H5C2__UPDATE_RP_FOR_EVICTION */ - -#endif /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ - - -/*------------------------------------------------------------------------- - * - * Macro: H5C2__UPDATE_RP_FOR_FLUSH - * - * Purpose: Update the replacement policy data structures for a flush - * of the specified cache entry. - * - * 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, 5/6/04 - * - * Modifications: - * - * JRM - 7/27/04 - * Converted the function H5C2_update_rp_for_flush() to the - * macro H5C2__UPDATE_RP_FOR_FLUSH in an effort to squeeze - * a bit more performance out of the cache. - * - * At least for the first cut, I am leaving the comments and - * white space in the macro. If they cause dificulties with - * pre-processor, I'll have to remove them. - * - * JRM - 7/28/04 - * Split macro into two versions, one supporting the clean and - * dirty LRU lists, and the other not. Yet another attempt - * at optimization. - * - * JRM - 3/20/06 - * While pinned entries can be flushed, they don't reside in - * the replacement policy data structures when unprotected. - * Thus I modified this macro to do nothing if the entry is - * pinned. - * - * JRM - 3/28/07 - * Added sanity checks based on the new is_read_only and - * ro_ref_count fields of struct H5C2_cache_entry_t. - * - *------------------------------------------------------------------------- - */ - -#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS - -#define H5C2__UPDATE_RP_FOR_FLUSH(cache_ptr, entry_ptr, fail_val) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( !((entry_ptr)->is_protected) ); \ - HDassert( !((entry_ptr)->is_read_only) ); \ - HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ - HDassert( (entry_ptr)->size > 0 ); \ - \ - if ( ! ((entry_ptr)->is_pinned) ) { \ - \ - /* modified LRU specific code */ \ - \ - /* remove the entry from the LRU list, and re-insert it at the \ - * head. \ - */ \ - \ - H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - /* since the entry is being flushed or cleared, one would think \ - * that it must be dirty -- but that need not be the case. Use the \ - * dirty flag to infer whether the entry is on the clean or dirty \ - * LRU list, and remove it. Then insert it at the head of the \ - * clean LRU list. \ - * \ - * The function presumes that a dirty entry will be either cleared \ - * or flushed shortly, so it is OK if we put a dirty entry on the \ - * clean LRU list. \ - */ \ - \ - if ( (entry_ptr)->is_dirty ) { \ - H5C2__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ - (cache_ptr)->dLRU_tail_ptr, \ - (cache_ptr)->dLRU_list_len, \ - (cache_ptr)->dLRU_list_size, (fail_val)) \ - } else { \ - H5C2__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ - (cache_ptr)->cLRU_tail_ptr, \ - (cache_ptr)->cLRU_list_len, \ - (cache_ptr)->cLRU_list_size, (fail_val)) \ - } \ - \ - H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ - (cache_ptr)->cLRU_tail_ptr, \ - (cache_ptr)->cLRU_list_len, \ - (cache_ptr)->cLRU_list_size, (fail_val)) \ - \ - /* End modified LRU specific code. */ \ - } \ -} /* H5C2__UPDATE_RP_FOR_FLUSH */ - -#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ - -#define H5C2__UPDATE_RP_FOR_FLUSH(cache_ptr, entry_ptr, fail_val) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( !((entry_ptr)->is_protected) ); \ - HDassert( !((entry_ptr)->is_read_only) ); \ - HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ - HDassert( (entry_ptr)->size > 0 ); \ - \ - if ( ! ((entry_ptr)->is_pinned) ) { \ - \ - /* modified LRU specific code */ \ - \ - /* remove the entry from the LRU list, and re-insert it at the \ - * head. \ - */ \ - \ - H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - /* End modified LRU specific code. */ \ - } \ -} /* H5C2__UPDATE_RP_FOR_FLUSH */ - -#endif /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ - - -/*------------------------------------------------------------------------- - * - * Macro: H5C2__UPDATE_RP_FOR_INSERTION - * - * Purpose: Update the replacement policy data structures for an - * insertion of the specified cache entry. - * - * 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, 5/17/04 - * - * Modifications: - * - * JRM - 7/27/04 - * Converted the function H5C2_update_rp_for_insertion() to the - * macro H5C2__UPDATE_RP_FOR_INSERTION in an effort to squeeze - * a bit more performance out of the cache. - * - * At least for the first cut, I am leaving the comments and - * white space in the macro. If they cause dificulties with - * pre-processor, I'll have to remove them. - * - * JRM - 7/28/04 - * Split macro into two version, one supporting the clean and - * dirty LRU lists, and the other not. Yet another attempt - * at optimization. - * - * JRM - 3/10/06 - * This macro should never be called on a pinned entry. - * Inserted an assert to verify this. - * - * JRM - 8/9/06 - * Not any more. We must now allow insertion of pinned - * entries. Updated macro to support this. - * - * JRM - 3/28/07 - * Added sanity checks using the new is_read_only and - * ro_ref_count fields of struct H5C2_cache_entry_t. - * - *------------------------------------------------------------------------- - */ - -#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS - -#define H5C2__UPDATE_RP_FOR_INSERTION(cache_ptr, entry_ptr, fail_val) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( !((entry_ptr)->is_protected) ); \ - HDassert( !((entry_ptr)->is_read_only) ); \ - HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ - HDassert( (entry_ptr)->size > 0 ); \ - \ - if ( (entry_ptr)->is_pinned ) { \ - \ - H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->pel_head_ptr, \ - (cache_ptr)->pel_tail_ptr, \ - (cache_ptr)->pel_len, \ - (cache_ptr)->pel_size, (fail_val)) \ - \ - } else { \ - \ - /* modified LRU specific code */ \ - \ - /* insert the entry at the head of the LRU list. */ \ - \ - H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - /* insert the entry at the head of the clean or dirty LRU list as \ - * appropriate. \ - */ \ - \ - if ( entry_ptr->is_dirty ) { \ - H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ - (cache_ptr)->dLRU_tail_ptr, \ - (cache_ptr)->dLRU_list_len, \ - (cache_ptr)->dLRU_list_size, (fail_val)) \ - } else { \ - H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ - (cache_ptr)->cLRU_tail_ptr, \ - (cache_ptr)->cLRU_list_len, \ - (cache_ptr)->cLRU_list_size, (fail_val)) \ - } \ - \ - /* End modified LRU specific code. */ \ - } \ -} - -#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ - -#define H5C2__UPDATE_RP_FOR_INSERTION(cache_ptr, entry_ptr, fail_val) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( !((entry_ptr)->is_protected) ); \ - HDassert( !((entry_ptr)->is_read_only) ); \ - HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ - HDassert( (entry_ptr)->size > 0 ); \ - \ - if ( (entry_ptr)->is_pinned ) { \ - \ - H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->pel_head_ptr, \ - (cache_ptr)->pel_tail_ptr, \ - (cache_ptr)->pel_len, \ - (cache_ptr)->pel_size, (fail_val)) \ - \ - } else { \ - \ - /* modified LRU specific code */ \ - \ - /* insert the entry at the head of the LRU list. */ \ - \ - H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - /* End modified LRU specific code. */ \ - } \ -} - -#endif /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ - - -/*------------------------------------------------------------------------- - * - * Macro: H5C2__UPDATE_RP_FOR_PROTECT - * - * Purpose: Update the replacement policy data structures for a - * protect of the specified cache entry. - * - * To do this, unlink the specified entry from any data - * structures used by the replacement policy, and add the - * entry to the protected list. - * - * 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, 5/17/04 - * - * Modifications: - * - * JRM - 7/27/04 - * Converted the function H5C2_update_rp_for_protect() to the - * macro H5C2__UPDATE_RP_FOR_PROTECT in an effort to squeeze - * a bit more performance out of the cache. - * - * At least for the first cut, I am leaving the comments and - * white space in the macro. If they cause dificulties with - * pre-processor, I'll have to remove them. - * - * JRM - 7/28/04 - * Split macro into two version, one supporting the clean and - * dirty LRU lists, and the other not. Yet another attempt - * at optimization. - * - * JRM - 3/17/06 - * Modified macro to attempt to remove pinned entriese from - * the pinned entry list instead of from the data structures - * maintained by the replacement policy. - * - * JRM - 3/28/07 - * Added sanity checks based on the new is_read_only and - * ro_ref_count fields of struct H5C2_cache_entry_t. - * - *------------------------------------------------------------------------- - */ - -#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS - -#define H5C2__UPDATE_RP_FOR_PROTECT(cache_ptr, entry_ptr, fail_val) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( !((entry_ptr)->is_protected) ); \ - HDassert( !((entry_ptr)->is_read_only) ); \ - HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ - HDassert( (entry_ptr)->size > 0 ); \ - \ - if ( (entry_ptr)->is_pinned ) { \ - \ - H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->pel_head_ptr, \ - (cache_ptr)->pel_tail_ptr, \ - (cache_ptr)->pel_len, \ - (cache_ptr)->pel_size, (fail_val)) \ - \ - } else { \ - \ - /* modified LRU specific code */ \ - \ - /* remove the entry from the LRU list. */ \ - \ - H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - /* Similarly, remove the entry from the clean or dirty LRU list \ - * as appropriate. \ - */ \ - \ - if ( (entry_ptr)->is_dirty ) { \ - \ - H5C2__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ - (cache_ptr)->dLRU_tail_ptr, \ - (cache_ptr)->dLRU_list_len, \ - (cache_ptr)->dLRU_list_size, (fail_val)) \ - \ - } else { \ - \ - H5C2__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ - (cache_ptr)->cLRU_tail_ptr, \ - (cache_ptr)->cLRU_list_len, \ - (cache_ptr)->cLRU_list_size, (fail_val)) \ - } \ - \ - /* End modified LRU specific code. */ \ - } \ - \ - /* Regardless of the replacement policy, or whether the entry is \ - * pinned, now add the entry to the protected list. \ - */ \ - \ - H5C2__DLL_APPEND((entry_ptr), (cache_ptr)->pl_head_ptr, \ - (cache_ptr)->pl_tail_ptr, \ - (cache_ptr)->pl_len, \ - (cache_ptr)->pl_size, (fail_val)) \ -} /* H5C2__UPDATE_RP_FOR_PROTECT */ - -#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ - -#define H5C2__UPDATE_RP_FOR_PROTECT(cache_ptr, entry_ptr, fail_val) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( !((entry_ptr)->is_protected) ); \ - HDassert( !((entry_ptr)->is_read_only) ); \ - HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ - HDassert( (entry_ptr)->size > 0 ); \ - \ - if ( (entry_ptr)->is_pinned ) { \ - \ - H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->pel_head_ptr, \ - (cache_ptr)->pel_tail_ptr, \ - (cache_ptr)->pel_len, \ - (cache_ptr)->pel_size, (fail_val)) \ - \ - } else { \ - \ - /* modified LRU specific code */ \ - \ - /* remove the entry from the LRU list. */ \ - \ - H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - /* End modified LRU specific code. */ \ - } \ - \ - /* Regardless of the replacement policy, or whether the entry is \ - * pinned, now add the entry to the protected list. \ - */ \ - \ - H5C2__DLL_APPEND((entry_ptr), (cache_ptr)->pl_head_ptr, \ - (cache_ptr)->pl_tail_ptr, \ - (cache_ptr)->pl_len, \ - (cache_ptr)->pl_size, (fail_val)) \ -} /* H5C2__UPDATE_RP_FOR_PROTECT */ - -#endif /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ - - -/*------------------------------------------------------------------------- - * - * Macro: H5C2__UPDATE_RP_FOR_RENAME - * - * Purpose: Update the replacement policy data structures for a - * rename of the specified cache entry. - * - * 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, 5/17/04 - * - * Modifications: - * - * JRM - 7/27/04 - * Converted the function H5C2_update_rp_for_rename() to the - * macro H5C2__UPDATE_RP_FOR_RENAME in an effort to squeeze - * a bit more performance out of the cache. - * - * At least for the first cut, I am leaving the comments and - * white space in the macro. If they cause dificulties with - * pre-processor, I'll have to remove them. - * - * JRM - 7/28/04 - * Split macro into two version, one supporting the clean and - * dirty LRU lists, and the other not. Yet another attempt - * at optimization. - * - * JRM - 6/23/05 - * Added the was_dirty parameter. It is possible that - * the entry was clean when it was renamed -- if so it - * it is in the clean LRU regardless of the current - * value of the is_dirty field. - * - * At present, all renamed entries are forced to be - * dirty. This macro is a bit more general that that, - * to allow it to function correctly should that policy - * be relaxed in the future. - * - * JRM - 3/17/06 - * Modified macro to do nothing if the entry is pinned. - * In this case, the entry is on the pinned entry list, not - * in the replacement policy data structures, so there is - * nothing to be done. - * - * JRM - 3/28/07 - * Added sanity checks using the new is_read_only and - * ro_ref_count fields of struct H5C2_cache_entry_t. - * - *------------------------------------------------------------------------- - */ - -#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS - -#define H5C2__UPDATE_RP_FOR_RENAME(cache_ptr, entry_ptr, was_dirty, fail_val) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( !((entry_ptr)->is_protected) ); \ - HDassert( !((entry_ptr)->is_read_only) ); \ - HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ - HDassert( (entry_ptr)->size > 0 ); \ - \ - if ( ! ((entry_ptr)->is_pinned) ) { \ - \ - /* modified LRU specific code */ \ - \ - /* remove the entry from the LRU list, and re-insert it at the head. \ - */ \ - \ - H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - /* remove the entry from either the clean or dirty LUR list as \ - * indicated by the was_dirty parameter \ - */ \ - if ( was_dirty ) { \ - \ - H5C2__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ - (cache_ptr)->dLRU_tail_ptr, \ - (cache_ptr)->dLRU_list_len, \ - (cache_ptr)->dLRU_list_size, (fail_val)) \ - \ - } else { \ - \ - H5C2__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ - (cache_ptr)->cLRU_tail_ptr, \ - (cache_ptr)->cLRU_list_len, \ - (cache_ptr)->cLRU_list_size, (fail_val)) \ - } \ - \ - /* insert the entry at the head of either the clean or dirty LRU \ - * list as appropriate. \ - */ \ - \ - if ( (entry_ptr)->is_dirty ) { \ - \ - H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ - (cache_ptr)->dLRU_tail_ptr, \ - (cache_ptr)->dLRU_list_len, \ - (cache_ptr)->dLRU_list_size, (fail_val)) \ - \ - } else { \ - \ - H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ - (cache_ptr)->cLRU_tail_ptr, \ - (cache_ptr)->cLRU_list_len, \ - (cache_ptr)->cLRU_list_size, (fail_val)) \ - } \ - \ - /* End modified LRU specific code. */ \ - } \ -} /* H5C2__UPDATE_RP_FOR_RENAME */ - -#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ - -#define H5C2__UPDATE_RP_FOR_RENAME(cache_ptr, entry_ptr, was_dirty, fail_val) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( !((entry_ptr)->is_protected) ); \ - HDassert( !((entry_ptr)->is_read_only) ); \ - HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ - HDassert( (entry_ptr)->size > 0 ); \ - \ - if ( ! ((entry_ptr)->is_pinned) ) { \ - \ - /* modified LRU specific code */ \ - \ - /* remove the entry from the LRU list, and re-insert it at the head. \ - */ \ - \ - H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - /* End modified LRU specific code. */ \ - } \ -} /* H5C2__UPDATE_RP_FOR_RENAME */ - -#endif /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ - - -/*------------------------------------------------------------------------- - * - * Macro: H5C2__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: - * - * JRM -- 3/28/07 - * Added sanity checks based on the new is_read_only and - * ro_ref_count fields of struct H5C2_cache_entry_t. - * - *------------------------------------------------------------------------- - */ - -#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS - -#define H5C2__UPDATE_RP_FOR_SIZE_CHANGE(cache_ptr, entry_ptr, new_size) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( !((entry_ptr)->is_protected) ); \ - HDassert( !((entry_ptr)->is_read_only) ); \ - HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ - HDassert( (entry_ptr)->size > 0 ); \ - HDassert( new_size > 0 ); \ - \ - if ( (entry_ptr)->is_pinned ) { \ - \ - H5C2__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 */ \ - \ - H5C2__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 ) { \ - \ - H5C2__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->dLRU_list_len, \ - (cache_ptr)->dLRU_list_size, \ - (entry_ptr)->size, \ - (new_size)); \ - \ - } else { \ - \ - H5C2__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. */ \ - } \ - \ -} /* H5C2__UPDATE_RP_FOR_SIZE_CHANGE */ - -#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ - -#define H5C2__UPDATE_RP_FOR_SIZE_CHANGE(cache_ptr, entry_ptr, new_size) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( !((entry_ptr)->is_protected) ); \ - HDassert( !((entry_ptr)->is_read_only) ); \ - HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ - HDassert( (entry_ptr)->size > 0 ); \ - HDassert( new_size > 0 ); \ - \ - if ( (entry_ptr)->is_pinned ) { \ - \ - H5C2__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 */ \ - \ - H5C2__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. */ \ - } \ - \ -} /* H5C2__UPDATE_RP_FOR_SIZE_CHANGE */ - -#endif /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ - - -/*------------------------------------------------------------------------- - * - * Macro: H5C2__UPDATE_RP_FOR_UNPIN - * - * Purpose: Update the replacement policy data structures for an - * unpin of the specified cache entry. - * - * To do this, unlink the specified entry from the protected - * entry list, and re-insert it in the data structures used - * by the current replacement policy. - * - * 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 macro - * should switch on the current policy and act accordingly. - * - * Return: N/A - * - * Programmer: John Mainzer, 3/22/06 - * - * Modifications: - * - * JRM -- 3/28/07 - * Added sanity checks based on the new is_read_only and - * ro_ref_count fields of struct H5C2_cache_entry_t. - * - *------------------------------------------------------------------------- - */ - -#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS - -#define H5C2__UPDATE_RP_FOR_UNPIN(cache_ptr, entry_ptr, fail_val) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( !((entry_ptr)->is_protected) ); \ - HDassert( !((entry_ptr)->is_read_only) ); \ - HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ - HDassert( (entry_ptr)->is_pinned); \ - HDassert( (entry_ptr)->size > 0 ); \ - \ - /* Regardless of the replacement policy, remove the entry from the \ - * pinned entry list. \ - */ \ - H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->pel_head_ptr, \ - (cache_ptr)->pel_tail_ptr, (cache_ptr)->pel_len, \ - (cache_ptr)->pel_size, (fail_val)) \ - \ - /* modified LRU specific code */ \ - \ - /* insert the entry at the head of the LRU list. */ \ - \ - H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - /* Similarly, insert the entry at the head of either the clean or \ - * dirty LRU list as appropriate. \ - */ \ - \ - if ( (entry_ptr)->is_dirty ) { \ - \ - H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ - (cache_ptr)->dLRU_tail_ptr, \ - (cache_ptr)->dLRU_list_len, \ - (cache_ptr)->dLRU_list_size, (fail_val)) \ - \ - } else { \ - \ - H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ - (cache_ptr)->cLRU_tail_ptr, \ - (cache_ptr)->cLRU_list_len, \ - (cache_ptr)->cLRU_list_size, (fail_val)) \ - } \ - \ - /* End modified LRU specific code. */ \ - \ -} /* H5C2__UPDATE_RP_FOR_UNPIN */ - -#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ - -#define H5C2__UPDATE_RP_FOR_UNPIN(cache_ptr, entry_ptr, fail_val) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( !((entry_ptr)->is_protected) ); \ - HDassert( !((entry_ptr)->is_read_only) ); \ - HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ - HDassert( (entry_ptr)->is_pinned); \ - HDassert( (entry_ptr)->size > 0 ); \ - \ - /* Regardless of the replacement policy, remove the entry from the \ - * pinned entry list. \ - */ \ - H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->pel_head_ptr, \ - (cache_ptr)->pel_tail_ptr, (cache_ptr)->pel_len, \ - (cache_ptr)->pel_size, (fail_val)) \ - \ - /* modified LRU specific code */ \ - \ - /* insert the entry at the head of the LRU list. */ \ - \ - H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - /* End modified LRU specific code. */ \ - \ -} /* H5C2__UPDATE_RP_FOR_UNPIN */ - -#endif /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ - - -/*------------------------------------------------------------------------- - * - * Macro: H5C2__UPDATE_RP_FOR_UNPROTECT - * - * Purpose: Update the replacement policy data structures for an - * unprotect of the specified cache entry. - * - * To do this, unlink the specified entry from the protected - * list, and re-insert it in the data structures used by the - * current replacement policy. - * - * 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, 5/19/04 - * - * Modifications: - * - * JRM - 7/27/04 - * Converted the function H5C2_update_rp_for_unprotect() to - * the macro H5C2__UPDATE_RP_FOR_UNPROTECT in an effort to - * squeeze a bit more performance out of the cache. - * - * At least for the first cut, I am leaving the comments and - * white space in the macro. If they cause dificulties with - * pre-processor, I'll have to remove them. - * - * JRM - 7/28/04 - * Split macro into two version, one supporting the clean and - * dirty LRU lists, and the other not. Yet another attempt - * at optimization. - * - * JRM - 3/17/06 - * Modified macro to put pinned entries on the pinned entry - * list instead of inserting them in the data structures - * maintained by the replacement policy. - * - *------------------------------------------------------------------------- - */ - -#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS - -#define H5C2__UPDATE_RP_FOR_UNPROTECT(cache_ptr, entry_ptr, fail_val) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( (entry_ptr)->is_protected); \ - HDassert( (entry_ptr)->size > 0 ); \ - \ - /* Regardless of the replacement policy, remove the entry from the \ - * protected list. \ - */ \ - H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->pl_head_ptr, \ - (cache_ptr)->pl_tail_ptr, (cache_ptr)->pl_len, \ - (cache_ptr)->pl_size, (fail_val)) \ - \ - if ( (entry_ptr)->is_pinned ) { \ - \ - H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->pel_head_ptr, \ - (cache_ptr)->pel_tail_ptr, \ - (cache_ptr)->pel_len, \ - (cache_ptr)->pel_size, (fail_val)) \ - \ - } else { \ - \ - /* modified LRU specific code */ \ - \ - /* insert the entry at the head of the LRU list. */ \ - \ - H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - /* Similarly, insert the entry at the head of either the clean or \ - * dirty LRU list as appropriate. \ - */ \ - \ - if ( (entry_ptr)->is_dirty ) { \ - \ - H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ - (cache_ptr)->dLRU_tail_ptr, \ - (cache_ptr)->dLRU_list_len, \ - (cache_ptr)->dLRU_list_size, (fail_val)) \ - \ - } else { \ - \ - H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ - (cache_ptr)->cLRU_tail_ptr, \ - (cache_ptr)->cLRU_list_len, \ - (cache_ptr)->cLRU_list_size, (fail_val)) \ - } \ - \ - /* End modified LRU specific code. */ \ - } \ - \ -} /* H5C2__UPDATE_RP_FOR_UNPROTECT */ - -#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ - -#define H5C2__UPDATE_RP_FOR_UNPROTECT(cache_ptr, entry_ptr, fail_val) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( (entry_ptr)->is_protected); \ - HDassert( (entry_ptr)->size > 0 ); \ - \ - /* Regardless of the replacement policy, remove the entry from the \ - * protected list. \ - */ \ - H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->pl_head_ptr, \ - (cache_ptr)->pl_tail_ptr, (cache_ptr)->pl_len, \ - (cache_ptr)->pl_size, (fail_val)) \ - \ - if ( (entry_ptr)->is_pinned ) { \ - \ - H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->pel_head_ptr, \ - (cache_ptr)->pel_tail_ptr, \ - (cache_ptr)->pel_len, \ - (cache_ptr)->pel_size, (fail_val)) \ - \ - } else { \ - \ - /* modified LRU specific code */ \ - \ - /* insert the entry at the head of the LRU list. */ \ - \ - H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, \ - (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - /* End modified LRU specific code. */ \ - } \ -} /* H5C2__UPDATE_RP_FOR_UNPROTECT */ - -#endif /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ - - /* * Private file-scope variables. */ @@ -2867,18 +426,27 @@ done: * Added initialization for metadata journaling related * fields in H5C2_t. * + * JRM -- 3/26/08 + * Added dxpl_id and journal_recovered parameters. Also + * added code to test to see if the file is marked as having + * journaling in progress, and fail if it does unless + * the journal_recovered parameter is TRUE. + * *------------------------------------------------------------------------- */ H5C2_t * -H5C2_create(size_t max_cache_size, +H5C2_create(H5F_t * f, + hid_t dxpl_id, + size_t max_cache_size, size_t min_clean_size, int max_type_id, const char * (* type_name_table_ptr), H5C2_write_permitted_func_t check_write_permitted, hbool_t write_permitted, H5C2_log_flush_func_t log_flush, - void * aux_ptr) + void * aux_ptr, + hbool_t journal_recovered) { int i; H5C2_t * cache_ptr = NULL; @@ -2913,8 +481,9 @@ H5C2_create(size_t max_cache_size, HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, NULL, "can't create skip list.") } - /* If we get this far, we should succeed. Go ahead and initialize all - * the fields. + /* If we get this far, we should succeed unless we detect journaling + * that was not cleaned up properly. Go ahead and initialize all + * the fields as we will need some of them for the journaling check. */ cache_ptr->magic = H5C2__H5C2_T_MAGIC; @@ -3056,12 +625,25 @@ H5C2_create(size_t max_cache_size, /* metadata journaling related fields */ cache_ptr->mdj_enabled = FALSE; + cache_ptr->trans_in_progress = FALSE; + cache_ptr->trans_api_name[0] = '\0'; + cache_ptr->trans_num = 0; + cache_ptr->last_trans_on_disk = 0; cache_ptr->mdj_file_name_ptr = NULL; cache_ptr->mdj_conf_block_addr = HADDR_UNDEF; cache_ptr->mdj_conf_block_len = 0; cache_ptr->mdj_conf_block_ptr = NULL; (cache_ptr->mdj_jbrb).magic = H5C2__H5C2_JBRB_T_MAGIC; + cache_ptr->tl_len = 0; + cache_ptr->tl_size = 0; + cache_ptr->tl_head_ptr = NULL; + cache_ptr->tl_tail_ptr = NULL; + cache_ptr->jwipl_len = 0; + cache_ptr->jwipl_size = 0; + cache_ptr->jwipl_head_ptr = NULL; + cache_ptr->jwipl_tail_ptr = NULL; + if ( H5C2_reset_cache_hit_rate_stats(cache_ptr) != SUCCEED ) { @@ -3076,6 +658,19 @@ H5C2_create(size_t max_cache_size, cache_ptr->skip_dxpl_id_checks = FALSE; cache_ptr->prefix[0] = '\0'; /* empty string */ + /* test to see if there is a metadata journal that must be recovered + * before we can access the file. Do this now after the cache is + * initialized, as the code for this test assumes a functional + * cache. + */ + + if ( H5C2_check_for_journaling(f, dxpl_id, cache_ptr, journal_recovered) + != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, NULL, \ + "H5C2_check_for_journaling() reports failure.") + } + /* Set return value */ ret_value = cache_ptr; @@ -3436,6 +1031,11 @@ done: * The function lost its file pointer (now passed in the * *cache_ptr), and one of the dxpl ids. * + * JRM -- 4/3/08 + * I don't think we need to do anything on an expunge + * vis-a-vis journaling. Comment is here just to make + * note of the fact that I have reviewed this function. + * *------------------------------------------------------------------------- */ @@ -3446,13 +1046,18 @@ H5C2_expunge_entry(H5F_t * f, haddr_t addr) { /* const char * fcn_name = "H5C2_expunge_entry()"; */ - H5C2_t * cache_ptr = f->shared->cache2; + H5C2_t * cache_ptr; herr_t result; herr_t ret_value = SUCCEED; /* Return value */ H5C2_cache_entry_t * entry_ptr = NULL; FUNC_ENTER_NOAPI(H5C2_expunge_entry, FAIL) + HDassert( f ); + HDassert( f->shared ); + + cache_ptr = f->shared->cache2; + HDassert( H5F_addr_defined(addr) ); HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); @@ -3638,6 +1243,9 @@ done: * but one can argue that I should just scream and die if I * ever detect the condidtion. * + * JRM -- 4/10/08 + * Added code to support journaling. + * *------------------------------------------------------------------------- */ herr_t @@ -3645,7 +1253,7 @@ H5C2_flush_cache(H5F_t *f, hid_t dxpl_id, unsigned flags) { - H5C2_t * cache_ptr = f->shared->cache2; + H5C2_t * cache_ptr; herr_t status; herr_t ret_value = SUCCEED; hbool_t destroy; @@ -3667,6 +1275,11 @@ H5C2_flush_cache(H5F_t *f, FUNC_ENTER_NOAPI(H5C2_flush_cache, FAIL) + HDassert( f ); + HDassert( f->shared ); + + cache_ptr = f->shared->cache2; + HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); HDassert( cache_ptr->skip_file_checks || f); @@ -3686,6 +1299,17 @@ H5C2_flush_cache(H5F_t *f, HDassert( ! ( cache_ptr->flush_in_progress ) ); + if ( cache_ptr->mdj_enabled ) { + + status = H5C2_journal_pre_flush(cache_ptr); + + if ( status != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "H5C2_journal_pre_flush() failed.") + } + } + cache_ptr->flush_in_progress = TRUE; if ( destroy ) { @@ -3971,7 +1595,19 @@ H5C2_flush_cache(H5F_t *f, } #endif /* H5C2_DO_SANITY_CHECKS */ - } + } + + if ( cache_ptr->mdj_enabled ) { + + status = H5C2_journal_post_flush(cache_ptr, + (hbool_t)(flush_marked_entries == FALSE)); + + if ( status != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "H5C2_journal_post_flush() failed.") + } + } done: @@ -4044,7 +1680,7 @@ herr_t H5C2_flush_to_min_clean(H5F_t * f, hid_t dxpl_id) { - H5C2_t * cache_ptr = f->shared->cache2; + H5C2_t * cache_ptr; herr_t result; herr_t ret_value = SUCCEED; hbool_t write_permitted; @@ -4059,6 +1695,11 @@ H5C2_flush_to_min_clean(H5F_t * f, FUNC_ENTER_NOAPI(H5C2_flush_to_min_clean, FAIL) + HDassert( f ); + HDassert( f->shared ); + + cache_ptr = f->shared->cache2; + HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); HDassert( cache_ptr->skip_file_checks || f ); @@ -4426,18 +2067,23 @@ H5C2_get_entry_status(H5F_t * f, hbool_t * is_pinned_ptr) { /* const char * fcn_name = "H5C2_get_entry_status()"; */ - H5C2_t * cache_ptr = f->shared->cache2; + H5C2_t * cache_ptr; herr_t ret_value = SUCCEED; /* Return value */ H5C2_cache_entry_t * entry_ptr = NULL; FUNC_ENTER_NOAPI(H5C2_get_entry_status, FAIL) + HDassert( f ); + HDassert( f->shared ); + + cache_ptr = f->shared->cache2; + HDassert( cache_ptr != NULL ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); HDassert( H5F_addr_defined(addr) ); HDassert( in_cache_ptr != NULL ); - /* this test duplicates tow of the above asserts, but we need an + /* this test duplicates two of the above asserts, but we need an * invocation of HGOTO_ERROR to keep the compiler happy. */ if ( ( cache_ptr == NULL ) || ( cache_ptr->magic != H5C2__H5C2_T_MAGIC ) ) { @@ -4670,6 +2316,12 @@ done: * JRM -- 12/31/07 * Added code supporting flash cache size increases. * + * JRM -- 3/26/08 + * Added code initializing the journaling related fields. + * Also added code to set the new entries last_trans field + * to the current transaction number and insert the entry + * in the transaction list if journaling is enabled. + * *------------------------------------------------------------------------- */ @@ -4683,7 +2335,7 @@ H5C2_insert_entry(H5F_t * f, unsigned int flags) { /* const char * fcn_name = "H5C2_insert_entry()"; */ - H5C2_t * cache_ptr = f->shared->cache2; + H5C2_t * cache_ptr; herr_t result; herr_t ret_value = SUCCEED; /* Return value */ hbool_t insert_pinned; @@ -4694,9 +2346,16 @@ H5C2_insert_entry(H5F_t * f, FUNC_ENTER_NOAPI(H5C2_insert_entry, FAIL) + HDassert( f ); + HDassert( f->shared ); + + cache_ptr = f->shared->cache2; + HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); HDassert( cache_ptr->skip_file_checks || f ); + HDassert( ( ! ( cache_ptr->mdj_enabled ) ) || + ( cache_ptr->trans_in_progress ) ); HDassert( type ); HDassert( H5F_addr_defined(addr) ); HDassert( thing ); @@ -4754,6 +2413,10 @@ H5C2_insert_entry(H5F_t * f, entry_ptr->aux_next = NULL; entry_ptr->aux_prev = NULL; + entry_ptr->last_trans = 0; + entry_ptr->trans_next = NULL; + entry_ptr->trans_prev = NULL; + H5C2__RESET_CACHE_ENTRY_STATS(entry_ptr) if ( ( cache_ptr->flash_size_increase_possible ) && @@ -4888,6 +2551,9 @@ H5C2_insert_entry(H5F_t * f, entry_ptr->flush_marker = FALSE; } + /* insert the entry in the transaction list if journaling is enabled */ + H5C2__INSERT_ENTRY_IN_TL(cache_ptr, entry_ptr, FAIL); + H5C2__UPDATE_RP_FOR_INSERTION(cache_ptr, entry_ptr, FAIL) #if H5C2_DO_EXTREME_SANITY_CHECKS @@ -5012,6 +2678,7 @@ H5C2_mark_entries_as_clean(H5F_t * f, FUNC_ENTER_NOAPI(H5C2_mark_entries_as_clean, FAIL) HDassert( f ); + HDassert( f->shared ); cache_ptr = f->shared->cache2; HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); @@ -5264,6 +2931,15 @@ done: * appropriate. * JRM -- 1/11/08 * + * Added code to either insert the entry at the head of + * the transaction list (if it isn't in the list already), or + * move it to the head of the transaction list (if it is + * on the transaction list) if journaling is enabled. In this + * case, set the entry's last_trans field to the current + * transaction number if it isn't set to this value already. + * + * JRM -- 3/31/08 + * *------------------------------------------------------------------------- */ @@ -5273,7 +2949,7 @@ H5C2_mark_pinned_entry_dirty(H5F_t * f, hbool_t size_changed, size_t new_size) { - H5C2_t * cache_ptr = f->shared->cache2; + H5C2_t * cache_ptr; herr_t ret_value = SUCCEED; /* Return value */ herr_t result; size_t size_increase; @@ -5281,8 +2957,15 @@ H5C2_mark_pinned_entry_dirty(H5F_t * f, FUNC_ENTER_NOAPI(H5C2_mark_pinned_entry_dirty, FAIL) + HDassert( f ); + HDassert( f->shared ); + + cache_ptr = f->shared->cache2; + HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); + HDassert( ( ! ( cache_ptr->mdj_enabled ) ) || + ( cache_ptr->trans_in_progress ) ); HDassert( thing ); HDassert( ( size_changed == TRUE ) || ( size_changed == FALSE ) ); @@ -5329,7 +3012,7 @@ H5C2_mark_pinned_entry_dirty(H5F_t * f, } } - /* update the protected entry list */ + /* update the pinned entry list */ H5C2__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr->pel_len), \ (cache_ptr->pel_size), \ (entry_ptr->size), (new_size)); @@ -5345,9 +3028,15 @@ H5C2_mark_pinned_entry_dirty(H5F_t * f, (new_size)); } + /* if journaling is enabled, and the entry is already in the + * transaction list, update that list for the size change as well. + */ + H5C2__UPDATE_TL_FOR_ENTRY_SIZE_CHANGE((cache_ptr), (entry_ptr), \ + (entry_ptr->size), (new_size)); + /* update statistics just before changing the entry size */ H5C2__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE((cache_ptr), (entry_ptr), \ - (new_size)); + (new_size)); /* finally, update the entry size proper */ entry_ptr->size = new_size; @@ -5358,6 +3047,12 @@ H5C2_mark_pinned_entry_dirty(H5F_t * f, H5C2__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL) } + /* if journaling is enabled, check to see if the entry is in the + * transaction list. If it isn't, insert it. If it is, move it to + * the head of the list. + */ + H5C2__UPDATE_TL_FOR_ENTRY_DIRTY(cache_ptr, entry_ptr, FAIL) + H5C2__UPDATE_STATS_FOR_DIRTY_PIN(cache_ptr, entry_ptr) done: @@ -5398,18 +3093,27 @@ done: * it once we deal with the problem of entries being protected * read only, and then dirtied. * + * JRM -- 3/31/08 + * Updated function to maintain the transaction list when + * journaling is enabled. + * *------------------------------------------------------------------------- */ herr_t H5C2_mark_pinned_or_protected_entry_dirty(H5F_t * f, void * thing) { - H5C2_t * cache_ptr = f->shared->cache2; + H5C2_t * cache_ptr; herr_t ret_value = SUCCEED; /* Return value */ H5C2_cache_entry_t * entry_ptr; FUNC_ENTER_NOAPI(H5C2_mark_pinned_or_protected_entry_dirty, FAIL) + HDassert( f ); + HDassert( f->shared ); + + cache_ptr = f->shared->cache2; + HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); HDassert( thing ); @@ -5423,11 +3127,20 @@ H5C2_mark_pinned_or_protected_entry_dirty(H5F_t * f, /* set the dirtied flag */ entry_ptr->dirtied = TRUE; + /* don't do anything with the transaction list now, as the + * entry will be added to the transaction list when it is + * unprotected. + */ + } else if ( entry_ptr->is_pinned ) { /* mark the entry as dirty if it isn't already */ entry_ptr->is_dirty = TRUE; + /* If journaling is enabled, must add the entry to the transaction + * list, if it is not there already. + */ + H5C2__UPDATE_TL_FOR_ENTRY_DIRTY(cache_ptr, entry_ptr, FAIL); if ( ! (entry_ptr->in_slist) ) { @@ -5438,8 +3151,8 @@ H5C2_mark_pinned_or_protected_entry_dirty(H5F_t * f, } else { - HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, \ - "Entry is neither pinned nor protected??") + HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, \ + "Entry is neither pinned nor protected??") } done: @@ -5479,7 +3192,7 @@ done: * Updated function to support renaming of pinned entries. * * JRM -- 8/24/06 - * Updated function to refrain from alterning the index, the + * Updated function to refrain from altering 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. @@ -5492,6 +3205,17 @@ done: * now handled by H5C2_flush_single_entry() -- hence the above * modification is now obsolete. * + * JRM -- 3/31/08 + * Updated function to check if journaling is enabled. If + * it is, the function now inserts the renamed entry in the + * transaction list (if it wasn't there already). + * + * Also added sanity checks that will scream and die if + * we attempt to rename an entry during either a destroy + * or flush if journaling is enabled. Recall that any + * rename should have already been triggered when the + * entry was serialized to construct its journal entry. + * *------------------------------------------------------------------------- */ @@ -5503,6 +3227,7 @@ H5C2_rename_entry(H5C2_t * cache_ptr, { herr_t ret_value = SUCCEED; /* Return value */ hbool_t was_dirty; + hbool_t had_jwip; H5C2_cache_entry_t * entry_ptr = NULL; H5C2_cache_entry_t * test_entry_ptr = NULL; #if H5C2_DO_SANITY_CHECKS @@ -5543,6 +3268,20 @@ H5C2_rename_entry(H5C2_t * cache_ptr, "Target entry is protected.") } + if ( ( entry_ptr->destroy_in_progress ) && + ( cache_ptr->mdj_enabled ) ) + { + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "rename on destroy when journaling is enabled.\n"); + } + + if ( ( entry_ptr->flush_in_progress ) && + ( cache_ptr->mdj_enabled ) ) + { + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "rename on flush when journaling is enabled.\n"); + } + H5C2__SEARCH_INDEX(cache_ptr, new_addr, test_entry_ptr, FAIL) if ( test_entry_ptr != NULL ) { /* we are hosed */ @@ -5629,7 +3368,19 @@ H5C2_rename_entry(H5C2_t * cache_ptr, #endif /* H5C2_DO_SANITY_CHECKS */ - H5C2__UPDATE_RP_FOR_RENAME(cache_ptr, entry_ptr, was_dirty, FAIL) + /* make note of whether the target entry had a journal write + * in progress -- will need this fact to update the replacement + * policy structures for the rename. + */ + had_jwip = ( entry_ptr->last_trans != 0 ); + + /* If journaling is enabled, add the entry to the transaction + * list, if it isn't there already. + */ + H5C2__UPDATE_TL_FOR_ENTRY_DIRTY(cache_ptr, entry_ptr, FAIL); + + H5C2__UPDATE_RP_FOR_RENAME(cache_ptr, entry_ptr, was_dirty, \ + had_jwip, FAIL); } } @@ -5679,14 +3430,19 @@ H5C2_resize_pinned_entry(H5F_t * f, size_t new_size) { /* const char * fcn_name = "H5C2_resize_pinned_entry()"; */ - H5C2_t * cache_ptr = f->shared->cache2; + H5C2_t * cache_ptr; herr_t ret_value = SUCCEED; /* Return value */ herr_t result; H5C2_cache_entry_t * entry_ptr; - size_t size_increase; + size_t size_increase; FUNC_ENTER_NOAPI(H5C2_resize_pinned_entry, FAIL) + HDassert( f ); + HDassert( f->shared ); + + cache_ptr = f->shared->cache2; + HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); HDassert( thing ); @@ -5818,12 +3574,17 @@ H5C2_pin_protected_entry(H5F_t UNUSED * f, void * thing) #endif { - H5C2_t *cache_ptr = f->shared->cache2; - herr_t ret_value = SUCCEED; /* Return value */ - H5C2_cache_entry_t * entry_ptr; + H5C2_t * cache_ptr; + herr_t ret_value = SUCCEED; /* Return value */ + H5C2_cache_entry_t * entry_ptr; FUNC_ENTER_NOAPI(H5C2_pin_protected_entry, FAIL) + HDassert( f ); + HDassert( f->shared ); + + cache_ptr = f->shared->cache2; + HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); HDassert( thing ); @@ -5944,6 +3705,11 @@ done: * Added to do a flash cache size increase if appropriate * when a large entry is loaded. * + * JRM 3/31/08 + * Updated function to insert the newly protected entry in + * the transaction list if journaling is enabled and the + * entry was dirtied on load. + * *------------------------------------------------------------------------- */ @@ -5957,7 +3723,7 @@ H5C2_protect(H5F_t * f, unsigned flags) { /* const char * fcn_name = "H5C2_protect()"; */ - H5C2_t * cache_ptr = f->shared->cache2; + H5C2_t * cache_ptr; hbool_t hit; hbool_t first_flush; hbool_t have_write_permitted = FALSE; @@ -5972,6 +3738,11 @@ H5C2_protect(H5F_t * f, FUNC_ENTER_NOAPI(H5C2_protect, NULL) /* check args */ + HDassert( f ); + HDassert( f->shared ); + + cache_ptr = f->shared->cache2; + HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); HDassert( cache_ptr->skip_file_checks || f ); @@ -6136,6 +3907,16 @@ H5C2_protect(H5F_t * f, H5C2__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, NULL) } + /* under rare (we hope) circumstances, the load routine will + * modify an entry as it loads it to repair corruption from + * a previous version of the library. If this happens, we must + * place the entry on the transaction list. + */ + if ( entry_ptr->is_dirty ) { + + H5C2__INSERT_ENTRY_IN_TL(cache_ptr, entry_ptr, NULL); + } + /* insert the entry in the data structures used by the replacement * policy. We are just going to take it out again when we update * the replacement policy for a protect, but this simplifies the @@ -6353,7 +4134,7 @@ H5C2_set_cache_auto_resize_config(const H5F_t * f, H5C2_auto_size_ctl_t *config_ptr) { /* const char *fcn_name = "H5C2_set_cache_auto_resize_config()"; */ - H5C2_t * cache_ptr = f->shared->cache2; + H5C2_t * cache_ptr; herr_t ret_value = SUCCEED; /* Return value */ herr_t result; size_t new_max_cache_size; @@ -6361,6 +4142,11 @@ H5C2_set_cache_auto_resize_config(const H5F_t * f, FUNC_ENTER_NOAPI(H5C2_set_cache_auto_resize_config, FAIL) + HDassert( f ); + HDassert( f->shared ); + + cache_ptr = f->shared->cache2; + if ( ( cache_ptr == NULL ) || ( cache_ptr->magic != H5C2__H5C2_T_MAGIC ) ) { HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad cache_ptr on entry.") @@ -6637,11 +4423,16 @@ herr_t H5C2_set_evictions_enabled(const H5F_t * f, hbool_t evictions_enabled) { - H5C2_t * cache_ptr = f->shared->cache2; + H5C2_t * cache_ptr; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5C2_set_evictions_enabled, FAIL) + HDassert( f ); + HDassert( f->shared ); + + cache_ptr = f->shared->cache2; + if ( ( cache_ptr == NULL ) || ( cache_ptr->magic != H5C2__H5C2_T_MAGIC ) ) { HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad cache_ptr on entry.") @@ -7384,12 +5175,17 @@ herr_t H5C2_unpin_entry(H5F_t * f, void * thing) { - H5C2_t *cache_ptr = f->shared->cache2; + H5C2_t *cache_ptr; herr_t ret_value = SUCCEED; /* Return value */ H5C2_cache_entry_t * entry_ptr; FUNC_ENTER_NOAPI(H5C2_unpin_entry, FAIL) + HDassert( f ); + HDassert( f->shared ); + + cache_ptr = f->shared->cache2; + HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); HDassert( thing ); @@ -7530,7 +5326,7 @@ H5C2_unprotect(H5F_t * f, size_t new_size) { /* const char * fcn_name = "H5C2_unprotect()"; */ - H5C2_t * cache_ptr = f->shared->cache2; + H5C2_t * cache_ptr; hbool_t deleted; hbool_t dirtied; hbool_t set_flush_marker; @@ -7561,6 +5357,11 @@ H5C2_unprotect(H5F_t * f, dirtied |= size_changed; + HDassert( f ); + HDassert( f->shared ); + + cache_ptr = f->shared->cache2; + HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); HDassert( cache_ptr->skip_file_checks || f ); @@ -10131,6 +7932,11 @@ done: * to disk. If dirty, the entry is removed from the slist * or not as requested. * + * JRM -- 3/31/08 + * If journaling is enabled, modified function to remove + * the target entry from the transaction list on a clear. + * Also added some sanity checks. + * *------------------------------------------------------------------------- */ @@ -10439,6 +8245,18 @@ H5C2_flush_single_entry(H5F_t * f, H5C2__UPDATE_RP_FOR_EVICTION(cache_ptr, entry_ptr, FAIL) } else { + /* If journaling is enabled, the target entry is being cleared, + * and it is on the transaction list, remove it from the transaction + * list and set its last_trans field to zero. + * + * Must do this now, as otherwise H5C2__UPDATE_RP_FOR_FLUSH may + * scream incorrectly about flushing an entry with a pending + * journal write. + */ + if ( clear_only ) { + H5C2__UPDATE_TL_FOR_ENTRY_CLEAR(cache_ptr, entry_ptr, FAIL); + } + /* We are either doing a flush or a clear. * * A clear and a flush are the same from the point of view of @@ -10484,8 +8302,6 @@ H5C2_flush_single_entry(H5F_t * f, * or a flush destroy. In either case, serialize the * entry and write it to disk. * - * If the entry is clean, we do nothing at this point. - * * If the serialize function changes the size or location * of the entry, and we are not doing a flush destroy, we * will have to touch up the cache to account for the @@ -10530,6 +8346,12 @@ H5C2_flush_single_entry(H5F_t * f, { if ( destroy ) { + if ( cache_ptr->mdj_enabled ) { + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "rename/resize on destroy when journaling enabled."); + } + /* We have already removed the entry from the * cache's data structures, so no need to update * them for the re-size and/or rename. All we need @@ -10570,6 +8392,12 @@ H5C2_flush_single_entry(H5F_t * f, } else { + if ( cache_ptr->mdj_enabled ) { + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "rename/resize on flush when journaling enabled."); + } + /* The entry is not being destroyed, and thus has not * been removed from the cache's data structures. * @@ -10816,6 +8644,10 @@ done: * JRM -- 10/12/07 * Added initialization for the new magic field. * + * JRM -- 3/26/08 + * Added initialization for the journaling related + * fields. + * *------------------------------------------------------------------------- */ @@ -10948,6 +8780,10 @@ H5C2_load_entry(H5F_t * f, entry_ptr->aux_next = NULL; entry_ptr->aux_prev = NULL; + entry_ptr->last_trans = 0; + entry_ptr->trans_next = NULL; + entry_ptr->trans_prev = NULL; + H5C2__RESET_CACHE_ENTRY_STATS(entry_ptr); ret_value = thing; diff --git a/src/H5C2journal.c b/src/H5C2journal.c index 27eabf7..53d0d71 100644 --- a/src/H5C2journal.c +++ b/src/H5C2journal.c @@ -46,13 +46,100 @@ #include "H5Fpkg.h" /* File access */ #include "H5C2pkg.h" /* Cache */ - + /**************************************************************************/ /************************* journaling code proper *************************/ /**************************************************************************/ /*------------------------------------------------------------------------- - * Function: H5C2__begin_transaction + * Function: H5C2_begin_journaling + * + * Purpose: Setup the metadata cache to begin journaling. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: John Mainzer + * March 26, 2008 + * + *------------------------------------------------------------------------- + */ + +herr_t +H5C2_begin_journaling(H5F_t * f, + hid_t dxpl_id, + H5C2_t * cache_ptr, + char * journal_file_name_ptr, + size_t buf_size, + int num_bufs, + hbool_t use_aio, + hbool_t human_readable) +{ + herr_t result; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5C2_begin_journaling, FAIL) + + HDassert( f != NULL ); + HDassert( f->name != NULL ); + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); + HDassert( cache_ptr->mdj_enabled == FALSE ); + HDassert( cache_ptr->trans_in_progress == FALSE ); + HDassert( cache_ptr->trans_num == 0 ); + HDassert( cache_ptr->last_trans_on_disk == 0 ); + HDassert( cache_ptr->tl_len == 0 ); + HDassert( cache_ptr->tl_size == 0 ); + HDassert( cache_ptr->tl_head_ptr == NULL ); + HDassert( cache_ptr->tl_tail_ptr == NULL ); + HDassert( cache_ptr->jwipl_len == 0 ); + HDassert( cache_ptr->jwipl_size == 0 ); + HDassert( cache_ptr->jwipl_head_ptr == NULL ); + HDassert( cache_ptr->jwipl_tail_ptr == NULL ); + HDassert( buf_size > 0 ); + HDassert( num_bufs > 0 ); + HDassert( journal_file_name_ptr != NULL ); + + if ( cache_ptr->mdj_enabled ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "metadata journaling already enabled on entry.") + } + + result = H5C2_jb__init(&(cache_ptr->mdj_jbrb), + f->name, + journal_file_name_ptr, + buf_size, + num_bufs, + use_aio, + human_readable); + + if ( result != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, "H5C2_jb__init() failed.") + } + + result = H5C2_mark_journaling_in_progress(f, + dxpl_id, + journal_file_name_ptr); + + if ( result != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_mark_journaling_in_progress() failed.") + } + + cache_ptr->mdj_enabled = TRUE; + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5C2_begin_journaling() */ + + +/*------------------------------------------------------------------------- + * Function: H5C2_begin_transaction * * Purpose: Handle book keeping for the beginning of a transaction, and * return the transaction ID assigned to the transaction in @@ -67,37 +154,136 @@ *------------------------------------------------------------------------- */ -/* This function is just a shell for now. -- JRM */ +herr_t +H5C2_begin_transaction(H5C2_t * cache_ptr, + uint64_t * trans_num_ptr, + const char * api_call_name) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5C2_begin_transaction, FAIL) + + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); + HDassert( cache_ptr->tl_len == 0 ); + HDassert( cache_ptr->tl_size == 0 ); + HDassert( cache_ptr->tl_head_ptr == NULL ); + HDassert( cache_ptr->tl_tail_ptr == NULL ); + HDassert( trans_num_ptr != NULL ); + HDassert( api_call_name != NULL ); + HDassert( HDstrlen(api_call_name) <= H5C2__MAX_API_NAME_LEN ); + + if ( cache_ptr->mdj_enabled ) { + + if ( cache_ptr->trans_in_progress ) { + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "transaction already in progress?.") + } + + HDstrncpy(cache_ptr->trans_api_name, api_call_name, + (size_t)H5C2__MAX_API_NAME_LEN); + cache_ptr->trans_num++; + + *trans_num_ptr = cache_ptr->trans_num; + + cache_ptr->trans_in_progress = TRUE; + } + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5C2_begin_transaction() */ + + +/*------------------------------------------------------------------------- + * Function: H5C2_end_journaling + * + * Purpose: Shutdown metadata journaling. + * + * To do this we must: + * + * 1) Flush the cache. This will also flush and truncate the + * journal file. + * + * 2) Mark the superblock to indicate that we are no longer + * journaling. + * + * 3) Tell the journal file write code to shutdown. This will + * also cause the journal file to be deleted. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: John Mainzer + * April 12, 2008 + * + *------------------------------------------------------------------------- + */ herr_t -H5C2__begin_transaction(H5C2_t * cache_ptr, - uint64_t * trans_num_ptr) +H5C2_end_journaling(H5F_t * f, + hid_t dxpl_id, + H5C2_t * cache_ptr) { + herr_t result; herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5C2__begin_transaction, FAIL) + FUNC_ENTER_NOAPI(H5C2_end_journaling, FAIL) + HDassert( f != NULL ); HDassert( cache_ptr != NULL ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); + HDassert( cache_ptr->mdj_enabled == TRUE ); + HDassert( cache_ptr->trans_in_progress == FALSE ); + HDassert( cache_ptr->tl_len == 0 ); + HDassert( cache_ptr->tl_size == 0 ); + HDassert( cache_ptr->tl_head_ptr == NULL ); + HDassert( cache_ptr->tl_tail_ptr == NULL ); + + if ( ! cache_ptr->mdj_enabled ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "metadata journaling not enabled on entry.") + } + + result = H5C2_flush_cache(f, dxpl_id, H5C2__NO_FLAGS_SET); + + if ( result < 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_flush_cache() failed.") + } - /* we need at least one error to keep the macros happy */ - if ( trans_num_ptr == NULL ) { + result = H5C2_unmark_journaling_in_progress(f, dxpl_id, cache_ptr); - HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ - "trans_num_ptr NULL on entry.") + if ( result < 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_unmark_journaling_in_progress() failed.") } - *trans_num_ptr = 1024; + result = H5C2_jb__takedown(&(cache_ptr->mdj_jbrb)); + + if ( result < 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__takedown() failed.") + } + + cache_ptr->mdj_enabled = FALSE; done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5C2__begin_transaction() */ +} /* H5C2_end_journaling() */ + /*------------------------------------------------------------------------- - * Function: H5C2__end_transaction + * Function: H5C2_end_transaction * * Purpose: Handle book keeping for the end of a transaction. * @@ -110,32 +296,638 @@ done: *------------------------------------------------------------------------- */ -/* This function is just a shell for now. -- JRM */ +herr_t +H5C2_end_transaction(H5F_t * f, + H5C2_t * cache_ptr, + uint64_t trans_num, + const char * api_call_name) +{ + uint64_t new_last_trans_on_disk = 0; + herr_t result; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5C2_end_transaction, FAIL) + + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); + HDassert( api_call_name != NULL ); + HDassert( HDstrlen(api_call_name) <= H5C2__MAX_API_NAME_LEN ); + HDassert( ( ! ( cache_ptr->mdj_enabled ) ) || + ( HDstrcmp(api_call_name, cache_ptr->trans_api_name) == 0 ) ); + + if ( cache_ptr->mdj_enabled ) { + + if ( ! ( cache_ptr->trans_in_progress ) ) { + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "transaction not in progress?!?!") + } + + if ( cache_ptr->trans_num != trans_num ) { + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "trans_num mis-match?!?!") + } + + /* if the transaction list is not empty, generate journal messages, + * and remove all entries from the transaction list. + */ + if ( cache_ptr->tl_len > 0 ) { + + result = H5C2_journal_transaction(f, cache_ptr); + + if ( result != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_journal_transaction() failed.") + } + } + + cache_ptr->trans_in_progress = FALSE; + + /* Get the last transaction on disk. If it has changed, remove + * all entries with completed journal writes from the journal write + * in progress list. + */ + + result = H5C2_jb__get_last_transaction_on_disk(&(cache_ptr->mdj_jbrb), + &new_last_trans_on_disk); + if ( result != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__get_last_transaction_on_disk() failed.") + } + + if ( cache_ptr->last_trans_on_disk < new_last_trans_on_disk ) { + + result = H5C2_update_for_new_last_trans_on_disk(cache_ptr, + new_last_trans_on_disk); + + if ( result != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_update_for_new_last_trans_on_disk() failed.") + } + } + } + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5C2_end_transaction() */ + + +/*------------------------------------------------------------------------- + * Function: H5C2_get_journal_config + * + * Purpose: Return the current metadata journaling status. + * + * If journaling is enabled, *journaling_enabled_ptr is + * set to TRUE, and the targets of the remaining pointer + * parameters will be set to reflect current journaling + * status if they are not NULL. + * + * If journaling is disabled, *journaling_enabled_ptr is set + * to FALSE, and the the targets of the remaining pointer + * parameters are not altered. + * + * The remaining parameters are discussed in detail below: + * + * journal_file_path_ptr is presumed to point to a buffer + * of length H5AC2__MAX_JOURNAL_FILE_NAME_LEN. If journaling + * is enabled, and the field is not null, the path to the + * journal file will be copied into this buffer to the + * extent that it fits. + * + * jbrb_buf_size_ptr is presumed to point to a size_t. If + * journaling is enabled and the field is not NULL, the size + * of the buffers used in the journal buffer ring buffer + * will be reported in *jbrb_buf_size_ptr. + * + * jbrb_num_bufs_ptr is presumed to point to an int. If + * journaling is enabled and the field is not NULL, the + * number of buffers in the ournal buffer ring buffer + * will be reported in *jbrb_num_bufs_ptr. + * + * jbrb_use_aio_ptr is presumed to point to a hbool_t. If + * journaling is enabled and the field is not NULL, + * *jbrb_use_aio_ptr will be set to true or false depending + * on whether the journal entry logging code has been + * instructed to use AIO. + * + * jbrb_human_readable_ptr is presumed to point to a hbool_t. If + * journaling is enabled and the field is not NULL, + * *jbrb_human_readable_ptr will be set to true or false depending + * on whether the journal entry logging code has been + * instructed to record the journal in human readable form. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: John Mainzer + * April 13, 2008 + * + *------------------------------------------------------------------------- + */ herr_t -H5C2__end_transaction(H5C2_t * cache_ptr, - uint64_t trans_num) +H5C2_get_journal_config(H5C2_t * cache_ptr, + hbool_t * journaling_enabled_ptr, + char * journal_file_path_ptr, + size_t * jbrb_buf_size_ptr, + int * jbrb_num_bufs_ptr, + hbool_t * jbrb_use_aio_ptr, + hbool_t * jbrb_human_readable_ptr) { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5C2__end_transaction, FAIL) + FUNC_ENTER_NOAPI(H5C2_get_journal_config, FAIL) + + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); + + if ( journaling_enabled_ptr == NULL ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "journaling_enabled_ptr NULL on entry!?!.") + } + + + if ( cache_ptr->mdj_enabled ) { + + *journaling_enabled_ptr = TRUE; + + if ( journal_file_path_ptr != NULL ) { + + HDsnprintf(journal_file_path_ptr, + H5AC2__MAX_JOURNAL_FILE_NAME_LEN, + "%s", + cache_ptr->mdj_file_name_ptr); + } + + if ( jbrb_buf_size_ptr != NULL ) { + + *jbrb_buf_size_ptr = (cache_ptr->mdj_jbrb).buf_size; + } + + if ( jbrb_num_bufs_ptr != NULL ) { + + *jbrb_num_bufs_ptr = (cache_ptr->mdj_jbrb).num_bufs; + } + + if ( jbrb_use_aio_ptr != NULL ) { + + *jbrb_use_aio_ptr = (cache_ptr->mdj_jbrb).use_aio; + } + + if ( jbrb_human_readable_ptr ) { + + *jbrb_human_readable_ptr = (cache_ptr->mdj_jbrb).human_readable; + } + + } else { + + *journaling_enabled_ptr = FALSE; + } + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5C2_get_journal_config() */ + + +/*------------------------------------------------------------------------- + * Function: H5C2_journal_post_flush() + * + * Purpose: Handle any journaling activities that are necessary + * after we flush the metadata cache. + * + * At present this means: + * + * 1) Verify that a transaction is still not in progress. + * + * 2) Verify that the journal write in progress list + * is still empty. + * + * 3) If the cache_is_clean parameter is true: + * + * a) Truncate the journal file + * + * b) Reset cache_ptr->trans_num and + * cache_ptr->last_trans_on_disk to zero. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: John Mainzer + * April 10, 2008 + * + *------------------------------------------------------------------------- + */ + +herr_t +H5C2_journal_post_flush(H5C2_t * cache_ptr, + hbool_t cache_is_clean) +{ + herr_t result; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5C2_journal_post_flush, FAIL) + + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); + HDassert( cache_ptr->mdj_enabled ); + + if ( cache_ptr->trans_in_progress ) { + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "Transaction in progress during flush?!?!?.") + } + + if ( cache_ptr->jwipl_len != 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "journal write in progress list isn't empty?!?!.") + } + + if ( cache_is_clean ) { + + result = H5C2_jb__trunc(&(cache_ptr->mdj_jbrb)); + + if ( result != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__trunc() failed.") + } + + cache_ptr->trans_num = (uint64_t)0; + cache_ptr->last_trans_on_disk = (uint64_t)0; + } + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5C2_journal_post_flush() */ + + +/*------------------------------------------------------------------------- + * Function: H5C2_journal_pre_flush() + * + * Purpose: Handle any journaling activities that are necessary + * before we flush the metadata cache. + * + * At present this means: + * + * 1) Verify that a transaction is not in progress. + * + * 2) Flush the journal to disk. + * + * 3) Get the ID of the last transaction on disk. + * + * 4) If the value obtained in 2) above has changed, + * remove all entries whose last transaction has + * made it to disk from the journal write in progress + * list. + * + * 5) Verify that the journal write in progress list is + * empty. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: John Mainzer + * April 10, 2008 + * + *------------------------------------------------------------------------- + */ + +herr_t +H5C2_journal_pre_flush(H5C2_t * cache_ptr) +{ + herr_t result; + uint64_t new_last_trans_on_disk; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5C2_journal_pre_flush, FAIL) + + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); + HDassert( cache_ptr->mdj_enabled ); + + if ( cache_ptr->trans_in_progress ) { + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "Transaction in progress during flush?!?!?.") + } + + result = H5C2_jb__flush(&(cache_ptr->mdj_jbrb)); + + if ( result != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__flush() failed.") + } + + result = H5C2_jb__get_last_transaction_on_disk(&(cache_ptr->mdj_jbrb), + &new_last_trans_on_disk); + if ( result != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__get_last_transaction_on_disk() failed.") + } + + if ( cache_ptr->last_trans_on_disk < new_last_trans_on_disk ) { + + result = H5C2_update_for_new_last_trans_on_disk(cache_ptr, + new_last_trans_on_disk); + + if ( result != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_update_for_new_last_trans_on_disk() failed.") + } + } + + if ( cache_ptr->jwipl_len != 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "journal write in progress list isn't empty?!?!.") + } + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5C2_journal_pre_flush() */ + + +/*------------------------------------------------------------------------- + * Function: H5C2_journal_transaction() + * + * Purpose: Generate journal messages for the current transaction. + * In passing, remove all entries from the transaction list. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: John Mainzer + * April 3, 2008 + * + *------------------------------------------------------------------------- + */ + +herr_t +H5C2_journal_transaction(H5F_t * f, + H5C2_t * cache_ptr) + +{ + char buf[H5C2__MAX_API_NAME_LEN + 128]; + H5C2_cache_entry_t * entry_ptr = NULL; + unsigned serialize_flags = 0; + haddr_t new_addr; + size_t new_len; + void * new_image_ptr; + void * thing; + herr_t result; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5C2_journal_transaction, FAIL) + HDassert( f != NULL ); HDassert( cache_ptr != NULL ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); + HDassert( cache_ptr->trans_in_progress ); + HDassert( cache_ptr->tl_len > 0 ); + + HDsnprintf(buf, H5C2__MAX_API_NAME_LEN + 128, "Begin transaction on %s.", + cache_ptr->trans_api_name); + + result = H5C2_jb__comment(&(cache_ptr->mdj_jbrb), buf); + + if ( result != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__comment() failed.") + } + + result = H5C2_jb__start_transaction(&(cache_ptr->mdj_jbrb), + cache_ptr->trans_num); + + if ( result != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__start_transaction() failed.") + } + + entry_ptr = cache_ptr->tl_tail_ptr; + while ( entry_ptr != NULL ) + { + HDassert( entry_ptr->is_dirty ); + HDassert( entry_ptr->last_trans == cache_ptr->trans_num ); + + if ( entry_ptr->is_protected ) + { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "Protected entry in TL at transaction close.") + } + + if ( entry_ptr->image_ptr == NULL ) + { + entry_ptr->image_ptr = H5MM_malloc(entry_ptr->size); + + if ( entry_ptr->image_ptr == NULL ) + { + + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ + "memory allocation failed for on disk image buffer.") + } + } + + result = entry_ptr->type->serialize(entry_ptr->addr, + entry_ptr->size, + entry_ptr->image_ptr, + (void *)entry_ptr, + &serialize_flags, + &new_addr, + &new_len, + &new_image_ptr); + if ( result != SUCCEED ) + { + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "unable to serialize entry") + } + + if ( serialize_flags != 0 ) + { + /* if the serialize_flags are not zero, the entry has been + * modified as a result of the serialize. Pass these changes + * on to the cache, and don't bother to write a journal entry + * at this time -- the protect/unprotect/rename will move the + * entry to the head of the transaction list, where we will + * handle it later. + */ + hbool_t resized; + hbool_t renamed; + + resized = (serialize_flags & H5C2__SERIALIZE_RESIZED_FLAG) != 0; + renamed = (serialize_flags & H5C2__SERIALIZE_RENAMED_FLAG) != 0; + + if ( ( renamed ) && ( ! resized ) ) + { + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "entry renamed but not resized?!?!") + } + + if ( resized ) + { + /* in the following protect/unprotect, use default + * dxpl_id as we know that the entry is in cache, + * and thus no I/O will take place. + */ + thing = H5C2_protect(f, H5P_DATASET_XFER_DEFAULT, + entry_ptr->type, entry_ptr->addr, + entry_ptr->size, NULL, + H5C2__NO_FLAGS_SET); + + if ( thing == NULL ) + { + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_protect() failed.") + } + + result = H5C2_unprotect(f, H5P_DATASET_XFER_DEFAULT, + entry_ptr->type, entry_ptr->addr, + thing, H5C2__SIZE_CHANGED_FLAG, + new_len); + + if ( result < 0 ) + { + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_unprotect() failed.") + } + + entry_ptr->image_ptr = new_image_ptr; + } + + if ( renamed ) + { + result = H5C2_rename_entry(cache_ptr, entry_ptr->type, + entry_ptr->addr, new_addr); + + if ( result < 0 ) + { + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_rename_entr() failed.") + } + } + } + else /* generate the journal entry & remove from transaction list */ + { + result = H5C2_jb__journal_entry(&(cache_ptr->mdj_jbrb), + cache_ptr->trans_num, + entry_ptr->addr, + entry_ptr->size, + entry_ptr->image_ptr); + + if ( result != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__journal_entry() failed.") + } + + H5C2__TRANS_DLL_REMOVE(entry_ptr, cache_ptr->tl_head_ptr, \ + cache_ptr->tl_tail_ptr, cache_ptr->tl_len, \ + cache_ptr->tl_size, FAIL); + } + entry_ptr = cache_ptr->tl_tail_ptr; + } + + result = H5C2_jb__end_transaction(&(cache_ptr->mdj_jbrb), + cache_ptr->trans_num); - /* we need at least one error to keep the macros happy */ - if ( trans_num != 1024 ) { + if ( result != SUCCEED ) { - HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ - "unexpected transaction number.") + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__end_transaction() failed.") } done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5C2__end_transaction() */ +} /* H5C2_journal_transaction() */ + + +/*------------------------------------------------------------------------- + * Function: H5C2_update_for_new_last_trans_on_disk() + * + * Purpose: Update the journal write in progress list for a change in + * the last transaction on disk. + * + * Specifically, update the last_trans_on_disk field of + * *cache_ptr, and then scan the journal write in progress + * list for entries whose last_trans field is now less than + * or equal to cache_ptr->last_trans_on_disk. Remove all + * these entries from the journal write in progress list, + * set their last_trans fields to zero, and insert then into + * the eviction policy data structures. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: John Mainzer + * April 3, 2008 + * + *------------------------------------------------------------------------- + */ + +herr_t +H5C2_update_for_new_last_trans_on_disk(H5C2_t * cache_ptr, + uint64_t new_last_trans_on_disk) +{ + H5C2_cache_entry_t * entry_ptr = NULL; + H5C2_cache_entry_t * prev_entry_ptr = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5C2_update_for_new_last_trans_on_disk, FAIL) + + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); + HDassert( cache_ptr->mdj_enabled ); + HDassert( cache_ptr->last_trans_on_disk <= new_last_trans_on_disk ); + + if ( cache_ptr->last_trans_on_disk < new_last_trans_on_disk ) { + + cache_ptr->last_trans_on_disk = new_last_trans_on_disk; + + entry_ptr = cache_ptr->jwipl_tail_ptr; + + while ( entry_ptr != NULL ) + { + prev_entry_ptr = entry_ptr->next; + + HDassert( entry_ptr->last_trans > 0 ); + + if ( entry_ptr->last_trans <= cache_ptr->last_trans_on_disk ) { + entry_ptr->last_trans = 0; + H5C2__UPDATE_RP_FOR_JOURNAL_WRITE_COMPLETE(cache_ptr, \ + entry_ptr, \ + FAIL) + } + + entry_ptr = prev_entry_ptr; + } + } + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5C2_update_for_new_last_trans_on_disk() */ /**************************************************************************/ @@ -143,7 +935,104 @@ done: /**************************************************************************/ /*------------------------------------------------------------------------- - * Function: H5C2__create_journal_config_block() + * Function: H5C2_check_for_journaling() + * + * Purpose: If the superblock extension of a newly opened HDF5 file + * indicates that journaling is in progress, the process + * that created the file failed to close it properly, and + * thus the file is almost certainly corrupted. + * + * The purpose of this function is to detect this condition, + * and either throw an error telling the user to run the + * recovery tool, or if so directed (presumably by the + * recovery tool) simply delete the metadata journaling + * configuration block and any reference to journaling in the + * superblock extension. + * + * JRM -- 3/26/08 + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: John Mainzer + * March 26, 2008 + * + *------------------------------------------------------------------------- + */ + +herr_t +H5C2_check_for_journaling(H5F_t * f, + hid_t dxpl_id, + H5C2_t * cache_ptr, + hbool_t journal_recovered) +{ + const char * l0 = + "This file was last written with metadata journaling enabled and was \n"; + const char * l1 = + "not closed cleanly. To allow HDF5 to read this file, please run the \n"; + const char * l2 = + "journal recovery tool on this file. The journal was written \n"; + const char * l3 = "to \""; + const char * l4 = "\".\n"; + herr_t result; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5C2_check_for_journaling, FAIL) + + HDassert( f ); + HDassert( cache_ptr ); + HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); + HDassert( cache_ptr->mdj_conf_block_addr == HADDR_UNDEF ); + HDassert( cache_ptr->mdj_conf_block_len == 0 ); + HDassert( cache_ptr->mdj_conf_block_ptr == NULL ); + HDassert( cache_ptr->mdj_file_name_ptr == NULL ); + + result = H5C2_get_journaling_in_progress(f, dxpl_id, cache_ptr); + + if ( result != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_get_journaling_in_progress() failed.") + } + + if ( cache_ptr->mdj_file_name_ptr != NULL ) /* journaling was in progress */ + { + if ( journal_recovered ) { + + /* delete the metadata journaling config block and the + * superblock extenstion refering to it. + */ + + result = H5C2_unmark_journaling_in_progress(f, dxpl_id, cache_ptr); + + if ( result != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_unmark_journaling_in_progress() failed.") + } + } else { + + /* we have to play some games here to set up an error message that + * contains the journal file path. In essence, what follows is a + * somewhat modified version of the HGOTO_ERROR() macro. + */ + (void)H5Epush2(H5E_DEFAULT, __FILE__, FUNC, __LINE__, H5E_ERR_CLS_g, + H5E_CACHE, H5E_CANTJOURNAL, "%s%s%s%s%s%s", + l0, l1, l2, l3, cache_ptr->mdj_file_name_ptr, l4); + (void)H5E_dump_api_stack((int)H5_IS_API(FUNC)); + HGOTO_DONE(FAIL) + + } + } + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5C2_check_for_journaling() */ + +/*------------------------------------------------------------------------- + * Function: H5C2_create_journal_config_block() * * Purpose: Given a string containing a journal file name and a pointer * to the associated instance of H5C2_t, allocate a journal @@ -167,7 +1056,7 @@ H5C2_create_journal_config_block(H5F_t * f, hid_t dxpl_id, const char * journal_file_name_ptr) { - H5C2_t * cache_ptr = f->shared->cache2; + H5C2_t * cache_ptr; size_t path_len = 0; hsize_t block_len = 0; haddr_t block_addr = HADDR_UNDEF; @@ -181,6 +1070,8 @@ H5C2_create_journal_config_block(H5F_t * f, FUNC_ENTER_NOAPI(H5C2_create_journal_config_block, FAIL) HDassert( f ); + HDassert( f->shared ); + cache_ptr = f->shared->cache2; HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); @@ -192,7 +1083,7 @@ H5C2_create_journal_config_block(H5F_t * f, HDassert( journal_file_name_ptr != NULL ); - path_len = strlen(journal_file_name_ptr) + 1; + path_len = HDstrlen(journal_file_name_ptr) + 1; HDassert( path_len > 0 ); @@ -277,7 +1168,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5C2__discard_journal_config_block() + * Function: H5C2_discard_journal_config_block() * * Purpose: Free the file and core space allocated to the metadata * journaling configuration block, and re-set all the associated @@ -307,12 +1198,14 @@ herr_t H5C2_discard_journal_config_block(H5F_t * f, hid_t dxpl_id) { - H5C2_t * cache_ptr = f->shared->cache2; + H5C2_t * cache_ptr; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5C2_discard_journal_config_block, FAIL) HDassert( f ); + HDassert( f->shared ); + cache_ptr = f->shared->cache2; HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); @@ -345,7 +1238,7 @@ done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5AC2__discard_journal_config_block() */ +} /* H5AC2_discard_journal_config_block() */ /*------------------------------------------------------------------------- @@ -381,18 +1274,17 @@ done: */ herr_t -H5C2_get_journaling_in_progress(H5F_t * f, - hid_t dxpl_id) +H5C2_get_journaling_in_progress(const H5F_t * f, + hid_t dxpl_id, + H5C2_t * cache_ptr) { - H5C2_t * cache_ptr = f->shared->cache2; herr_t result; herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5C2_mark_journaling_in_progress, FAIL) + FUNC_ENTER_NOAPI(H5C2_get_journaling_in_progress, FAIL) HDassert( f ); HDassert( f->shared != NULL ); - HDassert( ! f->shared->mdc_jrnl_enabled ); HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); HDassert( cache_ptr->mdj_conf_block_addr == HADDR_UNDEF ); @@ -401,9 +1293,13 @@ H5C2_get_journaling_in_progress(H5F_t * f, HDassert( cache_ptr->mdj_file_name_ptr == NULL ); if ( f->shared->mdc_jrnl_enabled == TRUE ) { + + cache_ptr->mdj_conf_block_addr = f->shared->mdc_jrnl_block_loc; + cache_ptr->mdj_conf_block_len = f->shared->mdc_jrnl_block_len; result = H5C2_load_journal_config_block(f, dxpl_id, + cache_ptr, cache_ptr->mdj_conf_block_addr, cache_ptr->mdj_conf_block_len); if ( result != SUCCEED ) { @@ -417,7 +1313,7 @@ done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5AC2__get_journal_config_block() */ +} /* H5C2_get_journaling_in_progress() */ /*------------------------------------------------------------------------- @@ -439,12 +1335,12 @@ done: */ herr_t -H5C2_load_journal_config_block(H5F_t * f, +H5C2_load_journal_config_block(const H5F_t * f, hid_t dxpl_id, + H5C2_t * cache_ptr, haddr_t block_addr, hsize_t block_len) { - H5C2_t * cache_ptr = f->shared->cache2; size_t path_len = 0; void * block_ptr = NULL; uint8_t version; @@ -457,6 +1353,7 @@ H5C2_load_journal_config_block(H5F_t * f, FUNC_ENTER_NOAPI(H5C2_load_journal_config_block, FAIL) HDassert( f ); + HDassert( f->shared ); HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); @@ -510,7 +1407,7 @@ H5C2_load_journal_config_block(H5F_t * f, * the journal file path. */ jfn_ptr = (char *)p; - if ( strlen(jfn_ptr) != path_len - 1 ) { + if ( HDstrlen(jfn_ptr) != path_len - 1 ) { HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ "Bad path_len in metadata journaling configuration block.") @@ -547,7 +1444,7 @@ done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5AC2__load_journal_config_block() */ +} /* H5C2_load_journal_config_block() */ /*------------------------------------------------------------------------- @@ -577,7 +1474,7 @@ H5C2_mark_journaling_in_progress(H5F_t * f, hid_t dxpl_id, const char * journal_file_name_ptr) { - H5C2_t * cache_ptr = f->shared->cache2; + H5C2_t * cache_ptr; herr_t result; herr_t ret_value = SUCCEED; /* Return value */ @@ -586,6 +1483,9 @@ H5C2_mark_journaling_in_progress(H5F_t * f, HDassert( f != NULL ); HDassert( f->shared != NULL ); HDassert( ! f->shared->mdc_jrnl_enabled ); + + cache_ptr = f->shared->cache2; + HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); HDassert( cache_ptr->mdj_conf_block_addr == HADDR_UNDEF ); @@ -690,11 +1590,13 @@ done: herr_t H5C2_unmark_journaling_in_progress(H5F_t * f, - hid_t dxpl_id) -{ + hid_t dxpl_id, #ifndef NDEBUG - H5C2_t * cache_ptr = f->shared->cache2; + H5C2_t * cache_ptr) +#else /* NDEBUG */ + H5C2_t UNUSED * cache_ptr) #endif /* NDEBUG */ +{ herr_t result; herr_t ret_value = SUCCEED; /* Return value */ @@ -1061,7 +1963,7 @@ H5C2_jb__write_to_buffer(H5C2_jbrb_t * struct_ptr, size_t size, const char * data, hbool_t is_end_trans, - unsigned long trans_num) + uint64_t trans_num) { herr_t ret_value = SUCCEED; unsigned long track_last_trans = 0; @@ -1436,8 +2338,8 @@ H5C2_jb__init(H5C2_jbrb_t * struct_ptr, struct_ptr->human_readable); /* Write the header message into the ring buffer */ - if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(temp), temp, FALSE, 0) - < 0) { + if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(temp), temp, FALSE, + (uint64_t)0) < 0) { HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ "H5C2_jb__write_to_buffer() failed.\n") @@ -1462,8 +2364,8 @@ done: * Wednesday, February 6, 2008 * * Purpose: Verify that there is no transaction in progress, and - * that the supplied transaction number is next in - * sequence. Then construct a start transaction message, + * that the supplied transaction number greater than + * the last. Then construct a start transaction message, * and write it to the current journal buffer. Make note * of the fact that the supplied transaction is in * progress. @@ -1474,7 +2376,7 @@ done: herr_t H5C2_jb__start_transaction(H5C2_jbrb_t * struct_ptr, - unsigned long trans_num) + uint64_t trans_num) { char temp[150]; @@ -1499,8 +2401,8 @@ H5C2_jb__start_transaction(H5C2_jbrb_t * struct_ptr, * with testing? */ - /* Verify that the supplied transaction number is next in sequence */ - if ( (struct_ptr->cur_trans + 1) != trans_num ) { + /* Verify that the supplied transaction number greater than the last */ + if ( (struct_ptr->cur_trans) >= trans_num ) { HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ "New transaction out of sequence.") @@ -1531,7 +2433,7 @@ H5C2_jb__start_transaction(H5C2_jbrb_t * struct_ptr, } /* end if */ /* Write start transaction message */ - HDsnprintf(temp, (size_t)150, "1 bgn_trans %ld\n", trans_num); + HDsnprintf(temp, (size_t)150, "1 bgn_trans %llu\n", trans_num); if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(temp), temp, FALSE, trans_num) < 0 ) { @@ -1568,7 +2470,7 @@ done: herr_t H5C2_jb__journal_entry(H5C2_jbrb_t * struct_ptr, - unsigned long trans_num, + uint64_t trans_num, haddr_t base_addr, size_t length, const uint8_t * body) @@ -1609,7 +2511,7 @@ H5C2_jb__journal_entry(H5C2_jbrb_t * struct_ptr, /* Write journal entry */ HDsnprintf(temp, (size_t)(length + 100), - "2 trans_num %ld length %zu base_addr 0x%lx body ", + "2 trans_num %llu length %zu base_addr 0x%lx body ", trans_num, length, (unsigned long)base_addr); /* <== fix this */ @@ -1683,7 +2585,7 @@ done: *****************************************************************************/ herr_t H5C2_jb__end_transaction(H5C2_jbrb_t * struct_ptr, - unsigned long trans_num) + uint64_t trans_num) { char temp[25]; herr_t ret_value = SUCCEED; @@ -1713,7 +2615,7 @@ H5C2_jb__end_transaction(H5C2_jbrb_t * struct_ptr, /* Prepare end transaction message */ - HDsnprintf(temp, (size_t)25, "3 end_trans %ld\n", trans_num); + HDsnprintf(temp, (size_t)25, "3 end_trans %llu\n", trans_num); /* Write end transaction message */ if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(temp), temp, @@ -1825,7 +2727,7 @@ done: herr_t H5C2_jb__get_last_transaction_on_disk(H5C2_jbrb_t * struct_ptr, - unsigned long * trans_num_ptr) + uint64_t * trans_num_ptr) { herr_t ret_value = SUCCEED; @@ -1885,6 +2787,7 @@ herr_t H5C2_jb__trunc(H5C2_jbrb_t * struct_ptr) { + int i; herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(H5C2_jb__trunc, FAIL) @@ -1917,6 +2820,16 @@ H5C2_jb__trunc(H5C2_jbrb_t * struct_ptr) struct_ptr->header_present = FALSE; struct_ptr->journal_is_empty = TRUE; + /* reset the transaction number fields */ + struct_ptr->cur_trans = 0; + struct_ptr->last_trans_on_disk = 0; + + /* reset the transaction tracking array */ + for (i=0; inum_bufs; i++) + { + (*struct_ptr->trans_tracking)[i] = 0; + } + if ( HDlseek(struct_ptr->journal_file_fd, (off_t)0, SEEK_SET) == (off_t)-1 ) { HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "Jounal file seek failed.") diff --git a/src/H5C2pkg.h b/src/H5C2pkg.h index 878e372..637e5e9 100644 --- a/src/H5C2pkg.h +++ b/src/H5C2pkg.h @@ -44,7 +44,7 @@ #include "H5SLprivate.h" /* Skip lists */ - /****************************************************************************** +/****************************************************************************** * * Structure: H5C2_jbrb_t * @@ -62,7 +62,7 @@ * * * magic: Unsigned 32-bit integer always set to - * H5C2__H5C2_JBRB_T_MAGIC. This field is used to validate + * H5C2__H5C2_JBRB_T_MAGIC. This field is used to validate * pointers to instances of H5C_jbrb_t. * * journal_file_fd: File Descriptor of the journal file that is being @@ -171,8 +171,8 @@ struct H5C2_jbrb_t hbool_t use_aio; hbool_t human_readable; hbool_t journal_is_empty; - unsigned long cur_trans; - unsigned long last_trans_on_disk; + uint64_t cur_trans; + uint64_t last_trans_on_disk; hbool_t trans_in_prog; const char * jname; const char * hdf5_file_name; @@ -727,11 +727,41 @@ struct H5C2_jbrb_t * be able to re-construct a HDF5 file with a consistent set of metadata * in the event of a crash. * - * mdj_enabled: Boolean flag used to indicate whether journaling is + * mdj_enabled: Boolean flag used to indicate whether journaling is * currently enabled. In general, the values of the * remaining fields in this section are undefined if * mdj_enabled is FALSE. * + * trans_in_progress Boolean flag used to indicate whether a metadata + * transaction is in progress. + * + * For purposes of metadata journaling, a transaction is a + * sequence of operations on metadata selected such that + * the HDF5 file metadata is in a consistent state both at + * the beginning and at the end of the sequence. + * + * At least to begin with, transactions will be closely tied + * to user level API calls. + * + * trans_api_name: Array of char of length H5C2__MAX_API_NAME_LEN + 1. Used + * to store the name of the API call associated with the + * current transaction. + * + * trans_num: uint64_t containing the id assigned to the current + * transaction (if trans_in_progress is TRUE), or of the + * last transaction completed (if trans_in_progress is FALSE), + * or zero if no transaction has been initiated yet. + * + * last_trans_on_disk: uint64_t containing the id assigned to the + * last transaction all of whose associated journal entries + * are on disk in the journal file. + * + * We must track this value, as to avoid messages from the + * future, we must not write a cache entry to file until + * the journal entries of all transactions in which it has + * been modified have been written to disk in the journal + * file. + * * mdj_file_name_ptr: Pointer to a string containing the path of the * journal file, or NULL if this path is undefined. * At present, the journal will always be stored in an @@ -775,6 +805,67 @@ struct H5C2_jbrb_t * mdj_jbrb: Instance of H5C2_jbrb_t used to manage logging of journal * entries to the journal file. * + * While a transaction is in progress, we must maintain a list of the + * entries that have been modified during the transaction so we can + * generate the appropriate journal entries. The following fields are + * used to maintain this list: + * + * tl_len: Number of entries currently residing on the transaction list. + * + * tl_size: Number of bytes of cache entries currently residing on the + * transaction list. + * + * tl_head_ptr: Pointer to the head of the doubly linked list of entries + * dirtied in the current transaction. Note that cache entries + * on this list are linked by their trans_next and trans_prev + * fields. + * + * This field is NULL if the list is empty. + * + * tl_tail_ptr: Pointer to the tail of the doubly linked list of entries + * dirtied in the current transaction. Note that cache entries + * on this list are linked by their trans_next and trans_prev + * fields. + * + * This field is NULL if the list is empty. + * + * When an entry is dirtied in a transaction, we must not flush it until + * all the journal entries generated by the transaction have reached disk + * in the journal file. + * + * We could just leave these entries in the LRU and skip over them when + * we scan the list for candidates for eviction. However, this will be + * costly, so we store them on the journal write in progress list instead + * until all the journal entries for the specified transaction reaches + * disk. + * + * jwipl_len: Number of entries currently residing on the journal + * entry write in progress list. + * + * jwipl_size: Number of bytes of cache entries currently residing on the + * journal entry write in progress list. + * + * jwipl_head_ptr: Pointer to the head of the doubly linked list of entries + * dirtied in some transaction n, where at least some of the + * journal entries generated in transaction n have not yet + * made it to disk in the journal file. + * + * Entries on this list are linked by their next and prev + * fields. + * + * This field is NULL if the list is empty. + * + * jwipl_tail_ptr: Pointer to the tail of the doubly linked list of entries + * dirtied in some transaction n, where at least some of the + * journal entries generated in transaction n have not yet + * made it to disk in the journal file. + * + * Entries on this list are linked by their next and prev + * fields. + * + * This field is NULL if the list is empty. + * + * * * Statistics collection fields: * @@ -1004,6 +1095,7 @@ struct H5C2_jbrb_t #define H5C2__H5C2_T_MAGIC 0x005CAC0F #define H5C2__MAX_NUM_TYPE_IDS 16 #define H5C2__PREFIX_LEN 32 +#define H5C2__MAX_API_NAME_LEN 128 #define H5C2__JOURNAL_MAGIC_LEN (size_t)4 #define H5C2__JOURNAL_CONF_MAGIC "MDJC" @@ -1097,11 +1189,23 @@ struct H5C2_t int64_t cache_accesses; hbool_t mdj_enabled; + hbool_t trans_in_progress; + char trans_api_name[H5C2__MAX_API_NAME_LEN]; + uint64_t trans_num; + uint64_t last_trans_on_disk; char * mdj_file_name_ptr; haddr_t mdj_conf_block_addr; hsize_t mdj_conf_block_len; void * mdj_conf_block_ptr; struct H5C2_jbrb_t mdj_jbrb; + int32_t tl_len; + size_t tl_size; + H5C2_cache_entry_t * tl_head_ptr; + H5C2_cache_entry_t * tl_tail_ptr; + int32_t jwipl_len; + size_t jwipl_size; + H5C2_cache_entry_t * jwipl_head_ptr; + H5C2_cache_entry_t * jwipl_tail_ptr; #if H5C2_COLLECT_CACHE_STATS @@ -1168,5 +1272,3162 @@ struct H5C2_t char prefix[H5C2__PREFIX_LEN]; }; + +/****************************************************************************/ +/***************************** Macro Definitions ****************************/ +/****************************************************************************/ + +/**************************************************************************** + * + * We maintain doubly linked lists of instances of H5C2_cache_entry_t for a + * variety of reasons -- protected list, LRU list, and the clean and dirty + * LRU lists at present. The following macros support linking and unlinking + * of instances of H5C2_cache_entry_t by both their regular and auxilary next + * and previous pointers. + * + * The size and length fields are also maintained. + * + * Note that the relevant pair of prev and next pointers are presumed to be + * NULL on entry in the insertion macros. + * + * Finally, observe that the sanity checking macros evaluate to the empty + * string when H5C2_DO_SANITY_CHECKS is FALSE. They also contain calls + * to the HGOTO_ERROR macro, which may not be appropriate in all cases. + * If so, we will need versions of the insertion and deletion macros which + * do not reference the sanity checking macros. + * JRM - 5/5/04 + * + * Changes: + * + * - Removed the line: + * + * ( ( (Size) == (entry_ptr)->size ) && ( (len) != 1 ) ) || + * + * from the H5C2__DLL_PRE_REMOVE_SC macro. With the addition of the + * epoch markers used in the age out based cache size reduction algorithm, + * this invarient need not hold, as the epoch markers are of size 0. + * + * One could argue that I should have given the epoch markers a positive + * size, but this would break the index_size = LRU_list_size + pl_size + * + pel_size invarient. + * + * Alternatively, I could pass the current decr_mode in to the macro, + * and just skip the check whenever epoch markers may be in use. + * + * However, any size errors should be caught when the cache is flushed + * and destroyed. Until we are tracking such an error, this should be + * good enough. + * JRM - 12/9/04 + * + * + * - In the H5C2__DLL_PRE_INSERT_SC macro, replaced the lines: + * + * ( ( (len) == 1 ) && + * ( ( (head_ptr) != (tail_ptr) ) || ( (Size) <= 0 ) || + * ( (head_ptr) == NULL ) || ( (head_ptr)->size != (Size) ) + * ) + * ) || + * + * with: + * + * ( ( (len) == 1 ) && + * ( ( (head_ptr) != (tail_ptr) ) || + * ( (head_ptr) == NULL ) || ( (head_ptr)->size != (Size) ) + * ) + * ) || + * + * Epoch markers have size 0, so we can now have a non-empty list with + * zero size. Hence the "( (Size) <= 0 )" clause cause false failures + * in the sanity check. Since "Size" is typically a size_t, it can't + * take on negative values, and thus the revised clause "( (Size) < 0 )" + * caused compiler warnings. + * JRM - 12/22/04 + * + * - In the H5C2__DLL_SC macro, replaced the lines: + * + * ( ( (len) == 1 ) && + * ( ( (head_ptr) != (tail_ptr) ) || ( (cache_ptr)->size <= 0 ) || + * ( (head_ptr) == NULL ) || ( (head_ptr)->size != (Size) ) + * ) + * ) || + * + * with + * + * ( ( (len) == 1 ) && + * ( ( (head_ptr) != (tail_ptr) ) || + * ( (head_ptr) == NULL ) || ( (head_ptr)->size != (Size) ) + * ) + * ) || + * + * Epoch markers have size 0, so we can now have a non-empty list with + * zero size. Hence the "( (Size) <= 0 )" clause cause false failures + * in the sanity check. Since "Size" is typically a size_t, it can't + * take on negative values, and thus the revised clause "( (Size) < 0 )" + * caused compiler warnings. + * JRM - 1/10/05 + * + * - Added the H5C2__DLL_UPDATE_FOR_SIZE_CHANGE macro and the associated + * sanity checking macros. These macro are used to update the size of + * a DLL when one of its entries changes size. + * + * JRM - 9/8/05 + * + * - Added a set of macros supporting doubly linked lists using the new + * trans_next and trans_prev fields in H5C2_cache_entry_t. These + * fields are used to maintain a list of entries that have been dirtied + * in the current transaction. At the end of the transaction, this + * list is used to generate the needed journal entries. + * + * JRM -- 3/27/08 + * + ****************************************************************************/ + +#if H5C2_DO_SANITY_CHECKS + +#define H5C2__DLL_PRE_REMOVE_SC(entry_ptr, head_ptr, tail_ptr, len, Size, fv) \ +if ( ( (head_ptr) == NULL ) || \ + ( (tail_ptr) == NULL ) || \ + ( (entry_ptr) == NULL ) || \ + ( (len) <= 0 ) || \ + ( (Size) < (entry_ptr)->size ) || \ + ( ( (entry_ptr)->prev == NULL ) && ( (head_ptr) != (entry_ptr) ) ) || \ + ( ( (entry_ptr)->next == NULL ) && ( (tail_ptr) != (entry_ptr) ) ) || \ + ( ( (len) == 1 ) && \ + ( ! ( ( (head_ptr) == (entry_ptr) ) && \ + ( (tail_ptr) == (entry_ptr) ) && \ + ( (entry_ptr)->next == NULL ) && \ + ( (entry_ptr)->prev == NULL ) && \ + ( (Size) == (entry_ptr)->size ) \ + ) \ + ) \ + ) \ + ) { \ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (fv), "DLL pre remove SC failed") \ +} + +#define H5C2__DLL_SC(head_ptr, tail_ptr, len, Size, fv) \ +if ( ( ( ( (head_ptr) == NULL ) || ( (tail_ptr) == NULL ) ) && \ + ( (head_ptr) != (tail_ptr) ) \ + ) || \ + ( (len) < 0 ) || \ + ( (Size) < 0 ) || \ + ( ( (len) == 1 ) && \ + ( ( (head_ptr) != (tail_ptr) ) || \ + ( (head_ptr) == NULL ) || ( (head_ptr)->size != (Size) ) \ + ) \ + ) || \ + ( ( (len) >= 1 ) && \ + ( ( (head_ptr) == NULL ) || ( (head_ptr)->prev != NULL ) || \ + ( (tail_ptr) == NULL ) || ( (tail_ptr)->next != NULL ) \ + ) \ + ) \ + ) { \ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (fv), "DLL sanity check failed") \ +} + +#define H5C2__DLL_PRE_INSERT_SC(entry_ptr, head_ptr, tail_ptr, len, Size, fv) \ +if ( ( (entry_ptr) == NULL ) || \ + ( (entry_ptr)->next != NULL ) || \ + ( (entry_ptr)->prev != NULL ) || \ + ( ( ( (head_ptr) == NULL ) || ( (tail_ptr) == NULL ) ) && \ + ( (head_ptr) != (tail_ptr) ) \ + ) || \ + ( (len) < 0 ) || \ + ( ( (len) == 1 ) && \ + ( ( (head_ptr) != (tail_ptr) ) || \ + ( (head_ptr) == NULL ) || ( (head_ptr)->size != (Size) ) \ + ) \ + ) || \ + ( ( (len) >= 1 ) && \ + ( ( (head_ptr) == NULL ) || ( (head_ptr)->prev != NULL ) || \ + ( (tail_ptr) == NULL ) || ( (tail_ptr)->next != NULL ) \ + ) \ + ) \ + ) { \ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (fv), "DLL pre insert SC failed") \ +} + +#define H5C2__DLL_PRE_SIZE_UPDATE_SC(dll_len, dll_size, old_size, new_size) \ +if ( ( (dll_len) <= 0 ) || \ + ( (dll_size) <= 0 ) || \ + ( (old_size) <= 0 ) || \ + ( (old_size) > (dll_size) ) || \ + ( (new_size) <= 0 ) || \ + ( ( (dll_len) == 1 ) && ( (old_size) != (dll_size) ) ) ) { \ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "DLL pre size update SC failed") \ +} + +#define H5C2__DLL_POST_SIZE_UPDATE_SC(dll_len, dll_size, old_size, new_size) \ +if ( ( (new_size) > (dll_size) ) || \ + ( ( (dll_len) == 1 ) && ( (new_size) != (dll_size) ) ) ) { \ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "DLL post size update SC failed") \ +} + +#else /* H5C2_DO_SANITY_CHECKS */ + +#define H5C2__DLL_PRE_REMOVE_SC(entry_ptr, head_ptr, tail_ptr, len, Size, fv) +#define H5C2__DLL_SC(head_ptr, tail_ptr, len, Size, fv) +#define H5C2__DLL_PRE_INSERT_SC(entry_ptr, head_ptr, tail_ptr, len, Size, fv) +#define H5C2__DLL_PRE_SIZE_UPDATE_SC(dll_len, dll_size, old_size, new_size) +#define H5C2__DLL_POST_SIZE_UPDATE_SC(dll_len, dll_size, old_size, new_size) + +#endif /* H5C2_DO_SANITY_CHECKS */ + + +#define H5C2__DLL_APPEND(entry_ptr, head_ptr, tail_ptr, len, Size, fail_val) \ + H5C2__DLL_PRE_INSERT_SC(entry_ptr, head_ptr, tail_ptr, len, Size, \ + fail_val) \ + if ( (head_ptr) == NULL ) \ + { \ + (head_ptr) = (entry_ptr); \ + (tail_ptr) = (entry_ptr); \ + } \ + else \ + { \ + (tail_ptr)->next = (entry_ptr); \ + (entry_ptr)->prev = (tail_ptr); \ + (tail_ptr) = (entry_ptr); \ + } \ + (len)++; \ + (Size) += (entry_ptr)->size; + +#define H5C2__DLL_PREPEND(entry_ptr, head_ptr, tail_ptr, len, Size, fail_val) \ + H5C2__DLL_PRE_INSERT_SC(entry_ptr, head_ptr, tail_ptr, len, Size, \ + fail_val) \ + if ( (head_ptr) == NULL ) \ + { \ + (head_ptr) = (entry_ptr); \ + (tail_ptr) = (entry_ptr); \ + } \ + else \ + { \ + (head_ptr)->prev = (entry_ptr); \ + (entry_ptr)->next = (head_ptr); \ + (head_ptr) = (entry_ptr); \ + } \ + (len)++; \ + (Size) += entry_ptr->size; + +#define H5C2__DLL_REMOVE(entry_ptr, head_ptr, tail_ptr, len, Size, fail_val) \ + H5C2__DLL_PRE_REMOVE_SC(entry_ptr, head_ptr, tail_ptr, len, Size, \ + fail_val) \ + { \ + if ( (head_ptr) == (entry_ptr) ) \ + { \ + (head_ptr) = (entry_ptr)->next; \ + if ( (head_ptr) != NULL ) \ + { \ + (head_ptr)->prev = NULL; \ + } \ + } \ + else \ + { \ + (entry_ptr)->prev->next = (entry_ptr)->next; \ + } \ + if ( (tail_ptr) == (entry_ptr) ) \ + { \ + (tail_ptr) = (entry_ptr)->prev; \ + if ( (tail_ptr) != NULL ) \ + { \ + (tail_ptr)->next = NULL; \ + } \ + } \ + else \ + { \ + (entry_ptr)->next->prev = (entry_ptr)->prev; \ + } \ + entry_ptr->next = NULL; \ + entry_ptr->prev = NULL; \ + (len)--; \ + (Size) -= entry_ptr->size; \ + } + +#define H5C2__DLL_UPDATE_FOR_SIZE_CHANGE(dll_len, dll_size, old_size, new_size) \ + H5C2__DLL_PRE_SIZE_UPDATE_SC(dll_len, dll_size, old_size, new_size) \ + (dll_size) -= (old_size); \ + (dll_size) += (new_size); \ + H5C2__DLL_POST_SIZE_UPDATE_SC(dll_len, dll_size, old_size, new_size) + +#if H5C2_DO_SANITY_CHECKS + +#define H5C2__AUX_DLL_PRE_REMOVE_SC(entry_ptr, hd_ptr, tail_ptr, len, Size, fv) \ +if ( ( (hd_ptr) == NULL ) || \ + ( (tail_ptr) == NULL ) || \ + ( (entry_ptr) == NULL ) || \ + ( (len) <= 0 ) || \ + ( (Size) < (entry_ptr)->size ) || \ + ( ( (Size) == (entry_ptr)->size ) && ( ! ( (len) == 1 ) ) ) || \ + ( ( (entry_ptr)->aux_prev == NULL ) && ( (hd_ptr) != (entry_ptr) ) ) || \ + ( ( (entry_ptr)->aux_next == NULL ) && ( (tail_ptr) != (entry_ptr) ) ) || \ + ( ( (len) == 1 ) && \ + ( ! ( ( (hd_ptr) == (entry_ptr) ) && ( (tail_ptr) == (entry_ptr) ) && \ + ( (entry_ptr)->aux_next == NULL ) && \ + ( (entry_ptr)->aux_prev == NULL ) && \ + ( (Size) == (entry_ptr)->size ) \ + ) \ + ) \ + ) \ + ) { \ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (fv), "aux DLL pre remove SC failed") \ +} + +#define H5C2__AUX_DLL_SC(head_ptr, tail_ptr, len, Size, fv) \ +if ( ( ( ( (head_ptr) == NULL ) || ( (tail_ptr) == NULL ) ) && \ + ( (head_ptr) != (tail_ptr) ) \ + ) || \ + ( (len) < 0 ) || \ + ( (Size) < 0 ) || \ + ( ( (len) == 1 ) && \ + ( ( (head_ptr) != (tail_ptr) ) || ( (Size) <= 0 ) || \ + ( (head_ptr) == NULL ) || ( (head_ptr)->size != (Size) ) \ + ) \ + ) || \ + ( ( (len) >= 1 ) && \ + ( ( (head_ptr) == NULL ) || ( (head_ptr)->aux_prev != NULL ) || \ + ( (tail_ptr) == NULL ) || ( (tail_ptr)->aux_next != NULL ) \ + ) \ + ) \ + ) { \ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (fv), "AUX DLL sanity check failed") \ +} + +#define H5C2__AUX_DLL_PRE_INSERT_SC(entry_ptr, hd_ptr, tail_ptr, len, Size, fv)\ +if ( ( (entry_ptr) == NULL ) || \ + ( (entry_ptr)->aux_next != NULL ) || \ + ( (entry_ptr)->aux_prev != NULL ) || \ + ( ( ( (hd_ptr) == NULL ) || ( (tail_ptr) == NULL ) ) && \ + ( (hd_ptr) != (tail_ptr) ) \ + ) || \ + ( (len) < 0 ) || \ + ( ( (len) == 1 ) && \ + ( ( (hd_ptr) != (tail_ptr) ) || ( (Size) <= 0 ) || \ + ( (hd_ptr) == NULL ) || ( (hd_ptr)->size != (Size) ) \ + ) \ + ) || \ + ( ( (len) >= 1 ) && \ + ( ( (hd_ptr) == NULL ) || ( (hd_ptr)->aux_prev != NULL ) || \ + ( (tail_ptr) == NULL ) || ( (tail_ptr)->aux_next != NULL ) \ + ) \ + ) \ + ) { \ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (fv), "AUX DLL pre insert SC failed") \ +} + +#else /* H5C2_DO_SANITY_CHECKS */ + +#define H5C2__AUX_DLL_PRE_REMOVE_SC(entry_ptr, hd_ptr, tail_ptr, len, Size, fv) +#define H5C2__AUX_DLL_SC(head_ptr, tail_ptr, len, Size, fv) +#define H5C2__AUX_DLL_PRE_INSERT_SC(entry_ptr, hd_ptr, tail_ptr, len, Size, fv) + +#endif /* H5C2_DO_SANITY_CHECKS */ + + +#define H5C2__AUX_DLL_APPEND(entry_ptr, head_ptr, tail_ptr, len, Size, fail_val)\ + H5C2__AUX_DLL_PRE_INSERT_SC(entry_ptr, head_ptr, tail_ptr, len, Size, \ + fail_val) \ + if ( (head_ptr) == NULL ) \ + { \ + (head_ptr) = (entry_ptr); \ + (tail_ptr) = (entry_ptr); \ + } \ + else \ + { \ + (tail_ptr)->aux_next = (entry_ptr); \ + (entry_ptr)->aux_prev = (tail_ptr); \ + (tail_ptr) = (entry_ptr); \ + } \ + (len)++; \ + (Size) += entry_ptr->size; + +#define H5C2__AUX_DLL_PREPEND(entry_ptr, head_ptr, tail_ptr, len, Size, fv) \ + H5C2__AUX_DLL_PRE_INSERT_SC(entry_ptr, head_ptr, tail_ptr, len, Size, \ + fv) \ + if ( (head_ptr) == NULL ) \ + { \ + (head_ptr) = (entry_ptr); \ + (tail_ptr) = (entry_ptr); \ + } \ + else \ + { \ + (head_ptr)->aux_prev = (entry_ptr); \ + (entry_ptr)->aux_next = (head_ptr); \ + (head_ptr) = (entry_ptr); \ + } \ + (len)++; \ + (Size) += entry_ptr->size; + +#define H5C2__AUX_DLL_REMOVE(entry_ptr, head_ptr, tail_ptr, len, Size, fv) \ + H5C2__AUX_DLL_PRE_REMOVE_SC(entry_ptr, head_ptr, tail_ptr, len, Size, \ + fv) \ + { \ + if ( (head_ptr) == (entry_ptr) ) \ + { \ + (head_ptr) = (entry_ptr)->aux_next; \ + if ( (head_ptr) != NULL ) \ + { \ + (head_ptr)->aux_prev = NULL; \ + } \ + } \ + else \ + { \ + (entry_ptr)->aux_prev->aux_next = (entry_ptr)->aux_next; \ + } \ + if ( (tail_ptr) == (entry_ptr) ) \ + { \ + (tail_ptr) = (entry_ptr)->aux_prev; \ + if ( (tail_ptr) != NULL ) \ + { \ + (tail_ptr)->aux_next = NULL; \ + } \ + } \ + else \ + { \ + (entry_ptr)->aux_next->aux_prev = (entry_ptr)->aux_prev; \ + } \ + entry_ptr->aux_next = NULL; \ + entry_ptr->aux_prev = NULL; \ + (len)--; \ + (Size) -= entry_ptr->size; \ + } + +#if H5C2_DO_SANITY_CHECKS + +#define H5C2__TRANS_DLL_PRE_REMOVE_SC(entry_ptr, hd_ptr, tail_ptr, \ + len, Size, fv) \ +if ( ( (hd_ptr) == NULL ) || \ + ( (tail_ptr) == NULL ) || \ + ( (entry_ptr) == NULL ) || \ + ( (len) <= 0 ) || \ + ( (Size) < (entry_ptr)->size ) || \ + ( ( (Size) == (entry_ptr)->size ) && ( ! ( (len) == 1 ) ) ) || \ + ( ( (entry_ptr)->trans_prev == NULL ) && ( (hd_ptr) != (entry_ptr) ) ) || \ + ( ( (entry_ptr)->trans_next == NULL ) && \ + ( (tail_ptr) != (entry_ptr) ) ) || \ + ( ( (len) == 1 ) && \ + ( ! ( ( (hd_ptr) == (entry_ptr) ) && ( (tail_ptr) == (entry_ptr) ) && \ + ( (entry_ptr)->trans_next == NULL ) && \ + ( (entry_ptr)->trans_prev == NULL ) && \ + ( (Size) == (entry_ptr)->size ) \ + ) \ + ) \ + ) \ + ) { \ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (fv), "TRANS DLL pre remove SC failed") \ +} + +#define H5C2__TRANS_DLL_SC(head_ptr, tail_ptr, len, Size, fv) \ +if ( ( ( ( (head_ptr) == NULL ) || ( (tail_ptr) == NULL ) ) && \ + ( (head_ptr) != (tail_ptr) ) \ + ) || \ + ( (len) < 0 ) || \ + ( (Size) < 0 ) || \ + ( ( (len) == 1 ) && \ + ( ( (head_ptr) != (tail_ptr) ) || ( (Size) <= 0 ) || \ + ( (head_ptr) == NULL ) || ( (head_ptr)->size != (Size) ) \ + ) \ + ) || \ + ( ( (len) >= 1 ) && \ + ( ( (head_ptr) == NULL ) || ( (head_ptr)->trans_prev != NULL ) || \ + ( (tail_ptr) == NULL ) || ( (tail_ptr)->trans_next != NULL ) \ + ) \ + ) \ + ) { \ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (fv), "TRANS DLL sanity check failed") \ +} + +#define H5C2__TRANS_DLL_PRE_INSERT_SC(entry_ptr, hd_ptr, tail_ptr, \ + len, Size, fv) \ +if ( ( (entry_ptr) == NULL ) || \ + ( ! ((entry_ptr)->is_dirty) ) || \ + ( (entry_ptr)->trans_next != NULL ) || \ + ( (entry_ptr)->trans_prev != NULL ) || \ + ( ( ( (hd_ptr) == NULL ) || ( (tail_ptr) == NULL ) ) && \ + ( (hd_ptr) != (tail_ptr) ) \ + ) || \ + ( (len) < 0 ) || \ + ( ( (len) == 1 ) && \ + ( ( (hd_ptr) != (tail_ptr) ) || ( (Size) <= 0 ) || \ + ( (hd_ptr) == NULL ) || ( (hd_ptr)->size != (Size) ) \ + ) \ + ) || \ + ( ( (len) >= 1 ) && \ + ( ( (hd_ptr) == NULL ) || ( (hd_ptr)->trans_prev != NULL ) || \ + ( (tail_ptr) == NULL ) || ( (tail_ptr)->trans_next != NULL ) \ + ) \ + ) \ + ) { \ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (fv), "TRANS DLL pre insert SC failed") \ +} + +#else /* H5C2_DO_SANITY_CHECKS */ + +#define H5C2__TRANS_DLL_PRE_REMOVE_SC(entry_ptr, hd_ptr, tail_ptr, len, Size, fv) +#define H5C2__TRANS_DLL_SC(head_ptr, tail_ptr, len, Size, fv) +#define H5C2__TRANS_DLL_PRE_INSERT_SC(entry_ptr, hd_ptr, tail_ptr, len, Size, fv) + +#endif /* H5C2_DO_SANITY_CHECKS */ + + +#define H5C2__TRANS_DLL_APPEND(entry_ptr, head_ptr, tail_ptr, len, \ + Size, fail_val) \ + H5C2__TRANS_DLL_PRE_INSERT_SC(entry_ptr, head_ptr, tail_ptr, len, \ + Size, fail_val) \ + if ( (head_ptr) == NULL ) \ + { \ + (head_ptr) = (entry_ptr); \ + (tail_ptr) = (entry_ptr); \ + } \ + else \ + { \ + (tail_ptr)->trans_next = (entry_ptr); \ + (entry_ptr)->trans_prev = (tail_ptr); \ + (tail_ptr) = (entry_ptr); \ + } \ + (len)++; \ + (Size) += entry_ptr->size; + +#define H5C2__TRANS_DLL_PREPEND(entry_ptr, head_ptr, tail_ptr, len, Size, fv) \ + H5C2__TRANS_DLL_PRE_INSERT_SC(entry_ptr, head_ptr, tail_ptr, len, \ + Size, fv) \ + if ( (head_ptr) == NULL ) \ + { \ + (head_ptr) = (entry_ptr); \ + (tail_ptr) = (entry_ptr); \ + } \ + else \ + { \ + (head_ptr)->trans_prev = (entry_ptr); \ + (entry_ptr)->trans_next = (head_ptr); \ + (head_ptr) = (entry_ptr); \ + } \ + (len)++; \ + (Size) += entry_ptr->size; + +#define H5C2__TRANS_DLL_REMOVE(entry_ptr, head_ptr, tail_ptr, len, Size, fv) \ + H5C2__TRANS_DLL_PRE_REMOVE_SC(entry_ptr, head_ptr, tail_ptr, len, \ + Size, fv) \ + { \ + if ( (head_ptr) == (entry_ptr) ) \ + { \ + (head_ptr) = (entry_ptr)->trans_next; \ + if ( (head_ptr) != NULL ) \ + { \ + (head_ptr)->trans_prev = NULL; \ + } \ + } \ + else \ + { \ + (entry_ptr)->trans_prev->trans_next = (entry_ptr)->trans_next; \ + } \ + if ( (tail_ptr) == (entry_ptr) ) \ + { \ + (tail_ptr) = (entry_ptr)->trans_prev; \ + if ( (tail_ptr) != NULL ) \ + { \ + (tail_ptr)->trans_next = NULL; \ + } \ + } \ + else \ + { \ + (entry_ptr)->trans_next->trans_prev = (entry_ptr)->trans_prev; \ + } \ + entry_ptr->trans_next = NULL; \ + entry_ptr->trans_prev = NULL; \ + (len)--; \ + (Size) -= entry_ptr->size; \ + } + + +/*********************************************************************** + * + * Stats collection macros + * + * The following macros must handle stats collection when this collection + * is enabled, and evaluate to the empty string when it is not. + * + * The sole exception to this rule is + * H5C2__UPDATE_CACHE_HIT_RATE_STATS(), which is always active as + * the cache hit rate stats are always collected and available. + * + * Changes: + * + * JRM -- 3/21/06 + * Added / updated macros for pinned entry related stats. + * + * JRM -- 8/9/06 + * More pinned entry stats related updates. + * + * JRM -- 3/31/07 + * Updated H5C2__UPDATE_STATS_FOR_PROTECT() to keep stats on + * read and write protects. + * + ***********************************************************************/ + +#define H5C2__UPDATE_CACHE_HIT_RATE_STATS(cache_ptr, hit) \ + (cache_ptr->cache_accesses)++; \ + if ( hit ) { \ + (cache_ptr->cache_hits)++; \ + } \ + +#if H5C2_COLLECT_CACHE_STATS + +#define H5C2__UPDATE_STATS_FOR_DIRTY_PIN(cache_ptr, entry_ptr) \ + (((cache_ptr)->dirty_pins)[(entry_ptr)->type->id])++; + +#define H5C2__UPDATE_STATS_FOR_UNPROTECT(cache_ptr) \ + 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 ) \ + (cache_ptr)->max_slist_size = (cache_ptr)->slist_size; \ + if ( (cache_ptr)->pel_len > (cache_ptr)->max_pel_len ) \ + (cache_ptr)->max_pel_len = (cache_ptr)->pel_len; \ + if ( (cache_ptr)->pel_size > (cache_ptr)->max_pel_size ) \ + (cache_ptr)->max_pel_size = (cache_ptr)->pel_size; + +#define H5C2__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 H5C2__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 ) \ + (cache_ptr)->max_index_size = (cache_ptr)->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 ) \ + (cache_ptr)->max_pl_size = (cache_ptr)->pl_size; \ + } else if ( (entry_ptr)->size > (new_size) ) { \ + ((cache_ptr)->size_decreases[(entry_ptr)->type->id])++; \ + } + +#define H5C2__UPDATE_STATS_FOR_HT_INSERTION(cache_ptr) \ + (cache_ptr)->total_ht_insertions++; + +#define H5C2__UPDATE_STATS_FOR_HT_DELETION(cache_ptr) \ + (cache_ptr)->total_ht_deletions++; + +#define H5C2__UPDATE_STATS_FOR_HT_SEARCH(cache_ptr, success, depth) \ + if ( success ) { \ + (cache_ptr)->successful_ht_searches++; \ + (cache_ptr)->total_successful_ht_search_depth += depth; \ + } else { \ + (cache_ptr)->failed_ht_searches++; \ + (cache_ptr)->total_failed_ht_search_depth += depth; \ + } + +#define H5C2__UPDATE_STATS_FOR_UNPIN(cache_ptr, entry_ptr) \ + ((cache_ptr)->unpins)[(entry_ptr)->type->id]++; + +#if H5C2_COLLECT_CACHE_ENTRY_STATS + +#define H5C2__RESET_CACHE_ENTRY_STATS(entry_ptr) \ + (entry_ptr)->accesses = 0; \ + (entry_ptr)->clears = 0; \ + (entry_ptr)->flushes = 0; \ + (entry_ptr)->pins = 0; + +#define H5C2__UPDATE_STATS_FOR_CLEAR(cache_ptr, entry_ptr) \ + (((cache_ptr)->clears)[(entry_ptr)->type->id])++; \ + if ( (entry_ptr)->is_pinned ) { \ + (((cache_ptr)->pinned_clears)[(entry_ptr)->type->id])++; \ + } \ + ((entry_ptr)->clears)++; + +#define H5C2__UPDATE_STATS_FOR_FLUSH(cache_ptr, entry_ptr) \ + (((cache_ptr)->flushes)[(entry_ptr)->type->id])++; \ + if ( (entry_ptr)->is_pinned ) { \ + (((cache_ptr)->pinned_flushes)[(entry_ptr)->type->id])++; \ + } \ + ((entry_ptr)->flushes)++; + +#define H5C2__UPDATE_STATS_FOR_EVICTION(cache_ptr, entry_ptr) \ + (((cache_ptr)->evictions)[(entry_ptr)->type->id])++; \ + if ( (entry_ptr)->accesses > \ + ((cache_ptr)->max_accesses)[(entry_ptr)->type->id] ) { \ + ((cache_ptr)->max_accesses)[(entry_ptr)->type->id] \ + = (entry_ptr)->accesses; \ + } \ + if ( (entry_ptr)->accesses < \ + ((cache_ptr)->min_accesses)[(entry_ptr)->type->id] ) { \ + ((cache_ptr)->min_accesses)[(entry_ptr)->type->id] \ + = (entry_ptr)->accesses; \ + } \ + if ( (entry_ptr)->clears > \ + ((cache_ptr)->max_clears)[(entry_ptr)->type->id] ) { \ + ((cache_ptr)->max_clears)[(entry_ptr)->type->id] \ + = (entry_ptr)->clears; \ + } \ + if ( (entry_ptr)->flushes > \ + ((cache_ptr)->max_flushes)[(entry_ptr)->type->id] ) { \ + ((cache_ptr)->max_flushes)[(entry_ptr)->type->id] \ + = (entry_ptr)->flushes; \ + } \ + if ( (entry_ptr)->size > \ + ((cache_ptr)->max_size)[(entry_ptr)->type->id] ) { \ + ((cache_ptr)->max_size)[(entry_ptr)->type->id] \ + = (entry_ptr)->size; \ + } \ + if ( (entry_ptr)->pins > \ + ((cache_ptr)->max_pins)[(entry_ptr)->type->id] ) { \ + ((cache_ptr)->max_pins)[(entry_ptr)->type->id] \ + = (entry_ptr)->pins; \ + } + +#define H5C2__UPDATE_STATS_FOR_INSERTION(cache_ptr, entry_ptr) \ + (((cache_ptr)->insertions)[(entry_ptr)->type->id])++; \ + if ( (entry_ptr)->is_pinned ) { \ + (((cache_ptr)->pinned_insertions)[(entry_ptr)->type->id])++; \ + ((cache_ptr)->pins)[(entry_ptr)->type->id]++; \ + (entry_ptr)->pins++; \ + if ( (cache_ptr)->pel_len > (cache_ptr)->max_pel_len ) \ + (cache_ptr)->max_pel_len = (cache_ptr)->pel_len; \ + if ( (cache_ptr)->pel_size > (cache_ptr)->max_pel_size ) \ + (cache_ptr)->max_pel_size = (cache_ptr)->pel_size; \ + } \ + 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 ) \ + (cache_ptr)->max_index_size = (cache_ptr)->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 ) \ + (cache_ptr)->max_slist_size = (cache_ptr)->slist_size; \ + if ( (entry_ptr)->size > \ + ((cache_ptr)->max_size)[(entry_ptr)->type->id] ) { \ + ((cache_ptr)->max_size)[(entry_ptr)->type->id] \ + = (entry_ptr)->size; \ + } + +#define H5C2__UPDATE_STATS_FOR_PROTECT(cache_ptr, entry_ptr, hit) \ + if ( hit ) \ + ((cache_ptr)->hits)[(entry_ptr)->type->id]++; \ + else \ + ((cache_ptr)->misses)[(entry_ptr)->type->id]++; \ + if ( ! ((entry_ptr)->is_read_only) ) { \ + ((cache_ptr)->write_protects)[(entry_ptr)->type->id]++; \ + } else { \ + ((cache_ptr)->read_protects)[(entry_ptr)->type->id]++; \ + if ( ((entry_ptr)->ro_ref_count) > \ + ((cache_ptr)->max_read_protects)[(entry_ptr)->type->id] ) { \ + ((cache_ptr)->max_read_protects)[(entry_ptr)->type->id] = \ + ((entry_ptr)->ro_ref_count); \ + } \ + } \ + 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 ) \ + (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; \ + if ( (cache_ptr)->pl_size > (cache_ptr)->max_pl_size ) \ + (cache_ptr)->max_pl_size = (cache_ptr)->pl_size; \ + if ( (entry_ptr)->size > \ + ((cache_ptr)->max_size)[(entry_ptr)->type->id] ) { \ + ((cache_ptr)->max_size)[(entry_ptr)->type->id] \ + = (entry_ptr)->size; \ + } \ + ((entry_ptr)->accesses)++; + +#define H5C2__UPDATE_STATS_FOR_PIN(cache_ptr, entry_ptr) \ + ((cache_ptr)->pins)[(entry_ptr)->type->id]++; \ + (entry_ptr)->pins++; \ + if ( (cache_ptr)->pel_len > (cache_ptr)->max_pel_len ) \ + (cache_ptr)->max_pel_len = (cache_ptr)->pel_len; \ + if ( (cache_ptr)->pel_size > (cache_ptr)->max_pel_size ) \ + (cache_ptr)->max_pel_size = (cache_ptr)->pel_size; + +#else /* H5C2_COLLECT_CACHE_ENTRY_STATS */ + +#define H5C2__RESET_CACHE_ENTRY_STATS(entry_ptr) + +#define H5C2__UPDATE_STATS_FOR_CLEAR(cache_ptr, entry_ptr) \ + if ( (entry_ptr)->is_pinned ) { \ + (((cache_ptr)->pinned_clears)[(entry_ptr)->type->id])++; \ + } \ + (((cache_ptr)->clears)[(entry_ptr)->type->id])++; + +#define H5C2__UPDATE_STATS_FOR_FLUSH(cache_ptr, entry_ptr) \ + (((cache_ptr)->flushes)[(entry_ptr)->type->id])++; \ + if ( (entry_ptr)->is_pinned ) { \ + (((cache_ptr)->pinned_flushes)[(entry_ptr)->type->id])++; \ + } + +#define H5C2__UPDATE_STATS_FOR_EVICTION(cache_ptr, entry_ptr) \ + (((cache_ptr)->evictions)[(entry_ptr)->type->id])++; + +#define H5C2__UPDATE_STATS_FOR_INSERTION(cache_ptr, entry_ptr) \ + (((cache_ptr)->insertions)[(entry_ptr)->type->id])++; \ + if ( (entry_ptr)->is_pinned ) { \ + (((cache_ptr)->pinned_insertions)[(entry_ptr)->type->id])++; \ + ((cache_ptr)->pins)[(entry_ptr)->type->id]++; \ + if ( (cache_ptr)->pel_len > (cache_ptr)->max_pel_len ) \ + (cache_ptr)->max_pel_len = (cache_ptr)->pel_len; \ + if ( (cache_ptr)->pel_size > (cache_ptr)->max_pel_size ) \ + (cache_ptr)->max_pel_size = (cache_ptr)->pel_size; \ + } \ + 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 ) \ + (cache_ptr)->max_index_size = (cache_ptr)->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 ) \ + (cache_ptr)->max_slist_size = (cache_ptr)->slist_size; + +#define H5C2__UPDATE_STATS_FOR_PROTECT(cache_ptr, entry_ptr, hit) \ + if ( hit ) \ + ((cache_ptr)->hits)[(entry_ptr)->type->id]++; \ + else \ + ((cache_ptr)->misses)[(entry_ptr)->type->id]++; \ + if ( ! ((entry_ptr)->is_read_only) ) { \ + ((cache_ptr)->write_protects)[(entry_ptr)->type->id]++; \ + } else { \ + ((cache_ptr)->read_protects)[(entry_ptr)->type->id]++; \ + if ( ((entry_ptr)->ro_ref_count) > \ + ((cache_ptr)->max_read_protects)[(entry_ptr)->type->id] ) { \ + ((cache_ptr)->max_read_protects)[(entry_ptr)->type->id] = \ + ((entry_ptr)->ro_ref_count); \ + } \ + } \ + 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 ) \ + (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; \ + if ( (cache_ptr)->pl_size > (cache_ptr)->max_pl_size ) \ + (cache_ptr)->max_pl_size = (cache_ptr)->pl_size; + +#define H5C2__UPDATE_STATS_FOR_PIN(cache_ptr, entry_ptr) \ + ((cache_ptr)->pins)[(entry_ptr)->type->id]++; \ + if ( (cache_ptr)->pel_len > (cache_ptr)->max_pel_len ) \ + (cache_ptr)->max_pel_len = (cache_ptr)->pel_len; \ + if ( (cache_ptr)->pel_size > (cache_ptr)->max_pel_size ) \ + (cache_ptr)->max_pel_size = (cache_ptr)->pel_size; + +#endif /* H5C2_COLLECT_CACHE_ENTRY_STATS */ + +#else /* H5C2_COLLECT_CACHE_STATS */ + +#define H5C2__RESET_CACHE_ENTRY_STATS(entry_ptr) +#define H5C2__UPDATE_STATS_FOR_DIRTY_PIN(cache_ptr, entry_ptr) +#define H5C2__UPDATE_STATS_FOR_UNPROTECT(cache_ptr) +#define H5C2__UPDATE_STATS_FOR_RENAME(cache_ptr, entry_ptr) +#define H5C2__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE(cache_ptr, entry_ptr, new_size) +#define H5C2__UPDATE_STATS_FOR_HT_INSERTION(cache_ptr) +#define H5C2__UPDATE_STATS_FOR_HT_DELETION(cache_ptr) +#define H5C2__UPDATE_STATS_FOR_HT_SEARCH(cache_ptr, success, depth) +#define H5C2__UPDATE_STATS_FOR_INSERTION(cache_ptr, entry_ptr) +#define H5C2__UPDATE_STATS_FOR_CLEAR(cache_ptr, entry_ptr) +#define H5C2__UPDATE_STATS_FOR_FLUSH(cache_ptr, entry_ptr) +#define H5C2__UPDATE_STATS_FOR_EVICTION(cache_ptr, entry_ptr) +#define H5C2__UPDATE_STATS_FOR_PROTECT(cache_ptr, entry_ptr, hit) +#define H5C2__UPDATE_STATS_FOR_PIN(cache_ptr, entry_ptr) +#define H5C2__UPDATE_STATS_FOR_UNPIN(cache_ptr, entry_ptr) + +#endif /* H5C2_COLLECT_CACHE_STATS */ + + +/*********************************************************************** + * + * Hash table access and manipulation macros: + * + * The following macros handle searches, insertions, and deletion in + * the hash table. + * + * When modifying these macros, remember to modify the similar macros + * in tst/cache.c + * + ***********************************************************************/ + +/* H5C2__HASH_TABLE_LEN is defined in H5C2pkg.h. It mut be a power of two. */ + +#define H5C2__HASH_MASK ((size_t)(H5C2__HASH_TABLE_LEN - 1) << 3) + +#define H5C2__HASH_FCN(x) (int)(((x) & H5C2__HASH_MASK) >> 3) + +#if H5C2_DO_SANITY_CHECKS + +#define H5C2__PRE_HT_INSERT_SC(cache_ptr, entry_ptr, fail_val) \ +if ( ( (cache_ptr) == NULL ) || \ + ( (cache_ptr)->magic != H5C2__H5C2_T_MAGIC ) || \ + ( (entry_ptr) == NULL ) || \ + ( ! H5F_addr_defined((entry_ptr)->addr) ) || \ + ( (entry_ptr)->ht_next != NULL ) || \ + ( (entry_ptr)->ht_prev != NULL ) || \ + ( (entry_ptr)->size <= 0 ) || \ + ( (k = H5C2__HASH_FCN((entry_ptr)->addr)) < 0 ) || \ + ( k >= H5C2__HASH_TABLE_LEN ) ) { \ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, fail_val, \ + "Pre HT insert SC failed") \ +} + +#define H5C2__PRE_HT_REMOVE_SC(cache_ptr, entry_ptr) \ +if ( ( (cache_ptr) == NULL ) || \ + ( (cache_ptr)->magic != H5C2__H5C2_T_MAGIC ) || \ + ( (cache_ptr)->index_len < 1 ) || \ + ( (entry_ptr) == NULL ) || \ + ( (cache_ptr)->index_size < (entry_ptr)->size ) || \ + ( ! H5F_addr_defined((entry_ptr)->addr) ) || \ + ( (entry_ptr)->size <= 0 ) || \ + ( H5C2__HASH_FCN((entry_ptr)->addr) < 0 ) || \ + ( H5C2__HASH_FCN((entry_ptr)->addr) >= H5C2__HASH_TABLE_LEN ) || \ + ( ((cache_ptr)->index)[(H5C2__HASH_FCN((entry_ptr)->addr))] \ + == NULL ) || \ + ( ( ((cache_ptr)->index)[(H5C2__HASH_FCN((entry_ptr)->addr))] \ + != (entry_ptr) ) && \ + ( (entry_ptr)->ht_prev == NULL ) ) || \ + ( ( ((cache_ptr)->index)[(H5C2__HASH_FCN((entry_ptr)->addr))] == \ + (entry_ptr) ) && \ + ( (entry_ptr)->ht_prev != NULL ) ) ) { \ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Pre HT remove SC failed") \ +} + +#define H5C2__PRE_HT_SEARCH_SC(cache_ptr, Addr, fail_val) \ +if ( ( (cache_ptr) == NULL ) || \ + ( (cache_ptr)->magic != H5C2__H5C2_T_MAGIC ) || \ + ( ! H5F_addr_defined(Addr) ) || \ + ( H5C2__HASH_FCN(Addr) < 0 ) || \ + ( H5C2__HASH_FCN(Addr) >= H5C2__HASH_TABLE_LEN ) ) { \ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, fail_val, "Pre HT search SC failed") \ +} + +#define H5C2__POST_SUC_HT_SEARCH_SC(cache_ptr, entry_ptr, Addr, k, fail_val) \ +if ( ( (cache_ptr) == NULL ) || \ + ( (cache_ptr)->magic != H5C2__H5C2_T_MAGIC ) || \ + ( (cache_ptr)->index_len < 1 ) || \ + ( (entry_ptr) == NULL ) || \ + ( (cache_ptr)->index_size < (entry_ptr)->size ) || \ + ( H5F_addr_ne((entry_ptr)->addr, (Addr)) ) || \ + ( (entry_ptr)->size <= 0 ) || \ + ( ((cache_ptr)->index)[k] == NULL ) || \ + ( ( ((cache_ptr)->index)[k] != (entry_ptr) ) && \ + ( (entry_ptr)->ht_prev == NULL ) ) || \ + ( ( ((cache_ptr)->index)[k] == (entry_ptr) ) && \ + ( (entry_ptr)->ht_prev != NULL ) ) || \ + ( ( (entry_ptr)->ht_prev != NULL ) && \ + ( (entry_ptr)->ht_prev->ht_next != (entry_ptr) ) ) || \ + ( ( (entry_ptr)->ht_next != NULL ) && \ + ( (entry_ptr)->ht_next->ht_prev != (entry_ptr) ) ) ) { \ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, fail_val, \ + "Post successful HT search SC failed") \ +} + +#define H5C2__POST_HT_SHIFT_TO_FRONT(cache_ptr, entry_ptr, k, fail_val) \ +if ( ( (cache_ptr) == NULL ) || \ + ( ((cache_ptr)->index)[k] != (entry_ptr) ) || \ + ( (entry_ptr)->ht_prev != NULL ) ) { \ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, fail_val, \ + "Post HT shift to front SC failed") \ +} + +#define H5C2__PRE_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) <= 0 ) || \ + ( (old_size) > (cache_ptr)->index_size ) || \ + ( (new_size) <= 0 ) || \ + ( ( (cache_ptr)->index_len == 1 ) && \ + ( (cache_ptr)->index_size != (old_size) ) ) ) { \ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "Pre HT entry size change SC failed") \ +} + +#define H5C2__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") \ +} + +#else /* H5C2_DO_SANITY_CHECKS */ + +#define H5C2__PRE_HT_INSERT_SC(cache_ptr, entry_ptr, fail_val) +#define H5C2__PRE_HT_REMOVE_SC(cache_ptr, entry_ptr) +#define H5C2__PRE_HT_SEARCH_SC(cache_ptr, Addr, fail_val) +#define H5C2__POST_SUC_HT_SEARCH_SC(cache_ptr, entry_ptr, Addr, k, fail_val) +#define H5C2__POST_HT_SHIFT_TO_FRONT(cache_ptr, entry_ptr, k, fail_val) +#define H5C2__PRE_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size) +#define H5C2__POST_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size) + +#endif /* H5C2_DO_SANITY_CHECKS */ + + +#define H5C2__INSERT_IN_INDEX(cache_ptr, entry_ptr, fail_val) \ +{ \ + int k; \ + H5C2__PRE_HT_INSERT_SC(cache_ptr, entry_ptr, fail_val) \ + k = H5C2__HASH_FCN((entry_ptr)->addr); \ + if ( ((cache_ptr)->index)[k] == NULL ) \ + { \ + ((cache_ptr)->index)[k] = (entry_ptr); \ + } \ + else \ + { \ + (entry_ptr)->ht_next = ((cache_ptr)->index)[k]; \ + (entry_ptr)->ht_next->ht_prev = (entry_ptr); \ + ((cache_ptr)->index)[k] = (entry_ptr); \ + } \ + (cache_ptr)->index_len++; \ + (cache_ptr)->index_size += (entry_ptr)->size; \ + H5C2__UPDATE_STATS_FOR_HT_INSERTION(cache_ptr) \ +} + +#define H5C2__DELETE_FROM_INDEX(cache_ptr, entry_ptr) \ +{ \ + int k; \ + H5C2__PRE_HT_REMOVE_SC(cache_ptr, entry_ptr) \ + k = H5C2__HASH_FCN((entry_ptr)->addr); \ + if ( (entry_ptr)->ht_next ) \ + { \ + (entry_ptr)->ht_next->ht_prev = (entry_ptr)->ht_prev; \ + } \ + if ( (entry_ptr)->ht_prev ) \ + { \ + (entry_ptr)->ht_prev->ht_next = (entry_ptr)->ht_next; \ + } \ + if ( ((cache_ptr)->index)[k] == (entry_ptr) ) \ + { \ + ((cache_ptr)->index)[k] = (entry_ptr)->ht_next; \ + } \ + (entry_ptr)->ht_next = NULL; \ + (entry_ptr)->ht_prev = NULL; \ + (cache_ptr)->index_len--; \ + (cache_ptr)->index_size -= (entry_ptr)->size; \ + H5C2__UPDATE_STATS_FOR_HT_DELETION(cache_ptr) \ +} + +#define H5C2__SEARCH_INDEX(cache_ptr, Addr, entry_ptr, fail_val) \ +{ \ + int k; \ + int depth = 0; \ + H5C2__PRE_HT_SEARCH_SC(cache_ptr, Addr, fail_val) \ + k = H5C2__HASH_FCN(Addr); \ + entry_ptr = ((cache_ptr)->index)[k]; \ + while ( ( entry_ptr ) && ( H5F_addr_ne(Addr, (entry_ptr)->addr) ) ) \ + { \ + (entry_ptr) = (entry_ptr)->ht_next; \ + (depth)++; \ + } \ + if ( entry_ptr ) \ + { \ + H5C2__POST_SUC_HT_SEARCH_SC(cache_ptr, entry_ptr, Addr, k, fail_val) \ + if ( entry_ptr != ((cache_ptr)->index)[k] ) \ + { \ + if ( (entry_ptr)->ht_next ) \ + { \ + (entry_ptr)->ht_next->ht_prev = (entry_ptr)->ht_prev; \ + } \ + HDassert( (entry_ptr)->ht_prev != NULL ); \ + (entry_ptr)->ht_prev->ht_next = (entry_ptr)->ht_next; \ + ((cache_ptr)->index)[k]->ht_prev = (entry_ptr); \ + (entry_ptr)->ht_next = ((cache_ptr)->index)[k]; \ + (entry_ptr)->ht_prev = NULL; \ + ((cache_ptr)->index)[k] = (entry_ptr); \ + H5C2__POST_HT_SHIFT_TO_FRONT(cache_ptr, entry_ptr, k, fail_val) \ + } \ + } \ + H5C2__UPDATE_STATS_FOR_HT_SEARCH(cache_ptr, (entry_ptr != NULL), depth) \ +} + +#define H5C2__SEARCH_INDEX_NO_STATS(cache_ptr, Addr, entry_ptr, fail_val) \ +{ \ + int k; \ + int depth = 0; \ + H5C2__PRE_HT_SEARCH_SC(cache_ptr, Addr, fail_val) \ + k = H5C2__HASH_FCN(Addr); \ + entry_ptr = ((cache_ptr)->index)[k]; \ + while ( ( entry_ptr ) && ( H5F_addr_ne(Addr, (entry_ptr)->addr) ) ) \ + { \ + (entry_ptr) = (entry_ptr)->ht_next; \ + (depth)++; \ + } \ + if ( entry_ptr ) \ + { \ + H5C2__POST_SUC_HT_SEARCH_SC(cache_ptr, entry_ptr, Addr, k, fail_val) \ + if ( entry_ptr != ((cache_ptr)->index)[k] ) \ + { \ + if ( (entry_ptr)->ht_next ) \ + { \ + (entry_ptr)->ht_next->ht_prev = (entry_ptr)->ht_prev; \ + } \ + HDassert( (entry_ptr)->ht_prev != NULL ); \ + (entry_ptr)->ht_prev->ht_next = (entry_ptr)->ht_next; \ + ((cache_ptr)->index)[k]->ht_prev = (entry_ptr); \ + (entry_ptr)->ht_next = ((cache_ptr)->index)[k]; \ + (entry_ptr)->ht_prev = NULL; \ + ((cache_ptr)->index)[k] = (entry_ptr); \ + H5C2__POST_HT_SHIFT_TO_FRONT(cache_ptr, entry_ptr, k, fail_val) \ + } \ + } \ +} + +#define H5C2__UPDATE_INDEX_FOR_SIZE_CHANGE(cache_ptr, old_size, new_size) \ +{ \ + H5C2__PRE_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size) \ + (cache_ptr)->index_size -= old_size; \ + (cache_ptr)->index_size += new_size; \ + H5C2__POST_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size) \ +} + + +/************************************************************************** + * + * Skip list insertion and deletion macros: + * + * These used to be functions, but I converted them to macros to avoid some + * function call overhead. + * + **************************************************************************/ + +/*------------------------------------------------------------------------- + * + * Macro: H5C2__INSERT_ENTRY_IN_SLIST + * + * Purpose: Insert the specified instance of H5C2_cache_entry_t into + * the skip list in the specified instance of H5C2_t. Update + * the associated length and size fields. + * + * Return: N/A + * + * Programmer: John Mainzer, 5/10/04 + * + * Modifications: + * + * JRM -- 7/21/04 + * Updated function to set the in_tree flag when inserting + * an entry into the tree. Also modified the function to + * update the tree size and len fields instead of the similar + * index fields. + * + * All of this is part of the modifications to support the + * hash table. + * + * JRM -- 7/27/04 + * Converted the function H5C2_insert_entry_in_tree() into + * the macro H5C2__INSERT_ENTRY_IN_TREE in the hopes of + * wringing a little more speed out of the cache. + * + * Note that we don't bother to check if the entry is already + * in the tree -- if it is, H5SL_insert() will fail. + * + * QAK -- 11/27/04 + * Switched over to using skip list routines. + * + * JRM -- 6/27/06 + * Added fail_val parameter. + * + * JRM -- 8/25/06 + * Added the H5C2_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 H5C2_DO_SANITY_CHECKS + +#define H5C2__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_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 ); \ + \ +} /* H5C2__INSERT_ENTRY_IN_SLIST */ + +#else /* H5C2_DO_SANITY_CHECKS */ + +#define H5C2__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_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; \ + \ + HDassert( (cache_ptr)->slist_len > 0 ); \ + HDassert( (cache_ptr)->slist_size > 0 ); \ + \ +} /* H5C2__INSERT_ENTRY_IN_SLIST */ + +#endif /* H5C2_DO_SANITY_CHECKS */ + + +/*------------------------------------------------------------------------- + * + * Function: H5C2__REMOVE_ENTRY_FROM_SLIST + * + * Purpose: Remove the specified instance of H5C2_cache_entry_t from the + * index skip list in the specified instance of H5C2_t. Update + * the associated length and size fields. + * + * Return: N/A + * + * Programmer: John Mainzer, 5/10/04 + * + * Modifications: + * + * JRM -- 7/21/04 + * Updated function for the addition of the hash table. + * + * JRM - 7/27/04 + * Converted from the function H5C2_remove_entry_from_tree() + * to the macro H5C2__REMOVE_ENTRY_FROM_TREE in the hopes of + * wringing a little more performance out of the cache. + * + * QAK -- 11/27/04 + * Switched over to using skip list routines. + * + * JRM -- 3/28/07 + * Updated sanity checks for the new is_read_only and + * ro_ref_count fields in H5C2_cache_entry_t. + * + *------------------------------------------------------------------------- + */ + +#define H5C2__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( (entry_ptr)->size > 0 ); \ + HDassert( (entry_ptr)->in_slist ); \ + HDassert( (cache_ptr)->slist_ptr ); \ + \ + if ( H5SL_remove((cache_ptr)->slist_ptr, &(entry_ptr)->addr) \ + != (entry_ptr) ) \ + \ + HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, \ + "Can't delete entry from skip list.") \ + \ + HDassert( (cache_ptr)->slist_len > 0 ); \ + (cache_ptr)->slist_len--; \ + HDassert( (cache_ptr)->slist_size >= (entry_ptr)->size ); \ + (cache_ptr)->slist_size -= (entry_ptr)->size; \ + (entry_ptr)->in_slist = FALSE; \ +} /* H5C2__REMOVE_ENTRY_FROM_SLIST */ + + +/*------------------------------------------------------------------------- + * + * Function: H5C2__UPDATE_SLIST_FOR_SIZE_CHANGE + * + * Purpose: Update cache_ptr->slist_size for a change in the size of + * and entry in the slist. + * + * Return: N/A + * + * Programmer: John Mainzer, 9/07/05 + * + * Modifications: + * + * JRM -- 8/27/06 + * Added the H5C2_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 H5C2_DO_SANITY_CHECKS + +#define H5C2__UPDATE_SLIST_FOR_SIZE_CHANGE(cache_ptr, old_size, new_size) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_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); \ + \ + (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) ) ); \ +} /* H5C2__REMOVE_ENTRY_FROM_SLIST */ + +#else /* H5C2_DO_SANITY_CHECKS */ + +#define H5C2__UPDATE_SLIST_FOR_SIZE_CHANGE(cache_ptr, old_size, new_size) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_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) ) ); \ +} /* H5C2__REMOVE_ENTRY_FROM_SLIST */ + +#endif /* H5C2_DO_SANITY_CHECKS */ + + +/************************************************************************** + * + * Replacement policy update macros: + * + * These used to be functions, but I converted them to macros to avoid some + * function call overhead. + * + **************************************************************************/ + +/*------------------------------------------------------------------------- + * + * Macro: H5C2__FAKE_RP_FOR_MOST_RECENT_ACCESS + * + * Purpose: For efficiency, we sometimes change the order of flushes -- + * but doing so can confuse the replacement policy. This + * macro exists to allow us to specify an entry as the + * most recently touched so we can repair any such + * confusion. + * + * 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 macro + * should switch on the current policy and act accordingly. + * + * Return: N/A + * + * Programmer: John Mainzer, 10/13/05 + * + * Modifications: + * + * JRM -- 3/20/06 + * Modified macro to ignore pinned entries. Pinned entries + * do not appear in the data structures maintained by the + * replacement policy code, and thus this macro has nothing + * to do if called for such an entry. + * + * JRM -- 3/28/07 + * Added sanity checks using the new is_read_only and + * ro_ref_count fields of struct H5C2_cache_entry_t. + * + * JRM -- 3/29/08 + * Added a sanity check to verify that the target entry + * does not have a pending journal entry write. + * + *------------------------------------------------------------------------- + */ + +#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS + +#define H5C2__FAKE_RP_FOR_MOST_RECENT_ACCESS(cache_ptr, entry_ptr, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( (entry_ptr)->size > 0 ); \ + HDassert( (entry_ptr)->last_trans == 0 ); \ + \ + if ( ! ((entry_ptr)->is_pinned) ) { \ + \ + /* modified LRU specific code */ \ + \ + /* remove the entry from the LRU list, and re-insert it at the head. \ + */ \ + \ + H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* Use the dirty flag to infer whether the entry is on the clean or \ + * dirty LRU list, and remove it. Then insert it at the head of \ + * the same LRU list. \ + * \ + * At least initially, all entries should be clean. That may \ + * change, so we may as well deal with both cases now. \ + */ \ + \ + if ( (entry_ptr)->is_dirty ) { \ + H5C2__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ + (cache_ptr)->dLRU_tail_ptr, \ + (cache_ptr)->dLRU_list_len, \ + (cache_ptr)->dLRU_list_size, (fail_val)) \ + \ + H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ + (cache_ptr)->dLRU_tail_ptr, \ + (cache_ptr)->dLRU_list_len, \ + (cache_ptr)->dLRU_list_size, (fail_val)) \ + } else { \ + H5C2__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ + (cache_ptr)->cLRU_tail_ptr, \ + (cache_ptr)->cLRU_list_len, \ + (cache_ptr)->cLRU_list_size, (fail_val)) \ + \ + H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ + (cache_ptr)->cLRU_tail_ptr, \ + (cache_ptr)->cLRU_list_len, \ + (cache_ptr)->cLRU_list_size, (fail_val)) \ + } \ + \ + /* End modified LRU specific code. */ \ + } \ +} /* H5C2__FAKE_RP_FOR_MOST_RECENT_ACCESS */ + +#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + +#define H5C2__FAKE_RP_FOR_MOST_RECENT_ACCESS(cache_ptr, entry_ptr, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( (entry_ptr)->size > 0 ); \ + HDassert( (entry_ptr)->last_trans == 0 ); \ + \ + if ( ! ((entry_ptr)->is_pinned) ) { \ + \ + /* modified LRU specific code */ \ + \ + /* remove the entry from the LRU list, and re-insert it at the head \ + */ \ + \ + H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* End modified LRU specific code. */ \ + } \ +} /* H5C2__FAKE_RP_FOR_MOST_RECENT_ACCESS */ + +#endif /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + + +/*------------------------------------------------------------------------- + * + * Macro: H5C2__UPDATE_RP_FOR_EVICTION + * + * Purpose: Update the replacement policy data structures for an + * eviction of the specified cache entry. + * + * 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: Non-negative on success/Negative on failure. + * + * Programmer: John Mainzer, 5/10/04 + * + * Modifications: + * + * JRM - 7/27/04 + * Converted the function H5C2_update_rp_for_eviction() to the + * macro H5C2__UPDATE_RP_FOR_EVICTION in an effort to squeeze + * a bit more performance out of the cache. + * + * At least for the first cut, I am leaving the comments and + * white space in the macro. If they cause dificulties with + * the pre-processor, I'll have to remove them. + * + * JRM - 7/28/04 + * Split macro into two version, one supporting the clean and + * dirty LRU lists, and the other not. Yet another attempt + * at optimization. + * + * JRM - 3/20/06 + * Pinned entries can't be evicted, so this entry should never + * be called on a pinned entry. Added assert to verify this. + * + * JRM -- 3/28/07 + * Added sanity checks for the new is_read_only and + * ro_ref_count fields of struct H5C2_cache_entry_t. + * + * JRM -- 3/29/08 + * Added sanity check to verify that the evicted entry + * does not have a pending journal entry write. + * + *------------------------------------------------------------------------- + */ + +#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS + +#define H5C2__UPDATE_RP_FOR_EVICTION(cache_ptr, entry_ptr, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( !((entry_ptr)->is_pinned) ); \ + HDassert( (entry_ptr)->size > 0 ); \ + HDassert( (entry_ptr)->last_trans == 0 ); \ + \ + /* modified LRU specific code */ \ + \ + /* remove the entry from the LRU list. */ \ + \ + H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* If the entry is clean when it is evicted, it should be on the \ + * clean LRU list, if it was dirty, it should be on the dirty LRU list. \ + * Remove it from the appropriate list according to the value of the \ + * dirty flag. \ + */ \ + \ + if ( (entry_ptr)->is_dirty ) { \ + \ + H5C2__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ + (cache_ptr)->dLRU_tail_ptr, \ + (cache_ptr)->dLRU_list_len, \ + (cache_ptr)->dLRU_list_size, (fail_val)) \ + } else { \ + H5C2__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ + (cache_ptr)->cLRU_tail_ptr, \ + (cache_ptr)->cLRU_list_len, \ + (cache_ptr)->cLRU_list_size, (fail_val)) \ + } \ + \ +} /* H5C2__UPDATE_RP_FOR_EVICTION */ + +#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + +#define H5C2__UPDATE_RP_FOR_EVICTION(cache_ptr, entry_ptr, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( !((entry_ptr)->is_pinned) ); \ + HDassert( (entry_ptr)->size > 0 ); \ + HDassert( (entry_ptr)->last_trans == 0 ); \ + \ + /* modified LRU specific code */ \ + \ + /* remove the entry from the LRU list. */ \ + \ + H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ +} /* H5C2__UPDATE_RP_FOR_EVICTION */ + +#endif /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + + +/*------------------------------------------------------------------------- + * + * Macro: H5C2__UPDATE_RP_FOR_FLUSH + * + * Purpose: Update the replacement policy data structures for a flush + * of the specified cache entry. + * + * 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, 5/6/04 + * + * Modifications: + * + * JRM - 7/27/04 + * Converted the function H5C2_update_rp_for_flush() to the + * macro H5C2__UPDATE_RP_FOR_FLUSH in an effort to squeeze + * a bit more performance out of the cache. + * + * At least for the first cut, I am leaving the comments and + * white space in the macro. If they cause dificulties with + * pre-processor, I'll have to remove them. + * + * JRM - 7/28/04 + * Split macro into two versions, one supporting the clean and + * dirty LRU lists, and the other not. Yet another attempt + * at optimization. + * + * JRM - 3/20/06 + * While pinned entries can be flushed, they don't reside in + * the replacement policy data structures when unprotected. + * Thus I modified this macro to do nothing if the entry is + * pinned. + * + * JRM - 3/28/07 + * Added sanity checks based on the new is_read_only and + * ro_ref_count fields of struct H5C2_cache_entry_t. + * + * JRM -- 3/29/08 + * Added sanity check to verify that the flushed entry + * does not have a pending journal entry write. + * + *------------------------------------------------------------------------- + */ + +#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS + +#define H5C2__UPDATE_RP_FOR_FLUSH(cache_ptr, entry_ptr, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( (entry_ptr)->size > 0 ); \ + HDassert( (entry_ptr)->last_trans == 0 ); \ + \ + if ( ! ((entry_ptr)->is_pinned) ) { \ + \ + /* modified LRU specific code */ \ + \ + /* remove the entry from the LRU list, and re-insert it at the \ + * head. \ + */ \ + \ + H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* since the entry is being flushed or cleared, one would think \ + * that it must be dirty -- but that need not be the case. Use the \ + * dirty flag to infer whether the entry is on the clean or dirty \ + * LRU list, and remove it. Then insert it at the head of the \ + * clean LRU list. \ + * \ + * The function presumes that a dirty entry will be either cleared \ + * or flushed shortly, so it is OK if we put a dirty entry on the \ + * clean LRU list. \ + */ \ + \ + if ( (entry_ptr)->is_dirty ) { \ + H5C2__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ + (cache_ptr)->dLRU_tail_ptr, \ + (cache_ptr)->dLRU_list_len, \ + (cache_ptr)->dLRU_list_size, (fail_val)) \ + } else { \ + H5C2__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ + (cache_ptr)->cLRU_tail_ptr, \ + (cache_ptr)->cLRU_list_len, \ + (cache_ptr)->cLRU_list_size, (fail_val)) \ + } \ + \ + H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ + (cache_ptr)->cLRU_tail_ptr, \ + (cache_ptr)->cLRU_list_len, \ + (cache_ptr)->cLRU_list_size, (fail_val)) \ + \ + /* End modified LRU specific code. */ \ + } \ +} /* H5C2__UPDATE_RP_FOR_FLUSH */ + +#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + +#define H5C2__UPDATE_RP_FOR_FLUSH(cache_ptr, entry_ptr, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( (entry_ptr)->size > 0 ); \ + HDassert( (entry_ptr)->last_trans == 0 ); \ + \ + if ( ! ((entry_ptr)->is_pinned) ) { \ + \ + /* modified LRU specific code */ \ + \ + /* remove the entry from the LRU list, and re-insert it at the \ + * head. \ + */ \ + \ + H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* End modified LRU specific code. */ \ + } \ +} /* H5C2__UPDATE_RP_FOR_FLUSH */ + +#endif /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + + +/*------------------------------------------------------------------------- + * + * Macro: H5C2__UPDATE_RP_FOR_INSERTION + * + * Purpose: Update the replacement policy data structures for an + * insertion of the specified cache entry. + * + * 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, 5/17/04 + * + * Modifications: + * + * JRM - 7/27/04 + * Converted the function H5C2_update_rp_for_insertion() to the + * macro H5C2__UPDATE_RP_FOR_INSERTION in an effort to squeeze + * a bit more performance out of the cache. + * + * At least for the first cut, I am leaving the comments and + * white space in the macro. If they cause dificulties with + * pre-processor, I'll have to remove them. + * + * JRM - 7/28/04 + * Split macro into two version, one supporting the clean and + * dirty LRU lists, and the other not. Yet another attempt + * at optimization. + * + * JRM - 3/10/06 + * This macro should never be called on a pinned entry. + * Inserted an assert to verify this. + * + * JRM - 8/9/06 + * Not any more. We must now allow insertion of pinned + * entries. Updated macro to support this. + * + * JRM - 3/28/07 + * Added sanity checks using the new is_read_only and + * ro_ref_count fields of struct H5C2_cache_entry_t. + * + * JRM - 3/29/30 + * Added sanity check that verifies that the last_trans field + * of the entry matches the trans_num field of the cache. + * Note that when journaling is disabled, both of these + * fields should contain zero. Also verify that either + * journaling is disabled or a transaction is in progress. + * + * Added code to put the entry in the journal write in + * progress list if entries last_trans field is non- + * zero and the entry is not pinned. + * + *------------------------------------------------------------------------- + */ + +#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS + +#define H5C2__UPDATE_RP_FOR_INSERTION(cache_ptr, entry_ptr, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( (entry_ptr)->size > 0 ); \ + HDassert( (entry_ptr)->last_trans == (cache_ptr)->trans_num ); \ + HDassert( ( ! ((cache_ptr)->mdj_enabled) ) || \ + ( (cache_ptr)->trans_in_progress ) ); \ + \ + if ( (entry_ptr)->is_pinned ) { \ + \ + H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->pel_head_ptr, \ + (cache_ptr)->pel_tail_ptr, \ + (cache_ptr)->pel_len, \ + (cache_ptr)->pel_size, (fail_val)) \ + \ + } else if ( (entry_ptr)->last_trans != 0 ) { \ + \ + HDassert( (cache_ptr)->mdj_enabled ); \ + HDassert( (cache_ptr)->trans_in_progress ); \ + H5C2__TRANS_DLL_PREPEND((entry_ptr), \ + ((cache_ptr)->jwipl_head_ptr), \ + ((cache_ptr)->jwipl_tail_ptr), \ + ((cache_ptr)->jwipl_len), \ + ((cache_ptr)->jwipl_size), fail_val) \ + \ + } else { \ + \ + /* modified LRU specific code */ \ + \ + /* insert the entry at the head of the LRU list. */ \ + \ + H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* insert the entry at the head of the clean or dirty LRU list as \ + * appropriate. \ + */ \ + \ + if ( entry_ptr->is_dirty ) { \ + H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ + (cache_ptr)->dLRU_tail_ptr, \ + (cache_ptr)->dLRU_list_len, \ + (cache_ptr)->dLRU_list_size, (fail_val)) \ + } else { \ + H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ + (cache_ptr)->cLRU_tail_ptr, \ + (cache_ptr)->cLRU_list_len, \ + (cache_ptr)->cLRU_list_size, (fail_val)) \ + } \ + \ + /* End modified LRU specific code. */ \ + } \ +} + +#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + +#define H5C2__UPDATE_RP_FOR_INSERTION(cache_ptr, entry_ptr, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( (entry_ptr)->size > 0 ); \ + HDassert( (entry_ptr)->last_trans == (cache_ptr)->trans_num ); \ + HDassert( ( ! ((cache_ptr)->mdj_enabled) ) || \ + ( (cache_ptr)->trans_in_progress ) ); \ + \ + if ( (entry_ptr)->is_pinned ) { \ + \ + H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->pel_head_ptr, \ + (cache_ptr)->pel_tail_ptr, \ + (cache_ptr)->pel_len, \ + (cache_ptr)->pel_size, (fail_val)) \ + \ + } else if ( (entry_ptr)->last_trans != 0 ) { \ + \ + HDassert( (cache_ptr)->mdj_enabled ); \ + HDassert( (cache_ptr)->trans_in_progress ); \ + H5C2__TRANS_DLL_PREPEND((entry_ptr), \ + ((cache_ptr)->jwipl_head_ptr), \ + ((cache_ptr)->jwipl_tail_ptr), \ + ((cache_ptr)->jwipl_len), \ + ((cache_ptr)->jwipl_size), (fail_val)) \ + \ + } else { \ + \ + /* modified LRU specific code */ \ + \ + /* insert the entry at the head of the LRU list. */ \ + \ + H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* End modified LRU specific code. */ \ + } \ +} + +#endif /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + + +/*------------------------------------------------------------------------- + * + * Macro: H5C2__UPDATE_RP_FOR_JOURNAL_WRITE_COMPLETE + * + * Purpose: Update the replacement policy data structures for the + * completion of the last pending journal write for the + * specified un-pinned and un-protected cache entry. + * + * If an entry with a pending journal write is not protected + * and is not pinned, it must be on the journal write in + * progress list. Unlink it from that list, and add it to + * the data structures used by the current replacement policy. + * + * 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. + * + * Note that the macro presumes that the entry's last_trans + * field is zero on entry. + * + * Return: N/A + * + * Programmer: John Mainzer, 3/31/08 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS + +#define H5C2__UPDATE_RP_FOR_JOURNAL_WRITE_COMPLETE(cache_ptr, entry_ptr, \ + fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ + HDassert( (cache_ptr)->mdj_enabled ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( !((entry_ptr)->is_pinned) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( (entry_ptr)->size > 0 ); \ + HDassert( (entry_ptr)->is_dirty ); \ + HDassert( (entry_ptr)->last_trans == 0 ); \ + \ + H5C2__DLL_REMOVE((entry_ptr), \ + ((cache_ptr)->jwipl_head_ptr), \ + ((cache_ptr)->jwipl_tail_ptr), \ + ((cache_ptr)->jwipl_len), \ + ((cache_ptr)->jwipl_size), \ + (fail_val)) \ + \ + /* modified LRU specific code */ \ + \ + /* insert the entry at the head of the LRU list. */ \ + \ + H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* insert the entry at the head of the clean or dirty LRU list as \ + * appropriate. \ + */ \ + \ + if ( entry_ptr->is_dirty ) { \ + H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ + (cache_ptr)->dLRU_tail_ptr, \ + (cache_ptr)->dLRU_list_len, \ + (cache_ptr)->dLRU_list_size, (fail_val)) \ + } else { \ + H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ + (cache_ptr)->cLRU_tail_ptr, \ + (cache_ptr)->cLRU_list_len, \ + (cache_ptr)->cLRU_list_size, (fail_val)) \ + } \ + \ + /* End modified LRU specific code. */ \ + \ +} /* H5C2__UPDATE_RP_FOR_JOURNAL_WRITE_COMPLETE */ + +#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + +#define H5C2__UPDATE_RP_FOR_JOURNAL_WRITE_COMPLETE(cache_ptr, entry_ptr, \ + fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ + HDassert( (cache_ptr)->mdj_enabled ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( !((entry_ptr)->is_pinned) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( (entry_ptr)->size > 0 ); \ + HDassert( (entry_ptr)->is_dirty ); \ + HDassert( (entry_ptr)->last_trans == 0 ); \ + \ + H5C2__DLL_REMOVE((entry_ptr), \ + ((cache_ptr)->jwipl_head_ptr), \ + ((cache_ptr)->jwipl_tail_ptr), \ + ((cache_ptr)->jwipl_len), \ + ((cache_ptr)->jwipl_size), \ + (fail_val)) \ + \ + /* modified LRU specific code */ \ + \ + /* insert the entry at the head of the LRU list. */ \ + \ + H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* End modified LRU specific code. */ \ + \ +} /* H5C2__UPDATE_RP_FOR_JOURNAL_WRITE_COMPLETE */ + +#endif /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + + +/*------------------------------------------------------------------------- + * + * Macro: H5C2__UPDATE_RP_FOR_PROTECT + * + * Purpose: Update the replacement policy data structures for a + * protect of the specified cache entry. + * + * To do this, unlink the specified entry from any data + * structures used by the replacement policy, and add the + * entry to the protected list. + * + * 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, 5/17/04 + * + * Modifications: + * + * JRM - 7/27/04 + * Converted the function H5C2_update_rp_for_protect() to the + * macro H5C2__UPDATE_RP_FOR_PROTECT in an effort to squeeze + * a bit more performance out of the cache. + * + * At least for the first cut, I am leaving the comments and + * white space in the macro. If they cause dificulties with + * pre-processor, I'll have to remove them. + * + * JRM - 7/28/04 + * Split macro into two version, one supporting the clean and + * dirty LRU lists, and the other not. Yet another attempt + * at optimization. + * + * JRM - 3/17/06 + * Modified macro to attempt to remove pinned entriese from + * the pinned entry list instead of from the data structures + * maintained by the replacement policy. + * + * JRM - 3/28/07 + * Added sanity checks based on the new is_read_only and + * ro_ref_count fields of struct H5C2_cache_entry_t. + * + * JRM - 3/29/08 + * Added code to remove the entry from the journal write in + * progress list if appropriate. Also related sanity checks. + * + *------------------------------------------------------------------------- + */ + +#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS + +#define H5C2__UPDATE_RP_FOR_PROTECT(cache_ptr, entry_ptr, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( (entry_ptr)->size > 0 ); \ + \ + if ( (entry_ptr)->is_pinned ) { \ + \ + H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->pel_head_ptr, \ + (cache_ptr)->pel_tail_ptr, \ + (cache_ptr)->pel_len, \ + (cache_ptr)->pel_size, (fail_val)) \ + \ + } else if ( (entry_ptr)->last_trans != 0 ) { \ + \ + HDassert( (cache_ptr)->mdj_enabled ); \ + HDassert( (entry_ptr)->is_dirty ); \ + H5C2__DLL_REMOVE((entry_ptr), \ + ((cache_ptr)->jwipl_head_ptr), \ + ((cache_ptr)->jwipl_tail_ptr), \ + ((cache_ptr)->jwipl_len), \ + ((cache_ptr)->jwipl_size), \ + (fail_val)) \ + \ + } else { \ + \ + /* modified LRU specific code */ \ + \ + /* remove the entry from the LRU list. */ \ + \ + H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* Similarly, remove the entry from the clean or dirty LRU list \ + * as appropriate. \ + */ \ + \ + if ( (entry_ptr)->is_dirty ) { \ + \ + H5C2__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ + (cache_ptr)->dLRU_tail_ptr, \ + (cache_ptr)->dLRU_list_len, \ + (cache_ptr)->dLRU_list_size, (fail_val)) \ + \ + } else { \ + \ + H5C2__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ + (cache_ptr)->cLRU_tail_ptr, \ + (cache_ptr)->cLRU_list_len, \ + (cache_ptr)->cLRU_list_size, (fail_val)) \ + } \ + \ + /* End modified LRU specific code. */ \ + } \ + \ + /* Regardless of the replacement policy, or whether the entry is \ + * pinned, now add the entry to the protected list. \ + */ \ + \ + H5C2__DLL_APPEND((entry_ptr), (cache_ptr)->pl_head_ptr, \ + (cache_ptr)->pl_tail_ptr, \ + (cache_ptr)->pl_len, \ + (cache_ptr)->pl_size, (fail_val)) \ +} /* H5C2__UPDATE_RP_FOR_PROTECT */ + +#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + +#define H5C2__UPDATE_RP_FOR_PROTECT(cache_ptr, entry_ptr, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( (entry_ptr)->size > 0 ); \ + \ + if ( (entry_ptr)->is_pinned ) { \ + \ + H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->pel_head_ptr, \ + (cache_ptr)->pel_tail_ptr, \ + (cache_ptr)->pel_len, \ + (cache_ptr)->pel_size, (fail_val)) \ + \ + } else if ( (entry_ptr)->last_trans != 0 ) { \ + \ + HDassert( (cache_ptr)->mdj_enabled ); \ + HDassert( (cache_ptr)->trans_in_progress ); \ + H5C2__DLL_REMOVE((entry_ptr), \ + ((cache_ptr)->jwipl_head_ptr), \ + ((cache_ptr)->jwipl_tail_ptr), \ + ((cache_ptr)->jwipl_len), \ + ((cache_ptr)->jwipl_size), \ + (fail_val)) \ + \ + } else { \ + \ + /* modified LRU specific code */ \ + \ + /* remove the entry from the LRU list. */ \ + \ + H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* End modified LRU specific code. */ \ + } \ + \ + /* Regardless of the replacement policy, or whether the entry is \ + * pinned, now add the entry to the protected list. \ + */ \ + \ + H5C2__DLL_APPEND((entry_ptr), (cache_ptr)->pl_head_ptr, \ + (cache_ptr)->pl_tail_ptr, \ + (cache_ptr)->pl_len, \ + (cache_ptr)->pl_size, (fail_val)) \ +} /* H5C2__UPDATE_RP_FOR_PROTECT */ + +#endif /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + + +/*------------------------------------------------------------------------- + * + * Macro: H5C2__UPDATE_RP_FOR_RENAME + * + * Purpose: Update the replacement policy data structures for a + * rename of the specified cache entry. + * + * 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, 5/17/04 + * + * Modifications: + * + * JRM - 7/27/04 + * Converted the function H5C2_update_rp_for_rename() to the + * macro H5C2__UPDATE_RP_FOR_RENAME in an effort to squeeze + * a bit more performance out of the cache. + * + * At least for the first cut, I am leaving the comments and + * white space in the macro. If they cause dificulties with + * pre-processor, I'll have to remove them. + * + * JRM - 7/28/04 + * Split macro into two version, one supporting the clean and + * dirty LRU lists, and the other not. Yet another attempt + * at optimization. + * + * JRM - 6/23/05 + * Added the was_dirty parameter. It is possible that + * the entry was clean when it was renamed -- if so it + * it is in the clean LRU regardless of the current + * value of the is_dirty field. + * + * At present, all renamed entries are forced to be + * dirty. This macro is a bit more general that that, + * to allow it to function correctly should that policy + * be relaxed in the future. + * + * JRM - 3/17/06 + * Modified macro to do nothing if the entry is pinned. + * In this case, the entry is on the pinned entry list, not + * in the replacement policy data structures, so there is + * nothing to be done. + * + * JRM - 3/28/07 + * Added sanity checks using the new is_read_only and + * ro_ref_count fields of struct H5C2_cache_entry_t. + * + * JRM - 3/29/08 + * Reworked macro to handle the case in which the renamed + * entry has a journal write pending -- this required the + * addition of the had_jwip parameter. Also added some + * related sanity checks. + * + *------------------------------------------------------------------------- + */ + +#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS + +#define H5C2__UPDATE_RP_FOR_RENAME(cache_ptr, entry_ptr, was_dirty, \ + had_jwip, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( (entry_ptr)->size > 0 ); \ + /* read following as: had_jwip => (entry_ptr)->last_trans != 0 */ \ + HDassert( ( (entry_ptr)->last_trans != 0 ) || ( ! (had_jwip) ) ); \ + \ + if ( ! ( (entry_ptr)->is_pinned ) ) { \ + \ + /* remove the entry from either the jwip list, or from the current \ + * replacement policy data structures, as appropriate. \ + */ \ + if ( had_jwip ) { /* must be on jwip list */ \ + \ + HDassert( (cache_ptr)->mdj_enabled ); \ + HDassert( (cache_ptr)->trans_in_progress ); \ + HDassert( (entry_ptr)->last_trans != 0 ); \ + HDassert( was_dirty ); \ + HDassert( (entry_ptr)->is_dirty ); \ + H5C2__DLL_REMOVE((entry_ptr), \ + ((cache_ptr)->jwipl_head_ptr), \ + ((cache_ptr)->jwipl_tail_ptr), \ + ((cache_ptr)->jwipl_len), \ + ((cache_ptr)->jwipl_size), \ + (fail_val)) \ + \ + } else { /* must be in replacement policy data structures */ \ + \ + /* begin modified LRU specific code */ \ + \ + /* remove the entry from the LRU list */ \ + \ + H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* remove the entry from either the clean or dirty LUR list as \ + * indicated by the was_dirty parameter \ + */ \ + if ( was_dirty ) { \ + \ + H5C2__AUX_DLL_REMOVE((entry_ptr), \ + (cache_ptr)->dLRU_head_ptr, \ + (cache_ptr)->dLRU_tail_ptr, \ + (cache_ptr)->dLRU_list_len, \ + (cache_ptr)->dLRU_list_size, \ + (fail_val)) \ + \ + } else { \ + \ + H5C2__AUX_DLL_REMOVE((entry_ptr), \ + (cache_ptr)->cLRU_head_ptr, \ + (cache_ptr)->cLRU_tail_ptr, \ + (cache_ptr)->cLRU_list_len, \ + (cache_ptr)->cLRU_list_size, \ + (fail_val)) \ + } \ + /* end modified LRU specific code */ \ + } \ + /* insert in either jwip list, or replacement policy data structures \ + * as appropriate. \ + */ \ + if ( (entry_ptr)->last_trans != 0 ) { /* goes in jwip list */ \ + \ + HDassert( (cache_ptr)->mdj_enabled ); \ + HDassert( (cache_ptr)->trans_in_progress ); \ + HDassert( (entry_ptr)->is_dirty ); \ + H5C2__DLL_PREPEND((entry_ptr), \ + ((cache_ptr)->jwipl_head_ptr), \ + ((cache_ptr)->jwipl_tail_ptr), \ + ((cache_ptr)->jwipl_len), \ + ((cache_ptr)->jwipl_size), fail_val) \ + \ + } else { /* goes back in the replacement policy data structures */ \ + \ + /* begin modified LRU specific code */ \ + \ + H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* insert the entry at the head of either the clean or dirty \ + * LRU list as appropriate. \ + */ \ + \ + if ( (entry_ptr)->is_dirty ) { \ + \ + H5C2__AUX_DLL_PREPEND((entry_ptr), \ + (cache_ptr)->dLRU_head_ptr, \ + (cache_ptr)->dLRU_tail_ptr, \ + (cache_ptr)->dLRU_list_len, \ + (cache_ptr)->dLRU_list_size, \ + (fail_val)) \ + \ + } else { \ + \ + H5C2__AUX_DLL_PREPEND((entry_ptr), \ + (cache_ptr)->cLRU_head_ptr, \ + (cache_ptr)->cLRU_tail_ptr, \ + (cache_ptr)->cLRU_list_len, \ + (cache_ptr)->cLRU_list_size, \ + (fail_val)) \ + } \ + \ + /* End modified LRU specific code. */ \ + } \ + } \ +} /* H5C2__UPDATE_RP_FOR_RENAME */ + +#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + +#define H5C2__UPDATE_RP_FOR_RENAME(cache_ptr, entry_ptr, was_dirty, \ + had_jwip, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( (entry_ptr)->size > 0 ); \ + /* read following as: had_jwip => (entry_ptr)->last_trans != 0 */ \ + HDassert( ( (entry_ptr)->last_trans != 0 ) || ( ! (had_jwip) ) ); \ + \ + if ( ! ( (entry_ptr)->is_pinned ) ) { \ + \ + /* remove the entry from either the jwip list, or from the current \ + * replacement policy data structures, as appropriate. \ + */ \ + if ( had_jwip ) { /* must be on jwip list */ \ + \ + HDassert( (cache_ptr)->mdj_enabled ); \ + HDassert( (cache_ptr)->trans_in_progress ); \ + HDassert( (entry_ptr)->last_trans != 0 ); \ + HDassert( was_dirty ); \ + HDassert( (entry_ptr)->is_dirty ); \ + H5C2__DLL_REMOVE((entry_ptr), \ + ((cache_ptr)->jwipl_head_ptr), \ + ((cache_ptr)->jwipl_tail_ptr), \ + ((cache_ptr)->jwipl_len), \ + ((cache_ptr)->jwipl_size), \ + (fail_val)) \ + \ + } else { /* must be in replacement policy data structures */ \ + \ + /* begin modified LRU specific code */ \ + \ + /* remove the entry from the LRU list */ \ + \ + H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* end modified LRU specific code */ \ + } \ + /* insert in either jwip list, or replacement policy data \ + * structures as appropriate. \ + */ \ + if ( (entry_ptr)->last_trans != 0 ) { /* goes in jwip list */ \ + \ + HDassert( (cache_ptr)->mdj_enabled ); \ + HDassert( (cache_ptr)->trans_in_progress ); \ + HDassert( (entry_ptr)->is_dirty ); \ + H5C2__DLL_PREPEND((entry_ptr), \ + ((cache_ptr)->jwipl_head_ptr), \ + ((cache_ptr)->jwipl_tail_ptr), \ + ((cache_ptr)->jwipl_len), \ + ((cache_ptr)->jwipl_size), fail_val) \ + \ + } else { /* goes back in the replacement policy data structures */ \ + \ + /* begin modified LRU specific code */ \ + \ + H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* End modified LRU specific code. */ \ + } \ + } \ +} /* H5C2__UPDATE_RP_FOR_RENAME */ + +#endif /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + + +/*------------------------------------------------------------------------- + * + * Macro: H5C2__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: + * + * JRM -- 3/28/07 + * Added sanity checks based on the new is_read_only and + * ro_ref_count fields of struct H5C2_cache_entry_t. + * + * JRM -- 3/29/08 + * Added code to deal with the journal write in progress + * list -- in essence, after checking to see if the entry is + * pinned, check to see if it is on the jwip list. If it + * is, update the size of that list. If not, proceed as + * before. + * + *------------------------------------------------------------------------- + */ + +#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS + +#define H5C2__UPDATE_RP_FOR_SIZE_CHANGE(cache_ptr, entry_ptr, new_size) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( (entry_ptr)->size > 0 ); \ + HDassert( new_size > 0 ); \ + \ + if ( (entry_ptr)->is_pinned ) { \ + \ + H5C2__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->pel_len, \ + (cache_ptr)->pel_size, \ + (entry_ptr)->size, \ + (new_size)); \ + \ + } else if ( (entry_ptr)->last_trans != 0 ) { \ + \ + HDassert( (cache_ptr)->mdj_enabled ); \ + HDassert( (entry_ptr)->is_dirty ); \ + H5C2__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->jwipl_len, \ + (cache_ptr)->jwipl_size, \ + (entry_ptr)->size, \ + (new_size)); \ + \ + } else { \ + \ + /* modified LRU specific code */ \ + \ + /* Update the size of the LRU list */ \ + \ + H5C2__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 ) { \ + \ + H5C2__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->dLRU_list_len, \ + (cache_ptr)->dLRU_list_size, \ + (entry_ptr)->size, \ + (new_size)); \ + \ + } else { \ + \ + H5C2__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. */ \ + } \ + \ +} /* H5C2__UPDATE_RP_FOR_SIZE_CHANGE */ + +#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + +#define H5C2__UPDATE_RP_FOR_SIZE_CHANGE(cache_ptr, entry_ptr, new_size) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( (entry_ptr)->size > 0 ); \ + HDassert( new_size > 0 ); \ + \ + if ( (entry_ptr)->is_pinned ) { \ + \ + H5C2__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->pel_len, \ + (cache_ptr)->pel_size, \ + (entry_ptr)->size, \ + (new_size)); \ + \ + } else if ( (entry_ptr)->last_trans != 0 ) { \ + \ + HDassert( (cache_ptr)->mdj_enabled ); \ + HDassert( (entry_ptr)->is_dirty ); \ + H5C2__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->jwipl_len, \ + (cache_ptr)->jwipl_size, \ + (entry_ptr)->size, \ + (new_size)); \ + \ + } else { \ + \ + /* modified LRU specific code */ \ + \ + /* Update the size of the LRU list */ \ + \ + H5C2__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. */ \ + } \ + \ +} /* H5C2__UPDATE_RP_FOR_SIZE_CHANGE */ + +#endif /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + + +/*------------------------------------------------------------------------- + * + * Macro: H5C2__UPDATE_RP_FOR_UNPIN + * + * Purpose: Update the replacement policy data structures for an + * unpin of the specified cache entry. + * + * To do this, unlink the specified entry from the protected + * entry list, and re-insert it in the data structures used + * by the current replacement policy. + * + * 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 macro + * should switch on the current policy and act accordingly. + * + * Return: N/A + * + * Programmer: John Mainzer, 3/22/06 + * + * Modifications: + * + * JRM -- 3/28/07 + * Added sanity checks based on the new is_read_only and + * ro_ref_count fields of struct H5C2_cache_entry_t. + * + * JRM -- 3/30/08 + * Added code to place the newly unpinned entry on the + * journal write pending list if appropriate. + * + *------------------------------------------------------------------------- + */ + +#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS + +#define H5C2__UPDATE_RP_FOR_UNPIN(cache_ptr, entry_ptr, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( (entry_ptr)->is_pinned); \ + HDassert( (entry_ptr)->size > 0 ); \ + \ + /* Regardless of the replacement policy, remove the entry from the \ + * pinned entry list. \ + */ \ + H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->pel_head_ptr, \ + (cache_ptr)->pel_tail_ptr, (cache_ptr)->pel_len, \ + (cache_ptr)->pel_size, (fail_val)) \ + \ + if ( (entry_ptr)->last_trans != 0 ) { \ + \ + /* put the entry in the jwip list */ \ + HDassert( (cache_ptr)->mdj_enabled ); \ + HDassert( (entry_ptr)->is_dirty ); \ + H5C2__DLL_PREPEND((entry_ptr), \ + ((cache_ptr)->jwipl_head_ptr), \ + ((cache_ptr)->jwipl_tail_ptr), \ + ((cache_ptr)->jwipl_len), \ + ((cache_ptr)->jwipl_size), fail_val) \ + \ + } else { /* put entry in the replacement policy data structures */ \ + \ + /* modified LRU specific code */ \ + \ + /* insert the entry at the head of the LRU list. */ \ + \ + H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* Similarly, insert the entry at the head of either the clean \ + * or dirty LRU list as appropriate. \ + */ \ + \ + if ( (entry_ptr)->is_dirty ) { \ + \ + H5C2__AUX_DLL_PREPEND((entry_ptr), \ + (cache_ptr)->dLRU_head_ptr, \ + (cache_ptr)->dLRU_tail_ptr, \ + (cache_ptr)->dLRU_list_len, \ + (cache_ptr)->dLRU_list_size, \ + (fail_val)) \ + \ + } else { \ + \ + H5C2__AUX_DLL_PREPEND((entry_ptr), \ + (cache_ptr)->cLRU_head_ptr, \ + (cache_ptr)->cLRU_tail_ptr, \ + (cache_ptr)->cLRU_list_len, \ + (cache_ptr)->cLRU_list_size, \ + (fail_val)) \ + } \ + \ + /* End modified LRU specific code. */ \ + } \ + \ +} /* H5C2__UPDATE_RP_FOR_UNPIN */ + +#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + +#define H5C2__UPDATE_RP_FOR_UNPIN(cache_ptr, entry_ptr, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( (entry_ptr)->is_pinned); \ + HDassert( (entry_ptr)->size > 0 ); \ + \ + /* Regardless of the replacement policy, remove the entry from the \ + * pinned entry list. \ + */ \ + H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->pel_head_ptr, \ + (cache_ptr)->pel_tail_ptr, (cache_ptr)->pel_len, \ + (cache_ptr)->pel_size, (fail_val)) \ + \ + if ( (entry_ptr)->last_trans != 0 ) { \ + \ + /* put the entry in the jwip list */ \ + HDassert( (cache_ptr)->mdj_enabled ); \ + HDassert( (entry_ptr)->is_dirty ); \ + H5C2__DLL_PREPEND((entry_ptr), \ + ((cache_ptr)->jwipl_head_ptr), \ + ((cache_ptr)->jwipl_tail_ptr), \ + ((cache_ptr)->jwipl_len), \ + ((cache_ptr)->jwipl_size), fail_val) \ + \ + } else { /* put entry in the replacement policy data structures */ \ + \ + /* modified LRU specific code */ \ + \ + /* insert the entry at the head of the LRU list. */ \ + \ + H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* End modified LRU specific code. */ \ + } \ + \ +} /* H5C2__UPDATE_RP_FOR_UNPIN */ + +#endif /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + + +/*------------------------------------------------------------------------- + * + * Macro: H5C2__UPDATE_RP_FOR_UNPROTECT + * + * Purpose: Update the replacement policy data structures for an + * unprotect of the specified cache entry. + * + * To do this, unlink the specified entry from the protected + * list, and re-insert it in the data structures used by the + * current replacement policy. + * + * 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, 5/19/04 + * + * Modifications: + * + * JRM - 7/27/04 + * Converted the function H5C2_update_rp_for_unprotect() to + * the macro H5C2__UPDATE_RP_FOR_UNPROTECT in an effort to + * squeeze a bit more performance out of the cache. + * + * At least for the first cut, I am leaving the comments and + * white space in the macro. If they cause dificulties with + * pre-processor, I'll have to remove them. + * + * JRM - 7/28/04 + * Split macro into two version, one supporting the clean and + * dirty LRU lists, and the other not. Yet another attempt + * at optimization. + * + * JRM - 3/17/06 + * Modified macro to put pinned entries on the pinned entry + * list instead of inserting them in the data structures + * maintained by the replacement policy. + * + * JRM - 3/30/08 + * Modified macro to put un-pinned entries with pending + * journal writes on the journal write in progress list. + * + *------------------------------------------------------------------------- + */ + +#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS + +#define H5C2__UPDATE_RP_FOR_UNPROTECT(cache_ptr, entry_ptr, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( (entry_ptr)->is_protected); \ + HDassert( (entry_ptr)->size > 0 ); \ + \ + /* Regardless of the replacement policy, remove the entry from the \ + * protected list. \ + */ \ + H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->pl_head_ptr, \ + (cache_ptr)->pl_tail_ptr, (cache_ptr)->pl_len, \ + (cache_ptr)->pl_size, (fail_val)) \ + \ + if ( (entry_ptr)->is_pinned ) { \ + \ + H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->pel_head_ptr, \ + (cache_ptr)->pel_tail_ptr, \ + (cache_ptr)->pel_len, \ + (cache_ptr)->pel_size, (fail_val)) \ + \ + } else if ( (entry_ptr)->last_trans != 0 ) { \ + \ + /* put the entry in the jwip list */ \ + HDassert( (cache_ptr)->mdj_enabled ); \ + HDassert( (entry_ptr)->is_dirty ); \ + H5C2__DLL_PREPEND((entry_ptr), \ + ((cache_ptr)->jwipl_head_ptr), \ + ((cache_ptr)->jwipl_tail_ptr), \ + ((cache_ptr)->jwipl_len), \ + ((cache_ptr)->jwipl_size), fail_val) \ + \ + } else { /* put the entry in the replacement policy data structures */ \ + \ + /* modified LRU specific code */ \ + \ + /* insert the entry at the head of the LRU list. */ \ + \ + H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* Similarly, insert the entry at the head of either the clean or \ + * dirty LRU list as appropriate. \ + */ \ + \ + if ( (entry_ptr)->is_dirty ) { \ + \ + H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ + (cache_ptr)->dLRU_tail_ptr, \ + (cache_ptr)->dLRU_list_len, \ + (cache_ptr)->dLRU_list_size, (fail_val)) \ + \ + } else { \ + \ + H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ + (cache_ptr)->cLRU_tail_ptr, \ + (cache_ptr)->cLRU_list_len, \ + (cache_ptr)->cLRU_list_size, (fail_val)) \ + } \ + \ + /* End modified LRU specific code. */ \ + } \ + \ +} /* H5C2__UPDATE_RP_FOR_UNPROTECT */ + +#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + +#define H5C2__UPDATE_RP_FOR_UNPROTECT(cache_ptr, entry_ptr, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( (entry_ptr)->is_protected); \ + HDassert( (entry_ptr)->size > 0 ); \ + \ + /* Regardless of the replacement policy, remove the entry from the \ + * protected list. \ + */ \ + H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->pl_head_ptr, \ + (cache_ptr)->pl_tail_ptr, (cache_ptr)->pl_len, \ + (cache_ptr)->pl_size, (fail_val)) \ + \ + if ( (entry_ptr)->is_pinned ) { \ + \ + H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->pel_head_ptr, \ + (cache_ptr)->pel_tail_ptr, \ + (cache_ptr)->pel_len, \ + (cache_ptr)->pel_size, (fail_val)) \ + \ + } else if ( (entry_ptr)->last_trans != 0 ) { \ + \ + /* put the entry in the jwip list */ \ + HDassert( (cache_ptr)->mdj_enabled ); \ + HDassert( (entry_ptr)->is_dirty ); \ + H5C2__DLL_PREPEND((entry_ptr), \ + ((cache_ptr)->jwipl_head_ptr), \ + ((cache_ptr)->jwipl_tail_ptr), \ + ((cache_ptr)->jwipl_len), \ + ((cache_ptr)->jwipl_size), fail_val) \ + \ + } else { \ + \ + /* modified LRU specific code */ \ + \ + /* insert the entry at the head of the LRU list. */ \ + \ + H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* End modified LRU specific code. */ \ + } \ +} /* H5C2__UPDATE_RP_FOR_UNPROTECT */ + +#endif /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + + +/************************************************************************** + * + * Transaction list update macros: + * + * When journaling is enabled, we must maintain the transaction list -- the + * list of all entries that have been dirtied during the current + * transaction. + * + * The following macros exist to support this task. + * + **************************************************************************/ + +/*------------------------------------------------------------------------- + * + * Macro: H5C2__INSERT_ENTRY_IN_TL() + * + * Purpose: Check to see if journaling is enabled. + * + * If it is, set the last_trans field of the target entry + * to the current transaction number, and insert the entry + * in the transaction list. + * + * Return: N/A + * + * Programmer: John Mainzer, 3/31/08 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +#define H5C2__INSERT_ENTRY_IN_TL(cache_ptr, entry_ptr, fail_val) \ +if ( cache_ptr->mdj_enabled ) \ +{ \ + HDassert( cache_ptr->trans_in_progress ); \ + HDassert( entry_ptr->last_trans == 0 ); \ + \ + entry_ptr->last_trans = cache_ptr->trans_num; \ + \ + H5C2__TRANS_DLL_PREPEND((entry_ptr), (cache_ptr->tl_head_ptr), \ + (cache_ptr->tl_tail_ptr), \ + (cache_ptr->tl_len), (cache_ptr->tl_size), \ + (fail_val)); \ +} /* H5C2__INSERT_ENTRY_IN_TL */ + + +/*------------------------------------------------------------------------- + * + * Macro: H5C2__UPDATE_TL_FOR_ENTRY_CLEAR + * + * Purpose: Check to see if journaling is enabled. + * + * If it is, see if the target entry is in the transaction + * list. If it is, remove it from the list, and set its + * last_trans field to the current transaction number minus + * 1. + * + * Return: N/A + * + * Programmer: John Mainzer, 3/31/08 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +#define H5C2__UPDATE_TL_FOR_ENTRY_CLEAR(cache_ptr, entry_ptr, fail_val) \ +if ( cache_ptr->mdj_enabled ) \ +{ \ + HDassert( cache_ptr->trans_in_progress ); \ + HDassert( entry_ptr->last_trans <= cache_ptr->trans_num ); \ + \ + if ( entry_ptr->last_trans == cache_ptr->trans_num ) { \ + \ + H5C2__TRANS_DLL_REMOVE((entry_ptr), (cache_ptr->tl_head_ptr), \ + (cache_ptr->tl_tail_ptr), \ + (cache_ptr->tl_len), \ + (cache_ptr->tl_size), (fail_val)); \ + entry_ptr->last_trans = cache_ptr->trans_num - 1; \ + } \ +} /* H5C2__UPDATE_TL_FOR_ENTRY_CLEAR */ + + +/*------------------------------------------------------------------------- + * + * Macro: H5C2__UPDATE_TL_FOR_ENTRY_DIRTY + * + * Purpose: Check to see if journaling is enabled. + * + * If it is, see if the target entry is in the transaction + * list. If it is, remove it from the list. If it isn't, + * set the entries last_trans field to the id of the current + * transaction. + * + * In either case, then insert the entry at the head of the + * transaction list. + * + * Return: N/A + * + * Programmer: John Mainzer, 3/31/08 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +#define H5C2__UPDATE_TL_FOR_ENTRY_DIRTY(cache_ptr, entry_ptr, fail_val) \ +if ( cache_ptr->mdj_enabled ) \ +{ \ + HDassert( cache_ptr->trans_in_progress ); \ + HDassert( entry_ptr->last_trans <= cache_ptr->trans_num ); \ + \ + if ( entry_ptr->last_trans == cache_ptr->trans_num ) { \ + \ + H5C2__TRANS_DLL_REMOVE((entry_ptr), (cache_ptr->tl_head_ptr), \ + (cache_ptr->tl_tail_ptr), \ + (cache_ptr->tl_len), \ + (cache_ptr->tl_size), (fail_val)); \ + } else { \ + entry_ptr->last_trans = cache_ptr->trans_num; \ + } \ + \ + H5C2__TRANS_DLL_PREPEND((entry_ptr), (cache_ptr->tl_head_ptr), \ + (cache_ptr->tl_tail_ptr), \ + (cache_ptr->tl_len), (cache_ptr->tl_size), \ + (fail_val)); \ +} /* H5C2__UPDATE_TL_FOR_ENTRY_DIRTY */ + + +/*------------------------------------------------------------------------- + * + * Macro: H5C2__UPDATE_TL_FOR_ENTRY_SIZE_CHANGE + * + * Purpose: Update the transaction list for a change in the size of + * one of its constituents. Note that it is the caller's + * responsibility to verify that the entry is in the + * transaction list. + * + * Return: N/A + * + * Programmer: John Mainzer, 3/31/08 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +#define H5C2__UPDATE_TL_FOR_ENTRY_SIZE_CHANGE(cache_ptr, entry_ptr, \ + old_size, new_size) \ +if ( (cache_ptr)->mdj_enabled ) { \ + HDassert( (cache_ptr)->trans_in_progress ); \ + if ( (entry_ptr)->last_trans == (cache_ptr)->trans_num ) { \ + H5C2__DLL_UPDATE_FOR_SIZE_CHANGE(((cache_ptr)->tl_len), \ + ((cache_ptr)->tl_size), \ + (old_size), (new_size)); \ + } \ +} /* H5C2__UPDATE_TL_FOR_ENTRY_SIZE_CHANGE() */ + #endif /* _H5C2pkg_H */ diff --git a/src/H5C2private.h b/src/H5C2private.h index 98120d7..4f42927 100644 --- a/src/H5C2private.h +++ b/src/H5C2private.h @@ -784,6 +784,37 @@ typedef herr_t (*H5C2_log_flush_func_t)(H5C2_t * cache_ptr, * there is no previous item, it should be NULL. * * + * Fields supporting metadata journaling: + * + * last_trans: unit64_t containing the ID of the last transaction in + * which this entry was dirtied. If journaling is disabled, + * or if the entry has never been dirtied in a transaction, + * this field should be set to zero. Once we notice that + * the specified transaction has made it to disk, we will + * reset this field to zero as well. + * + * We must maintain this field, as to avoid messages from + * the future, we must not flush a dirty entry to disk + * until the last transaction in which it was dirtied + * has made it to disk in the journal file. + * + * trans_next: Next pointer in the entries modified in the current + * transaction list. This field should always be null + * unless journaling is enabled, the entry is dirty, + * and last_trans field contains the current transaction + * number. Even if all these conditions are fulfilled, + * the field will still be NULL if this is the last + * entry on the list. + * + * trans_prev: Previous pointer in the entries modified in the current + * transaction list. This field should always be null + * unless journaling is enabled, the entry is dirty, + * and last_trans field contains the current transaction + * number. Even if all these conditions are fulfilled, + * the field will still be NULL if this is the first + * entry on the list. + * + * * Cache entry stats collection fields: * * These fields should only be compiled in when both H5C2_COLLECT_CACHE_STATS @@ -844,6 +875,13 @@ typedef struct H5C2_cache_entry_t struct H5C2_cache_entry_t * aux_next; struct H5C2_cache_entry_t * aux_prev; + + /* fields supporting journaling */ + + uint64_t last_trans; + struct H5C2_cache_entry_t * trans_next; + struct H5C2_cache_entry_t * trans_prev; + #if H5C2_COLLECT_CACHE_ENTRY_STATS /* cache entry stats fields */ @@ -1268,14 +1306,17 @@ typedef struct H5C2_auto_size_ctl_t #define H5C2__READ_ONLY_FLAG 0x0400 #define H5C2__CHECK_SIZE_FLAG 0x0800 -H5_DLL H5C2_t * H5C2_create(size_t max_cache_size, +H5_DLL H5C2_t * H5C2_create(H5F_t * f, + hid_t dxpl_id, + size_t max_cache_size, size_t min_clean_size, int max_type_id, const char * (* type_name_table_ptr), H5C2_write_permitted_func_t check_write_permitted, hbool_t write_permitted, H5C2_log_flush_func_t log_flush, - void * aux_ptr); + void * aux_ptr, + hbool_t journal_recovered); H5_DLL void H5C2_def_auto_resize_rpt_fcn(H5C2_t * cache_ptr, int32_t version, @@ -1297,8 +1338,8 @@ H5_DLL herr_t H5C2_expunge_entry(H5F_t * f, haddr_t addr); H5_DLL herr_t H5C2_flush_cache(H5F_t *f, - hid_t dxpl_id, - unsigned flags); + hid_t dxpl_id, + unsigned flags); H5_DLL herr_t H5C2_flush_to_min_clean(H5F_t * f, @@ -1412,11 +1453,46 @@ H5_DLL herr_t H5C2_validate_resize_config(H5C2_auto_size_ctl_t * config_ptr, /***************** journaling function definitions proper: ****************/ /**************************************************************************/ -H5_DLL herr_t H5C2__begin_transaction(H5C2_t * cache_ptr, - uint64_t * trans_num_ptr); +H5_DLL herr_t H5C2_begin_journaling(H5F_t * f, + hid_t dxpl_id, + H5C2_t * cache_ptr, + char * journal_file_name_ptr, + size_t buf_size, + int num_bufs, + hbool_t use_aio, + hbool_t human_readable); + +H5_DLL herr_t H5C2_begin_transaction(H5C2_t * cache_ptr, + uint64_t * trans_num_ptr, + const char * api_call_name); + +H5_DLL herr_t H5C2_end_journaling(H5F_t * f, + hid_t dxpl_id, + H5C2_t * cache_ptr); -H5_DLL herr_t H5C2__end_transaction(H5C2_t * cache_ptr, - uint64_t trans_num); +H5_DLL herr_t H5C2_end_transaction(H5F_t * f, + H5C2_t * cache_ptr, + uint64_t trans_num, + const char * api_call_name); + +H5_DLL herr_t H5C2_get_journal_config(H5C2_t * cache_ptr, + hbool_t * journaling_enabled_ptr, + char * journal_file_path_ptr, + size_t * jbrb_buf_size_ptr, + int * jbrb_num_bufs_ptr, + hbool_t * jbrb_use_aio_ptr, + hbool_t * jbrb_human_readable_ptr); + +H5_DLL herr_t H5C2_journal_post_flush(H5C2_t * cache_ptr, + hbool_t cache_is_clean); + +H5_DLL herr_t H5C2_journal_pre_flush(H5C2_t * cache_ptr); + +H5_DLL herr_t H5C2_journal_transaction(H5F_t * f, + H5C2_t * cache_ptr); + +H5_DLL herr_t H5C2_update_for_new_last_trans_on_disk(H5C2_t * cache_ptr, + uint64_t new_last_trans_on_disk); /*****************************************************************************/ @@ -1433,7 +1509,7 @@ H5_DLL herr_t H5C2_jb__write_to_buffer(H5C2_jbrb_t * struct_ptr, size_t size, const char * data, hbool_t is_end_trans, - unsigned long trans_num); + uint64_t trans_num); H5_DLL herr_t H5C2_jb__init(H5C2_jbrb_t * struct_ptr, const char * HDF5_file_name, @@ -1444,22 +1520,22 @@ H5_DLL herr_t H5C2_jb__init(H5C2_jbrb_t * struct_ptr, hbool_t human_readable); H5_DLL herr_t H5C2_jb__start_transaction(H5C2_jbrb_t * struct_ptr, - unsigned long trans_num); + uint64_t trans_num); H5_DLL herr_t H5C2_jb__journal_entry(H5C2_jbrb_t * struct_ptr, - unsigned long trans_num, + uint64_t trans_num, haddr_t base_addr, size_t length, const uint8_t * body); H5_DLL herr_t H5C2_jb__end_transaction(H5C2_jbrb_t * struct_ptr, - unsigned long trans_num); + uint64_t trans_num); H5_DLL herr_t H5C2_jb__comment(H5C2_jbrb_t * struct_ptr, const char * comment_ptr); H5_DLL herr_t H5C2_jb__get_last_transaction_on_disk(H5C2_jbrb_t * struct_ptr, - unsigned long * trans_num_ptr); + uint64_t * trans_num_ptr); H5_DLL herr_t H5C2_jb__trunc(H5C2_jbrb_t * struct_ptr); @@ -1480,6 +1556,11 @@ H5_DLL herr_t H5C2_jb__bin2hex(const uint8_t * buf, /********** journal config block management function definitions: ************/ /*****************************************************************************/ +H5_DLL herr_t H5C2_check_for_journaling(H5F_t * f, + hid_t dxpl_id, + H5C2_t * cache_ptr, + hbool_t journal_recovered); + H5_DLL herr_t H5C2_create_journal_config_block(H5F_t *f, hid_t dxpl_id, const char * journal_file_name_ptr); @@ -1487,11 +1568,13 @@ H5_DLL herr_t H5C2_create_journal_config_block(H5F_t *f, H5_DLL herr_t H5C2_discard_journal_config_block(H5F_t * f, hid_t dxpl_id); -H5_DLL herr_t H5C2_get_journaling_in_progress(H5F_t * f, - hid_t dxpl_id); +H5_DLL herr_t H5C2_get_journaling_in_progress(const H5F_t * f, + hid_t dxpl_id, + H5C2_t * cache_ptr); -H5_DLL herr_t H5C2_load_journal_config_block(H5F_t * f, +H5_DLL herr_t H5C2_load_journal_config_block(const H5F_t * f, hid_t dxpl_id, + H5C2_t * cache_ptr, haddr_t block_addr, hsize_t block_len); @@ -1500,7 +1583,8 @@ H5_DLL herr_t H5C2_mark_journaling_in_progress(H5F_t * f, const char * journal_file_name_ptr); H5_DLL herr_t H5C2_unmark_journaling_in_progress(H5F_t * f, - hid_t dxpl_id); + hid_t dxpl_id, + H5C2_t * cache_ptr); diff --git a/src/H5D.c b/src/H5D.c index 684ccf4..b120736 100644 --- a/src/H5D.c +++ b/src/H5D.c @@ -32,6 +32,7 @@ #include "H5Eprivate.h" /* Error handling */ #include "H5FLprivate.h" /* Free lists */ #include "H5Iprivate.h" /* IDs */ +#include "H5AC2private.h" /* Metadata cache */ /****************/ @@ -133,7 +134,7 @@ H5Dcreate2(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, const H5S_t *space; /* Dataspace for dataset */ hid_t ret_value; /* Return value */ - FUNC_ENTER_API_META(H5Dcreate2, FAIL) + FUNC_ENTER_API_META(H5Dcreate2, loc_id, FAIL) H5TRACE7("i", "i*siiiii", loc_id, name, type_id, space_id, lcpl_id, dcpl_id, dapl_id); @@ -226,7 +227,7 @@ H5Dcreate_anon(hid_t loc_id, hid_t type_id, hid_t space_id, hid_t dcpl_id, const H5S_t *space; /* Dataspace for dataset */ hid_t ret_value; /* Return value */ - FUNC_ENTER_API_META(H5Dcreate_anon, FAIL) + FUNC_ENTER_API_META(H5Dcreate_anon, loc_id, FAIL) H5TRACE5("i", "iiiii", loc_id, type_id, space_id, dcpl_id, dapl_id); /* Check arguments */ @@ -372,7 +373,7 @@ H5Dclose(hid_t dset_id) H5D_t *dset; /* Dataset object to release */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Dclose, FAIL) + FUNC_ENTER_API_META(H5Dclose, dset_id, FAIL) H5TRACE1("e", "i", dset_id); /* Check args */ @@ -994,7 +995,7 @@ H5Dset_extent(hid_t dset_id, const hsize_t *size) H5D_t *dset; /* Dataset for this operation */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Dset_extent, FAIL) + FUNC_ENTER_API_META(H5Dset_extent, dset_id, FAIL) H5TRACE2("e", "i*h", dset_id, size); /* Check args */ diff --git a/src/H5Ddeprec.c b/src/H5Ddeprec.c index 7d6cc02..2810f5a 100644 --- a/src/H5Ddeprec.c +++ b/src/H5Ddeprec.c @@ -45,6 +45,7 @@ #include "H5Dpkg.h" /* Datasets */ #include "H5Eprivate.h" /* Error handling */ #include "H5Iprivate.h" /* IDs */ +#include "H5AC2private.h" /* Metadata cache */ /****************/ @@ -147,7 +148,7 @@ H5Dcreate1(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, const H5S_t *space; /* Dataspace for dataset */ hid_t ret_value; /* Return value */ - FUNC_ENTER_API_META(H5Dcreate1, FAIL) + FUNC_ENTER_API_META(H5Dcreate1, loc_id, FAIL) H5TRACE5("i", "i*siii", loc_id, name, type_id, space_id, dcpl_id); /* Check arguments */ @@ -284,7 +285,7 @@ H5Dextend(hid_t dset_id, const hsize_t *size) H5D_t *dset; herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Dextend, FAIL) + FUNC_ENTER_API_META(H5Dextend, dset_id, FAIL) H5TRACE2("e", "i*h", dset_id, size); /* Check args */ diff --git a/src/H5Dio.c b/src/H5Dio.c index a3148c8..78140e0 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -32,6 +32,7 @@ #include "H5Sprivate.h" /* Dataspace functions */ #include "H5SLprivate.h" /* Skip lists */ #include "H5Vprivate.h" /* Vector and array functions */ +#include "H5AC2private.h" /* Metadata cache */ #ifdef H5_HAVE_PARALLEL /* Remove this if H5R_DATASET_REGION is no longer used in this file */ @@ -388,7 +389,7 @@ H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, char fake_char; herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Dwrite, FAIL) + FUNC_ENTER_API_META(H5Dwrite, dset_id, FAIL) H5TRACE6("e", "iiiii*x", dset_id, mem_type_id, mem_space_id, file_space_id, plist_id, buf); diff --git a/src/H5F.c b/src/H5F.c index 4bac4a7..e5b191d 100644 --- a/src/H5F.c +++ b/src/H5F.c @@ -935,8 +935,13 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf) /* Create a metadata cache with modified API along side the regular * version. For now, this is just for testing. Once we get it * fully in use, we will delete the old version. + * + * Note the use of H5P_DATASET_XFER_DEFAULT for the dxpl_id parameter + * of H5AC2_create(). We may want to change this. */ - if(H5AC2_create(f, (H5AC2_cache_config_t *)&(f->shared->mdc_initCacheCfg)) < 0) + if(H5AC2_create(f, H5P_DATASET_XFER_DEFAULT, + (H5AC2_cache_config_t *)&(f->shared->mdc_initCacheCfg)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create meta data cache2") /* Create the file's "open object" information */ @@ -1432,7 +1437,8 @@ H5Fcreate(const char *filename, unsigned flags, hid_t fcpl_id, hid_t fapl_id) H5F_t *new_file = NULL; /*file struct for new file */ hid_t ret_value; /*return value */ - FUNC_ENTER_API_META(H5Fcreate, FAIL) + /* can't journal at this point, as the file doesn't exist yet. */ + FUNC_ENTER_API(H5Fcreate, FAIL) H5TRACE4("i", "*sIuii", filename, flags, fcpl_id, fapl_id); /* Check/fix arguments */ @@ -1484,7 +1490,7 @@ done: if(H5F_close(new_file) < 0) HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problems closing file") - FUNC_LEAVE_API_META(ret_value) + FUNC_LEAVE_API(ret_value) } /* end H5Fcreate() */ @@ -1534,7 +1540,13 @@ H5Fopen(const char *filename, unsigned flags, hid_t fapl_id) H5F_t *new_file = NULL; /*file struct for new file */ hid_t ret_value; /*return value */ - FUNC_ENTER_API_META(H5Fopen, FAIL) + /* can't journal at this point as the file is not open */ + /* In theory, opening the file shouldn't generate any dirty metadata, + * but we do have one case where we fix some object automatically + * when we first touch it. Can this happen here? If so, we will + * have to do somethings to start a transaction before this happens. + */ + FUNC_ENTER_API(H5Fopen, FAIL) H5TRACE3("i", "*sIui", filename, flags, fapl_id); /* Check/fix arguments. */ @@ -1564,7 +1576,7 @@ done: if(ret_value < 0 && new_file && H5F_try_close(new_file) < 0) HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problems closing file") - FUNC_LEAVE_API_META(ret_value) + FUNC_LEAVE_API(ret_value) } /* end H5Fopen() */ @@ -1601,7 +1613,8 @@ H5Fflush(hid_t object_id, H5F_scope_t scope) H5O_loc_t *oloc = NULL; herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Fflush, FAIL) + /* don't start a transaction here, as a flush must not modify metadata. */ + FUNC_ENTER_API(H5Fflush, FAIL) H5TRACE2("e", "iFs", object_id, scope); switch(H5I_get_type(object_id)) { @@ -1651,7 +1664,7 @@ H5Fflush(hid_t object_id, H5F_scope_t scope) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "flush failed") done: - FUNC_LEAVE_API_META(ret_value) + FUNC_LEAVE_API(ret_value) } /* end H5Fflush() */ @@ -2011,7 +2024,8 @@ H5Fclose(hid_t file_id) { herr_t ret_value = SUCCEED; - FUNC_ENTER_API_META(H5Fclose, FAIL) + /* This function shouldn't change metadata, so don't start a transaction */ + FUNC_ENTER_API(H5Fclose, FAIL) H5TRACE1("e", "i", file_id); /* Check/fix arguments. */ @@ -2026,7 +2040,7 @@ H5Fclose(hid_t file_id) HGOTO_ERROR(H5E_ATOM, H5E_CANTCLOSEFILE, FAIL, "decrementing file ID failed") done: - FUNC_LEAVE_API_META(ret_value) + FUNC_LEAVE_API(ret_value) } /* end H5Fclose() */ @@ -2059,7 +2073,8 @@ H5Freopen(hid_t file_id) H5F_t *new_file = NULL; hid_t ret_value; - FUNC_ENTER_API_META(H5Freopen, FAIL) + /* should be no metadata changes, so done start a transaction */ + FUNC_ENTER_API(H5Freopen, FAIL) H5TRACE1("i", "i", file_id); /* Check arguments */ @@ -2087,7 +2102,7 @@ done: if(H5F_dest(new_file, H5AC_dxpl_id) < 0) HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file") - FUNC_LEAVE_API_META(ret_value) + FUNC_LEAVE_API(ret_value) } /* end H5Freopen() */ @@ -3369,6 +3384,7 @@ H5Fset_mdc_config(hid_t file_id, /* pass the resize configuration to the modified cache as well. */ result = H5AC2_set_cache_auto_resize_config(file, + H5P_DATASET_XFER_DEFAULT, (H5AC2_cache_config_t *)config_ptr); if ( result != SUCCEED ) { diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h index 291fc88..b68f141 100644 --- a/src/H5FDpublic.h +++ b/src/H5FDpublic.h @@ -89,19 +89,12 @@ typedef enum H5FD_mem_t { #define H5FD_MEM_SOHM_TABLE H5FD_MEM_OHDR #define H5FD_MEM_SOHM_INDEX H5FD_MEM_BTREE -/* Map metadata journaling configuration block to raw for now, as it is of - * arbitrary size, and the metadata cache will be managing it directly, - * without passing it through the metadata cache proper. +/* Per discussion with Quincey, I'm mapping the metadata journaling + * configuration block to super. * - * JRM -- 3/11/08 - * - * Quincey: I suspect this is bogus. However, I gather that adding a - * new memory type is a bit of a bother, so I'm trying to avoid - * it until I talk to you. Please let me know what you think - * I should do here. - * -- JRM + * JRM -- 3/20/08 */ -#define H5FD_MEM_MDJCONFIG H5FD_MEM_DRAW +#define H5FD_MEM_MDJCONFIG H5FD_MEM_SUPER /* * A free-list map which maps all types of allocation requests to a single diff --git a/src/H5Fmount.c b/src/H5Fmount.c index 92882ae..7eee769 100644 --- a/src/H5Fmount.c +++ b/src/H5Fmount.c @@ -27,6 +27,7 @@ #include "H5Iprivate.h" /* IDs */ #include "H5Pprivate.h" /* Property lists */ #include "H5MMprivate.h" /* Memory management */ +#include "H5AC2private.h" /* Metadata cache */ /* PRIVATE PROTOTYPES */ static herr_t H5F_mount(H5G_loc_t *loc, const char *name, H5F_t *child, @@ -482,7 +483,12 @@ H5Fmount(hid_t loc_id, const char *name, hid_t child_id, hid_t plist_id) H5F_t *child = NULL; herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Fmount, FAIL) + /* Not sure this will generate any dirty metadata... + * + * Also we must work out how we are going to deal with journaling + * in such cases. + */ + FUNC_ENTER_API_META(H5Fmount, loc_id, FAIL) H5TRACE4("e", "i*sii", loc_id, name, child_id, plist_id); /* Check arguments */ @@ -532,7 +538,12 @@ H5Funmount(hid_t loc_id, const char *name) H5G_loc_t loc; herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Funmount, FAIL) + /* Not sure that this will generate any dirty metadata. + * + * Also, must decide how we are going to deal with journaling + * in such cases. + */ + FUNC_ENTER_API_META(H5Funmount, loc_id, FAIL) H5TRACE2("e", "i*s", loc_id, name); /* Check args */ diff --git a/src/H5G.c b/src/H5G.c index 8af54d9..256edc3 100644 --- a/src/H5G.c +++ b/src/H5G.c @@ -89,6 +89,7 @@ #include "H5Iprivate.h" /* IDs */ #include "H5Lprivate.h" /* Links */ #include "H5Pprivate.h" /* Property lists */ +#include "H5AC2private.h" /* Metadata cache */ /* Local macros */ #define H5G_RESERVED_ATOMS 0 @@ -146,7 +147,7 @@ H5Gcreate2(hid_t loc_id, const char *name, hid_t lcpl_id, hid_t gcpl_id, H5G_t *grp = NULL; /* New group created */ hid_t ret_value; /* Return value */ - FUNC_ENTER_API_META(H5Gcreate2, FAIL) + FUNC_ENTER_API_META(H5Gcreate2, loc_id, FAIL) H5TRACE5("i", "i*siii", loc_id, name, lcpl_id, gcpl_id, gapl_id); /* Check arguments */ @@ -286,7 +287,7 @@ H5Gcreate_anon(hid_t loc_id, hid_t gcpl_id, hid_t gapl_id) H5G_t *grp = NULL; hid_t ret_value; - FUNC_ENTER_API_META(H5Gcreate_anon, FAIL) + FUNC_ENTER_API_META(H5Gcreate_anon, loc_id, FAIL) H5TRACE3("i", "iii", loc_id, gcpl_id, gapl_id); /* Check arguments */ @@ -661,7 +662,8 @@ H5Gclose(hid_t group_id) { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Gclose, FAIL) + /* Can this change metadata? If not, no need for a transaction. */ + FUNC_ENTER_API_META(H5Gclose, group_id, FAIL) H5TRACE1("e", "i", group_id); /* Check args */ diff --git a/src/H5Gdeprec.c b/src/H5Gdeprec.c index 03a380b..07de86a 100644 --- a/src/H5Gdeprec.c +++ b/src/H5Gdeprec.c @@ -46,6 +46,7 @@ #include "H5Iprivate.h" /* IDs */ #include "H5Lprivate.h" /* Links */ #include "H5Pprivate.h" /* Property lists */ +#include "H5AC2private.h" /* Metadata cache */ /****************/ @@ -203,7 +204,7 @@ H5Gcreate1(hid_t loc_id, const char *name, size_t size_hint) hid_t tmp_gcpl = (-1); /* Temporary group creation property list */ hid_t ret_value; /* Return value */ - FUNC_ENTER_API_META(H5Gcreate1, FAIL) + FUNC_ENTER_API_META(H5Gcreate1, loc_id, FAIL) H5TRACE3("i", "i*sz", loc_id, name, size_hint); /* Check arguments */ @@ -325,7 +326,7 @@ H5Glink(hid_t cur_loc_id, H5G_link_t type, const char *cur_name, const char *new { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Glink, FAIL) + FUNC_ENTER_API_META(H5Glink, cur_loc_id, FAIL) H5TRACE4("e", "iLl*s*s", cur_loc_id, type, cur_name, new_name); /* Check arguments */ @@ -371,7 +372,7 @@ H5Glink2(hid_t cur_loc_id, const char *cur_name, H5G_link_t type, { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Glink2, FAIL) + FUNC_ENTER_API_META(H5Glink2, cur_loc_id, FAIL) H5TRACE5("e", "i*sLli*s", cur_loc_id, cur_name, type, new_loc_id, new_name); /* Check arguments */ @@ -474,7 +475,7 @@ H5Gmove(hid_t src_loc_id, const char *src_name, const char *dst_name) { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Gmove, FAIL) + FUNC_ENTER_API_META(H5Gmove, src_loc_id, FAIL) H5TRACE3("e", "i*s*s", src_loc_id, src_name, dst_name); /* Call common routine to move the link */ @@ -499,7 +500,7 @@ H5Gmove2(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id, { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Gmove2, FAIL) + FUNC_ENTER_API_META(H5Gmove2, src_loc_id, FAIL) H5TRACE4("e", "i*si*s", src_loc_id, src_name, dst_loc_id, dst_name); /* Call common routine to move the link */ @@ -581,7 +582,7 @@ H5Gunlink(hid_t loc_id, const char *name) H5G_loc_t loc; /* Group's location */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Gunlink, FAIL) + FUNC_ENTER_API_META(H5Gunlink, loc_id, FAIL) H5TRACE2("e", "i*s", loc_id, name); /* Check arguments */ @@ -654,7 +655,7 @@ H5Gset_comment(hid_t loc_id, const char *name, const char *comment) H5G_loc_t loc; herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Gset_comment, FAIL) + FUNC_ENTER_API_META(H5Gset_comment, loc_id, FAIL) H5TRACE3("e", "i*s*s", loc_id, name, comment); if(H5G_loc(loc_id, &loc) < 0) diff --git a/src/H5I.c b/src/H5I.c index 97e1f99..195c0e7 100644 --- a/src/H5I.c +++ b/src/H5I.c @@ -48,6 +48,7 @@ #include "H5Ipkg.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ #include "H5Oprivate.h" /* Object headers */ +#include "H5AC2private.h" /* Metadata cache */ /* Define this to compile in support for dumping ID information */ /* #define H5I_DEBUG_OUTPUT */ @@ -1261,7 +1262,7 @@ H5Idec_ref(hid_t id) { int ret_value; /* Return value */ - FUNC_ENTER_API_META(H5Idec_ref, FAIL); + FUNC_ENTER_API_META(H5Idec_ref, id, FAIL); H5TRACE1("Is", "i", id); /* Check arguments */ @@ -1386,7 +1387,7 @@ H5Iinc_ref(hid_t id) { int ret_value; /* Return value */ - FUNC_ENTER_API_META(H5Iinc_ref, FAIL); + FUNC_ENTER_API_META(H5Iinc_ref, id, FAIL); H5TRACE1("Is", "i", id); /* Check arguments */ diff --git a/src/H5L.c b/src/H5L.c index d90bdcc..238815a 100644 --- a/src/H5L.c +++ b/src/H5L.c @@ -37,6 +37,7 @@ #include "H5MMprivate.h" /* Memory management */ #include "H5Oprivate.h" /* File objects */ #include "H5Pprivate.h" /* Property lists */ +#include "H5AC2private.h" /* Metadata cache */ /****************/ /* Local Macros */ @@ -314,7 +315,7 @@ H5Lmove(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id, H5G_loc_t dst_loc, *dst_loc_p; herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Lmove, FAIL) + FUNC_ENTER_API_META(H5Lmove, src_loc_id, FAIL) H5TRACE6("e", "i*si*sii", src_loc_id, src_name, dst_loc_id, dst_name, lcpl_id, lapl_id); @@ -372,7 +373,7 @@ H5Lcopy(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id, H5G_loc_t dst_loc, *dst_loc_p; herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Lcopy, FAIL) + FUNC_ENTER_API_META(H5Lcopy, src_loc_id, FAIL) H5TRACE6("e", "i*si*sii", src_loc_id, src_name, dst_loc_id, dst_name, lcpl_id, lapl_id); @@ -433,7 +434,7 @@ H5Lcreate_soft(const char *link_target, H5G_loc_t link_loc; /* Group location for new link */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Lcreate_soft, FAIL) + FUNC_ENTER_API_META(H5Lcreate_soft, link_loc_id, FAIL) H5TRACE5("e", "*si*sii", link_target, link_loc_id, link_name, lcpl_id, lapl_id); /* Check arguments */ @@ -479,7 +480,7 @@ H5Lcreate_hard(hid_t cur_loc_id, const char *cur_name, H5G_loc_t new_loc, *new_loc_p; herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Lcreate_hard, FAIL) + FUNC_ENTER_API_META(H5Lcreate_hard, cur_loc_id, FAIL) H5TRACE6("e", "i*si*sii", cur_loc_id, cur_name, new_loc_id, new_name, lcpl_id, lapl_id); @@ -548,7 +549,7 @@ H5Lcreate_ud(hid_t link_loc_id, const char *link_name, H5L_type_t link_type, H5G_loc_t link_loc; herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Lcreate_ud, FAIL) + FUNC_ENTER_API_META(H5Lcreate_ud, link_loc_id, FAIL) H5TRACE7("e", "i*sLl*xzii", link_loc_id, link_name, link_type, udata, udata_size, lcpl_id, lapl_id); @@ -590,7 +591,7 @@ H5Ldelete(hid_t loc_id, const char *name, hid_t lapl_id) H5G_loc_t loc; /* Group's location */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Ldelete, FAIL) + FUNC_ENTER_API_META(H5Ldelete, loc_id, FAIL) H5TRACE3("e", "i*si", loc_id, name, lapl_id); /* Check arguments */ @@ -635,7 +636,7 @@ H5Ldelete_by_idx(hid_t loc_id, const char *group_name, H5L_trav_rmbi_t udata; /* User data for callback */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Ldelete_by_idx, FAIL) + FUNC_ENTER_API_META(H5Ldelete_by_idx, loc_id, FAIL) H5TRACE6("e", "i*sIiIohi", loc_id, group_name, idx_type, order, n, lapl_id); /* Check arguments */ diff --git a/src/H5Lexternal.c b/src/H5Lexternal.c index 43751b3..70ed4b3 100644 --- a/src/H5Lexternal.c +++ b/src/H5Lexternal.c @@ -25,8 +25,9 @@ #include "H5Iprivate.h" /* IDs */ #include "H5Lpkg.h" /* Links */ #include "H5MMprivate.h" /* Memory management */ -#include "H5Opublic.h" /* File objects */ +#include "H5Opublic.h" /* File objects */ #include "H5Pprivate.h" /* Property lists */ +#include "H5AC2private.h" /* Metadata cache */ static hid_t H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group, const void *udata, size_t UNUSED udata_size, hid_t lapl_id); @@ -311,7 +312,7 @@ H5Lcreate_external(const char *file_name, const char *obj_name, uint8_t *p; /* Pointer into external link buffer */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Lcreate_external, FAIL) + FUNC_ENTER_API_META(H5Lcreate_external, link_loc_id, FAIL) H5TRACE6("e", "*s*si*sii", file_name, obj_name, link_loc_id, link_name, lcpl_id, lapl_id); diff --git a/src/H5O.c b/src/H5O.c index 9f666d0..f72fe7e 100644 --- a/src/H5O.c +++ b/src/H5O.c @@ -46,6 +46,7 @@ #include "H5MFprivate.h" /* File memory management */ #include "H5Opkg.h" /* Object headers */ #include "H5SMprivate.h" /* Shared object header messages */ +#include "H5AC2private.h" /* Metadata cache */ /****************/ @@ -411,7 +412,7 @@ H5Olink(hid_t obj_id, hid_t new_loc_id, const char *new_name, hid_t lcpl_id, H5G_loc_t obj_loc; herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Olink, FAIL) + FUNC_ENTER_API_META(H5Olink, obj_id, FAIL) H5TRACE5("e", "ii*sii", obj_id, new_loc_id, new_name, lcpl_id, lapl_id); /* Check arguments */ @@ -463,7 +464,7 @@ H5Oincr_refcount(hid_t object_id) H5O_loc_t *oloc; herr_t ret_value = SUCCEED; - FUNC_ENTER_API_META(H5Oincr_refcount, FAIL) + FUNC_ENTER_API_META(H5Oincr_refcount, object_id, FAIL) H5TRACE1("e", "i", object_id); /* Get the object's oloc so we can adjust its link count */ @@ -504,7 +505,7 @@ H5Odecr_refcount(hid_t object_id) H5O_loc_t *oloc; herr_t ret_value = SUCCEED; - FUNC_ENTER_API_META(H5Odecr_refcount, FAIL) + FUNC_ENTER_API_META(H5Odecr_refcount, object_id, FAIL) H5TRACE1("e", "i", object_id); /* Get the object's oloc so we can adjust its link count */ @@ -692,7 +693,7 @@ H5Oset_comment(hid_t obj_id, const char *comment) H5G_loc_t loc; /* Location of group */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Oset_comment, FAIL) + FUNC_ENTER_API_META(H5Oset_comment, obj_id, FAIL) H5TRACE2("e", "i*s", obj_id, comment); /* Check args */ @@ -732,7 +733,7 @@ H5Oset_comment_by_name(hid_t loc_id, const char *name, const char *comment, H5G_loc_t loc; /* Location of group */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Oset_comment_by_name, FAIL) + FUNC_ENTER_API_META(H5Oset_comment_by_name, loc_id, FAIL) H5TRACE4("e", "i*s*si", loc_id, name, comment, lapl_id); /* Check args */ @@ -862,7 +863,10 @@ H5Oclose(hid_t object_id) { herr_t ret_value = SUCCEED; - FUNC_ENTER_API_META(H5Oclose, FAIL) + /* Will this ever change metadata? No need for a transaction unless + * it does. + */ + FUNC_ENTER_API_META(H5Oclose, object_id, FAIL) H5TRACE1("e", "i", object_id); /* Get the type of the object and close it in the correct way */ diff --git a/src/H5Ocopy.c b/src/H5Ocopy.c index 334883d..5233f79 100644 --- a/src/H5Ocopy.c +++ b/src/H5Ocopy.c @@ -43,6 +43,8 @@ #include "H5MMprivate.h" /* Memory management */ #include "H5Opkg.h" /* Object headers */ #include "H5Pprivate.h" /* Property lists */ +#include "H5AC2private.h" /* Metadata cache */ + /****************/ /* Local Macros */ @@ -185,7 +187,7 @@ H5Ocopy(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id, herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Ocopy, FAIL) + FUNC_ENTER_API_META(H5Ocopy, dst_loc_id, FAIL) H5TRACE6("e", "i*si*sii", src_loc_id, src_name, dst_loc_id, dst_name, ocpypl_id, lcpl_id); diff --git a/src/H5R.c b/src/H5R.c index c68cf5d..63da596 100644 --- a/src/H5R.c +++ b/src/H5R.c @@ -29,6 +29,7 @@ #include "H5MMprivate.h" /* Memory management */ #include "H5Rpkg.h" /* References */ #include "H5Sprivate.h" /* Dataspaces */ +#include "H5AC2private.h" /* Metadata cache */ /* Local macro definitions */ @@ -311,7 +312,7 @@ H5Rcreate(void *ref, hid_t loc_id, const char *name, H5R_type_t ref_type, hid_t H5S_t *space = NULL; /* Pointer to dataspace containing region */ herr_t ret_value; /* Return value */ - FUNC_ENTER_API_META(H5Rcreate, FAIL) + FUNC_ENTER_API_META(H5Rcreate, loc_id, FAIL) H5TRACE5("e", "*xi*sRti", ref, loc_id, name, ref_type, space_id); /* Check args */ diff --git a/src/H5T.c b/src/H5T.c index e0a7faa..ea5957d 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -38,6 +38,7 @@ #include "H5MMprivate.h" /*memory management */ #include "H5Pprivate.h" /* Property Lists */ #include "H5Tpkg.h" /*data-type functions */ +#include "H5AC2private.h" /* Metadata cache */ /* Check for header needed for SGI floating-point code */ #ifdef H5_HAVE_SYS_FPU_H @@ -1700,7 +1701,7 @@ H5Tclose(hid_t type_id) H5T_t *dt = NULL; herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Tclose, FAIL) + FUNC_ENTER_API_META(H5Tclose, type_id, FAIL) H5TRACE1("e", "i", type_id); /* Check args */ diff --git a/src/H5Tcommit.c b/src/H5Tcommit.c index 0beeeea..885227a 100644 --- a/src/H5Tcommit.c +++ b/src/H5Tcommit.c @@ -32,6 +32,7 @@ #include "H5Lprivate.h" /* Links */ #include "H5Pprivate.h" /* Property lists */ #include "H5Tpkg.h" /* Datatypes */ +#include "H5AC2private.h" /* Metadata cache */ /* Static local functions */ static H5T_t *H5T_open_oid(const H5G_loc_t *loc, hid_t dxpl_id); @@ -80,7 +81,7 @@ H5Tcommit2(hid_t loc_id, const char *name, hid_t type_id, hid_t lcpl_id, H5T_t *type; /* Datatype for ID */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Tcommit2, FAIL) + FUNC_ENTER_API_META(H5Tcommit2, loc_id, FAIL) H5TRACE6("e", "i*siiii", loc_id, name, type_id, lcpl_id, tcpl_id, tapl_id); /* Check arguments */ @@ -229,7 +230,7 @@ H5Tcommit_anon(hid_t loc_id, hid_t type_id, hid_t tcpl_id, hid_t tapl_id) H5T_t *type = NULL; herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Tcommit_anon, FAIL) + FUNC_ENTER_API_META(H5Tcommit_anon, loc_id, FAIL) H5TRACE4("e", "iiii", loc_id, type_id, tcpl_id, tapl_id); /* Check arguments */ diff --git a/src/H5Tdeprec.c b/src/H5Tdeprec.c index 0ddf26e..fad2b05 100644 --- a/src/H5Tdeprec.c +++ b/src/H5Tdeprec.c @@ -46,6 +46,7 @@ #include "H5FOprivate.h" /* File objects */ #include "H5Iprivate.h" /* IDs */ #include "H5Tpkg.h" /* Datatypes */ +#include "H5AC2private.h" /* Metadata cache */ #ifndef H5_NO_DEPRECATED_SYMBOLS @@ -128,7 +129,7 @@ H5Tcommit1(hid_t loc_id, const char *name, hid_t type_id) H5T_t *type; /* Datatype for ID */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API_META(H5Tcommit1, FAIL) + FUNC_ENTER_API_META(H5Tcommit1, loc_id, FAIL) H5TRACE3("e", "i*si", loc_id, name, type_id); /* Check arguments */ diff --git a/src/H5private.h b/src/H5private.h index 54f99ac1..48fbd01 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -1233,14 +1233,26 @@ static herr_t H5_INTERFACE_INIT_FUNC(void); { /* Use this macro for API functions that [could] modify metadata */ -#define FUNC_ENTER_API_META(func_name,err) {{ \ + +#define FUNC_ENTER_API_META(func_name, id, err) {{ \ FUNC_ENTER_API_VARS(func_name) \ FUNC_ENTER_COMMON(func_name,H5_IS_API(#func_name)); \ FUNC_ENTER_API_THREADSAFE; \ FUNC_ENTER_API_COMMON(func_name,err); \ /* Clear thread error stack entering public functions */ \ - H5E_clear_stack(NULL); \ - { + H5E_clear_stack(NULL); \ + { \ + uint64_t trans_num = 0; \ + H5O_loc_t id_oloc; \ + hbool_t do_transaction = FALSE; \ + hbool_t id_oloc_open = FALSE; \ + hbool_t transaction_begun = FALSE; \ + if (H5AC2_begin_transaction(id, &do_transaction, &id_oloc, \ + &id_oloc_open, &transaction_begun, \ + &trans_num, FUNC) < 0) { \ + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, err, \ + "H5AC2_begin_transaction() failed."); \ + } /* * Use this macro for API functions that shouldn't clear the error stack @@ -1388,7 +1400,14 @@ static herr_t H5_INTERFACE_INIT_FUNC(void); }} /*end scope from beginning of FUNC_ENTER*/ /* Use this macro to match the FUNC_ENTER_API_META macro */ + #define FUNC_LEAVE_API_META(ret_value) \ + if ( H5AC2_end_transaction(do_transaction, &id_oloc, \ + id_oloc_open, transaction_begun, \ + trans_num, FUNC) < 0 ) { \ + HDONE_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5AC2_end_transaction() failed."); \ + } \ FINISH_MPE_LOG; \ H5TRACE_RETURN(ret_value); \ H5_POP_FUNC; \ diff --git a/test/cache2.c b/test/cache2.c index f414184..a769ab7 100644 --- a/test/cache2.c +++ b/test/cache2.c @@ -16431,6 +16431,8 @@ check_flush_protected_err(void) *------------------------------------------------------------------------- */ +extern H5C2_t * saved_cache2; + static unsigned check_destroy_pinned_err(void) { @@ -16465,17 +16467,21 @@ check_destroy_pinned_err(void) unpin_entry2(file_ptr, 0, 0); -/* FIXME: Related to earlier hack with same tag, have John check for - * correctness... -QAK - */ -#ifdef OLD_WAY if ( H5C2_dest(file_ptr, H5P_DATASET_XFER_DEFAULT) < 0 ) { pass2 = FALSE; failure_mssg2 = "destroy failed after unpin.\n"; - } -#endif /* OLD_WAY */ + } else { + file_ptr->shared->cache2 = NULL; + } + } + + if ( saved_cache2 != NULL ) { + + file_ptr->shared->cache2 = saved_cache2; + saved_cache2 = NULL; + } /* call takedown_cache2() with a NULL file_ptr parameter. @@ -16549,17 +16555,21 @@ check_destroy_protected_err(void) unprotect_entry2(file_ptr, 0, 0, TRUE, H5C2__NO_FLAGS_SET); -/* FIXME: Related to earlier hack with same tag, have John check for - * correctness... -QAK - */ -#ifdef OLD_WAY if ( H5C2_dest(file_ptr, H5P_DATASET_XFER_DEFAULT) < 0 ) { pass2 = FALSE; failure_mssg2 = "destroy failed after unprotect.\n"; - } -#endif /* OLD_WAY */ + } else { + file_ptr->shared->cache2 = NULL; + } + } + + if ( saved_cache2 != NULL ) { + + file_ptr->shared->cache2 = saved_cache2; + saved_cache2 = NULL; + } /* call takedown_cache2() with a NULL file_ptr parameter. diff --git a/test/cache2_common.c b/test/cache2_common.c index 332ab36..d0571ed 100644 --- a/test/cache2_common.c +++ b/test/cache2_common.c @@ -40,6 +40,11 @@ const char *FILENAME[] = { hid_t saved_fid = -1; /* store the file id here between cache setup * and takedown. */ +H5C2_t * saved_cache2 = NULL; /* store the pointer to the instance of + * of H5C2_t created by H5Fcreate() + * here between test cache setup and + * shutdown. + */ hbool_t write_permitted2 = TRUE; hbool_t pass2 = TRUE; /* set to false on error */ @@ -1888,7 +1893,7 @@ entry_in_cache2(H5C2_t * cache_ptr, HDassert( entry_ptr->type == type ); HDassert( entry_ptr == entry_ptr->self ); - H5C2__SEARCH_INDEX(cache_ptr, entry_ptr->addr, test_ptr) + H5C2_TEST__SEARCH_INDEX(cache_ptr, entry_ptr->addr, test_ptr) if ( test_ptr != NULL ) { @@ -2592,7 +2597,11 @@ verify_unprotected2(void) * * Modifications: * - * None. + * Updated for changes in the parameter list of H5C2_create(). + * These changes are needed for journaling. We do nothing + * with these parameters here -- will write another version + * of this routine for journaling tests. + * JRM -- 3/27/08 * *****************************************************************************/ @@ -2725,11 +2734,42 @@ setup_cache2(size_t max_cache_size, if ( pass2 ) { -/* FIXME: I'm in a hurry here, I'll need to talk to John about the best way - * to do this right... -QAK - */ -#ifdef OLD_WAY + /* A bit of fancy footwork here: + * + * The call to H5Fcreate() allocates an instance of H5C2_t, + * initializes it, and stores its address in f->shared->cache2. + * + * We don't want to use this cache, as it has a bunch of extra + * initialization that may change over time, and in any case + * it will not in general be configured the way we want it. + * + * We used to deal with this problem by storing the file pointer + * in another instance of H5C2_t, and then ignoring the original + * version. However, this strategy doesn't work any more, as + * we can't store the file pointer in the instance of H5C2_t, + * and we have modified many cache2 routines to use a file + * pointer to look up the target cache. + * + * Thus we now make note of the address of the instance of + * H5C2_t created by the call to H5Fcreate(), set + * file_ptr->shared->cache2 to NULL, call H5C2_create() + * to allocate a new instance of H5C2_t for test purposes, + * and store than new instance's address in + * file_ptr->shared->cache2. + * + * On shut down, we call H5C2_dest on our instance of H5C2_t, + * set file_ptr->shared->cache2 to point to the original + * instance, and then close the file normally. + */ + + HDassert( saved_cache2 == NULL ); + + saved_cache2 = file_ptr->shared->cache2; + + file_ptr->shared->cache2 = NULL; + cache_ptr = H5C2_create(file_ptr, + H5P_DATASET_XFER_DEFAULT, max_cache_size, min_clean_size, (NUMBER_OF_ENTRY_TYPES - 1), @@ -2737,21 +2777,10 @@ setup_cache2(size_t max_cache_size, check_write_permitted2, TRUE, NULL, - NULL); -#else /* OLD_WAY */ - H5C2_dest(file_ptr, H5P_DATASET_XFER_DEFAULT); - - cache_ptr = H5C2_create(max_cache_size, - min_clean_size, - (NUMBER_OF_ENTRY_TYPES - 1), - (const char **)entry_type_names2, - check_write_permitted2, - TRUE, NULL, - NULL); + FALSE); file_ptr->shared->cache2 = cache_ptr; -#endif /* OLD_WAY */ } if ( show_progress ) /* 5 */ @@ -2869,13 +2898,13 @@ takedown_cache2(H5F_t * file_ptr, flush_cache2(file_ptr, TRUE, FALSE, FALSE); -/* FIXME: Related to earlier hack with same tag, have John check for - * correctness... -QAK - */ -#ifdef OLD_WAY H5C2_dest(file_ptr, H5P_DATASET_XFER_DEFAULT); -#endif /* OLD_WAY */ + if ( saved_cache2 != NULL ) { + + file_ptr->shared->cache2 = saved_cache2; + saved_cache2 = NULL; + } } if ( saved_fid != -1 ) { @@ -2917,7 +2946,6 @@ takedown_cache2(H5F_t * file_ptr, * * Purpose: Expunge the entry indicated by the type and index. * - * Do nothing if pass2 is FALSE on entry. * * Return: void * diff --git a/test/cache2_common.h b/test/cache2_common.h index 47b9b5a..d8ee4fe 100644 --- a/test/cache2_common.h +++ b/test/cache2_common.h @@ -319,8 +319,8 @@ typedef struct test_entry_t */ } test_entry_t; -/* The following is a cut down copy of the hash table manipulation - * macros from H5C.c, which have been further modified to avoid references +/* The following are cut down test versions of the hash table manipulation + * macros from H5C2pkg.c, which have been further modified to avoid references * to the error reporting macros. Needless to say, these macros must be * updated as necessary. */ @@ -328,7 +328,7 @@ typedef struct test_entry_t #define H5C2__HASH_MASK ((size_t)(H5C2__HASH_TABLE_LEN - 1) << 3) #define H5C2__HASH_FCN(x) (int)(((x) & H5C2__HASH_MASK) >> 3) -#define H5C2__PRE_HT_SEARCH_SC(cache_ptr, Addr) \ +#define H5C2_TEST__PRE_HT_SEARCH_SC(cache_ptr, Addr) \ if ( ( (cache_ptr) == NULL ) || \ ( (cache_ptr)->magic != H5C2__H5C2_T_MAGIC ) || \ ( ! H5F_addr_defined(Addr) ) || \ @@ -337,33 +337,33 @@ if ( ( (cache_ptr) == NULL ) || \ HDfprintf(stdout, "Pre HT search SC failed.\n"); \ } -#define H5C2__POST_SUC_HT_SEARCH_SC(cache_ptr, entry_ptr, Addr, k) \ -if ( ( (cache_ptr) == NULL ) || \ - ( (cache_ptr)->magic != H5C2__H5C2_T_MAGIC ) || \ - ( (cache_ptr)->index_len < 1 ) || \ - ( (entry_ptr) == NULL ) || \ - ( (cache_ptr)->index_size < (entry_ptr)->size ) || \ - ( H5F_addr_ne((entry_ptr)->addr, (Addr)) ) || \ - ( (entry_ptr)->size <= 0 ) || \ - ( ((cache_ptr)->index)[k] == NULL ) || \ - ( ( ((cache_ptr)->index)[k] != (entry_ptr) ) && \ - ( (entry_ptr)->ht_prev == NULL ) ) || \ - ( ( ((cache_ptr)->index)[k] == (entry_ptr) ) && \ - ( (entry_ptr)->ht_prev != NULL ) ) || \ - ( ( (entry_ptr)->ht_prev != NULL ) && \ - ( (entry_ptr)->ht_prev->ht_next != (entry_ptr) ) ) || \ - ( ( (entry_ptr)->ht_next != NULL ) && \ - ( (entry_ptr)->ht_next->ht_prev != (entry_ptr) ) ) ) { \ - HDfprintf(stdout, "Post successful HT search SC failed.\n"); \ +#define H5C2_TEST__POST_SUC_HT_SEARCH_SC(cache_ptr, entry_ptr, Addr, k) \ +if ( ( (cache_ptr) == NULL ) || \ + ( (cache_ptr)->magic != H5C2__H5C2_T_MAGIC ) || \ + ( (cache_ptr)->index_len < 1 ) || \ + ( (entry_ptr) == NULL ) || \ + ( (cache_ptr)->index_size < (entry_ptr)->size ) || \ + ( H5F_addr_ne((entry_ptr)->addr, (Addr)) ) || \ + ( (entry_ptr)->size <= 0 ) || \ + ( ((cache_ptr)->index)[k] == NULL ) || \ + ( ( ((cache_ptr)->index)[k] != (entry_ptr) ) && \ + ( (entry_ptr)->ht_prev == NULL ) ) || \ + ( ( ((cache_ptr)->index)[k] == (entry_ptr) ) && \ + ( (entry_ptr)->ht_prev != NULL ) ) || \ + ( ( (entry_ptr)->ht_prev != NULL ) && \ + ( (entry_ptr)->ht_prev->ht_next != (entry_ptr) ) ) || \ + ( ( (entry_ptr)->ht_next != NULL ) && \ + ( (entry_ptr)->ht_next->ht_prev != (entry_ptr) ) ) ) { \ + HDfprintf(stdout, "Post successful HT search SC failed.\n"); \ } -#define H5C2__SEARCH_INDEX(cache_ptr, Addr, entry_ptr) \ +#define H5C2_TEST__SEARCH_INDEX(cache_ptr, Addr, entry_ptr) \ { \ int k; \ int depth = 0; \ - H5C2__PRE_HT_SEARCH_SC(cache_ptr, Addr) \ - k = H5C2__HASH_FCN(Addr); \ + H5C2_TEST__PRE_HT_SEARCH_SC(cache_ptr, Addr) \ + k = H5C2__HASH_FCN(Addr); \ entry_ptr = ((cache_ptr)->index)[k]; \ while ( ( entry_ptr ) && ( H5F_addr_ne(Addr, (entry_ptr)->addr) ) ) \ { \ @@ -372,7 +372,7 @@ if ( ( (cache_ptr) == NULL ) || \ } \ if ( entry_ptr ) \ { \ - H5C2__POST_SUC_HT_SEARCH_SC(cache_ptr, entry_ptr, Addr, k) \ + H5C2_TEST__POST_SUC_HT_SEARCH_SC(cache_ptr, entry_ptr, Addr, k) \ if ( entry_ptr != ((cache_ptr)->index)[k] ) \ { \ if ( (entry_ptr)->ht_next ) \ diff --git a/test/cache2_journal.c b/test/cache2_journal.c index da5502d..7789ced 100644 --- a/test/cache2_journal.c +++ b/test/cache2_journal.c @@ -71,8 +71,8 @@ static void check_legal_calls(void); static void check_transaction_tracking(void); static void write_verify_trans_num(H5C2_jbrb_t * struct_ptr, - unsigned long trans_num, - unsigned long verify_val); + uint64_t trans_num, + uint64_t verify_val); @@ -406,6 +406,7 @@ check_mdj_config_block_IO(void) result = H5C2_load_journal_config_block(file_ptr, H5P_DATASET_XFER_DEFAULT, + cache_ptr, block_addr, block_len); @@ -604,6 +605,7 @@ test_mdj_conf_blk_read_write_discard(H5F_t * file_ptr, result = H5C2_load_journal_config_block(file_ptr, H5P_DATASET_XFER_DEFAULT, + cache_ptr, block_addr, block_len); @@ -1593,8 +1595,8 @@ write_flush_verify(H5C2_jbrb_t * struct_ptr, if ( pass2 ) { - if ( H5C2_jb__write_to_buffer(struct_ptr, (size_t)size, data, 0, 0) - != SUCCEED ) { + if ( H5C2_jb__write_to_buffer(struct_ptr, (size_t)size, + data, 0, (uint64_t)0) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__write_to_buffer failed"; @@ -1663,8 +1665,8 @@ write_noflush_verify(H5C2_jbrb_t * struct_ptr, if ( pass2 ) { - if ( H5C2_jb__write_to_buffer(struct_ptr, (size_t)size, data, 0, 0) - != SUCCEED ) { + if ( H5C2_jb__write_to_buffer(struct_ptr, (size_t)size, + data, 0, (uint64_t)0) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__write_to_buffer failed"; @@ -1781,7 +1783,7 @@ check_message_format(void) if ( pass2 ) { if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, - /* trans number */ 1) + /* trans number */ (uint64_t)1) != SUCCEED ) { pass2 = FALSE; @@ -1799,7 +1801,7 @@ check_message_format(void) if ( pass2 ) { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, - /* trans number */ 1, + /* trans number */ (uint64_t)1, /* base address */ (haddr_t)0, /* data length */ 1, /* data */ (const uint8_t *)"A") @@ -1820,7 +1822,7 @@ check_message_format(void) if ( pass2 ) { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, - /* trans number */ 1, + /* trans number */ (uint64_t)1, /* base address */ (haddr_t)1, /* data length */ 2, /* data */ (const uint8_t *)"AB") @@ -1841,7 +1843,7 @@ check_message_format(void) if ( pass2 ) { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, - /* trans number */ 1, + /* trans number */ (uint64_t)1, /* base address */ (haddr_t)3, /* data length */ 4, /* data */ (const uint8_t *)"CDEF") @@ -1861,7 +1863,7 @@ check_message_format(void) /* End transaction */ if ( pass2 ) { if ( H5C2_jb__end_transaction(/* H5C2_jbrb_t */ &jbrb_struct, - /* trans number */ 1) + /* trans number */ (uint64_t)1) != SUCCEED ) { pass2 = FALSE; @@ -1879,7 +1881,7 @@ check_message_format(void) if ( pass2 ) { if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, - /* trans number */ 2) + /* trans number */ (uint64_t)2) != SUCCEED ) { pass2 = FALSE; @@ -1897,7 +1899,7 @@ check_message_format(void) if ( pass2 ) { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, - /* trans number */ 2, + /* trans number */ (uint64_t)2, /* base address */ (haddr_t)285, /* data length */ 11, /* data */ (const uint8_t *)"Test Data?!") @@ -1917,7 +1919,7 @@ check_message_format(void) /* End transaction */ if ( pass2 ) { if ( H5C2_jb__end_transaction(/* H5C2_jbrb_t */ &jbrb_struct, - /* trans number */ 2) + /* trans number */ (uint64_t)2) != SUCCEED ) { pass2 = FALSE; @@ -1999,7 +2001,7 @@ check_message_format(void) if ( pass2 ) { if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, - /* trans number */ 3) + /* trans number */ (uint64_t)3) != SUCCEED ) { pass2 = FALSE; @@ -2017,7 +2019,7 @@ check_message_format(void) if ( pass2 ) { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, - /* trans number */ 3, + /* trans number */ (uint64_t)3, /* base address */ (haddr_t)28591, /* data length */ 6, /* data */ (const uint8_t *)"#1nN`}") @@ -2037,7 +2039,7 @@ check_message_format(void) /* End transaction */ if ( pass2 ) { if ( H5C2_jb__end_transaction(/* H5C2_jbrb_t */ &jbrb_struct, - /* trans number */ 3) + /* trans number */ (uint64_t)3) != SUCCEED ) { pass2 = FALSE; @@ -2243,14 +2245,18 @@ check_legal_calls(void) if ( show_progress ) /* 2 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); - +#if 0 /* Start transaction 2. This should FAIL because transaction 1 has not occurred yet. Ensure that it fails, and flag an error if it does not. */ + /* transaction numbers need not be sequential, only monitonically + * increasing -- thus this is not an error any more. + * -- JRM + */ if ( pass2 ) { if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, - /* Transaction # */ 2) + /* Transaction # */ (uint64_t)2) == SUCCEED ) { pass2 = FALSE; @@ -2259,7 +2265,7 @@ check_legal_calls(void) } /* end if */ } /* end if */ - +#endif if ( show_progress ) /* 3 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); @@ -2270,7 +2276,7 @@ check_legal_calls(void) if ( pass2 ) { if ( H5C2_jb__end_transaction(/* H5C2_jbrb_t */ &jbrb_struct, - /* Transaction # */ 1) + /* Transaction # */ (uint64_t)1) == SUCCEED ) { pass2 = FALSE; @@ -2290,7 +2296,7 @@ check_legal_calls(void) if ( pass2 ) { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, - /* Transaction # */ 1, + /* Transaction # */ (uint64_t)1, /* Base Address */ (haddr_t)123456789, /* Length */ 16, /* Body */ (const uint8_t *)"This should fail") @@ -2311,7 +2317,7 @@ check_legal_calls(void) if ( pass2 ) { if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, - /* Transaction # */ 1) + /* Transaction # */ (uint64_t)1) != SUCCEED ) { pass2 = FALSE; @@ -2331,7 +2337,7 @@ check_legal_calls(void) if ( pass2 ) { if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, - /* Transaction # */ 1) + /* Transaction # */ (uint64_t)1) == SUCCEED ) { pass2 = FALSE; @@ -2350,7 +2356,7 @@ check_legal_calls(void) if ( pass2 ) { if ( H5C2_jb__end_transaction(/* H5C2_jbrb_t */ &jbrb_struct, - /* Transaction # */ 1) + /* Transaction # */ (uint64_t)1) == SUCCEED ) { pass2 = FALSE; @@ -2370,7 +2376,7 @@ check_legal_calls(void) if ( pass2 ) { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, - /* Transaction # */ 2, + /* Transaction # */ (uint64_t)2, /* Base Address */ (haddr_t)123456789, /* Length */ 16, /* Body */ (const uint8_t *)"This should fail") @@ -2391,7 +2397,7 @@ check_legal_calls(void) if ( pass2 ) { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, - /* Transaction # */ 1, + /* Transaction # */ (uint64_t)1, /* Base Address */ (haddr_t)123456789, /* Length */ 51, /* Body */ (const uint8_t *)"This is the first transaction during transaction 1.") @@ -2431,7 +2437,7 @@ check_legal_calls(void) if ( pass2 ) { if ( H5C2_jb__end_transaction(/* H5C2_jbrb_t */ &jbrb_struct, - /* Transaction # */ 1) + /* Transaction # */ (uint64_t)1) != SUCCEED ) { pass2 = FALSE; @@ -2451,7 +2457,7 @@ check_legal_calls(void) if ( pass2 ) { if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, - /* Transaction # */ 1) + /* Transaction # */ (uint64_t)1) == SUCCEED ) { pass2 = FALSE; @@ -2469,7 +2475,7 @@ check_legal_calls(void) if ( pass2 ) { if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, - /* Transaction # */ 2) + /* Transaction # */ (uint64_t)2) != SUCCEED ) { pass2 = FALSE; @@ -2487,7 +2493,7 @@ check_legal_calls(void) if ( pass2 ) { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, - /* Transaction # */ 2, + /* Transaction # */ (uint64_t)2, /* Base Address */ (haddr_t)7465, /* Length */ 51, /* Body */ (const uint8_t *)"This is the first transaction during transaction 2!") @@ -2508,7 +2514,7 @@ check_legal_calls(void) if ( pass2 ) { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, - /* Transaction # */ 2, + /* Transaction # */ (uint64_t)2, /* Base Address */ (haddr_t)123456789, /* Length */ 60, /* Body */ (const uint8_t *)"... And here's your second transaction during transaction 2.") @@ -2529,7 +2535,7 @@ check_legal_calls(void) if ( pass2 ) { if ( H5C2_jb__end_transaction(/* H5C2_jbrb_t */ &jbrb_struct, - /* Transaction # */ 2) + /* Transaction # */ (uint64_t)2) != SUCCEED ) { pass2 = FALSE; @@ -2791,8 +2797,8 @@ check_transaction_tracking(void) for (i = 1; i < 11; i++) { write_verify_trans_num(/* H5C2_jbrb_t */ &jbrb_struct, - /* transaction num */ (unsigned long)i, - /* expected trans */(unsigned long)expected_tval[i]); + /* transaction num */ (uint64_t)i, + /* expected trans */(uint64_t)expected_tval[i]); } /* end for */ @@ -2896,8 +2902,8 @@ check_transaction_tracking(void) for (i=1; i<20; i++) { write_verify_trans_num(/* H5C2_ujbrb_t */&jbrb_struct, - /* transaction num */(unsigned long)i, - /* expected trans on disk */(unsigned long)i); + /* transaction num */(uint64_t)i, + /* expected trans on disk */(uint64_t)i); } /* end for */ @@ -3003,21 +3009,45 @@ check_transaction_tracking(void) case where end transaction messages start in one buffer and end in another buffer. Also tests the case where one transaction ends several buffers ahead of the next transaction end. */ - write_verify_trans_num(&jbrb_struct, 1, 0); /* 1 in bufs, 0 on disk */ - write_verify_trans_num(&jbrb_struct, 2, 1); /* 2 in bufs, 1 on disk */ - write_verify_trans_num(&jbrb_struct, 3, 3); /* nothing in bufs, 3 on disk */ - H5C2_jb__write_to_buffer(&jbrb_struct, 10, "XXXXXXXXX\n", 0, 0); - write_verify_trans_num(&jbrb_struct, 4, 3); /* 1 in bufs, 0 on disk */ - write_verify_trans_num(&jbrb_struct, 5, 5); /* 2 in bufs, 1 on disk */ - write_verify_trans_num(&jbrb_struct, 6, 5); /* nothing in bufs, 3 on disk */ - H5C2_jb__write_to_buffer(&jbrb_struct, 10, "XXXXXXXXX\n", 0, 0); - write_verify_trans_num(&jbrb_struct, 7, 7); /* 1 in bufs, 0 on disk */ - write_verify_trans_num(&jbrb_struct, 8, 7); /* 2 in bufs, 1 on disk */ - write_verify_trans_num(&jbrb_struct, 9, 8); /* nothing in bufs, 3 on disk */ - H5C2_jb__write_to_buffer(&jbrb_struct, 10, "XXXXXXXXX\n", 0, 0); - write_verify_trans_num(&jbrb_struct, 10, 9); /* 1 in bufs, 0 on disk */ - write_verify_trans_num(&jbrb_struct, 11, 10); /* 2 in bufs, 1 on disk */ - write_verify_trans_num(&jbrb_struct, 12, 12); /* nothing in buf, 3 on disk */ + write_verify_trans_num(&jbrb_struct, + (uint64_t)1, + (uint64_t)0); /* 1 in bufs, 0 on disk */ + write_verify_trans_num(&jbrb_struct, + (uint64_t)2, + (uint64_t)1); /* 2 in bufs, 1 on disk */ + write_verify_trans_num(&jbrb_struct, + (uint64_t)3, + (uint64_t)3); /* nothing in bufs, 3 on disk */ + H5C2_jb__write_to_buffer(&jbrb_struct, 10, "XXXXXXXXX\n", 0, (uint64_t)0); + write_verify_trans_num(&jbrb_struct, + (uint64_t)4, + (uint64_t)3); /* 1 in bufs, 0 on disk */ + write_verify_trans_num(&jbrb_struct, + (uint64_t)5, + (uint64_t)5); /* 2 in bufs, 1 on disk */ + write_verify_trans_num(&jbrb_struct, + (uint64_t)6, + (uint64_t)5); /* nothing in bufs, 3 on disk */ + H5C2_jb__write_to_buffer(&jbrb_struct, 10, "XXXXXXXXX\n", 0, (uint64_t)0); + write_verify_trans_num(&jbrb_struct, + (uint64_t)7, + (uint64_t)7); /* 1 in bufs, 0 on disk */ + write_verify_trans_num(&jbrb_struct, + (uint64_t)8, + (uint64_t)7); /* 2 in bufs, 1 on disk */ + write_verify_trans_num(&jbrb_struct, + (uint64_t)9, + (uint64_t)8); /* nothing in bufs, 3 on disk */ + H5C2_jb__write_to_buffer(&jbrb_struct, 10, "XXXXXXXXX\n", 0, (uint64_t)0); + write_verify_trans_num(&jbrb_struct, + (uint64_t)10, + (uint64_t)9); /* 1 in bufs, 0 on disk */ + write_verify_trans_num(&jbrb_struct, + (uint64_t)11, + (uint64_t)10); /* 2 in bufs, 1 on disk */ + write_verify_trans_num(&jbrb_struct, + (uint64_t)12, + (uint64_t)12); /* nothing in buf, 3 on disk */ if ( show_progress ) /* 10 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, @@ -3118,8 +3148,8 @@ check_transaction_tracking(void) for (i=1; i<5; i++) { write_verify_trans_num(/* H5C2_jbrb_t */ &jbrb_struct, - /* transaction num */ (unsigned long)i, - /* expected returned trans */ (unsigned long)i); + /* transaction num */ (uint64_t)i, + /* expected returned trans */ (uint64_t)i); } /* end for */ @@ -3204,10 +3234,10 @@ check_transaction_tracking(void) **************************************************************************/ static void write_verify_trans_num(H5C2_jbrb_t * struct_ptr, - unsigned long trans_num, - unsigned long verify_val) + uint64_t trans_num, + uint64_t verify_val) { - unsigned long trans_verify; + uint64_t trans_verify; /* Write an entire transaction. (start, journal entry, end). * As long as the supplied transaction number is less than 1000, diff --git a/test/testfiles/err_compat_1 b/test/testfiles/err_compat_1 index 032e7bc..f5215ed 100644 --- a/test/testfiles/err_compat_1 +++ b/test/testfiles/err_compat_1 @@ -21,6 +21,9 @@ HDF5-DIAG: Error detected in HDF5 (version (number)) thread (IDs): #001: (file name) line (number) in test_error(): H5Dwrite shouldn't succeed major: Error API minor: Write failed - #002: (file name) line (number) in H5Dwrite(): not a dataset + #002: (file name) line (number) in H5Dwrite(): H5AC2_begin_transaction() failed. + major: Object cache + minor: Unable to write to journal file + #003: (file name) line (number) in H5AC2_begin_transaction(): H5I_get_type() reports bad id major: Invalid arguments to routine minor: Inappropriate type diff --git a/test/testfiles/error_test_1 b/test/testfiles/error_test_1 index 20f669d..767340e 100644 --- a/test/testfiles/error_test_1 +++ b/test/testfiles/error_test_1 @@ -15,7 +15,10 @@ Error Test-DIAG: Error detected in Error Program (1.0) thread (IDs): major: Error in API minor: Error in H5Eget_num HDF5-DIAG: Error detected in HDF5 (version (number)) thread (IDs): - #000: (file name) line (number) in H5Dwrite(): not a dataset + #000: (file name) line (number) in H5Dwrite(): H5AC2_begin_transaction() failed. + major: Object cache + minor: Unable to write to journal file + #001: (file name) line (number) in H5AC2_begin_transaction(): H5I_get_type() reports bad id major: Invalid arguments to routine minor: Inappropriate type Error Test-DIAG: Error detected in Error Program (1.0) thread (IDs): @@ -26,6 +29,9 @@ Error Test-DIAG: Error detected in Error Program (1.0) thread (IDs): major: Error in IO minor: Error in H5Dwrite HDF5-DIAG: Error detected in HDF5 (version (number)) thread (IDs): - #002: (file name) line (number) in H5Dwrite(): not a dataset + #002: (file name) line (number) in H5Dwrite(): H5AC2_begin_transaction() failed. + major: Object cache + minor: Unable to write to journal file + #003: (file name) line (number) in H5AC2_begin_transaction(): H5I_get_type() reports bad id major: Invalid arguments to routine minor: Inappropriate type diff --git a/test/testhdf5.c b/test/testhdf5.c index 5b174be..d98407d 100644 --- a/test/testhdf5.c +++ b/test/testhdf5.c @@ -44,6 +44,7 @@ main(int argc, char *argv[]) TestInit(argv[0], NULL, NULL); /* Tests are generally arranged from least to most complexity... */ + AddTest("config", test_configure, cleanup_configure, "Configure definitions", NULL); AddTest("metadata", test_metadata, cleanup_metadata, "Encoding/decoding metadata", NULL); AddTest("checksum", test_checksum, cleanup_checksum, "Checksum algorithm", NULL); diff --git a/testpar/t_cache2.c b/testpar/t_cache2.c index aa64bea..2dd8c70 100644 --- a/testpar/t_cache2.c +++ b/testpar/t_cache2.c @@ -2255,7 +2255,7 @@ expunge_entry(H5C2_t * cache_ptr, HDassert( ((entry_ptr->header).type)->id == DATUM_ENTRY_TYPE ); HDassert( ! ((entry_ptr->header).is_dirty) ); - result = H5C2_get_entry_status(cache_ptr, entry_ptr->base_addr, + result = H5C2_get_entry_status(file_ptr, entry_ptr->base_addr, NULL, &in_cache, NULL, NULL, NULL); if ( result < 0 ) { @@ -3329,7 +3329,7 @@ setup_cache_for_test(hid_t * fid_ptr, } if ( file_ptr == NULL ) { - nerrors++; + if ( verbose ) { HDfprintf(stdout, "%d:%s: Can't get file_ptr.\n", world_mpi_rank, fcn_name); @@ -3376,8 +3376,8 @@ setup_cache_for_test(hid_t * fid_ptr, config.rpt_fcn_enabled = TRUE; - if ( H5AC2_set_cache_auto_resize_config(cache_ptr, &config) - != SUCCEED ) { + if ( H5AC2_set_cache_auto_resize_config(file_ptr, + H5P_DATASET_XFER_DEFAULT, &config) != SUCCEED ) { HDfprintf(stdout, "%d:%s: H5AC2_set_cache_auto_resize_config() failed.\n", @@ -5576,7 +5576,7 @@ trace_file_check(void) const char * expected_output[] = { "### HDF5 metadata cache trace file version 2 ###\n", - "H5AC2_set_cache_auto_resize_config 1 0 1 0 \"t_cache2_trace.txt\" 1 0 1048576 0.500000 16777216 1048576 50000 1 0.900000 2.000000 1 4194304 1 1.000000 0.250000 3 0.999000 0.900000 1 1048576 3 1 0.100000 262144 0\n", + "H5AC2_set_cache_auto_resize_config 1 0 1 0 \"t_cache2_trace.txt\" 1 0 1048576 0.500000 16777216 1048576 50000 1 0.900000 2.000000 1 4194304 1 1.000000 0.250000 3 0.999000 0.900000 1 1048576 3 1 0.100000 262144 0 \"\" 0 4096 1 0 0 0\n", "H5AC2_set 0x400 2 15 0x0 2 0\n", "H5AC2_set 0x402 2 15 0x0 2 0\n", "H5AC2_set 0x404 4 15 0x0 4 0\n", @@ -5671,8 +5671,8 @@ trace_file_check(void) config.open_trace_file = TRUE; strcpy(config.trace_file_name, "t_cache2_trace.txt"); - if ( H5AC2_set_cache_auto_resize_config(cache_ptr, &config) - != SUCCEED ) { + if ( H5AC2_set_cache_auto_resize_config(file_ptr, + H5P_DATASET_XFER_DEFAULT, &config) != SUCCEED ) { nerrors++; HDfprintf(stdout, @@ -5735,8 +5735,8 @@ trace_file_check(void) config.close_trace_file = TRUE; config.trace_file_name[0] = '\0'; - if ( H5AC2_set_cache_auto_resize_config(cache_ptr, &config) - != SUCCEED ) { + if ( H5AC2_set_cache_auto_resize_config(file_ptr, + H5P_DATASET_XFER_DEFAULT, &config) != SUCCEED ) { nerrors++; HDfprintf(stdout, -- cgit v0.12