summaryrefslogtreecommitdiffstats
path: root/src/H5C2pkg.h
diff options
context:
space:
mode:
authorJohn Mainzer <mainzer@hdfgroup.org>2008-04-25 14:55:20 (GMT)
committerJohn Mainzer <mainzer@hdfgroup.org>2008-04-25 14:55:20 (GMT)
commit2c84019fcaca9a1cb2a415564d8b88e3dd88479d (patch)
tree22b8d155072c707be3f408185d739b1d65c2f085 /src/H5C2pkg.h
parentde68c607843fbfa55f94a661cf8cf58ad09adc0c (diff)
downloadhdf5-2c84019fcaca9a1cb2a415564d8b88e3dd88479d.zip
hdf5-2c84019fcaca9a1cb2a415564d8b88e3dd88479d.tar.gz
hdf5-2c84019fcaca9a1cb2a415564d8b88e3dd88479d.tar.bz2
[svn-r14863] Checking in code supporting metadata journaling in the serial case.
While this code doesn't break any of the existing tests, it HAS NOT been tested beyond that. Also mods needed to integrate the journaling code with Quincey's latest mods, and to adapt existing test code to slight changes caused by the addition of journaling. Finally, fixed an undefined variable bug in the HL code exposed by the journaling mods. Tested serial under Linux (Phoenix) and parallel under Linux (Kagiso).
Diffstat (limited to 'src/H5C2pkg.h')
-rw-r--r--src/H5C2pkg.h3271
1 files changed, 3266 insertions, 5 deletions
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 */