summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hl/src/H5PT.c11
-rw-r--r--src/H5A.c19
-rw-r--r--src/H5AC2.c425
-rw-r--r--src/H5AC2private.h40
-rw-r--r--src/H5AC2public.h66
-rw-r--r--src/H5ACprivate.h12
-rw-r--r--src/H5ACpublic.h20
-rw-r--r--src/H5Adeprec.c3
-rw-r--r--src/H5C2.c2780
-rw-r--r--src/H5C2journal.c1025
-rw-r--r--src/H5C2pkg.h3271
-rw-r--r--src/H5C2private.h118
-rw-r--r--src/H5D.c9
-rw-r--r--src/H5Ddeprec.c5
-rw-r--r--src/H5Dio.c3
-rw-r--r--src/H5F.c38
-rw-r--r--src/H5FDpublic.h15
-rw-r--r--src/H5Fmount.c15
-rw-r--r--src/H5G.c8
-rw-r--r--src/H5Gdeprec.c15
-rw-r--r--src/H5I.c5
-rw-r--r--src/H5L.c15
-rw-r--r--src/H5Lexternal.c5
-rw-r--r--src/H5O.c16
-rw-r--r--src/H5Ocopy.c4
-rw-r--r--src/H5R.c3
-rw-r--r--src/H5T.c3
-rw-r--r--src/H5Tcommit.c5
-rw-r--r--src/H5Tdeprec.c3
-rw-r--r--src/H5private.h25
-rw-r--r--test/cache2.c34
-rw-r--r--test/cache2_common.c76
-rw-r--r--test/cache2_common.h50
-rw-r--r--test/cache2_journal.c144
-rw-r--r--test/testfiles/err_compat_15
-rw-r--r--test/testfiles/error_test_110
-rw-r--r--test/testhdf5.c1
-rw-r--r--testpar/t_cache2.c18
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; i<struct_ptr->num_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,