summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/H5AC2.c2
-rw-r--r--src/H5C2.c2
-rw-r--r--src/H5C2journal.c5517
-rw-r--r--src/H5C2pkg.h1556
-rw-r--r--src/H5C2private.h396
-rw-r--r--src/H5MF.c2
-rw-r--r--src/H5private.h4
7 files changed, 5594 insertions, 1885 deletions
diff --git a/src/H5AC2.c b/src/H5AC2.c
index beb2927..966eec4 100644
--- a/src/H5AC2.c
+++ b/src/H5AC2.c
@@ -48,6 +48,8 @@
*-------------------------------------------------------------------------
*/
+#include <aio.h>
+
#define H5AC2_PACKAGE /*suppress error about including H5AC2pkg */
#define H5C2_PACKAGE /*suppress error about including H5C2pkg */
#define H5F_PACKAGE /*suppress error about including H5Fpkg */
diff --git a/src/H5C2.c b/src/H5C2.c
index b3b635f..dd4105a 100644
--- a/src/H5C2.c
+++ b/src/H5C2.c
@@ -95,6 +95,8 @@
*
**************************************************************************/
+#include <aio.h>
+
#define H5C2_PACKAGE /*suppress error about including H5C2pkg */
#define H5F_PACKAGE /*suppress error about including H5Fpkg */
diff --git a/src/H5C2journal.c b/src/H5C2journal.c
index 88f815e..71833fc 100644
--- a/src/H5C2journal.c
+++ b/src/H5C2journal.c
@@ -22,12 +22,12 @@
* Purpose: This file is a general catchall for functions supporting
* metadata journaling. Note that journaling must be tighly
* integrated with the metadata cache, and thus this file only
- * contains only that code that can be easily separated from
+ * contains only that code that can be easily separated from
* the rest of the cache code.
*
* Observe also that to minimize overhead, it is quite possible
* that many of the functions in this file will be converted
- * into macros at some point in the future.
+ * into macros at some point in the future.
*
* Modifications:
*
@@ -36,6 +36,11 @@
*-------------------------------------------------------------------------
*/
+#include <aio.h>
+#include <strings.h>
+#include <unistd.h>
+
+
#define H5F_PACKAGE /* suppress error about including H5Fpkg */
#define H5C2_PACKAGE /* suppress error about including H5C2pkg */
@@ -78,6 +83,57 @@ static herr_t H5C2_get_journaling_in_progress(const H5F_t * f,
static herr_t H5C2_grow_mdjsc_callback_table(H5C2_t * cache_ptr);
+static herr_t H5C2_jb_aio__await_buffer_write_completion(
+ H5C2_jbrb_t * struct_ptr,
+ int buf_num);
+
+static herr_t H5C2_jb_aio__await_async_fsync_completion(
+ H5C2_jbrb_t * struct_ptr);
+
+static herr_t H5C2_jb_aio__flush(H5C2_jbrb_t * struct_ptr);
+
+static herr_t H5C2_jb_aio__get_last_transaction_on_disk(
+ H5C2_jbrb_t * struct_ptr,
+ uint64_t * trans_num_ptr);
+
+static herr_t H5C2_jb_aio__make_space_in_ring_buffer(H5C2_jbrb_t * struct_ptr);
+
+static herr_t H5C2_jb_aio__note_completed_async_buffer_writes(
+ H5C2_jbrb_t * struct_ptr);
+
+static herr_t H5C2_jb_aio__note_completed_async_fsyncs(
+ H5C2_jbrb_t * struct_ptr);
+
+static herr_t H5C2_jb_aio__prep_next_buf_for_use(H5C2_jbrb_t * struct_ptr,
+ uint64_t last_trans_in_ring_buffer);
+
+static herr_t H5C2_jb_aio__queue_async_fsync(H5C2_jbrb_t * struct_ptr);
+
+static herr_t H5C2_jb_aio__queue_buffer_write(H5C2_jbrb_t * struct_ptr,
+ int buf_num,
+ hbool_t partial_write_ok);
+
+static herr_t H5C2_jb_aio__sync_file(H5C2_jbrb_t * struct_ptr);
+
+static herr_t H5C2_jb_aio__sync_q__append(H5C2_jbrb_t * struct_ptr,
+ struct H5C2_jbrb_sync_q_entry_t * entry_ptr);
+
+static herr_t H5C2_jb_aio__sync_q__discard_head(H5C2_jbrb_t * struct_ptr);
+
+static herr_t H5C2_jb_aio__test_buffer_write_complete(H5C2_jbrb_t * struct_ptr,
+ int buf_num,
+ hbool_t *complete_ptr);
+
+static herr_t H5C2_jb_aio__test_next_async_fsync_complete(
+ H5C2_jbrb_t * struct_ptr,
+ hbool_t *sync_complete_ptr);
+
+herr_t H5C2_jb_aio__write_to_buffer(H5C2_jbrb_t * struct_ptr,
+ size_t size,
+ const char * data,
+ hbool_t is_end_trans,
+ uint64_t trans_num);
+
static herr_t H5C2_jb_bjf__comment(H5C2_jbrb_t * struct_ptr,
const char * comment_ptr);
@@ -108,7 +164,7 @@ static herr_t H5C2_jb_bjf__write_chksum(H5C2_jbrb_t * struct_ptr,
static herr_t H5C2_jb_bjf__write_length(H5C2_jbrb_t * struct_ptr,
size_t length,
- hbool_t is_end_trans,
+ hbool_t is_end_trans,
uint64_t trans_num);
static herr_t H5C2_jb_bjf__write_offset(H5C2_jbrb_t * struct_ptr,
@@ -142,9 +198,23 @@ static herr_t H5C2_jb_hrjf__journal_entry(H5C2_jbrb_t * struct_ptr,
size_t length,
const uint8_t * body);
-static herr_t H5C2_jb_hrjf__start_transaction(H5C2_jbrb_t * struct_ptr,
- uint64_t trans_num);
+static herr_t H5C2_jb_sio__flush(H5C2_jbrb_t * struct_ptr);
+static herr_t H5C2_jb_sio__flush_full_buffers(H5C2_jbrb_t * struct_ptr);
+
+static herr_t H5C2_jb_sio__get_last_transaction_on_disk(
+ H5C2_jbrb_t * struct_ptr,
+ uint64_t * trans_num_ptr);
+
+static herr_t H5C2_jb_sio__write_to_buffer(H5C2_jbrb_t * struct_ptr,
+ size_t size,
+ const char * data,
+ hbool_t is_end_trans,
+ uint64_t trans_num);
+
+herr_t H5C2_jb_stats__dump(H5C2_jbrb_t * struct_ptr);
+
+herr_t H5C2_jb_stats__reset(H5C2_jbrb_t * struct_ptr);
static herr_t H5C2_shrink_mdjsc_callback_table(H5C2_t * cache_ptr);
@@ -170,14 +240,14 @@ static herr_t H5C2_shrink_mdjsc_callback_table(H5C2_t * cache_ptr);
* structure.
*
* JRM -- 8/18/08
- * Added code to flush the cache before journaling
+ * Added code to flush the cache before journaling
* starts, and to call the metadata journaling status
* change callbacks after journaling has been started.
*
* JRM -- 2/10/09
- * Added journal_magic variable and supporting code.
+ * Added journal_magic variable and supporting code.
*
- * The idea is to assign a random magic number to both the
+ * The idea is to assign a random magic number to both the
* journal file, and to the journal configuration information
* information in the super block so that it will be hard to
* apply the wrong journal file to a corrupted hdf5 file.
@@ -233,7 +303,7 @@ H5C2_begin_journaling(H5F_t * f,
if ( result < 0 ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "H5C2_flush_cache() failed.")
+ "H5C2_flush_cache() failed.")
}
journal_magic = (int32_t)HDrand();
@@ -294,8 +364,8 @@ done:
* Function: H5C2_begin_transaction
*
* Purpose: Handle book keeping for the beginning of a transaction, and
- * return the transaction ID assigned to the transaction in
- * *trans_num_ptr.
+ * return the transaction ID assigned to the transaction in
+ * *trans_num_ptr.
*
* Return: Success: SUCCEED
* Failure: FAIL
@@ -361,7 +431,7 @@ done:
* journal file.
*
* 2) Mark the superblock to indicate that we are no longer
- * journaling. Note that this will flush the HDF5 file
+ * journaling. Note that this will flush the HDF5 file
* again in passing.
*
* 3) Tell the journal file write code to shutdown. This will
@@ -409,7 +479,7 @@ H5C2_end_journaling(H5F_t * f,
if ( result < 0 ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "H5C2_flush_cache() failed.")
+ "H5C2_flush_cache() failed.")
}
HDassert( cache_ptr->mdj_enabled );
@@ -422,7 +492,7 @@ H5C2_end_journaling(H5F_t * f,
cache_ptr->mdj_enabled = FALSE;
/* Remove the journal configuration information from the superblock
- * extension. In passing, also discard the cache's copies of the
+ * extension. In passing, also discard the cache's copies of the
* metadata journaling magic, and the journal file name.
*/
result = H5C2_unmark_journaling_in_progress(f, dxpl_id, cache_ptr);
@@ -569,14 +639,14 @@ done:
* Purpose: Return the current metadata journaling status in an
* instance of H5C2_mdj_config_t.
*
- * If journaling is enabled, config_ptr->enable_journaling
+ * If journaling is enabled, config_ptr->enable_journaling
* is set to TRUE, and the remaining fields in *config_ptr
* will be set to reflect current journaling status.
*
* If journaling is disabled, config_ptr->enable_journaling
* is set to FALSE, and the remaining fields of *config_ptr
* are undefined.
- *
+ *
* Return: Success: SUCCEED
* Failure: FAIL
*
@@ -612,7 +682,7 @@ H5C2_get_journal_config(H5C2_t * cache_ptr,
config_ptr->enable_journaling = TRUE;
- HDstrncpy(&(config_ptr->journal_file_path[0]),
+ HDstrncpy(&(config_ptr->journal_file_path[0]),
cache_ptr->jnl_file_name,
H5C2__MAX_JOURNAL_FILE_NAME_LEN);
@@ -625,7 +695,7 @@ H5C2_get_journal_config(H5C2_t * cache_ptr,
config_ptr->jbrb_use_aio = (cache_ptr->mdj_jbrb).use_aio;
config_ptr->jbrb_human_readable = (cache_ptr->mdj_jbrb).human_readable;
-
+
} else {
config_ptr->enable_journaling = FALSE;
@@ -657,9 +727,9 @@ done:
*
* b) Truncate the journal file
*
- * c) Reset cache_ptr->trans_num and
+ * c) Reset cache_ptr->trans_num and
* cache_ptr->last_trans_on_disk to zero.
- *
+ *
* Return: Success: SUCCEED
* Failure: FAIL
*
@@ -724,7 +794,7 @@ H5C2_journal_post_flush(H5F_t * f,
HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
"H5C2_jb__trunc() failed.")
}
-
+
cache_ptr->trans_num = (uint64_t)0;
cache_ptr->last_trans_on_disk = (uint64_t)0;
}
@@ -751,13 +821,13 @@ done:
* 3) Get the ID of the last transaction on disk.
*
* 4) If the value obtained in 3) above has changed,
- * remove all entries whose last transaction has
+ * remove all entries whose last transaction has
* made it to disk from the journal write in progress
* list.
*
* 5) Verify that the journal write in progress list is
* empty.
- *
+ *
* Return: Success: SUCCEED
* Failure: FAIL
*
@@ -812,7 +882,7 @@ H5C2_journal_pre_flush(H5C2_t * cache_ptr)
HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
"H5C2_update_for_new_last_trans_on_disk() failed.")
}
- }
+ }
if ( cache_ptr->jwipl_len != 0 ) {
@@ -857,11 +927,11 @@ H5C2_journal_transaction(H5F_t * f,
size_t new_len;
void * new_image_ptr;
void * thing;
- herr_t result;
+ herr_t result;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5C2_journal_transaction, FAIL)
-
+
HDassert( f != NULL );
HDassert( cache_ptr != NULL );
HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC );
@@ -879,7 +949,7 @@ H5C2_journal_transaction(H5F_t * f,
"H5C2_jb__comment() failed.")
}
- result = H5C2_jb__start_transaction(&(cache_ptr->mdj_jbrb),
+ result = H5C2_jb__start_transaction(&(cache_ptr->mdj_jbrb),
cache_ptr->trans_num);
if ( result != SUCCEED ) {
@@ -897,7 +967,7 @@ H5C2_journal_transaction(H5F_t * f,
resized = FALSE;
renamed = FALSE;
- if ( entry_ptr->is_protected )
+ if ( entry_ptr->is_protected )
{
HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
@@ -916,7 +986,7 @@ H5C2_journal_transaction(H5F_t * f,
}
}
- /* This should always be true, unless the entry has already been
+ /* This should always be true, unless the entry has already been
* serialized in this function, and that serialization caused the
* entry to be resized (and possibly renamed as well).
*/
@@ -941,16 +1011,18 @@ H5C2_journal_transaction(H5F_t * f,
if ( serialize_flags != 0 ) {
- /* if the serialize_flags are not zero, the entry has been
+ /* if the serialize_flags are not zero, the entry has been
* modified as a result of the serialize. Pass these changes
- * on to the cache, and don't bother to write a journal entry
- * at this time -- the protect/unprotect/rename will move the
- * entry to the head of the transaction list, where we will
+ * on to the cache, and don't bother to write a journal entry
+ * at this time -- the protect/unprotect/rename will move the
+ * entry to the head of the transaction list, where we will
* handle it later.
*/
- resized = (serialize_flags & H5C2__SERIALIZE_RESIZED_FLAG) != 0;
- renamed = (serialize_flags & H5C2__SERIALIZE_RENAMED_FLAG) != 0;
+ resized =
+ (hbool_t)((serialize_flags & H5C2__SERIALIZE_RESIZED_FLAG) != 0);
+ renamed =
+ (hbool_t)((serialize_flags & H5C2__SERIALIZE_RENAMED_FLAG) != 0);
if ( ( renamed ) && ( ! resized ) ) {
@@ -958,7 +1030,7 @@ H5C2_journal_transaction(H5F_t * f,
"entry renamed but not resized?!?!")
}
- if ( resized )
+ if ( resized )
{
/* in the following protect/unprotect, the dxpl_id
* is irrelement, as we know that the entry is in cache,
@@ -966,7 +1038,7 @@ H5C2_journal_transaction(H5F_t * f,
*/
thing = H5C2_protect(f, dxpl_id,
entry_ptr->type, entry_ptr->addr,
- entry_ptr->size, NULL,
+ entry_ptr->size, NULL,
H5C2__NO_FLAGS_SET);
if ( thing == NULL ) {
@@ -977,7 +1049,7 @@ H5C2_journal_transaction(H5F_t * f,
result = H5C2_unprotect(f, dxpl_id,
entry_ptr->type, entry_ptr->addr,
- thing, H5C2__SIZE_CHANGED_FLAG,
+ thing, H5C2__SIZE_CHANGED_FLAG,
new_len);
if ( result < 0 ) {
@@ -1009,12 +1081,12 @@ H5C2_journal_transaction(H5F_t * f,
* the journal entry, & remove from the transaction list.
*/
if ( ( ! resized ) && ( ! renamed ) ) {
-
+
result = H5C2_jb__journal_entry(&(cache_ptr->mdj_jbrb),
cache_ptr->trans_num,
entry_ptr->addr,
entry_ptr->size,
- entry_ptr->image_ptr);
+ (uint8_t *)(entry_ptr->image_ptr));
if ( result != SUCCEED ) {
@@ -1051,7 +1123,7 @@ done:
* Purpose: Update the journal write in progress list for a change in
* the last transaction on disk.
*
- * Specifically, update the last_trans_on_disk field of
+ * Specifically, update the last_trans_on_disk field of
* *cache_ptr, and then scan the journal write in progress
* list for entries whose last_trans field is now less than
* or equal to cache_ptr->last_trans_on_disk. Remove all
@@ -1060,7 +1132,7 @@ done:
* the eviction policy data structures.
*
* Similarly, scan the pinned entry list for entries whose
- * last_trans field is now less than or equal to
+ * last_trans field is now less than or equal to
* cache_ptr->last_trans_on_disk. In this case, just set
* the last trans field to 0. Note that here we assume that
* the pinned entry list will always be small -- if this
@@ -1149,14 +1221,14 @@ done:
*
* Purpose: If the superblock extension of a newly opened HDF5 file
* indicates that journaling is in progress, the process
- * that created the file failed to close it properly, and
+ * that created the file failed to close it properly, and
* thus the file is almost certainly corrupted.
*
* The purpose of this function is to detect this condition,
- * and either throw an error telling the user to run the
- * recovery tool, or if so directed (presumably by the
- * recovery tool) simply delete the metadata journaling
- * configuration block and any reference to journaling in the
+ * and either throw an error telling the user to run the
+ * recovery tool, or if so directed (presumably by the
+ * recovery tool) simply delete the metadata journaling
+ * configuration block and any reference to journaling in the
* superblock extension.
*
* JRM -- 3/26/08
@@ -1180,7 +1252,7 @@ H5C2_check_for_journaling(H5F_t * f,
"This file was last written with metadata journaling enabled and was \n";
const char * l1 =
"not closed cleanly. To allow HDF5 to read this file, please run the \n";
- const char * l2 =
+ const char * l2 =
"journal recovery tool on this file. The journal was written \n";
const char * l3 = "to \"";
const char * l4 = "\".\n";
@@ -1215,8 +1287,8 @@ H5C2_check_for_journaling(H5F_t * f,
* we were.
*/
- result = H5C2_unmark_journaling_in_progress(f,
- dxpl_id,
+ result = H5C2_unmark_journaling_in_progress(f,
+ dxpl_id,
cache_ptr);
if ( result != SUCCEED ) {
@@ -1226,14 +1298,14 @@ H5C2_check_for_journaling(H5F_t * f,
}
} else {
- /* we have to play some games here to set up an error message
- * that contains the journal file path. In essence, what
- * follows is a somewhat modified version of the HGOTO_ERROR()
+ /* we have to play some games here to set up an error message
+ * that contains the journal file path. In essence, what
+ * follows is a somewhat modified version of the HGOTO_ERROR()
* macro.
*/
- (void)H5Epush2(H5E_DEFAULT, __FILE__, FUNC, __LINE__,
- H5E_ERR_CLS_g, H5E_CACHE, H5E_CANTJOURNAL,
- "%s%s%s%s%s%s", l0, l1, l2, l3,
+ (void)H5Epush2(H5E_DEFAULT, __FILE__, FUNC, __LINE__,
+ H5E_ERR_CLS_g, H5E_CACHE, H5E_CANTJOURNAL,
+ "%s%s%s%s%s%s", l0, l1, l2, l3,
cache_ptr->jnl_file_name, l4);
(void)H5E_dump_api_stack((int)H5_IS_API(FUNC));
HGOTO_DONE(FAIL)
@@ -1253,7 +1325,7 @@ done:
* Function: H5C2_get_journaling_in_progress()
*
* Purpose: Query the HDF5 file to see if it is marked as having
- * journaling in progress. Update the journaling
+ * journaling in progress. Update the journaling
* configuration fields in the cache structure accordingly.
*
* At least initially, the purpose of this function is
@@ -1279,8 +1351,8 @@ done:
* March 11, 2008
*
* Changes: JRM -- 2/20/09
- * Reworked to reflect the move of the journal file name
- * and magic from the journaling configuration block to
+ * Reworked to reflect the move of the journal file name
+ * and magic from the journaling configuration block to
* the metadata journaling superblock extension message.
* Note that the journaling configuration block no longer
* exists.
@@ -1310,7 +1382,7 @@ H5C2_get_journaling_in_progress(const H5F_t * f,
"journaling enabled but jnl file name empty?!?.")
}
- if ( f->shared->mdc_jnl_file_name_len >
+ if ( f->shared->mdc_jnl_file_name_len >
H5C2__MAX_JOURNAL_FILE_NAME_LEN ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
@@ -1318,14 +1390,14 @@ H5C2_get_journaling_in_progress(const H5F_t * f,
}
cache_ptr->jnl_magic = f->shared->mdc_jnl_magic;
- cache_ptr->jnl_file_name_len = f->shared->mdc_jnl_file_name_len;
+ cache_ptr->jnl_file_name_len = (int32_t)f->shared->mdc_jnl_file_name_len;
HDstrncpy(cache_ptr->jnl_file_name,
f->shared->mdc_jnl_file_name,
f->shared->mdc_jnl_file_name_len + 1);
if ( ( (cache_ptr->jnl_file_name)[cache_ptr->jnl_file_name_len]
!= '\0' ) ||
- ( HDstrlen(cache_ptr->jnl_file_name) !=
+ ( HDstrlen(cache_ptr->jnl_file_name) !=
(size_t)(cache_ptr->jnl_file_name_len) ) ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
@@ -1343,14 +1415,14 @@ done:
/*-------------------------------------------------------------------------
* Function: H5C2_mark_journaling_in_progress()
*
- * Purpose: Modify the HDF5 file to indicate that journaling is
- * in progress, and flush the file to disk.
+ * Purpose: Modify the HDF5 file to indicate that journaling is
+ * in progress, and flush the file to disk.
*
- * The objective here is to allow us to detect the fact
- * the file was being journaled if we crash before we
+ * The objective here is to allow us to detect the fact
+ * the file was being journaled if we crash before we
* close the file properly.
*
- * Note that the function assumes that the file is not
+ * Note that the function assumes that the file is not
* currently marked as having journaling in progress.
*
* Return: Success: SUCCEED
@@ -1403,7 +1475,7 @@ H5C2_mark_journaling_in_progress(H5F_t * f,
}
cache_ptr->jnl_magic = journal_magic;
- cache_ptr->jnl_file_name_len = HDstrlen(journal_file_name_ptr);
+ cache_ptr->jnl_file_name_len = (int32_t)HDstrlen(journal_file_name_ptr);
if ( cache_ptr->jnl_file_name_len <= 0 ) {
@@ -1422,8 +1494,8 @@ H5C2_mark_journaling_in_progress(H5F_t * f,
(size_t)(cache_ptr->jnl_file_name_len + 1));
/* now, load the journaling information into shared, and then call
- * H5F_super_write_mdj_msg() to write the metadata journaling
- * superblock extension message to file.
+ * H5F_super_write_mdj_msg() to write the metadata journaling
+ * superblock extension message to file.
*/
f->shared->mdc_jnl_enabled = TRUE;
f->shared->mdc_jnl_magic = journal_magic;
@@ -1455,12 +1527,12 @@ done:
/*-------------------------------------------------------------------------
* Function: H5C2_unmark_journaling_in_progress()
*
- * Purpose: Modify the HDF5 file to indicate that journaling is
- * not in progress, and flush the file to disk.
+ * Purpose: Modify the HDF5 file to indicate that journaling is
+ * not in progress, and flush the file to disk.
*
* The objective here is to remove the messages indicating
- * that the file is being journaled. We will typically do
- * this either on file close, or if directed to cease
+ * that the file is being journaled. We will typically do
+ * this either on file close, or if directed to cease
* journaling. Once these messages are removed, we will
* be able to open the file without triggering a "journaling
* in progress" failure.
@@ -1475,10 +1547,10 @@ done:
* March 11, 2008
*
* Changes: JRM -- 2/20/09
- * Reworked function to reflect the move of the journal
+ * Reworked function to reflect the move of the journal
* file name and magic from the metadata journaling config
- * block and into a superblock extension message. Note that
- * the metadata journaling configuration block no longer
+ * block and into a superblock extension message. Note that
+ * the metadata journaling configuration block no longer
* exists.
*
*-------------------------------------------------------------------------
@@ -1520,7 +1592,7 @@ H5C2_unmark_journaling_in_progress(H5F_t * f,
cache_ptr->jnl_file_name_len = 0;
(cache_ptr->jnl_file_name)[0] = '\0';
- /* now, mark f->shared to indicate that journaling is not in
+ /* now, mark f->shared to indicate that journaling is not in
* progress, and then call H5F_super_write_mdj_msg() to write
* the changes to disk.
*/
@@ -1568,7 +1640,7 @@ done:
*/
static herr_t
-H5C2_call_mdjsc_callbacks(H5C2_t * cache_ptr,
+H5C2_call_mdjsc_callbacks(H5C2_t * cache_ptr,
hid_t dxpl_id,
H5C2_mdj_config_t * config_ptr)
{
@@ -1587,27 +1659,27 @@ H5C2_call_mdjsc_callbacks(H5C2_t * cache_ptr,
HDassert( ( cache_ptr->mdjsc_cb_tbl_fl_head == -1 ) ||
( cache_ptr->num_mdjsc_cbs < cache_ptr->mdjsc_cb_tbl_len ) );
- if ( ( cache_ptr->num_mdjsc_cbs < 0 )
+ if ( ( cache_ptr->num_mdjsc_cbs < 0 )
||
- ( cache_ptr->num_mdjsc_cbs > cache_ptr->mdjsc_cb_tbl_len )
+ ( cache_ptr->num_mdjsc_cbs > cache_ptr->mdjsc_cb_tbl_len )
||
- ( cache_ptr->mdjsc_cb_tbl_fl_head < -1 )
+ ( cache_ptr->mdjsc_cb_tbl_fl_head < -1 )
||
- ( cache_ptr->mdjsc_cb_tbl_fl_head > cache_ptr->mdjsc_cb_tbl_len )
+ ( cache_ptr->mdjsc_cb_tbl_fl_head > cache_ptr->mdjsc_cb_tbl_len )
||
- ( cache_ptr->mdjsc_cb_tbl_max_idx_in_use < -1 )
+ ( cache_ptr->mdjsc_cb_tbl_max_idx_in_use < -1 )
||
- ( cache_ptr->mdjsc_cb_tbl_max_idx_in_use >=
- cache_ptr->mdjsc_cb_tbl_len )
+ ( cache_ptr->mdjsc_cb_tbl_max_idx_in_use >=
+ cache_ptr->mdjsc_cb_tbl_len )
||
- ( cache_ptr->mdjsc_cb_tbl_len < H5C2__MIN_MDJSC_CB_TBL_LEN )
+ ( cache_ptr->mdjsc_cb_tbl_len < H5C2__MIN_MDJSC_CB_TBL_LEN )
||
( ( cache_ptr->num_mdjsc_cbs == cache_ptr->mdjsc_cb_tbl_len )
&&
- ( ( cache_ptr->mdjsc_cb_tbl_fl_head != -1 )
+ ( ( cache_ptr->mdjsc_cb_tbl_fl_head != -1 )
||
( cache_ptr->mdjsc_cb_tbl_max_idx_in_use !=
- cache_ptr->mdjsc_cb_tbl_len - 1 )
+ cache_ptr->mdjsc_cb_tbl_len - 1 )
)
)
||
@@ -1652,7 +1724,7 @@ done:
* Function: H5C2_deregister_mdjsc_callback()
*
* Purpose: Deregister a metadata journaling status change callback,
- * shrinking the metadata journaling status callback table
+ * shrinking the metadata journaling status callback table
* as necessary.
*
* Return: Success: SUCCEED
@@ -1682,10 +1754,10 @@ H5C2_deregister_mdjsc_callback(H5C2_t * cache_ptr,
}
if ( ( cache_ptr->mdjsc_cb_tbl == NULL ) ||
- ( ( cache_ptr->num_mdjsc_cbs == cache_ptr->mdjsc_cb_tbl_len )
+ ( ( cache_ptr->num_mdjsc_cbs == cache_ptr->mdjsc_cb_tbl_len )
&&
( cache_ptr->mdjsc_cb_tbl_fl_head != -1 ) ) ||
- ( ( cache_ptr->mdjsc_cb_tbl_fl_head < 0 )
+ ( ( cache_ptr->mdjsc_cb_tbl_fl_head < 0 )
&&
( cache_ptr->num_mdjsc_cbs != cache_ptr->mdjsc_cb_tbl_len ) ) ||
( cache_ptr->mdjsc_cb_tbl_len < H5C2__MIN_MDJSC_CB_TBL_LEN ) ||
@@ -1694,7 +1766,7 @@ H5C2_deregister_mdjsc_callback(H5C2_t * cache_ptr,
( cache_ptr->num_mdjsc_cbs < 0 ) ||
( ( cache_ptr->mdjsc_cb_tbl_max_idx_in_use < 0 ) &&
( cache_ptr->num_mdjsc_cbs > 0 ) ) ) {
-
+
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "mdjsc_cb_tbl corrupt(1)?!?!");
}
@@ -1710,19 +1782,19 @@ H5C2_deregister_mdjsc_callback(H5C2_t * cache_ptr,
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "bad idx?!?");
} else if ( ((cache_ptr->mdjsc_cb_tbl)[idx]).fcn_ptr == NULL ) {
-
+
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"callback already deregistered");
-
+
} else if ( ((cache_ptr->mdjsc_cb_tbl)[idx]).fl_next != -1 ) {
-
+
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "free list corrupted.");
}
((cache_ptr->mdjsc_cb_tbl)[idx]).fcn_ptr = NULL;
((cache_ptr->mdjsc_cb_tbl)[idx]).data_ptr = NULL;
- ((cache_ptr->mdjsc_cb_tbl)[idx]).fl_next =
+ ((cache_ptr->mdjsc_cb_tbl)[idx]).fl_next =
cache_ptr->mdjsc_cb_tbl_fl_head;
cache_ptr->mdjsc_cb_tbl_fl_head = idx;
(cache_ptr->num_mdjsc_cbs)--;
@@ -1752,19 +1824,19 @@ H5C2_deregister_mdjsc_callback(H5C2_t * cache_ptr,
if ( ( cache_ptr->num_mdjsc_cbs >= cache_ptr->mdjsc_cb_tbl_len )
||
- ( ( cache_ptr->num_mdjsc_cbs < cache_ptr->mdjsc_cb_tbl_len )
+ ( ( cache_ptr->num_mdjsc_cbs < cache_ptr->mdjsc_cb_tbl_len )
&&
- ( cache_ptr->num_mdjsc_cbs > 0 )
+ ( cache_ptr->num_mdjsc_cbs > 0 )
&&
- ( ( cache_ptr->mdjsc_cb_tbl_fl_head < 0 )
+ ( ( cache_ptr->mdjsc_cb_tbl_fl_head < 0 )
||
( cache_ptr->mdjsc_cb_tbl_fl_head >= cache_ptr->mdjsc_cb_tbl_len )
- )
- )
+ )
+ )
||
- ( ( cache_ptr->num_mdjsc_cbs == 0 )
+ ( ( cache_ptr->num_mdjsc_cbs == 0 )
&&
- ( cache_ptr->mdjsc_cb_tbl_max_idx_in_use != -1 )
+ ( cache_ptr->mdjsc_cb_tbl_max_idx_in_use != -1 )
)
) {
@@ -1776,7 +1848,7 @@ H5C2_deregister_mdjsc_callback(H5C2_t * cache_ptr,
if ( ( fraction_in_use < H5C2__MDJSC_CB_TBL_MIN_ACTIVE_RATIO ) &&
( cache_ptr->mdjsc_cb_tbl_len > H5C2__MIN_MDJSC_CB_TBL_LEN ) &&
- ( cache_ptr->mdjsc_cb_tbl_max_idx_in_use <
+ ( cache_ptr->mdjsc_cb_tbl_max_idx_in_use <
(cache_ptr->mdjsc_cb_tbl_len / 2) ) ) {
herr_t result;
@@ -1833,7 +1905,7 @@ H5C2_grow_mdjsc_callback_table(H5C2_t * cache_ptr)
if ( ( cache_ptr->num_mdjsc_cbs != cache_ptr->mdjsc_cb_tbl_len ) ||
( cache_ptr->mdjsc_cb_tbl_fl_head != -1 ) ||
- ( cache_ptr->mdjsc_cb_tbl_max_idx_in_use !=
+ ( cache_ptr->mdjsc_cb_tbl_max_idx_in_use !=
cache_ptr->mdjsc_cb_tbl_len - 1 ) ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
@@ -1844,8 +1916,8 @@ H5C2_grow_mdjsc_callback_table(H5C2_t * cache_ptr)
old_mdjsc_cb_tbl_len = cache_ptr->mdjsc_cb_tbl_len;
new_mdjsc_cb_tbl_len = 2 * old_mdjsc_cb_tbl_len;
- new_mdjsc_cb_tbl = H5MM_malloc((size_t)new_mdjsc_cb_tbl_len *
- sizeof(H5C2_mdjsc_record_t));
+ new_mdjsc_cb_tbl = (H5C2_mdjsc_record_t *)
+ H5MM_malloc((size_t)new_mdjsc_cb_tbl_len * sizeof(H5C2_mdjsc_record_t));
if ( new_mdjsc_cb_tbl == NULL ) {
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \
@@ -1869,7 +1941,7 @@ H5C2_grow_mdjsc_callback_table(H5C2_t * cache_ptr)
cache_ptr->mdjsc_cb_tbl_len = new_mdjsc_cb_tbl_len;
cache_ptr->mdjsc_cb_tbl_fl_head = old_mdjsc_cb_tbl_len;
- old_mdjsc_cb_tbl = H5MM_xfree(old_mdjsc_cb_tbl);
+ old_mdjsc_cb_tbl = (H5C2_mdjsc_record_t *)H5MM_xfree(old_mdjsc_cb_tbl);
if ( old_mdjsc_cb_tbl != NULL ) {
@@ -1889,7 +1961,7 @@ done:
* Function: H5C2_register_mdjsc_callback()
*
* Purpose: Register a metadata journaling status change callback,
- * growing the metadata journaling status callback table
+ * growing the metadata journaling status callback table
* as necessary.
*
* Return: Success: SUCCEED
@@ -1972,18 +2044,18 @@ H5C2_register_mdjsc_callback(H5C2_t * cache_ptr,
(cache_ptr->num_mdjsc_cbs)++;
if ( ( ( cache_ptr->num_mdjsc_cbs == cache_ptr->mdjsc_cb_tbl_len ) &&
- ( cache_ptr->mdjsc_cb_tbl_fl_head != -1 )
- )
+ ( cache_ptr->mdjsc_cb_tbl_fl_head != -1 )
+ )
||
- ( cache_ptr->num_mdjsc_cbs > cache_ptr->mdjsc_cb_tbl_len )
+ ( cache_ptr->num_mdjsc_cbs > cache_ptr->mdjsc_cb_tbl_len )
||
- ( ( cache_ptr->num_mdjsc_cbs < cache_ptr->mdjsc_cb_tbl_len )
+ ( ( cache_ptr->num_mdjsc_cbs < cache_ptr->mdjsc_cb_tbl_len )
&&
- ( ( cache_ptr->mdjsc_cb_tbl_fl_head < 0 )
+ ( ( cache_ptr->mdjsc_cb_tbl_fl_head < 0 )
||
( cache_ptr->mdjsc_cb_tbl_fl_head >= cache_ptr->mdjsc_cb_tbl_len )
- )
- )
+ )
+ )
) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "mdjsc_cb_tbl corrupt(2)?!?!");
@@ -2060,7 +2132,7 @@ H5C2_shrink_mdjsc_callback_table(H5C2_t * cache_ptr)
if ( ( cache_ptr->num_mdjsc_cbs >= cache_ptr->mdjsc_cb_tbl_len ) ||
( (cache_ptr->mdjsc_cb_tbl_len / 2) < H5C2__MIN_MDJSC_CB_TBL_LEN ) ||
( cache_ptr->mdjsc_cb_tbl_fl_head == -1 ) ||
- ( cache_ptr->mdjsc_cb_tbl_max_idx_in_use >=
+ ( cache_ptr->mdjsc_cb_tbl_max_idx_in_use >=
cache_ptr->mdjsc_cb_tbl_len / 2 ) ||
( fraction_in_use >= H5C2__MDJSC_CB_TBL_MIN_ACTIVE_RATIO ) ) {
@@ -2074,10 +2146,10 @@ H5C2_shrink_mdjsc_callback_table(H5C2_t * cache_ptr)
new_mdjsc_cb_tbl_len = old_mdjsc_cb_tbl_len / 2;
while ( ( (new_mdjsc_cb_tbl_len / 2) >= H5C2__MIN_MDJSC_CB_TBL_LEN ) &&
- ( (((double)(cache_ptr->num_mdjsc_cbs)) /
- ((double)new_mdjsc_cb_tbl_len)) <=
+ ( (((double)(cache_ptr->num_mdjsc_cbs)) /
+ ((double)new_mdjsc_cb_tbl_len)) <=
H5C2__MDJSC_CB_TBL_MIN_ACTIVE_RATIO ) &&
- ( (new_mdjsc_cb_tbl_len / 2) >
+ ( (new_mdjsc_cb_tbl_len / 2) >
cache_ptr->mdjsc_cb_tbl_max_idx_in_use ) )
{
new_mdjsc_cb_tbl_len /= 2;
@@ -2090,8 +2162,8 @@ H5C2_shrink_mdjsc_callback_table(H5C2_t * cache_ptr)
"error in computation of new_mdjsc_cb_tbl_len?!?!");
}
- new_mdjsc_cb_tbl = H5MM_malloc(new_mdjsc_cb_tbl_len *
- sizeof(H5C2_mdjsc_record_t));
+ new_mdjsc_cb_tbl = (H5C2_mdjsc_record_t *)
+ H5MM_malloc((size_t)new_mdjsc_cb_tbl_len * sizeof(H5C2_mdjsc_record_t));
if ( new_mdjsc_cb_tbl == NULL ) {
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \
@@ -2107,7 +2179,7 @@ H5C2_shrink_mdjsc_callback_table(H5C2_t * cache_ptr)
new_mdjsc_cb_tbl[i].fcn_ptr = NULL;
new_mdjsc_cb_tbl[i].data_ptr = NULL;
new_mdjsc_cb_tbl[i].fl_next = -1;
-
+
if ( new_fl_head == -1 ) {
new_fl_head = i;
@@ -2135,7 +2207,7 @@ H5C2_shrink_mdjsc_callback_table(H5C2_t * cache_ptr)
cache_ptr->mdjsc_cb_tbl_fl_head = new_fl_head;
cache_ptr->mdjsc_cb_tbl_len = new_mdjsc_cb_tbl_len;
- old_mdjsc_cb_tbl = H5MM_xfree(old_mdjsc_cb_tbl);
+ old_mdjsc_cb_tbl = ( H5C2_mdjsc_record_t *)H5MM_xfree(old_mdjsc_cb_tbl);
if ( old_mdjsc_cb_tbl != NULL ) {
@@ -2155,12 +2227,16 @@ done:
/**************************************************************************/
/* The following macros are wrappers for the low level binary journal file
- * functions. They exist, as it is likely that these function will be
- * converted into macros once we have asynchronous journal file writes
- * running, and by setting up these wrappers now, we will make this
+ * functions. They exist, as it is likely that these function will be
+ * converted into macros once we have asynchronous journal file writes
+ * running, and by setting up these wrappers now, we will make this
* conversion easier.
*/
+#if 1 /* JRM */
+ /* remove print statements from these macros. -- JRM */
+#endif /* JRM */
+
#define H5C2_JB_BJF__WRITE_BUFFER(struct_ptr, \
buf_size, \
buf_ptr, \
@@ -2232,11 +2308,2610 @@ if ( H5C2_jb_bjf__write_trans_num((struct_ptr), (is_end_trans), \
/******************************************************************************
*
+ * Function: H5C2_jb_aio__await_buffer_write_completion()
+ *
+ * Programmer: John Mainzer
+ *
+ * Purpose: Await completion of the asynchronous write of the
+ * specified buffer.
+ *
+ * Verify that AIO is enabled, that the specified
+ * buffer exists and has been queued for an asynchronous
+ * write which has not been logged as complete.
+ *
+ * Test to see if the write has completed -- if it has
+ * not, await its completion.
+ *
+ * Then mark the write as complete and return.
+ *
+ * Returns: SUCCEED on success.
+ *
+ ******************************************************************************/
+
+static herr_t
+H5C2_jb_aio__await_buffer_write_completion(H5C2_jbrb_t * struct_ptr,
+ int buf_num)
+{
+ int result;
+ herr_t ret_value = SUCCEED;
+ struct aiocb * aiocb_ptr = NULL;
+ const struct aiocb * aiocb_list[1] = { NULL };
+
+ FUNC_ENTER_NOAPI(H5C2_jb_aio__await_buffer_write_completion, FAIL)
+
+ HDassert( struct_ptr != NULL );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+ HDassert( struct_ptr->use_aio );
+ HDassert( struct_ptr->aio_ctl_blks != NULL );
+ HDassert( buf_num >= 0 );
+ HDassert( buf_num < struct_ptr->num_bufs );
+
+ aiocb_ptr = &((*(struct_ptr->aio_ctl_blks))[buf_num]);
+
+ if ( aiocb_ptr->aio_fildes != struct_ptr->journal_file_fd ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "unexpected file descriptor in target buffer aio ctl blk")
+ }
+
+ /* wait until the request completes */
+ aiocb_list[0] = aiocb_ptr;
+ result = aio_suspend(aiocb_list, 1, NULL);
+
+ if ( result != 0 ) {
+
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
+ "call to aio_suspend() failed.")
+ }
+#if 0 /* JRM */
+ /* check to see if there were any errors */
+ result = aio_error(aiocb_ptr);
+ if ( result != 0 ) {
+
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
+ "aio_error() reports something other than success.")
+ }
+#else /* JRM */
+ /* verify that aio_error() returns something other than EINPROGRESS */
+ result = aio_error(aiocb_ptr);
+
+ if ( result != 0 ) {
+
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
+ "aio_error() reports error after aio_suspend() returns")
+ }
+
+ /* call aio_return() to complete the write */
+ result = aio_return(aiocb_ptr);
+ if ( result == -1 ) {
+
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
+ "aio_error() reports something other than success.")
+
+ }
+ /* TODO: Verify the number of bytes written? */
+#endif /* JRM */
+
+ H5C2__JBRB__UPDATE_STATS_FOR_BUF_WRITE_COMPLETE(struct_ptr, TRUE)
+
+ /* mark the aio control block to indicate no write in progress */
+ aiocb_ptr->aio_fildes = -1;
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C2_jb_aio__await_buffer_write_completion() */
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb_aio__await_async_fsync_completion()
+ *
+ * Programmer: John Mainzer
+ *
+ * Purpose: Verify that AIO is enabled, taht struct_ptr->
+ * use_aio_fsync is TRUE, and that the sync queue
+ * is not empty.
+ *
+ * Then await completion of the asynchronous fsync
+ * at the head of the sync queue, update struct_ptr->
+ * last_trans_on_disk, remove and discard the instance
+ * of H5C2_jbrb_sync_q_entry_t at the head of the sync
+ * queue, and return.
+ *
+ * JRM -- 2/10/10
+ *
+ * Returns: SUCCEED on success.
+ * FAIL otherwise.
+ *
+ ******************************************************************************/
+
+#define H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG 0
+
+#if 1
+static herr_t
+H5C2_jb_aio__await_async_fsync_completion(H5C2_jbrb_t * struct_ptr)
+{
+ int result;
+ herr_t ret_value = SUCCEED;
+ struct H5C2_jbrb_sync_q_entry_t * head_ptr = NULL;
+ struct aiocb * aiocb_ptr = NULL;
+
+ FUNC_ENTER_NOAPI(H5C2_jb_aio__await_async_fsync_completion, FAIL)
+
+ HDassert( struct_ptr != NULL );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+ HDassert( struct_ptr->use_aio );
+ HDassert( struct_ptr->use_aio_fsync );
+ HDassert( struct_ptr->aio_sync_q_len > 0 );
+
+ head_ptr = struct_ptr->aio_sync_q_head;
+
+ HDassert( head_ptr != NULL );
+ HDassert( head_ptr->magic == H5C2__H5C2_JBRB_SYNC_Q_T_MAGIC );
+
+ aiocb_ptr = &(head_ptr->ctl_blk);
+
+ if ( aiocb_ptr->aio_fildes != struct_ptr->journal_file_fd ) {
+
+#if H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG
+ HDfprintf(stdout, "%s: bad fd in ctl blk?!?\n", FUNC);
+#endif /* H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG */
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "bad fd in ctl blk?!?")
+ }
+
+ /* can't use aio_suspend() with an aiocb from a call to aio_fsync()
+ * hence loop until aio_error() returns either 0 or something other
+ * than EINPROGRESS.
+ */
+ do
+ {
+ result = aio_error(aiocb_ptr);
+
+ if ( ( result != 0 ) && ( result != EINPROGRESS ) ) {
+
+#if H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG
+ HDfprintf(stdout, "%s: call to aio_error() reports error.\n", FUNC);
+ HDfprintf(stdout, "%s: errno = %d (%s).\n", FUNC, errno,
+ strerror(errno));
+#endif /* H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG */
+
+ HGOTO_ERROR(H5E_IO, H5E_SYNCFAIL, FAIL, \
+ "aio_error() reports error.")
+ }
+
+ H5C2__JBRB__UPDATE_STATS_FOR_AIO_ERROR_CALL_AWAITING_SYNC(struct_ptr)
+
+ } while ( result != 0 );
+
+ /* call aio_return() to complete the aio_fsync() */
+ result = aio_return(aiocb_ptr);
+
+ if ( result == -1 ) {
+
+#if H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG
+ HDfprintf(stdout,
+ "%s: aio_return() reports something other than success.\n",
+ FUNC);
+#endif /* H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG */
+
+ HGOTO_ERROR(H5E_IO, H5E_SYNCFAIL, FAIL, \
+ "aio_return() reports something other than success.")
+
+ }
+
+ /* the aio_fsync() completed successfully -- update last trans on disk,
+ * and discard the head of the sync queue.
+ */
+
+ HDassert( struct_ptr->last_trans_on_disk <= head_ptr->last_trans_in_sync );
+ HDassert( head_ptr->last_trans_in_sync <= struct_ptr->last_trans_written );
+
+#if H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG
+ HDfprintf(stdout, "%s: changing last trans on disk from %lld to %lld.\n",
+ FUNC, struct_ptr->last_trans_on_disk,
+ head_ptr->last_trans_in_sync);
+#endif /* H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG */
+
+ H5C2__JBRB__UPDATE_STATS_FOR_ASYNC_SYNC_COMPLETED(struct_ptr, TRUE)
+
+ struct_ptr->last_trans_on_disk = head_ptr->last_trans_in_sync;
+ aiocb_ptr->aio_fildes = -1;
+
+ if ( H5C2_jb_aio__sync_q__discard_head(struct_ptr) != SUCCEED ) {
+
+#if H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG
+ HDfprintf(stdout,
+ "%s: H5C2_jb_aio__sync_q__discard_head() failed.\n", FUNC);
+#endif /* H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG */
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__sync_q__discard_head() failed.")
+ }
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C2_jb_aio__await_async_fsync_completion() */
+#else
+static herr_t
+H5C2_jb_aio__await_async_fsync_completion(H5C2_jbrb_t * struct_ptr)
+{
+ int result;
+ herr_t ret_value = SUCCEED;
+ struct H5C2_jbrb_sync_q_entry_t * head_ptr = NULL;
+ struct aiocb * aiocb_ptr = NULL;
+ const struct aiocb * aiocb_list[1] = { NULL };
+
+ FUNC_ENTER_NOAPI(H5C2_jb_aio__await_async_fsync_completion, FAIL)
+
+ HDassert( struct_ptr != NULL );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+ HDassert( struct_ptr->use_aio );
+ HDassert( struct_ptr->use_aio_fsync );
+ HDassert( struct_ptr->aio_sync_q_len > 0 );
+
+ head_ptr = struct_ptr->aio_sync_q_head;
+
+ HDassert( head_ptr != NULL );
+ HDassert( head_ptr->magic == H5C2__H5C2_JBRB_SYNC_Q_T_MAGIC );
+
+ aiocb_ptr = &(head_ptr->ctl_blk);
+
+ if ( aiocb_ptr->aio_fildes != struct_ptr->journal_file_fd ) {
+
+#if H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG
+ HDfprintf(stdout, "%s: bad fd in ctl blk?!?\n", FUNC);
+#endif /* H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG */
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "bad fd in ctl blk?!?")
+ }
+
+ /* wait until the fsync request completes */
+ aiocb_list[0] = aiocb_ptr;
+ result = aio_suspend(aiocb_list, 1, NULL);
+
+ if ( result != 0 ) {
+
+#if H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG
+ HDfprintf(stdout, "%s: call to aio_suspend() failed.\n", FUNC);
+ HDfprintf(stdout, "%s: errno = %d (%s).\n", FUNC, errno,
+ strerror(errno));
+#endif /* H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG */
+
+ HGOTO_ERROR(H5E_IO, H5E_SYNCFAIL, FAIL, \
+ "call to aio_suspend() failed.")
+ }
+
+ /* verify that aio_error() returns good status */
+ result = aio_error(aiocb_ptr);
+
+ if ( result != 0 ) {
+
+#if H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG
+ HDfprintf(stdout,
+ "%s: aio_error() reports error after aio_suspend() returns.\n",
+ FUNC);
+#endif /* H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG */
+
+ HGOTO_ERROR(H5E_IO, H5E_SYNCFAIL, FAIL, \
+ "aio_error() reports error after aio_suspend() returns")
+ }
+
+ /* call aio_return() to complete the aio_fsync() */
+ result = aio_return(aiocb_ptr);
+ if ( result == -1 ) {
+
+#if H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG
+ HDfprintf(stdout,
+ "%s: aio_return() reports something other than success.\n",
+ FUNC);
+#endif /* H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG */
+
+ HGOTO_ERROR(H5E_IO, H5E_SYNCFAIL, FAIL, \
+ "aio_return() reports something other than success.")
+
+ }
+
+ /* the aio_fsync() completed successfully -- update last trans on disk,
+ * and discard the head of the sync queue.
+ */
+
+ HDassert( struct_ptr->last_trans_on_disk <= head_ptr->last_trans_in_sync );
+ HDassert( head_ptr->last_trans_in_sync <= struct_ptr->last_trans_written );
+
+#if H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG
+ HDfprintf(stdout, "%s: changing last trans on disk from %lld to %lld.\n",
+ FUNC, struct_ptr->last_trans_on_disk,
+ head_ptr->last_trans_in_sync);
+#endif /* H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG */
+
+ struct_ptr->last_trans_on_disk = head_ptr->last_trans_in_sync;
+ aiocb_ptr->aio_fildes = -1;
+
+ if ( H5C2_jb_aio__sync_q__discard_head(struct_ptr) != SUCCEED ) {
+
+#if H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG
+ HDfprintf(stdout,
+ "%s: H5C2_jb_aio__sync_q__discard_head() failed.\n", FUNC);
+#endif /* H5C2_JB_AIO__AWAIT_ASYNC_FSYNC_COMPLETION__DEBUG */
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__sync_q__discard_head() failed.")
+ }
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C2_jb_aio__await_async_fsync_completion() */
+#endif
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb_aio__await_completion_of_all_async_fsyncs
+ *
+ * Programmer: John Mainzer
+ * 2/10/10
+ *
+ * Purpose: Verify that AIO is enabled, and that struct_ptr->
+ * use_aio_fsync is TRUE.
+ *
+ * Then await completion of all asynchronous fsyncs
+ * currently in progress -- if any. As each fsync
+ * completes, update struct_ptr->last_trans_on_disk,
+ * and discard the head of the sync queue.
+ *
+ * Returns: SUCCEED on success.
+ * FAIL otherwise.
+ *
+ ******************************************************************************/
+
+#define H5C2_JB_AIO__AWAIT_COMPLETION_OF_ALL_ASYNC_FSYNCS__DEBUG 0
+
+herr_t
+H5C2_jb_aio__await_completion_of_all_async_fsyncs(H5C2_jbrb_t * struct_ptr)
+{
+ herr_t result;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5C2_jb_aio__await_completion_of_all_async_fsyncs, FAIL)
+
+ HDassert( struct_ptr != NULL );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+ HDassert( struct_ptr->use_aio );
+ HDassert( struct_ptr->use_aio_fsync );
+
+#if H5C2_JB_AIO__AWAIT_COMPLETION_OF_ALL_ASYNC_FSYNCS__DEBUG
+ HDfprintf(stdout, "%s: entering -- aio_sync_q_len = %d.\n",
+ FUNC, (int)(struct_ptr->aio_sync_q_len));
+#endif /* H5C2_JB_AIO__AWAIT_COMPLETION_OF_ALL_ASYNC_FSYNCS__DEBUG */
+
+ while ( struct_ptr->aio_sync_q_len > 0 ) {
+
+ result = H5C2_jb_aio__await_async_fsync_completion(struct_ptr);
+
+ if ( result != SUCCEED ) {
+
+#if H5C2_JB_AIO__AWAIT_COMPLETION_OF_ALL_ASYNC_FSYNCS__DEBUG
+ HDfprintf(stdout,
+ "H5C2_jb_aio__await_async_fsync_completion() failed.\n",
+ FUNC);
+#endif /* H5C2_JB_AIO__AWAIT_COMPLETION_OF_ALL_ASYNC_FSYNCS__DEBUG */
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__await_async_fsync_completion() failed.")
+ }
+ } /* while */
+
+ HDassert( struct_ptr->aio_sync_q_len == 0 );
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C2_jb_aio__await_completion_of_all_async_fsyncs() */
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb_aio__await_completion_of_all_pending_writes
+ *
+ * Programmer: John Mainzer
+ * 1/12/10
+ *
+ * Purpose: Await completion of all asynchronous writes currently
+ * in progress -- if any. As each write completes, mark
+ * the associated buffer as free by updating
+ * struct_ptr->get and decrementing
+ * struct_ptr->bufs_in_use.
+ *
+ * Note that the buffer indicated by struct_ptr->put
+ * may or may not be involved in a write when this
+ * function is called. Infer whether it is via the
+ * aio contol blocks array.
+ *
+ * Returns: SUCCEED on success.
+ *
+ ******************************************************************************/
+
+#define H5C2_JB_AIO__AWAIT_COMPLETION_OF_ALL_PENDING_WRITES__DEBUG 0
+
+herr_t
+H5C2_jb_aio__await_completion_of_all_pending_writes(H5C2_jbrb_t * struct_ptr)
+{
+ hbool_t done = FALSE;
+ int result;
+ herr_t ret_value = SUCCEED;
+ struct aiocb * aiocb_ptr = NULL;
+
+ FUNC_ENTER_NOAPI(H5C2_jb_aio__await_completion_of_all_pending_writes, FAIL)
+
+ HDassert( struct_ptr != NULL );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+ HDassert( struct_ptr->use_aio );
+
+ if ( struct_ptr->bufs_in_use <= 0 ) {
+
+ done = TRUE;
+ }
+
+ while ( ! done ) {
+
+ aiocb_ptr = &((*(struct_ptr->aio_ctl_blks))[struct_ptr->get]);
+
+ if ( aiocb_ptr->aio_fildes != -1 ) {
+
+ result = H5C2_jb_aio__await_buffer_write_completion(struct_ptr,
+ struct_ptr->get);
+
+ if ( result != SUCCEED ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__await_buffer_write_completion() failed.");
+ }
+
+ /* Update the last transaction written, and then set the
+ * transaction tracking array entry of the buffer whose
+ * write just completed to zero.
+ */
+ HDassert( struct_ptr->last_trans_written <=
+ (*struct_ptr->trans_tracking)[struct_ptr->get] );
+
+ struct_ptr->last_trans_written = (uint64_t)
+ (*struct_ptr->trans_tracking)[struct_ptr->get];
+
+ (*struct_ptr->trans_tracking)[struct_ptr->get] = 0;
+
+#if H5C2_JB_AIO__AWAIT_COMPLETION_OF_ALL_PENDING_WRITES__DEBUG
+ HDfprintf(stdout,
+ "%s: last_trans_written = %lld, get/put = %d/%d\n",
+ FUNC, (long long)(struct_ptr->last_trans_written),
+ struct_ptr->get, struct_ptr->put);
+#endif /* H5C2_JB_AIO__AWAIT_COMPLETION_OF_ALL_PENDING_WRITES__DEBUG */
+
+ /* decrement writes in progress */
+ struct_ptr->writes_in_progress--;
+
+ /* decrement bufs in use */
+ struct_ptr->bufs_in_use--;
+
+ HDassert(
+ ( struct_ptr->writes_in_progress == struct_ptr->bufs_in_use ) ||
+ ( struct_ptr->writes_in_progress == struct_ptr->bufs_in_use - 1 ) );
+
+ /* Update get to reference the next entry in the ring buffer
+ * if get and put are not the same.
+ *
+ * If they are the same, verify that bufs_in_use and
+ * writes_in_progress are both zero, and then set done to TRUE
+ */
+ if ( struct_ptr->get != struct_ptr->put ) {
+
+ struct_ptr->get =
+ (struct_ptr->get + 1) % (struct_ptr->num_bufs);
+
+ } else {
+
+ HDassert( struct_ptr->bufs_in_use == 0 );
+ HDassert( struct_ptr->writes_in_progress == 0 );
+
+ done = TRUE;
+
+ }
+ } else {
+
+ HDassert( struct_ptr->get == struct_ptr->put );
+
+ done = TRUE;
+ }
+ } /* while */
+
+ HDassert( struct_ptr->bufs_in_use <= 1 );
+
+ HDassert( struct_ptr->writes_in_progress == 0 );
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C2_jb_aio__await_completion_of_all_pending_writes() */
+
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb_aio__flush
+ *
+ * Programmer: John Mainzer
+ * 1/11/10
+ *
+ * Purpose: Verify that there is no transaction in progress and
+ * that aio is enabled.
+ *
+ * Test to see if the current buffer (indicated by
+ * struct_ptr->put) is dirty. If it is, queue a write
+ * of the current buffer.
+ *
+ * Await completion of all outstanding writes.
+ *
+ * Sync the file.
+ *
+ * Update struct_ptr->last_trans_on_disk.
+ *
+ * Returns: SUCCEED on success.
+ *
+ ******************************************************************************/
+
+#define H5C2_JB_AIO__FLUSH__DEBUG 0
+
+static herr_t
+H5C2_jb_aio__flush(H5C2_jbrb_t * struct_ptr)
+{
+ hbool_t cur_buf_was_dirty = FALSE;
+ herr_t result;
+ herr_t ret_value = SUCCEED;
+ uint64_t last_trans_in_ring_buffer;
+
+ FUNC_ENTER_NOAPI(H5C2_jb_aio__flush, FAIL)
+
+ /* Check Arguments and status */
+ HDassert( struct_ptr != NULL );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+ HDassert( struct_ptr->use_aio );
+ HDassert( struct_ptr->trans_in_prog == FALSE );
+ HDassert( ( ( struct_ptr->writes_in_progress == struct_ptr->bufs_in_use )
+ &&
+ ( struct_ptr->bufs_in_use < struct_ptr->num_bufs )
+ &&
+ ( struct_ptr->cur_buf_free_space == struct_ptr->buf_size )
+ )
+ ||
+ ( ( struct_ptr->writes_in_progress + 1 == struct_ptr->bufs_in_use )
+ &&
+ ( struct_ptr->cur_buf_free_space < struct_ptr->buf_size )
+ &&
+ ( struct_ptr->cur_buf_free_space > 0 )
+ )
+ ||
+ ( ( struct_ptr->writes_in_progress == struct_ptr->bufs_in_use )
+ &&
+ ( struct_ptr->bufs_in_use == struct_ptr->num_bufs )
+ &&
+ ( struct_ptr->cur_buf_free_space == 0 )
+ )
+ );
+
+
+ /* make note of the last transaction in the ring buffer */
+ last_trans_in_ring_buffer = (*struct_ptr->trans_tracking)[struct_ptr->put];
+
+#if H5C2_JB_AIO__FLUSH__DEBUG
+ HDfprintf(stdout, "%s: trans_tracking[%d] = %lld\n", FUNC, struct_ptr->get,
+ (*struct_ptr->trans_tracking)[struct_ptr->get]);
+ HDfprintf(stdout, "%s: trans_tracking[%d] = %lld\n", FUNC, struct_ptr->put,
+ (*struct_ptr->trans_tracking)[struct_ptr->put]);
+#endif /* H5C2_JB_AIO__FLUSH__DEBUG */
+
+ /* if the current buffer (indicated by struct_ptr->put) is dirty,
+ * but not full, queue a write of the buffer. The dirty part should
+ * be obvious. The not full part is required, as
+ * H5C2_jb_aio__write_to_buffer() will have already queued the write
+ * if the buffer is full.
+ *
+ * In passing, make note of whether the current buffer is dirty --
+ * need to know this so we can setup the buffer properly after
+ * the flush.
+ */
+ if ( struct_ptr->cur_buf_free_space < struct_ptr->buf_size ) {
+
+ cur_buf_was_dirty = TRUE;
+
+ if ( struct_ptr->cur_buf_free_space > 0 ) {
+
+ /* kick off an asynchronous write of the current buffer */
+ result = H5C2_jb_aio__queue_buffer_write(struct_ptr,
+ struct_ptr->put,
+ TRUE);
+
+ if ( result != SUCCEED ) {
+
+#if H5C2_JB_AIO__FLUSH__DEBUG
+ HDfprintf(stdout,
+ "%s: H5C2_jb_aio__queue_buffer_write() failed.\n",
+ FUNC);
+#endif /* H5C2_JB_AIO__FLUSH__DEBUG */
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__queue_buffer_write() failed.");
+ }
+ }
+ }
+
+ /* await completion of all outstanding writes */
+
+ result = H5C2_jb_aio__await_completion_of_all_pending_writes(struct_ptr);
+
+ if ( result != SUCCEED ) {
+
+#if H5C2_JB_AIO__FLUSH__DEBUG
+ HDfprintf(stdout,
+ "%s: H5C2_jb_aio__await_completion_of_all_pending_writes() failed.\n",
+ FUNC);
+#endif /* H5C2_JB_AIO__FLUSH__DEBUG */
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__await_completion_of_all_pending_writes() failed.");
+ }
+
+ HDassert( struct_ptr->bufs_in_use == 0 );
+ HDassert( struct_ptr->writes_in_progress == 0 );
+ HDassert( struct_ptr->put == struct_ptr->get );
+
+ /* sync out the file */
+
+ result = H5C2_jb_aio__sync_file(struct_ptr);
+
+ if ( result != SUCCEED ) {
+
+#if H5C2_JB_AIO__FLUSH__DEBUG
+ HDfprintf(stdout,
+ "%s: H5C2_jb_aio__sync_file() failed.\n",
+ FUNC);
+#endif /* H5C2_JB_AIO__FLUSH__DEBUG */
+
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__sync_file() failed.");
+ }
+
+ /* If the current buffer was dirty on entry, it was flushed and must
+ * be prepared for use.
+ *
+ * Don't call H5C2_jb_aio__prep_next_buf_for_use() for this, as
+ * it assumes that the current buffer is full and dirty -- neither
+ * of which is the case at present.
+ *
+ * further, H5C2_jb_aio__prep_next_buf_for_use() will also
+ * increment put, which will cause problems if we don't increment
+ * get as well.
+ */
+ if ( cur_buf_was_dirty ) {
+
+ /* the following assignment is redundant if struct_ptr->use_aio_fsync
+ * is TRUE, as struct_ptr->last_trans_on_disk will already be
+ * set correctly. Verify this with an assert.
+ */
+#if 1 /* JRM */
+ if ( ( struct_ptr->use_aio_fsync ) &&
+ ( struct_ptr->last_trans_on_disk != last_trans_in_ring_buffer ) ) {
+
+ HDfprintf(stdout, "%s: ltod = %lld, ltirb = %lld\n",
+ FUNC, struct_ptr->last_trans_on_disk,
+ last_trans_in_ring_buffer);
+ }
+#endif /* JRM */
+ HDassert( ( ! struct_ptr->use_aio_fsync ) ||
+ ( struct_ptr->last_trans_on_disk ==
+ last_trans_in_ring_buffer ) );
+ struct_ptr->last_trans_on_disk = last_trans_in_ring_buffer;
+
+ /* set the cur_buf_free_space */
+ struct_ptr->cur_buf_free_space = struct_ptr->buf_size;
+
+ /* set the head pointer to point to the beginning of the
+ * current buffer
+ */
+ struct_ptr->head = (*struct_ptr->buf)[struct_ptr->put];
+
+ /* load the transaction tracking array for the current buffer with the
+ * id of the last transaction fully written to the ring buffer.
+ */
+ HDassert( (*struct_ptr->trans_tracking)[struct_ptr->put] == 0 );
+
+ (*struct_ptr->trans_tracking)[struct_ptr->put] =
+ last_trans_in_ring_buffer;
+
+ } else {
+
+ HDassert( struct_ptr->cur_buf_free_space == struct_ptr->buf_size );
+ HDassert( struct_ptr->head == (*struct_ptr->buf)[struct_ptr->put] );
+ }
+
+ HDassert( struct_ptr->bufs_in_use == 0 );
+ HDassert( struct_ptr->writes_in_progress == 0 );
+ HDassert( struct_ptr->put == struct_ptr->get );
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C2_jb_aio__flush() */
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb_aio__get_last_transaction_on_disk
+ *
+ * Programmer: John Mainzer
+ * 1/19/10
+ *
+ * Purpose: Determine the last transaction fully on disk,
+ * and place its transaction number in *trans_num_ptr.
+ * If no transaction has made it to disk, load zero
+ * into *trans_num_ptr.
+ *
+ * If aio_fsync() is not available, stall pending
+ * completion of all writes in progress, and then
+ * sync the file out using fsync().
+ *
+ * If aio_fsync() is available, note any asynchronous
+ * syncs that have completed since the last check.
+ * This will update struct_ptr->last_trans_on_disk
+ * as appropriate.
+ *
+ * In either case, return the ID of the last
+ * transaction known to be on disk.
+ *
+ * Returns: SUCCEED on success.
+ *
+ ******************************************************************************/
+
+static herr_t
+H5C2_jb_aio__get_last_transaction_on_disk(H5C2_jbrb_t * struct_ptr,
+ uint64_t * trans_num_ptr)
+{
+ hbool_t ring_buffer_was_full = FALSE;
+ herr_t result;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5C2_jb_aio__get_last_transaction_on_disk, FAIL)
+
+ /* Check Arguments */
+ HDassert( struct_ptr != NULL );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+ HDassert( struct_ptr->use_aio );
+ HDassert( trans_num_ptr != NULL );
+ HDassert( ( ( struct_ptr->writes_in_progress == struct_ptr->bufs_in_use )
+ &&
+ ( struct_ptr->bufs_in_use < struct_ptr->num_bufs )
+ &&
+ ( struct_ptr->cur_buf_free_space == struct_ptr->buf_size )
+ )
+ ||
+ ( ( struct_ptr->writes_in_progress + 1 == struct_ptr->bufs_in_use )
+ &&
+ ( struct_ptr->cur_buf_free_space < struct_ptr->buf_size )
+ &&
+ ( struct_ptr->cur_buf_free_space > 0 )
+ )
+ ||
+ ( ( struct_ptr->writes_in_progress == struct_ptr->bufs_in_use )
+ &&
+ ( struct_ptr->bufs_in_use == struct_ptr->num_bufs )
+ &&
+ ( struct_ptr->cur_buf_free_space == 0 )
+ )
+ );
+
+ if ( struct_ptr->use_aio_fsync ) {
+
+ result = H5C2_jb_aio__note_completed_async_buffer_writes(struct_ptr);
+
+ if ( result != SUCCEED ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__note_completed_async_buffer_writes() failed.")
+ }
+
+ result = H5C2_jb_aio__note_completed_async_fsyncs(struct_ptr);
+
+ if ( result != SUCCEED ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__note_completed_async_fsyncs() failed.")
+ }
+ } else {
+
+ /* aio_fsync() is not available */
+
+ if ( struct_ptr->writes_in_progress == struct_ptr->num_bufs ) {
+
+ ring_buffer_was_full = TRUE;
+ }
+
+ /* await completion of all outstanding writes */
+
+ result =
+ H5C2_jb_aio__await_completion_of_all_pending_writes(struct_ptr);
+
+ if ( result != SUCCEED ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__await_completion_of_all_pending_writes() failed.");
+ }
+
+ HDassert( struct_ptr->bufs_in_use <= 1 );
+ HDassert( ( struct_ptr->get == struct_ptr->put ) ||
+ ( ((struct_ptr->get + 1) % struct_ptr->num_bufs) ==
+ struct_ptr->put ) );
+
+ /* sync out the file */
+
+ result = H5C2_jb_aio__sync_file(struct_ptr);
+
+ if ( result != SUCCEED ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__sync_file() failed.");
+ }
+
+
+ /* update last transaction on disk */
+
+ struct_ptr->last_trans_on_disk = struct_ptr->last_trans_written;
+
+
+ /* if the ring buffer was full, put was not advanced to the next
+ * buffer in the ring buffer, nor were the associated fields updated
+ * to refer to the next buffer.
+ *
+ * In this case, we must prepare the next buffer for use.
+ *
+ * Don't call H5C2_jb_aio__prep_next_buf_for_use() for this, as
+ * it assumes that the current buffer is full and dirty -- neither
+ * of which is the case at present.
+ *
+ * further, H5C2_jb_aio__prep_next_buf_for_use() will also
+ * increment put, which will cause problems if we don't increment
+ * get as well.
+ */
+ if ( ring_buffer_was_full ) {
+
+ HDassert( struct_ptr->bufs_in_use == 0 );
+ HDassert( struct_ptr->get == struct_ptr->put );
+
+ /* set the cur_buf_free_space */
+ struct_ptr->cur_buf_free_space = struct_ptr->buf_size;
+
+ /* set the head pointer to point to the beginning of the
+ * current buffer
+ */
+ struct_ptr->head = (*struct_ptr->buf)[struct_ptr->put];
+
+ /* load the transaction tracking array for the current buffer
+ * with the id of the last transaction fully written to the
+ * ring buffer.
+ */
+ HDassert( (*struct_ptr->trans_tracking)[struct_ptr->put] == 0 );
+
+ (*struct_ptr->trans_tracking)[struct_ptr->put] =
+ struct_ptr->last_trans_written;
+
+ }
+ }
+
+ /* report last trans on disk */
+
+ *trans_num_ptr = struct_ptr->last_trans_on_disk;
+
+ /* closing sanity check */
+
+ HDassert( ( ( struct_ptr->writes_in_progress == struct_ptr->bufs_in_use )
+ &&
+ ( struct_ptr->bufs_in_use < struct_ptr->num_bufs )
+ &&
+ ( struct_ptr->cur_buf_free_space == struct_ptr->buf_size )
+ )
+ ||
+ ( ( struct_ptr->writes_in_progress + 1 == struct_ptr->bufs_in_use )
+ &&
+ ( struct_ptr->cur_buf_free_space < struct_ptr->buf_size )
+ &&
+ ( struct_ptr->cur_buf_free_space > 0 )
+ )
+ ||
+ ( ( struct_ptr->writes_in_progress == struct_ptr->bufs_in_use )
+ &&
+ ( struct_ptr->bufs_in_use == struct_ptr->num_bufs )
+ &&
+ ( struct_ptr->cur_buf_free_space == 0 )
+ )
+ );
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C2_jb_aio__get_last_transaction_on_disk */
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb_aio__make_space_in_ring_buffer()
+ *
+ * Programmer: John Mainzer
+ *
+ * Purpose: Make at least one buffer available for writing.
+ *
+ * Do this by awaiting completion of the oldest
+ * asynchronous write, and then marking this buffer
+ * as available on the ring buffer.
+ *
+ * Then repeatedly test the remaining oldest write
+ * to see if it has completed, and mark its buffer
+ * available if it has until either a write that
+ * has not completed is encountered, or we run out
+ * of writes in progress.
+ *
+ * Note that this function presumes that it will not
+ * be called unless the ring buffer is completely full.
+ * The function will fail if this is not the case.
+ *
+ * Returns: SUCCEED if no errors are encountered.
+ *
+ ******************************************************************************/
+
+static herr_t
+H5C2_jb_aio__make_space_in_ring_buffer(H5C2_jbrb_t * struct_ptr)
+{
+ hbool_t done = FALSE;
+ hbool_t buf_write_complete;
+ herr_t ret_value = SUCCEED;
+ herr_t result;
+ uint64_t last_trans_in_ring_buffer;
+
+ FUNC_ENTER_NOAPI(H5C2_jb_aio__make_space_in_ring_buffer, FAIL)
+
+ HDassert( struct_ptr != NULL );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+ HDassert( struct_ptr->use_aio == TRUE );
+ HDassert( struct_ptr->bufs_in_use == struct_ptr->num_bufs );
+ HDassert( struct_ptr->bufs_in_use == struct_ptr->writes_in_progress );
+ HDassert( ((struct_ptr->put + 1) % struct_ptr->num_bufs) ==
+ struct_ptr->get );
+ HDassert( struct_ptr->cur_buf_free_space == 0 );
+
+ /* free up the oldest (or least recently dirtied) buffer */
+ result = H5C2_jb_aio__await_buffer_write_completion(struct_ptr,
+ struct_ptr->get);
+
+ if ( result != SUCCEED ) {
+#if 1 /* JRM */
+ HDassert(FALSE);
+#endif /* JRM */
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__await_buffer_write_completion() failed.")
+ }
+
+ /* Update the last transaction written, and then set the transaction
+ * tracking array entry of the buffer whose write just completed to zero.
+ */
+ HDassert( struct_ptr->last_trans_written <=
+ (*struct_ptr->trans_tracking)[struct_ptr->get] );
+ struct_ptr->last_trans_written =
+ (*struct_ptr->trans_tracking)[struct_ptr->get];
+ (*struct_ptr->trans_tracking)[struct_ptr->get] = 0;
+
+ /* decrements writes in progress */
+ struct_ptr->writes_in_progress--;
+
+ /* decrement bufs in use */
+ struct_ptr->bufs_in_use--;
+
+ HDassert( ( struct_ptr->writes_in_progress == struct_ptr->bufs_in_use ) ||
+ ( struct_ptr->writes_in_progress == struct_ptr->bufs_in_use - 1 ) );
+
+ /* update get to reference the next entry in the ring buffer */
+ struct_ptr->get = (struct_ptr->get + 1) % (struct_ptr->num_bufs);
+
+ /* Since we now have a free buffer, prepare it for use */
+
+ last_trans_in_ring_buffer = (*struct_ptr->trans_tracking)[struct_ptr->put];
+
+ result = H5C2_jb_aio__prep_next_buf_for_use(struct_ptr,
+ last_trans_in_ring_buffer);
+
+ if ( result != SUCCEED ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__prep_next_buf_for_use() failed.")
+ }
+
+ HDassert( ((struct_ptr->put + 1) % struct_ptr->num_bufs) ==
+ struct_ptr->get );
+ HDassert( struct_ptr->bufs_in_use + 1 == struct_ptr->num_bufs );
+
+ /* now scan through the ring buffer marking buffers as available
+ * until we either hit a buffer whose write is still in progress,
+ * or all buffers are available for re-use.
+ */
+
+#if 1 /* JRM */
+
+ result = H5C2_jb_aio__note_completed_async_buffer_writes(struct_ptr);
+
+ if ( result != SUCCEED ) {
+#if 1 /* JRM */
+ HDassert(FALSE);
+#endif /* JRM */
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__note_completed_async_buffer_writes() failed.")
+ }
+
+#else /* delete this branch if all goes well -- JRM */
+
+ while ( ! done ) {
+
+ buf_write_complete = FALSE;
+
+ result = H5C2_jb_aio__test_buffer_write_complete(struct_ptr,
+ struct_ptr->get,
+ &buf_write_complete);
+
+ if ( result != SUCCEED ) {
+#if 1 /* JRM */
+ HDassert(FALSE);
+#endif /* JRM */
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__test_buffer_write_complete() failed.")
+ }
+
+ if ( buf_write_complete ) {
+
+ /* decrements writes in progress */
+ struct_ptr->writes_in_progress--;
+
+ /* decrement bufs in use */
+ struct_ptr->bufs_in_use--;
+
+ /* Update the last transaction written, and then set the
+ * transaction tracking array entry of the buffer whose
+ * write just completed to zero.
+ */
+ HDassert( struct_ptr->last_trans_written <=
+ (*struct_ptr->trans_tracking)[struct_ptr->get] );
+
+ struct_ptr->last_trans_written =
+ (*struct_ptr->trans_tracking)[struct_ptr->get];
+
+ (*struct_ptr->trans_tracking)[struct_ptr->get] = 0;
+
+ HDassert( struct_ptr->writes_in_progress ==
+ struct_ptr->bufs_in_use );
+
+ /* mark the buffer as available */
+
+ struct_ptr->get = (struct_ptr->get + 1) % (struct_ptr->num_bufs);
+
+ if ( struct_ptr->bufs_in_use == 0 ) {
+
+ /* all buffer writes are complete */
+
+ HDassert( struct_ptr->put == struct_ptr->get );
+ done = TRUE;
+
+ } else {
+
+ HDassert( struct_ptr->put != struct_ptr->get );
+
+ }
+ } else {
+
+ /* we have hit a buffer whose write is still in progress */
+ done = TRUE;
+ }
+ }
+
+#endif /* JRM */
+
+ HDassert( struct_ptr->writes_in_progress == struct_ptr->bufs_in_use );
+
+ if ( struct_ptr->use_aio_fsync ) {
+
+ result = H5C2_jb_aio__note_completed_async_fsyncs(struct_ptr);
+
+ if ( result != SUCCEED ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__note_completed_async_fsyncs() failed.")
+ }
+ }
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C2_jb_aio__make_space_in_ring_buffer() */
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb_aio__note_completed_async_buffer_writes
+ *
+ * Programmer: John Mainzer
+ * 2/10/10
+ *
+ * Purpose: Verify that AIO is enabled.
+ *
+ * Then, if there are any writes in progress, check to
+ * see if the oldest one has completed. If it has,
+ * update *struct_ptr to reflect this. Specifically
+ * update the last_trans_written, put, and
+ * writes_in_progress fields to reflect the completion
+ * of the write.
+ *
+ * Repeat until there are no writes in progress, or
+ * the oldest write is still in progress.
+ *
+ * Returns: SUCCEED on success.
+ * FAIL otherwise.
+ *
+ ******************************************************************************/
+
+#define H5C2_JB_AIO__NOTE_COMPLETED_ASYNC_BUFFER_WRITES__DEBUG 0
+
+static herr_t
+H5C2_jb_aio__note_completed_async_buffer_writes(H5C2_jbrb_t * struct_ptr)
+{
+ herr_t result;
+ herr_t ret_value = SUCCEED;
+ hbool_t write_completed = TRUE;
+
+ FUNC_ENTER_NOAPI(H5C2_jb_aio__note_completed_async_buffer_writes, FAIL)
+
+ HDassert( struct_ptr != NULL );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+ HDassert( struct_ptr->use_aio );
+
+ while ( ( struct_ptr->writes_in_progress > 0 ) &&
+ ( write_completed ) ) {
+
+ result = H5C2_jb_aio__test_buffer_write_complete(struct_ptr,
+ struct_ptr->get,
+ &write_completed);
+
+ if ( result != SUCCEED ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__test_buffer_write_complete() failed.")
+ }
+
+ if ( write_completed ) {
+
+ H5C2__JBRB__UPDATE_STATS_FOR_BUF_WRITE_COMPLETE(struct_ptr, FALSE)
+
+ /* Update the last transaction written, and then set the
+ * transaction tracking array entry of the buffer whose
+ * write just completed to zero.
+ */
+ HDassert( struct_ptr->last_trans_written <=
+ (*struct_ptr->trans_tracking)[struct_ptr->get] );
+
+ struct_ptr->last_trans_written =
+ (*struct_ptr->trans_tracking)[struct_ptr->get];
+
+ (*struct_ptr->trans_tracking)[struct_ptr->get] = 0;
+
+
+ /* decrements writes in progress */
+ struct_ptr->writes_in_progress--;
+
+ /* decrement bufs in use */
+ struct_ptr->bufs_in_use--;
+
+ HDassert( ( struct_ptr->writes_in_progress ==
+ struct_ptr->bufs_in_use )
+ ||
+ ( struct_ptr->writes_in_progress + 1 ==
+ struct_ptr->bufs_in_use ) );
+
+ /* mark the buffer as available */
+
+ struct_ptr->get = (struct_ptr->get + 1) % (struct_ptr->num_bufs);
+
+#if H5C2_JB_AIO__NOTE_COMPLETED_ASYNC_BUFFER_WRITES__DEBUG
+ if ( ! ( ( ( struct_ptr->bufs_in_use == 0 )
+ &&
+ ( struct_ptr->put == struct_ptr->get )
+ )
+ ||
+ ( ( struct_ptr->bufs_in_use > 0 )
+ &&
+ ( struct_ptr->put != struct_ptr->get )
+ )
+ )
+ ) {
+ HDfprintf(stdout, "%s: biu/put/get = %d/%d/%d.\n",
+ FUNC,
+ (int)(struct_ptr->bufs_in_use),
+ (int)(struct_ptr->put),
+ (int)(struct_ptr->get));
+ }
+#endif /* H5C2_JB_AIO__NOTE_COMPLETED_ASYNC_BUFFER_WRITES__DEBUG */
+
+ HDassert( ( ( struct_ptr->bufs_in_use == 0 )
+ &&
+ ( struct_ptr->put == struct_ptr->get )
+ )
+ ||
+ ( ( struct_ptr->bufs_in_use == 1 )
+ &&
+ ( struct_ptr->cur_buf_free_space > 0 )
+ &&
+ ( struct_ptr->put == struct_ptr->get )
+ )
+ ||
+ ( ( struct_ptr->bufs_in_use > 0 )
+ &&
+ ( struct_ptr->put != struct_ptr->get )
+ )
+ );
+ }
+ } /* while */
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C2_jb_aio__note_completed_async_buffer_writes() */
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb_aio__note_completed_async_fsyncs
+ *
+ * Programmer: John Mainzer
+ * 2/10/10
+ *
+ * Purpose: Verify that AIO is enabled, and that struct_ptr->
+ * use_aio_fsync is TRUE.
+ *
+ * Then, if the sync queue is not empty, test to see
+ * if the asynchronous fsync associated with the
+ * instance of struct H5C2_jbrb_sync_q_entry_t at the
+ * head of the sync queue has completed.
+ *
+ * If it hasn't, return.
+ *
+ * If it has, update struct_ptr->last_trans_on_disk,
+ * discard the head of the sync queue, and repeat if
+ * the sync queue is not empty..
+ *
+ * Returns: SUCCEED on success.
+ * FAIL otherwise.
+ *
+ * Changes: Modified the function to never let the sync queue
+ * contain fewer entryies than
+ * struct_ptr->writes_in_progress.
+ *
+ * This forces us to complete each buffer write before
+ * we complete the associated aio_fsync() -- and
+ * maintains the expected relationship between
+ * last_trans_queued, last_trans_written, and
+ * last_trans_on_disk.
+ *
+ ******************************************************************************/
+
+static herr_t
+H5C2_jb_aio__note_completed_async_fsyncs(H5C2_jbrb_t * struct_ptr)
+{
+ herr_t result;
+ herr_t ret_value = SUCCEED;
+ hbool_t sync_completed = TRUE;
+
+ FUNC_ENTER_NOAPI(H5C2_jb_aio__note_completed_async_fsyncs, FAIL)
+
+ HDassert( struct_ptr != NULL );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+ HDassert( struct_ptr->use_aio );
+ HDassert( struct_ptr->use_aio_fsync );
+
+ while ( ( struct_ptr->aio_sync_q_len > 0 ) &&
+ ( struct_ptr->aio_sync_q_len > struct_ptr->writes_in_progress ) &&
+ ( sync_completed ) ) {
+
+ result = H5C2_jb_aio__test_next_async_fsync_complete(struct_ptr,
+ &sync_completed);
+
+ if ( result != SUCCEED ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__test_next_async_fsync_complete() failed.")
+ }
+ } /* while */
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C2_jb_aio__note_completed_async_fsyncs() */
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb_aio__prep_next_buf_for_use()
+ *
+ * Programmer: John Mainzer
+ *
+ * Purpose: Prepare the next free buffer in the ring buffer
+ * for use.
+ *
+ * Note that this function assumes that there
+ * is a next free buffer, and will fail if there is
+ * not.
+ *
+ * Note also that this function is for use with AIO
+ * only. In the SIO case, we do some extra book keeping
+ * which is not managed here.
+ *
+ * Returns: SUCCEED on success.
+ *
+ ******************************************************************************/
+
+static herr_t
+H5C2_jb_aio__prep_next_buf_for_use(H5C2_jbrb_t * struct_ptr,
+ uint64_t last_trans_in_ring_buffer)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5C2_jb_aio__prep_next_buf_for_use, FAIL)
+
+ HDassert( struct_ptr != NULL );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+ HDassert( struct_ptr->use_aio == TRUE );
+
+ if ( ( struct_ptr->bufs_in_use >= struct_ptr->num_bufs ) ||
+ ( struct_ptr->cur_buf_free_space != 0 ) ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "no free buffer or space left in current buffer.")
+ }
+
+ /* increment put to reference the next buffer in the ring buffer */
+ struct_ptr->put = (struct_ptr->put + 1) % (struct_ptr->num_bufs);
+
+ /* set the cur_buf_free_space */
+ struct_ptr->cur_buf_free_space = struct_ptr->buf_size;
+
+ /* set the head pointer to point to the beginning of the newly
+ * available buffer.
+ */
+ struct_ptr->head = (*struct_ptr->buf)[struct_ptr->put];
+
+ /* load the transaction tracking array for the current buffer with the
+ * id of the last transaction fully written to the ring buffer.
+ */
+ HDassert( (*struct_ptr->trans_tracking)[struct_ptr->put] == 0 );
+
+ (*struct_ptr->trans_tracking)[struct_ptr->put] = last_trans_in_ring_buffer;
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C2_jb_aio__prep_next_buf_for_use() */
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb_aio__queue_async_fsync()
+ *
+ * Programmer: John Mainzer
+ *
+ * Purpose: Queue an asynchronous fsync -- if possible.
+ *
+ * Verify that AIO is enabled, and that use_aio_fsync
+ * is TRUE.
+ *
+ * Then allocate an instance of H5C2_jbrb_sync_q_entry_t,
+ * load it with the last transaction queued and a
+ * correctly configured aio control block, and attempt
+ * to queue an asynchronous fsync via aio_fsync().
+ *
+ * If aio_fsync() is not supported, (i.e. it fails
+ * with ENOSYS or EINVAL), set struct_ptr->use_aio_fsync
+ * to FALSE, discard the instance of
+ * H5C2_jbrb_sync_q_entry_t and return.
+ *
+ * if aio_fsync() fails with EAGAIN, retry until either
+ * success, failure with some other error, or the retry
+ * limit is exceeded. In the latter two cases, flag
+ * an error and quit.
+ *
+ * If aio_fsync() fails with any error other than
+ * EAGAIN, EINVAL, or ENOSYS, flag an error and quit.
+ *
+ * If the aio_fsync() is queued successfully, add the
+ * instance of H5C2_jbrb_sync_q_entry_t to the tail of
+ * the aio sync queue, and then return.
+ *
+ * If the instance of H5C2_jbrb_sync_q_entry_t is
+ * allocated, but the call to aio_fsync() fails for
+ * any reason, discard the instance of
+ * H5C2_jbrb_sync_q_entry_t before exiting.
+ *
+ * JRM -- 2/8/10
+ *
+ * Returns: SUCCEED on success.
+ *
+ ******************************************************************************/
+
+#define H5C2_JB_AIO__QUEUE_ASYNC_FSYNC__DEBUG 0
+#define AIO_FSYNC_MAX_RETRIES 120
+
+static herr_t
+H5C2_jb_aio__queue_async_fsync(H5C2_jbrb_t * struct_ptr)
+{
+ herr_t ret_value = SUCCEED;
+ herr_t herr_result;
+ hbool_t sync_complete;
+ hbool_t sync_queued = FALSE;
+ int result;
+ int retries = -1;
+ struct H5C2_jbrb_sync_q_entry_t * entry_ptr = NULL;
+
+ HDassert( struct_ptr != NULL );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+ HDassert( struct_ptr->journal_file_fd >= 0 );
+ HDassert( struct_ptr->use_aio );
+ HDassert( struct_ptr->use_aio_fsync );
+
+ FUNC_ENTER_NOAPI(H5C2_jb_aio__queue_async_fsync, FAIL)
+
+ entry_ptr = (struct H5C2_jbrb_sync_q_entry_t *)
+ H5MM_malloc(sizeof(struct H5C2_jbrb_sync_q_entry_t));
+
+ if ( entry_ptr == NULL ) {
+
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \
+ "memory allocation failed for aio sync queue entry.")
+ }
+
+ entry_ptr->magic = H5C2__H5C2_JBRB_SYNC_Q_T_MAGIC;
+ entry_ptr->last_trans_in_sync = struct_ptr->last_trans_queued;
+ bzero((void *)(&(entry_ptr->ctl_blk)), sizeof(struct aiocb));
+ entry_ptr->ctl_blk.aio_fildes = struct_ptr->journal_file_fd;
+ entry_ptr->next = NULL;
+
+ do {
+
+ result = aio_fsync(O_SYNC, &(entry_ptr->ctl_blk));
+
+ if ( result != 0 ) {
+
+ if ( ( errno == EINVAL ) ||
+ ( errno == ENOSYS ) ) {
+
+#if H5C2_JB_AIO__QUEUE_ASYNC_FSYNC__DEBUG
+ HDfprintf(stdout,
+ "%s: aio_fsync() not supported. errno = %d (%s)\n",
+ FUNC, errno, strerror(errno));
+#endif /* H5C2_JB_AIO__QUEUE_ASYNC_FSYNC__DEBUG */
+ HDassert( struct_ptr->aio_sync_q_len == 0 );
+ struct_ptr->use_aio_fsync = FALSE;
+
+ } else if ( errno == EAGAIN ) {
+
+ retries++;
+
+ if ( retries > AIO_FSYNC_MAX_RETRIES ) {
+
+#if H5C2_JB_AIO__QUEUE_ASYNC_FSYNC__DEBUG
+ HDfprintf(stdout,
+ "%s: retry limit on calls to aio_fsync() exceeded\n",
+ FUNC);
+#endif /* H5C2_JB_AIO__QUEUE_ASYNC_FSYNC__DEBUG */
+
+ HGOTO_ERROR(H5E_IO, H5E_SYNCFAIL, FAIL, \
+ "retry limit on calls to aio_fsync() exceeded.")
+ }
+
+ /* if we get errno == EAGAIN, it is possible that
+ * the problem is too many aio operations in progress.
+ * Thus, if the sync queue is not empty, check to
+ * see if an asynchronous sync has completed, and
+ * retire it if it has.
+ */
+ if ( struct_ptr->aio_sync_q_len > 0 ) {
+
+ herr_result =
+ H5C2_jb_aio__test_next_async_fsync_complete(struct_ptr,
+ &sync_complete);
+ }
+ } else {
+
+#if H5C2_JB_AIO__QUEUE_ASYNC_FSYNC__DEBUG
+ HDfprintf(stdout,
+ "%s: aio_fsync() failed. errno = %d (%s)\n",
+ FUNC, errno, strerror(errno));
+#endif /* H5C2_JB_AIO__QUEUE_ASYNC_FSYNC__DEBUG */
+
+ HGOTO_ERROR(H5E_IO, H5E_SYNCFAIL, FAIL, \
+ "call to aio_fsync() failed.")
+ }
+ }
+ } while ( ( result != 0 ) &&
+ ( struct_ptr->use_aio_fsync ) );
+
+ if ( result == 0 ) {
+
+ herr_result = H5C2_jb_aio__sync_q__append(struct_ptr, entry_ptr);
+
+ if ( herr_result != SUCCEED ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__sync_q__append() failed.")
+
+ }
+
+ sync_queued = TRUE;
+
+ H5C2__JBRB__UPDATE_STATS_FOR_ASYNC_SYNCS_QUEUED(struct_ptr);
+
+#if H5C2_JB_AIO__QUEUE_ASYNC_FSYNC__DEBUG
+ HDfprintf(stdout,
+ "%s: queued async fsync. last trans = %lld, q_len = %lld.\n",
+ FUNC,
+ (long long)(entry_ptr->last_trans_in_sync),
+ (long long)(struct_ptr->aio_sync_q_len));
+#endif /* H5C2_JB_AIO__QUEUE_ASYNC_FSYNC__DEBUG */
+
+ }
+done:
+
+ if ( ( entry_ptr != NULL ) &&
+ ( ! sync_queued ) ) { /* discard *entry_ptr */
+
+ entry_ptr->magic = 0;
+ entry_ptr = (struct H5C2_jbrb_sync_q_entry_t *)H5MM_xfree(entry_ptr);
+
+ if ( entry_ptr != NULL ) {
+
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \
+ "free of entry_ptr failed.");
+ }
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C2_jb_aio__queue_async_fsync() */
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb_aio__queue_buffer_write
+ *
+ * Programmer: John Mainzer
+ *
+ * Purpose: Queue an asynchronous write of the specified buffer,
+ * and update struct_ptr->last_trans_queue if appropriate.
+ * If struct_ptr->use_aio_fsync is TRUE, queue and
+ * asynchronous fsync after the buffer write has
+ * been queued.
+ *
+ * Verify that AIO is enabled, that buffer specified
+ * exists, and is not already involved in an
+ * asynchronous write.
+ *
+ * Further verify that the buffer is not empty, and that
+ * either partial_write_ok is TRUE, or the buffer is full.
+ *
+ * Returns: SUCCEED on success.
+ * FAIL otherwise
+ *
+ ******************************************************************************/
+
+#define H5C2_JB_AIO__QUEUE_BUFFER_WRITE__DEBUG 0
+#define AIO_WRITE_MAX_RETRIES 120
+
+static herr_t
+H5C2_jb_aio__queue_buffer_write(H5C2_jbrb_t * struct_ptr,
+ int buf_num,
+ hbool_t partial_write_ok)
+{
+ hbool_t write_queued = FALSE;
+ int result;
+ int retries = -1;
+#if H5C2_JB_AIO__QUEUE_BUFFER_WRITE__DEBUG
+ static int writes_queued = 0;
+#endif /* H5C2_JB_AIO__QUEUE_BUFFER_WRITE__DEBUG */
+ uint64_t last_trans_in_buf;
+ herr_t herr_result;
+ herr_t ret_value = SUCCEED;
+ hsize_t bytes_to_write;
+ void * buf_ptr = NULL;
+ struct aiocb * aiocb_ptr = NULL;
+
+ HDassert( struct_ptr != NULL );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+ HDassert( struct_ptr->buf_size > 0 );
+ HDassert( struct_ptr->journal_file_fd >= 0 );
+ HDassert( struct_ptr->use_aio );
+ HDassert( struct_ptr->trans_tracking != NULL );
+ HDassert( struct_ptr->aio_ctl_blks != NULL );
+ HDassert( buf_num >= 0 );
+ HDassert( buf_num < struct_ptr->num_bufs );
+
+ FUNC_ENTER_NOAPI(H5C2_jb_aio__queue_buffer_write, FAIL)
+
+ if ( struct_ptr->cur_buf_free_space >= struct_ptr->buf_size ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "attempt to queue write of an empty buffer.")
+ }
+
+ if ( ( struct_ptr->cur_buf_free_space > 0 ) &&
+ ( ! partial_write_ok ) ) {
+
+#if H5C2_JB_AIO__QUEUE_BUFFER_WRITE__DEBUG
+ HDfprintf(stdout,
+ "%s: buffer not full and partial_write_ok == FALSE.\n",
+ FUNC);
+#endif /* H5C2_JB_AIO__QUEUE_BUFFER_WRITE__DEBUG */
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "buffer not full and partial_write_ok == FALSE.")
+ }
+
+ last_trans_in_buf = (*struct_ptr->trans_tracking)[struct_ptr->put];
+
+ HDassert( last_trans_in_buf >= struct_ptr->last_trans_queued );
+ HDassert( struct_ptr->last_trans_queued >= struct_ptr->last_trans_written );
+ HDassert( struct_ptr->last_trans_written >=
+ struct_ptr->last_trans_on_disk );
+
+ aiocb_ptr = &((*(struct_ptr->aio_ctl_blks))[buf_num]);
+
+ if ( aiocb_ptr->aio_fildes != -1 ) {
+
+#if H5C2_JB_AIO__QUEUE_BUFFER_WRITE__DEBUG
+ HDfprintf(stdout,
+ "%s: AIO write alread in progress for target buffer?\n",
+ FUNC);
+#endif /* H5C2_JB_AIO__QUEUE_BUFFER_WRITE__DEBUG */
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "AIO write alread in progress for target buffer?")
+ }
+
+ buf_ptr = (void *)((*struct_ptr->buf)[buf_num]);
+
+ if ( buf_ptr == NULL ) {
+
+#if H5C2_JB_AIO__QUEUE_BUFFER_WRITE__DEBUG
+ HDfprintf(stdout,
+ "%s: ((*struct_ptr->buf)[buf_num]) == NULL?!?\n",
+ FUNC);
+#endif /* H5C2_JB_AIO__QUEUE_BUFFER_WRITE__DEBUG */
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "((*struct_ptr->buf)[buf_num]) == NULL?!?")
+ }
+
+ HDassert( struct_ptr->buf_size > struct_ptr->cur_buf_free_space);
+
+ bytes_to_write = struct_ptr->buf_size - struct_ptr->cur_buf_free_space;
+
+ /* all looks good -- setup to initiate the write ... */
+
+ bzero((void *)aiocb_ptr, sizeof(struct aiocb));
+
+ aiocb_ptr->aio_fildes = struct_ptr->journal_file_fd;
+ aiocb_ptr->aio_offset = struct_ptr->aio_next_buf_offset;
+ aiocb_ptr->aio_buf = buf_ptr;
+ aiocb_ptr->aio_nbytes = bytes_to_write;
+
+ /* ... and kick it off */
+ do {
+
+ result = aio_write(aiocb_ptr);
+
+ if ( result != 0 ) {
+
+ if ( errno == EAGAIN ) {
+
+ sleep(1);
+ retries++;
+
+ } else {
+
+#if H5C2_JB_AIO__QUEUE_BUFFER_WRITE__DEBUG
+ HDfprintf(stdout,
+ "%s: aio_write(aiocb_ptr) failed. errno = %d (%s)\n",
+ FUNC, errno, strerror(errno));
+ HDfprintf(stdout, "%s: offset/size = %lld/%d\n",
+ FUNC,
+ (long long)struct_ptr->aio_next_buf_offset,
+ (int)bytes_to_write);
+#endif /* H5C2_JB_AIO__QUEUE_BUFFER_WRITE__DEBUG */
+
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
+ "call to aio_write() failed.")
+ }
+ }
+ } while ( ( result != 0 ) && ( retries <= AIO_WRITE_MAX_RETRIES ) );
+
+#if H5C2_JB_AIO__QUEUE_BUFFER_WRITE__DEBUG
+ if ( retries > 0 ) {
+
+ HDfprintf(stdout,
+ "%s: aio_write() retries = %d, writes queued = %d\n",
+ FUNC, retries, writes_queued);
+ HDfprintf(stdout, "%s: offset/size = %lld/%d\n", FUNC,
+ (long long)struct_ptr->aio_next_buf_offset,
+ (int)bytes_to_write);
+ } else {
+ HDfprintf(stdout, "%s: aio_write(): offset/size = %lld/%d\n", FUNC,
+ (long long)struct_ptr->aio_next_buf_offset,
+ (int)bytes_to_write);
+ }
+#endif /* H5C2_JB_AIO__QUEUE_BUFFER_WRITE__DEBUG */
+
+
+ if ( ( result != 0 ) && ( retries > AIO_WRITE_MAX_RETRIES ) ) {
+
+#if H5C2_JB_AIO__QUEUE_BUFFER_WRITE__DEBUG
+ HDfprintf(stdout, "%s: retry limit on calls to aio_write() exceeded\n",
+ FUNC);
+#endif /* H5C2_JB_AIO__QUEUE_BUFFER_WRITE__DEBUG */
+
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
+ "retry limit on calls to aio_write() exceeded.")
+ }
+
+#if H5C2_JB_AIO__QUEUE_BUFFER_WRITE__DEBUG
+ writes_queued++;
+#endif /* H5C2_JB_AIO__QUEUE_BUFFER_WRITE__DEBUG */
+
+ H5C2__JBRB__UPDATE_STATS_FOR_BUF_WRITE_QUEUED(struct_ptr, \
+ (struct_ptr->cur_buf_free_space > 0 ))
+
+ /* note that another write is in progress */
+ struct_ptr->writes_in_progress++;
+#if H5C2_JB_AIO__QUEUE_BUFFER_WRITE__DEBUG
+ if ( struct_ptr->writes_in_progress != struct_ptr->bufs_in_use ) {
+ HDfprintf(stdout, "%s: wip = %d, biu = %d.\n", FUNC,
+ struct_ptr->writes_in_progress,
+ struct_ptr->bufs_in_use);
+ }
+#endif /* H5C2_JB_AIO__QUEUE_BUFFER_WRITE__DEBUG */
+ HDassert( struct_ptr->writes_in_progress == struct_ptr->bufs_in_use );
+
+ /* update struct_ptr->last_trans_queued */
+ struct_ptr->last_trans_queued = last_trans_in_buf;
+
+ /* update struct_ptr->aio_next_buf_offset */
+ struct_ptr->aio_next_buf_offset += bytes_to_write;
+
+ /* if aio_fsync() is available, queue a sync to force the
+ * data just written to disk.
+ */
+ if ( struct_ptr->use_aio_fsync ) {
+
+ herr_result = H5C2_jb_aio__queue_async_fsync(struct_ptr);
+
+ if ( herr_result != SUCCEED ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__queue_async_fsync() failed.")
+ }
+ }
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C2_jb_aio__queue_buffer_write() */
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb_aio__sync_file()
+ *
+ * Programmer: John Mainzer
+ * 1/13/10
+ *
+ * Purpose: Sync out the journal file.
+ *
+ * Verify that AIO is enabled, and that all pending
+ * writes are complete.
+ *
+ * Note that this last precondition should not be
+ * necessary. However, given the incomplete state
+ * of many AIO implementation, it seems wise to
+ * allow all writes to complete before calling fsync().
+ *
+ * If struct_ptr->use_aio_fsync is TRUE, await
+ * completion of all asynchronous fsyncs on the sync
+ * queue. When this is done, the file should be
+ * synced.
+ *
+ * If struct_ptr->use_aio_fsync is FALSE, call
+ * fsync().
+ *
+ * Returns: SUCCEED if no errors are detected,
+ * FAIL otherwise.
+ *
+ ******************************************************************************/
+
+#define H5C2_JB_AIO__SYNC_FILE__DEBUG 0
+
+static herr_t
+H5C2_jb_aio__sync_file(H5C2_jbrb_t * struct_ptr)
+{
+ int result;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5C2_jb_aio__sync_file, FAIL)
+
+ HDassert( struct_ptr != NULL );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+ HDassert( struct_ptr->journal_file_fd >= 0 );
+ HDassert( struct_ptr->use_aio );
+
+ if ( struct_ptr->writes_in_progress != 0 ) {
+
+#if H5C2_JB_AIO__SYNC_FILE__DEBUG
+ HDfprintf(stdout, "%s: async write in progress on entry.\n", FUNC);
+#endif /* H5C2_JB_AIO__SYNC_FILE__DEBUG */
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "async write in progress on entry")
+ }
+
+ if ( struct_ptr->use_aio_fsync ) {
+
+ result = H5C2_jb_aio__await_completion_of_all_async_fsyncs(struct_ptr);
+
+ if ( result != 0 ) {
+
+#if H5C2_JB_AIO__SYNC_FILE__DEBUG
+ HDfprintf(stdout,
+ "%s: H5C2_jb_aio__await_completion_of_all_async_fsyncs() failed.\n",
+ FUNC);
+#endif /* H5C2_JB_AIO__SYNC_FILE__DEBUG */
+
+ HGOTO_ERROR(H5E_IO, H5E_SYNCFAIL, FAIL, \
+ "H5C2_jb_aio__await_completion_of_all_async_fsyncs() failed.");
+ }
+ } else {
+
+ result = fsync(struct_ptr->journal_file_fd);
+
+ if ( result != 0 ) {
+
+#if H5C2_JB_AIO__SYNC_FILE__DEBUG
+ HDfprintf(stdout, "%s: fsync() failed.\n", FUNC);
+#endif /* H5C2_JB_AIO__SYNC_FILE__DEBUG */
+
+ HGOTO_ERROR(H5E_IO, H5E_SYNCFAIL, FAIL, "fsync() failed.");
+ }
+
+ H5C2__JBRB__UPDATE_STATS_FOR_CALL_TO_FSYNC(struct_ptr)
+ }
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C2_jb_aio__sync_file() */
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb_aio__sync_q__append()
+ *
+ * Purpose: Append an instance of H5C2_jbrb_sync_q_entry_t to
+ * the sync queue.
+ *
+ * Verify that AIO is enabled, and that the supplied
+ * instance of H5C2_jbrb_sync_q_entry_t has the correct
+ * magic value. Then append to the end of the sync
+ * queue.
+ * JRM -- 2/9/10
+ *
+ * Returns: SUCCEED if no errors are detected,
+ * FAIL otherwise.
+ *
+ ******************************************************************************/
+
+static herr_t
+H5C2_jb_aio__sync_q__append(H5C2_jbrb_t * struct_ptr,
+ struct H5C2_jbrb_sync_q_entry_t * entry_ptr)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5C2_jb_aio__sync_q__append, FAIL)
+
+ HDassert( struct_ptr != NULL );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+ HDassert( struct_ptr->use_aio );
+ HDassert( entry_ptr != NULL );
+ HDassert( entry_ptr->magic == H5C2__H5C2_JBRB_SYNC_Q_T_MAGIC );
+ HDassert( entry_ptr->next == NULL );
+
+ /* this should be an assert, but we need to include one call to
+ * HGOTO_ERROR() to keep the compiler happy
+ */
+ if ( ! struct_ptr->use_aio_fsync ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "struct_ptr->use_aio_fsync FALSE on entry")
+ }
+
+ /* add the *entry_ptr to the sync queue */
+
+ if ( struct_ptr->aio_sync_q_len == 0 ) {
+
+ HDassert( struct_ptr->aio_sync_q_head == NULL );
+ HDassert( struct_ptr->aio_sync_q_tail == NULL );
+
+ struct_ptr->aio_sync_q_head = entry_ptr;
+ struct_ptr->aio_sync_q_tail = entry_ptr;
+ struct_ptr->aio_sync_q_len = 1;
+
+ } else {
+
+ HDassert( struct_ptr->aio_sync_q_head != NULL );
+ HDassert( struct_ptr->aio_sync_q_tail != NULL );
+ HDassert( struct_ptr->aio_sync_q_len > 0 );
+ HDassert( ( ( struct_ptr->aio_sync_q_len == 1 ) &&
+ ( struct_ptr->aio_sync_q_head ==
+ struct_ptr->aio_sync_q_tail )
+ )
+ ||
+ ( ( struct_ptr->aio_sync_q_len > 1 ) &&
+ ( struct_ptr->aio_sync_q_head !=
+ struct_ptr->aio_sync_q_tail )
+ )
+ );
+ HDassert( struct_ptr->aio_sync_q_tail->magic ==
+ H5C2__H5C2_JBRB_SYNC_Q_T_MAGIC );
+ HDassert( struct_ptr->aio_sync_q_tail->next == NULL );
+
+ struct_ptr->aio_sync_q_tail->next = entry_ptr;
+ struct_ptr->aio_sync_q_tail = entry_ptr;
+ struct_ptr->aio_sync_q_len++;
+ }
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C2_jb_aio__sync_q__append() */
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb_aio__sync_q__append()
+ *
+ * Purpose: Append an instance of H5C2_jbrb_sync_q_entry_t to
+ * the sync queue.
+ *
+ * Verify that AIO is enabled, and that the supplied
+ * instance of H5C2_jbrb_sync_q_entry_t has the correct
+ * magic value. Then append to the end of the sync
+ * queue.
+ * JRM -- 2/9/10
+ *
+ * Returns: SUCCEED if no errors are detected,
+ * FAIL otherwise.
+ *
+ ******************************************************************************/
+
+static herr_t
+H5C2_jb_aio__sync_q__discard_head(H5C2_jbrb_t * struct_ptr)
+{
+ herr_t ret_value = SUCCEED;
+ struct H5C2_jbrb_sync_q_entry_t * head_ptr = NULL;
+
+ FUNC_ENTER_NOAPI(H5C2_jb_aio__sync_q__discard_head, FAIL)
+
+ HDassert( struct_ptr != NULL );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+ HDassert( struct_ptr->use_aio );
+ HDassert( struct_ptr->use_aio_fsync );
+
+ /* this should be an assert, but we need to include one call to
+ * HGOTO_ERROR() to keep the compiler happy
+ */
+ if ( struct_ptr->aio_sync_q_len <= 0 ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "sync queue empty on entry?!?")
+ }
+
+ head_ptr = struct_ptr->aio_sync_q_head;
+ HDassert( head_ptr != NULL );
+ HDassert( head_ptr->magic == H5C2__H5C2_JBRB_SYNC_Q_T_MAGIC );
+
+ /* unlink *head_ptr from the queue */
+
+ /* add the *entry_ptr to the sync queue */
+
+ if ( struct_ptr->aio_sync_q_len == 1 ) {
+
+ HDassert( struct_ptr->aio_sync_q_head == head_ptr );
+ HDassert( struct_ptr->aio_sync_q_tail == head_ptr );
+ HDassert( head_ptr->next == NULL );
+
+ struct_ptr->aio_sync_q_head = NULL;
+ struct_ptr->aio_sync_q_tail = NULL;
+ struct_ptr->aio_sync_q_len = 0;
+
+ } else {
+
+ HDassert( struct_ptr->aio_sync_q_len >= 2 );
+ HDassert( struct_ptr->aio_sync_q_head == head_ptr );
+ HDassert( struct_ptr->aio_sync_q_tail != NULL );
+ HDassert( struct_ptr->aio_sync_q_tail != head_ptr );
+ HDassert( head_ptr->next != NULL );
+ HDassert( head_ptr->next->magic == H5C2__H5C2_JBRB_SYNC_Q_T_MAGIC );
+ HDassert( struct_ptr->aio_sync_q_tail->next == NULL );
+
+ struct_ptr->aio_sync_q_head = head_ptr->next;
+ head_ptr->next = NULL;
+ struct_ptr->aio_sync_q_len--;
+ }
+
+ /* and then discard it */
+
+ head_ptr->magic = 0;
+ head_ptr = (struct H5C2_jbrb_sync_q_entry_t *)H5MM_xfree(head_ptr);
+
+ if ( head_ptr != NULL ) {
+
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \
+ "free of *head_ptr failed.");
+ }
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C2_jb_aio__sync_q__discard_head() */
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb_aio__test_buffer_write_complete()
+ *
+ * Programmer: John Mainzer
+ *
+ * Purpose: Test to see if an asynchronous write has completed.
+ *
+ * Verify that AIO is enabled, that buffer specified
+ * exists, and that an asynchronous write of the buffer
+ * has been queued.
+ *
+ * If it is, mark it complete, set *complete_ptr
+ * to TRUE, mark the associate AIO control block as
+ * having no write in progress, and return.
+ *
+ * It it isn't, set *complete_ptr to FALSE and return
+ *
+ * Returns: SUCCEED if no errors are detected,
+ * FAIL otherwise.
+ *
+ ******************************************************************************/
+
+static herr_t
+H5C2_jb_aio__test_buffer_write_complete(H5C2_jbrb_t * struct_ptr,
+ int buf_num,
+ hbool_t *complete_ptr)
+{
+ int result;
+ herr_t ret_value = SUCCEED;
+ struct aiocb * aiocb_ptr = NULL;
+
+ FUNC_ENTER_NOAPI(H5C2_jb_aio__test_buffer_write_complete, FAIL)
+
+ HDassert( struct_ptr != NULL );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+ HDassert( struct_ptr->buf_size > 0 );
+ HDassert( struct_ptr->journal_file_fd >= 0 );
+ HDassert( struct_ptr->use_aio );
+ HDassert( struct_ptr->aio_ctl_blks != NULL );
+ HDassert( buf_num >= 0 );
+ HDassert( buf_num < struct_ptr->num_bufs );
+ HDassert( complete_ptr != NULL );
+
+ aiocb_ptr = &((*(struct_ptr->aio_ctl_blks))[buf_num]);
+
+ if ( aiocb_ptr->aio_fildes < 0 ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "AIO write not in progress for target buffer?")
+ }
+
+ result = aio_error(aiocb_ptr);
+
+ if ( result == EINPROGRESS ) {
+
+ /* the write is still in progress -- set *complete_ptr to
+ * FALSE and do nothing.
+ */
+ *complete_ptr = FALSE;
+
+ } else if ( result == 0 ) {
+
+ /* call aio_return() to complete the write */
+ result = aio_return(aiocb_ptr);
+ if ( result == -1 ) {
+
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
+ "aio_error() reports something other than success.")
+
+ }
+ /* TODO: Verify the number of bytes written? */
+
+ /* the write completed successfully -- set *complete_ptr
+ * to TRUE, mark the aio control block as having no write
+ * in progress.
+ */
+
+ aiocb_ptr->aio_fildes = -1;
+
+ *complete_ptr = TRUE;
+
+ } else {
+
+ /* the write failed -- scream and die. */
+
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "target async write failed.")
+
+ }
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C2_jb_aio__test_buffer_write_complete() */
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb_aio__test_next_async_fsync_complete()
+ *
+ * Purpose: Test to see if the asynchronous fsync at the head
+ * of the sync queue is complete.
+ *
+ * If it is, finish up the call to aio_fsync(), update
+ * last_trans_on_disk, remove the associated instance of
+ * H5C2_jbrb_sync_q_entry_t from the sync queue, set
+ * *sync_complete_ptr to TRUE, and return.
+ *
+ * If it isn't, set *sync_complete_ptr to FALSE, and
+ * return.
+ *
+ * In either case, verify that AIO is enabled, that
+ * struct_ptr->use_aio_fsync is TRUE, and that the
+ * sync queue is not empty.
+ * JRM -- 2/10/10
+ *
+ * Returns: SUCCEED if no errors are detected,
+ * FAIL otherwise.
+ *
+ ******************************************************************************/
+
+#define H5C2_JB_AIO__TEST_NEXT_ASYNC_FSYNC_COMPLETE__DEBUG 0
+
+static herr_t
+H5C2_jb_aio__test_next_async_fsync_complete(H5C2_jbrb_t * struct_ptr,
+ hbool_t *sync_complete_ptr)
+{
+ int result;
+ herr_t ret_value = SUCCEED;
+ struct H5C2_jbrb_sync_q_entry_t * head_ptr = NULL;
+ struct aiocb * aiocb_ptr = NULL;
+
+ FUNC_ENTER_NOAPI(H5C2_jb_aio__test_next_async_fsync_complete, FAIL)
+
+ HDassert( struct_ptr != NULL );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+ HDassert( struct_ptr->use_aio );
+ HDassert( struct_ptr->use_aio_fsync );
+ HDassert( struct_ptr->aio_sync_q_len > 0 );
+ HDassert( sync_complete_ptr != NULL );
+
+ head_ptr = struct_ptr->aio_sync_q_head;
+
+ HDassert( head_ptr != NULL );
+ HDassert( head_ptr->magic == H5C2__H5C2_JBRB_SYNC_Q_T_MAGIC );
+
+ aiocb_ptr = &(head_ptr->ctl_blk);
+
+ if ( aiocb_ptr->aio_fildes != struct_ptr->journal_file_fd ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "bad fd in ctl blk?!?")
+ }
+
+ result = aio_error(aiocb_ptr);
+
+ if ( result == EINPROGRESS ) {
+
+ /* the write is still in progress -- set *sync_complete_ptr to
+ * FALSE and do nothing.
+ */
+ *sync_complete_ptr = FALSE;
+
+ } else if ( result == 0 ) {
+
+ /* call aio_return() to complete the aio_fsync() */
+ result = aio_return(aiocb_ptr);
+
+ if ( result == -1 ) {
+
+ HGOTO_ERROR(H5E_IO, H5E_SYNCFAIL, FAIL, \
+ "aio_error() reports something other than success.")
+
+ }
+
+ /* the aio_fsync() completed successfully -- update last trans on disk,
+ * discard the head of the sync queue, and set *sync_complete_ptr to
+ * TRUE.
+ */
+
+#if H5C2_JB_AIO__TEST_NEXT_ASYNC_FSYNC_COMPLETE__DEBUG
+ HDfprintf(stdout, "%s: ltod/ltw/ltis = %lld/%lld/%lld.\n",
+ FUNC,
+ (long long)(struct_ptr->last_trans_on_disk),
+ (long long)(struct_ptr->last_trans_written),
+ (long long)(head_ptr->last_trans_in_sync));
+#endif /* H5C2_JB_AIO__TEST_NEXT_ASYNC_FSYNC_COMPLETE__DEBUG */
+
+ HDassert( (uint64_t)(struct_ptr->last_trans_on_disk) <=
+ (uint64_t)(head_ptr->last_trans_in_sync) );
+ HDassert( (uint64_t)(head_ptr->last_trans_in_sync) <=
+ (uint64_t)(struct_ptr->last_trans_written) );
+
+#if H5C2_JB_AIO__TEST_NEXT_ASYNC_FSYNC_COMPLETE__DEBUG
+ HDfprintf(stdout, "%s: changing last trans on disk from %lld to %lld.\n",
+ FUNC, struct_ptr->last_trans_on_disk,
+ head_ptr->last_trans_in_sync);
+#endif /* H5C2_JB_AIO__TEST_NEXT_ASYNC_FSYNC_COMPLETE__DEBUG */
+
+ H5C2__JBRB__UPDATE_STATS_FOR_ASYNC_SYNC_COMPLETED(struct_ptr, FALSE)
+
+ aiocb_ptr->aio_fildes = -1;
+
+ struct_ptr->last_trans_on_disk = head_ptr->last_trans_in_sync;
+
+ if ( H5C2_jb_aio__sync_q__discard_head(struct_ptr) != SUCCEED ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__sync_q__discard_head() failed.")
+ }
+
+ *sync_complete_ptr = TRUE;
+
+ } else {
+
+ /* the sync failed -- scream and die. */
+
+ HGOTO_ERROR(H5E_IO, H5E_SYNCFAIL, FAIL, "target async fsync failed.")
+
+ }
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C2_jb_aio__test_next_async_fsync_complete() */
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb_aio__write_to_buffer
+ *
+ * Programmer: John Mainzer
+ * 0/09/10
+ *
+ * Purpose: Copy the contents of the supplied data buffer into
+ * the ring buffers, kicking off asynchronous writes
+ * as the buffers fill, and stalling on completion of
+ * writes as needed when the ring buffer fills.
+ *
+ * Returns: SUCCEED on success.
+ *
+ ******************************************************************************/
+
+#define H5C2_JB_AIO__WRITE_TO_BUFFER__DEBUG 0
+
+herr_t
+H5C2_jb_aio__write_to_buffer(H5C2_jbrb_t * struct_ptr,
+ size_t size,
+ const char * data,
+ hbool_t is_end_trans,
+ uint64_t trans_num)
+{
+ hbool_t just_called_make_space_in_ring_buffer = FALSE;
+ herr_t ret_value = SUCCEED;
+ herr_t result;
+ size_t size_remaining;
+ const char * data_remaining;
+ uint64_t last_trans_in_ring_buffer;
+
+ FUNC_ENTER_NOAPI(H5C2_jb_aio__write_to_buffer, FAIL)
+
+ /* Check Arguments */
+ HDassert( struct_ptr != NULL );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+ HDassert( struct_ptr->use_aio == TRUE );
+ HDassert( size > 0 );
+ HDassert( data != 0 );
+ HDassert( ( struct_ptr->human_readable == FALSE ) ||
+ ( HDstrlen(data) == size ) );
+ HDassert( ( ( struct_ptr->writes_in_progress == struct_ptr->bufs_in_use )
+ &&
+ ( struct_ptr->bufs_in_use < struct_ptr->num_bufs )
+ &&
+ ( struct_ptr->cur_buf_free_space == struct_ptr->buf_size )
+ )
+ ||
+ ( ( struct_ptr->writes_in_progress + 1 == struct_ptr->bufs_in_use )
+ &&
+ ( struct_ptr->cur_buf_free_space < struct_ptr->buf_size )
+ &&
+ ( struct_ptr->cur_buf_free_space > 0 )
+ )
+ ||
+ ( ( struct_ptr->writes_in_progress == struct_ptr->bufs_in_use )
+ &&
+ ( struct_ptr->bufs_in_use == struct_ptr->num_bufs )
+ &&
+ ( struct_ptr->cur_buf_free_space == 0 )
+ )
+ );
+
+ /* make space in the ring buffer if necessary. As
+ * struct_ptr->cur_buf_free_space will always be greater
+ * than zero if there is any space in the ring buffer,
+ * it is sufficient to check that value and call
+ * H5C2_jb_aio__make_space_in_ring_buffer() if it is zero.
+ */
+ if ( struct_ptr->cur_buf_free_space <= 0 ) {
+
+ HDassert( struct_ptr->bufs_in_use == struct_ptr->num_bufs );
+ HDassert( struct_ptr->writes_in_progress == struct_ptr->bufs_in_use );
+
+ result = H5C2_jb_aio__make_space_in_ring_buffer(struct_ptr);
+
+ if ( result != SUCCEED ) {
+
+#if H5C2_JB_AIO__WRITE_TO_BUFFER__DEBUG
+ HDfprintf(stdout,
+ "%s: H5C2_jb_aio__make_space_in_ring_buffer(1) failed.\n",
+ FUNC);
+#endif /* H5C2_JB_AIO__WRITE_TO_BUFFER__DEBUG */
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__make_space_in_ring_buffer(1) failed.")
+ }
+
+ just_called_make_space_in_ring_buffer = TRUE;
+
+ HDassert( struct_ptr->writes_in_progress == struct_ptr->bufs_in_use );
+ }
+
+ data_remaining = data;
+ size_remaining = size;
+
+ while ( ( size_remaining >= struct_ptr->cur_buf_free_space ) &&
+ ( struct_ptr->cur_buf_free_space > 0 ) ) {
+
+ HDassert( struct_ptr->cur_buf_free_space > 0 );
+
+ if ( struct_ptr->cur_buf_free_space == struct_ptr->buf_size ) {
+
+ struct_ptr->bufs_in_use += 1;
+
+ HDassert( struct_ptr->bufs_in_use <= struct_ptr->num_bufs );
+ }
+
+ HDassert( (struct_ptr->writes_in_progress + 1) ==
+ struct_ptr->bufs_in_use );
+
+ /* fill the remainder of the current buffer with data */
+ HDmemcpy(struct_ptr->head,
+ (const void *)data_remaining,
+ struct_ptr->cur_buf_free_space);
+
+ data_remaining = data_remaining + struct_ptr->cur_buf_free_space;
+ size_remaining = size_remaining - struct_ptr->cur_buf_free_space;
+
+ struct_ptr->cur_buf_free_space = 0;
+
+ if ( ( is_end_trans ) && ( size_remaining == 0 ) ) {
+
+ (*struct_ptr->trans_tracking)[struct_ptr->put] = trans_num;
+
+#if H5C2_JB_AIO__WRITE_TO_BUFFER__DEBUG
+ HDfprintf(stdout, "%s: set trans_tracking[%d] to %lld (1).\n",
+ FUNC, struct_ptr->put, trans_num);
+#endif /* H5C2_JB_AIO__WRITE_TO_BUFFER__DEBUG */
+ }
+
+ HDassert( struct_ptr->bufs_in_use ==
+ (struct_ptr->writes_in_progress + 1 ) );
+
+ /* kick off an asynchronous write of the current buffer */
+ result = H5C2_jb_aio__queue_buffer_write(struct_ptr,
+ struct_ptr->put,
+ FALSE);
+
+ if ( result != SUCCEED ) {
+
+#if H5C2_JB_AIO__WRITE_TO_BUFFER__DEBUG
+ HDfprintf(stdout,
+ "%s: H5C2_jb_aio__queue_buffer_write() failed.\n",
+ FUNC);
+#endif /* H5C2_JB_AIO__WRITE_TO_BUFFER__DEBUG */
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__queue_buffer_write() failed.");
+ }
+
+ just_called_make_space_in_ring_buffer = FALSE;
+
+ HDassert( struct_ptr->bufs_in_use == struct_ptr->writes_in_progress );
+
+ /* if there is another free buffer, call
+ * H5C2_jb_aio__prep_next_buf_for_use().
+ *
+ * otherwise, if we still have data to write, call
+ * H5C2_jb_aio__make_space_in_ring_buffer() to free up
+ * space to continue the write.
+ */
+ if ( struct_ptr->bufs_in_use < struct_ptr->num_bufs ) {
+
+ last_trans_in_ring_buffer =
+ (*struct_ptr->trans_tracking)[struct_ptr->put];
+
+#if H5C2_JB_AIO__WRITE_TO_BUFFER__DEBUG
+ HDfprintf(stdout, "%s: set trans_tracking[%d] to %lld (2).\n",
+ FUNC, struct_ptr->put, trans_num);
+#endif /* H5C2_JB_AIO__WRITE_TO_BUFFER__DEBUG */
+
+ result = H5C2_jb_aio__prep_next_buf_for_use(struct_ptr,
+ last_trans_in_ring_buffer);
+
+ if ( result != SUCCEED ) {
+
+#if H5C2_JB_AIO__WRITE_TO_BUFFER__DEBUG
+ HDfprintf(stdout,
+ "%s: H5C2_jb_aio__prep_next_buf_for_use() failed.\n",
+ FUNC);
+#endif /* H5C2_JB_AIO__WRITE_TO_BUFFER__DEBUG */
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__prep_next_buf_for_use() failed.")
+ }
+ } else if ( size_remaining > 0 ) {
+
+ result = H5C2_jb_aio__make_space_in_ring_buffer(struct_ptr);
+
+ if ( result != SUCCEED ) {
+
+#if H5C2_JB_AIO__WRITE_TO_BUFFER__DEBUG
+ HDfprintf(stdout,
+ "%s: H5C2_jb_aio__make_space_in_ring_buffer() failed.\n",
+ FUNC);
+#endif /* H5C2_JB_AIO__WRITE_TO_BUFFER__DEBUG */
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__make_space_in_ring_buffer(2) failed.")
+ }
+ just_called_make_space_in_ring_buffer = TRUE;
+ }
+
+ HDassert( ( struct_ptr->writes_in_progress ==
+ struct_ptr->bufs_in_use ) ||
+ ( (struct_ptr->writes_in_progress + 1) ==
+ struct_ptr->bufs_in_use ) );
+
+ } /* while */
+
+ HDassert( ( size_remaining < struct_ptr->cur_buf_free_space ) ||
+ ( size_remaining == 0 ) );
+
+ if ( size_remaining > 0 ) {
+
+ /* increment bufs_in_use if we are about to write to an empty buffer */
+ if ( struct_ptr->cur_buf_free_space == struct_ptr->buf_size ) {
+
+ HDassert( struct_ptr->bufs_in_use ==
+ struct_ptr->writes_in_progress );
+
+ struct_ptr->bufs_in_use += 1;
+
+ HDassert( struct_ptr->bufs_in_use <= struct_ptr->num_bufs );
+ }
+
+ /* copy data into the current buffer */
+ HDmemcpy(struct_ptr->head,
+ (const void *)data_remaining,
+ size_remaining);
+
+ struct_ptr->head += size_remaining;
+ struct_ptr->cur_buf_free_space -= size_remaining;
+
+ if ( is_end_trans ) {
+
+ (*struct_ptr->trans_tracking)[struct_ptr->put] = trans_num;
+
+#if H5C2_JB_AIO__WRITE_TO_BUFFER__DEBUG
+ HDfprintf(stdout, "%s: set trans_tracking[%d] to %lld (3).\n",
+ FUNC, struct_ptr->put, trans_num);
+#endif /* H5C2_JB_AIO__WRITE_TO_BUFFER__DEBUG */
+ }
+ }
+
+ HDassert( ( ( struct_ptr->writes_in_progress == struct_ptr->bufs_in_use )
+ &&
+ ( struct_ptr->bufs_in_use < struct_ptr->num_bufs )
+ &&
+ ( struct_ptr->cur_buf_free_space == struct_ptr->buf_size )
+ )
+ ||
+ ( ( struct_ptr->writes_in_progress + 1 == struct_ptr->bufs_in_use )
+ &&
+ ( struct_ptr->cur_buf_free_space < struct_ptr->buf_size )
+ &&
+ ( struct_ptr->cur_buf_free_space > 0 )
+ )
+ ||
+ ( ( struct_ptr->writes_in_progress == struct_ptr->bufs_in_use )
+ &&
+ ( struct_ptr->bufs_in_use == struct_ptr->num_bufs )
+ &&
+ ( struct_ptr->cur_buf_free_space == 0 )
+ )
+ );
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C2_jb_aio__write_to_buffer */
+
+
+
+/******************************************************************************
+ *
* Function: H5C2_jb_bjf__comment
*
* Programmer: John Mainzer
*
- * Purpose: In the binary journal file format, a comment is
+ * Purpose: In the binary journal file format, a comment is
* a no-op. Thus in this function, we simply verify
* that we are in fact writing a binary journal file,
* and then return.
@@ -2245,14 +4920,14 @@ if ( H5C2_jb_bjf__write_trans_num((struct_ptr), (is_end_trans), \
*
******************************************************************************/
-static herr_t
+static herr_t
H5C2_jb_bjf__comment(H5C2_jbrb_t * struct_ptr,
const char * comment_ptr)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5C2_jb_bjf__comment, FAIL)
-
+
/* Check Arguments */
HDassert( struct_ptr != NULL );
HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
@@ -2282,13 +4957,13 @@ done:
* Programmer: John Mainzer
*
* Purpose: Verify that the supplied transaction is in progress,
- * and that at least one journal entry has been written
- * under it.
+ * and that at least one journal entry has been written
+ * under it.
*
- * Then write an end transaction message to the ring
+ * Then write an end transaction message to the ring
* buffer.
*
- * Make note that the supplied transaction is closed,
+ * Make note that the supplied transaction is closed,
* and that no transaction is in progress.
*
* Returns: SUCCEED on success.
@@ -2309,7 +4984,7 @@ H5C2_jb_bjf__end_transaction(H5C2_jbrb_t * struct_ptr,
HDassert( struct_ptr != NULL );
HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
HDassert( struct_ptr->human_readable == FALSE );
-
+
/* Verify that the supplied transaction is in progress */
if ( ( struct_ptr->trans_in_prog != TRUE ) ||
( struct_ptr->cur_trans != trans_num ) ) {
@@ -2317,9 +4992,9 @@ H5C2_jb_bjf__end_transaction(H5C2_jbrb_t * struct_ptr,
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"Transaction not in progress or bad transaction number.")
} /* end if */
-
- /* Verify that at least one journal entry has been written under
- * the current transaction
+
+ /* Verify that at least one journal entry has been written under
+ * the current transaction
*/
if ( struct_ptr->jentry_written != TRUE ) {
@@ -2341,8 +5016,8 @@ H5C2_jb_bjf__end_transaction(H5C2_jbrb_t * struct_ptr,
trans_num, \
/* fail_return */ FAIL)
- /* reset boolean flag indicating that at least one journal entry has
- * been written under transaction
+ /* reset boolean flag indicating that at least one journal entry has
+ * been written under transaction
*/
struct_ptr->jentry_written = FALSE;
@@ -2350,7 +5025,7 @@ H5C2_jb_bjf__end_transaction(H5C2_jbrb_t * struct_ptr,
struct_ptr->trans_in_prog = FALSE;
done:
-
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5C2_jb_bjf__end_transaction */
@@ -2362,15 +5037,15 @@ done:
*
* Programmer: John Mainzer
*
- * Purpose: Write an end of address space message with the
+ * Purpose: Write an end of address space message with the
* supplied EOA in binary format to the journal file.
*
- * Note that EOA messages are not generated by the
- * metadata cache, and thus are not associated with
+ * Note that EOA messages are not generated by the
+ * metadata cache, and thus are not associated with
* transactions. Since H5C2_jb__write_to_buffer()
- * expects a transaction number, we use
+ * expects a transaction number, we use
* struct_ptr->cur_trans and pass is_end_trans
- * as FALSE. However, this is just a cluge to
+ * as FALSE. However, this is just a cluge to
* keep pre-existing code happy.
*
* Returns: SUCCEED on success.
@@ -2379,21 +5054,21 @@ done:
*
******************************************************************************/
-static herr_t
+static herr_t
H5C2_jb_bjf__eoa(H5C2_jbrb_t * struct_ptr,
haddr_t eoa)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5C2_jb_bjf__eoa, FAIL)
-
+
/* Check Arguments */
HDassert( struct_ptr != NULL );
HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
HDassert( struct_ptr->human_readable == FALSE );
HDassert( struct_ptr->hdf5_file_name != NULL );
- /* Verify that header message is present in journal file or ring buffer.
- * If not, write it.
+ /* Verify that header message is present in journal file or ring buffer.
+ * If not, write it.
*/
if ( struct_ptr->header_present == FALSE ) {
@@ -2404,10 +5079,10 @@ H5C2_jb_bjf__eoa(H5C2_jbrb_t * struct_ptr,
}
} /* end if */
- /* Note that EOA messages are not generated by the metadata cache, and
- * thus are not associated with transactions. Since
- * H5C2_jb__write_to_buffer() expects a transaction number, we use
- * struct_ptr->cur_trans and pass is_end_trans as FALSE. However,
+ /* Note that EOA messages are not generated by the metadata cache, and
+ * thus are not associated with transactions. Since
+ * H5C2_jb__write_to_buffer() expects a transaction number, we use
+ * struct_ptr->cur_trans and pass is_end_trans as FALSE. However,
* this is just a cluge to keep pre-existing code happy.
*/
@@ -2446,7 +5121,7 @@ done:
*
******************************************************************************/
-static herr_t
+static herr_t
H5C2_jb_bjf__journal_entry(H5C2_jbrb_t * struct_ptr,
uint64_t trans_num,
haddr_t base_addr,
@@ -2507,8 +5182,8 @@ H5C2_jb_bjf__journal_entry(H5C2_jbrb_t * struct_ptr,
trans_num, \
/* fail_return */ FAIL)
- /* Indicate that at least one journal entry has been written under
- * this transaction
+ /* Indicate that at least one journal entry has been written under
+ * this transaction
*/
struct_ptr->jentry_written = TRUE;
@@ -2527,9 +5202,9 @@ done:
* Programmer: John Mainzer
*
* Purpose: Verify that there is no transaction in progress, and
- * that the supplied transaction number greater than
- * the last. Then write a binary start transaction
- * message to the ring buffer. Make note of the fact
+ * that the supplied transaction number greater than
+ * the last. Then write a binary start transaction
+ * message to the ring buffer. Make note of the fact
* that the supplied transaction is in progress.
*
* Returns: SUCCEED on success.
@@ -2538,7 +5213,7 @@ done:
*
******************************************************************************/
-static herr_t
+static herr_t
H5C2_jb_bjf__start_transaction(H5C2_jbrb_t * struct_ptr,
uint64_t trans_num)
@@ -2551,7 +5226,7 @@ H5C2_jb_bjf__start_transaction(H5C2_jbrb_t * struct_ptr,
HDassert(struct_ptr);
HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC);
HDassert(struct_ptr->human_readable == FALSE );
-
+
/* Verify that there is no transaction in progress */
if ( struct_ptr->trans_in_prog != FALSE ) {
@@ -2566,8 +5241,8 @@ H5C2_jb_bjf__start_transaction(H5C2_jbrb_t * struct_ptr,
"New transaction out of sequence.")
} /* end if */
- /* Verify that header message is present in journal file or ring buffer.
- * If not, write it.
+ /* Verify that header message is present in journal file or ring buffer.
+ * If not, write it.
*/
if ( struct_ptr->header_present == FALSE ) {
@@ -2593,13 +5268,13 @@ H5C2_jb_bjf__start_transaction(H5C2_jbrb_t * struct_ptr,
/* is_end_trans */ FALSE, \
trans_num, \
/* fail_return */ FAIL)
-
+
/* Make note of the fact that supplied transaction is in progress */
struct_ptr->trans_in_prog = TRUE;
struct_ptr->cur_trans = trans_num;
done:
-
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5C2_jb_bjf__start_transaction */
@@ -2612,16 +5287,16 @@ done:
* Programmer: John Mainzer
* 4/24/09
*
- * Purpose: Copy the supplied buffer to the ring buffer as
+ * Purpose: Copy the supplied buffer to the ring buffer as
* efficiently as possible.
*
- * If there is space available in the current buffer in
- * the ring buffer is big enough, just memcpy the
+ * If there is space available in the current buffer in
+ * the ring buffer is big enough, just memcpy the
* supplied buffer directly into the ring buffer buffer
- * and update its fields accordingly.
+ * and update its fields accordingly.
*
- * If the supplied buffer will cross ring buffer buffer
- * boundaries, for now just call
+ * If the supplied buffer will cross ring buffer buffer
+ * boundaries, for now just call
* H5C2_jb__write_to_buffer().
*
* In either case, if struct_ptr->chksum_cur_msg is TRUE,
@@ -2634,11 +5309,13 @@ done:
* Returns: SUCCEED on success.
* FAIL on failure.
*
- * Changes: None.
+ * Changes: Updated to updated fields used only in the SIO case
+ * only when SIO is selected.
+ * JRM -- 1/14/10
*
******************************************************************************/
-static herr_t
+static herr_t
H5C2_jb_bjf__write_buffer(H5C2_jbrb_t * struct_ptr,
size_t buf_size,
const char * buf_ptr,
@@ -2653,7 +5330,30 @@ H5C2_jb_bjf__write_buffer(H5C2_jbrb_t * struct_ptr,
HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
HDassert( buf_size > 0 );
HDassert( buf_ptr != NULL );
- HDassert( trans_num > 0 );
+ HDassert( trans_num > 0 );
+ HDassert( ( ! struct_ptr->use_aio )
+ ||
+ ( ( struct_ptr->writes_in_progress == struct_ptr->bufs_in_use )
+ &&
+ ( struct_ptr->bufs_in_use < struct_ptr->num_bufs )
+ &&
+ ( struct_ptr->cur_buf_free_space == struct_ptr->buf_size )
+ )
+ ||
+ ( ( struct_ptr->writes_in_progress + 1 == struct_ptr->bufs_in_use )
+ &&
+ ( struct_ptr->cur_buf_free_space < struct_ptr->buf_size )
+ &&
+ ( struct_ptr->cur_buf_free_space > 0 )
+ )
+ ||
+ ( ( struct_ptr->writes_in_progress == struct_ptr->bufs_in_use )
+ &&
+ ( struct_ptr->bufs_in_use == struct_ptr->num_bufs )
+ &&
+ ( struct_ptr->cur_buf_free_space == 0 )
+ )
+ );
/* is_end_trans must be FALSE if struct_ptr->chksum_cur_msg is TRUE.
* Throw an error if this invarient doesn't hold.
@@ -2668,8 +5368,8 @@ H5C2_jb_bjf__write_buffer(H5C2_jbrb_t * struct_ptr,
/* Update the check sum if required */
if ( struct_ptr->chksum_cur_msg ) {
- struct_ptr->msg_chksum = H5_checksum_metadata((const void *)(buf_ptr),
- buf_size,
+ struct_ptr->msg_chksum = H5_checksum_metadata((const void *)(buf_ptr),
+ buf_size,
struct_ptr->msg_chksum);
}
@@ -2677,18 +5377,29 @@ H5C2_jb_bjf__write_buffer(H5C2_jbrb_t * struct_ptr,
/* If the buffer will fit in the current ring buffer buffer with space
* left over, just memcpy() it in and touch up the ring buffer
- * fields accordingly.
+ * fields accordingly.
*
- * This is the common case, so when we convert this function into
- * a macro, this will allow us to avoid a function call in the vast
+ * This is the common case, so when we convert this function into
+ * a macro, this will allow us to avoid a function call in the vast
* majority of cases.
*/
/* write data into journal buffer */
HDmemcpy(struct_ptr->head, (const void *)buf_ptr, buf_size);
- /* increment bufs_in_use as necessary */
- if ( ( struct_ptr->bufs_in_use == 0 ) ) {
+ /* increment bufs_in_use as necessary -- do this differently
+ * for aio and sio.
+ */
+ if ( ( ( struct_ptr->bufs_in_use == 0 )
+ &&
+ ( ! struct_ptr->use_aio )
+ )
+ ||
+ ( ( struct_ptr->cur_buf_free_space == struct_ptr->buf_size )
+ &&
+ ( struct_ptr->use_aio )
+ )
+ ) {
struct_ptr->bufs_in_use++;
}
@@ -2696,27 +5407,32 @@ H5C2_jb_bjf__write_buffer(H5C2_jbrb_t * struct_ptr,
/* update head pointer */
struct_ptr->head = &(struct_ptr->head[buf_size]);
- /* update rb_free_space */
- struct_ptr->rb_free_space -= buf_size;
-
/* update current buffer usage */
struct_ptr->cur_buf_free_space -= buf_size;
- /* update end of buffer space */
- struct_ptr->rb_space_to_rollover -= buf_size;
+ if ( ! struct_ptr->use_aio ) {
+
+ /* update fields used only with SIO: */
+
+ /* update rb_free_space */
+ struct_ptr->rb_free_space -= buf_size;
+
+ /* update end of buffer space */
+ struct_ptr->rb_space_to_rollover -= buf_size;
+ }
if ( is_end_trans == TRUE ) {
(*struct_ptr->trans_tracking)[struct_ptr->put] = trans_num;
- }
+ }
HDassert( struct_ptr->cur_buf_free_space > 0 );
} else {
/* Here, handle the case where the write will reach the edge
- * of a ring buffer buffer. This gets a bit more complex, so
- * for now at least, we will call H5C2_jb__write_to_buffer().
+ * of a ring buffer buffer. This gets a bit more complex, so
+ * for now at least, we will call H5C2_jb__write_to_buffer().
* If this proves too costly, further optimizations will be necessary.
*/
@@ -2728,12 +5444,35 @@ H5C2_jb_bjf__write_buffer(H5C2_jbrb_t * struct_ptr,
}
}
+ HDassert( ( ! struct_ptr->use_aio )
+ ||
+ ( ( struct_ptr->writes_in_progress == struct_ptr->bufs_in_use )
+ &&
+ ( struct_ptr->bufs_in_use < struct_ptr->num_bufs )
+ &&
+ ( struct_ptr->cur_buf_free_space == struct_ptr->buf_size )
+ )
+ ||
+ ( ( struct_ptr->writes_in_progress + 1 == struct_ptr->bufs_in_use )
+ &&
+ ( struct_ptr->cur_buf_free_space < struct_ptr->buf_size )
+ &&
+ ( struct_ptr->cur_buf_free_space > 0 )
+ )
+ ||
+ ( ( struct_ptr->writes_in_progress == struct_ptr->bufs_in_use )
+ &&
+ ( struct_ptr->bufs_in_use == struct_ptr->num_bufs )
+ &&
+ ( struct_ptr->cur_buf_free_space == 0 )
+ )
+ );
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5C2_jb_bjf__write_buffer() */
-
+
/******************************************************************************
*
@@ -2744,15 +5483,15 @@ done:
*
* Purpose: Write the checksum of a binary journal file message
* to the ring buffer as eficiently as possible. Note
- * that this checksum is computed only on the body of
+ * that this checksum is computed only on the body of
* the message -- not the signature and version.
*
- * If there is space available in the current buffer in
+ * If there is space available in the current buffer in
* the ring buffer is big enough, just write the chksum
- * directly into the ring buffer buffer and update its
- * fields accordingly.
+ * directly into the ring buffer buffer and update its
+ * fields accordingly.
*
- * If the chksum will cross ring buffer buffer boundaries,
+ * If the chksum will cross ring buffer buffer boundaries,
* for now just call H5C2_jb__write_to_buffer().
*
* Note that this function will probably prove to be
@@ -2763,9 +5502,11 @@ done:
* FAIL on failure.
*
******************************************************************************/
-static herr_t
-H5C2_jb_bjf__write_chksum(H5C2_jbrb_t * struct_ptr, hbool_t is_end_trans,
- uint64_t trans_num)
+
+static herr_t
+H5C2_jb_bjf__write_chksum(H5C2_jbrb_t * struct_ptr,
+ hbool_t is_end_trans,
+ uint64_t trans_num)
{
uint8_t *p;
herr_t ret_value = SUCCEED; /* Return value */
@@ -2775,19 +5516,22 @@ H5C2_jb_bjf__write_chksum(H5C2_jbrb_t * struct_ptr, hbool_t is_end_trans,
/* Sanity check */
HDassert(struct_ptr != NULL);
HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC);
- HDassert(trans_num > 0);
+ HDassert(trans_num > 0);
- if(!struct_ptr->chksum_cur_msg)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, "struct_ptr->chksum_cur_msg is false?!?!.")
+ if ( ! struct_ptr->chksum_cur_msg ) {
- if(H5C2__CHECKSUM_SIZE < struct_ptr->cur_buf_free_space) {
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "struct_ptr->chksum_cur_msg is false?!?!.")
+ }
+
+ if ( H5C2__CHECKSUM_SIZE < struct_ptr->cur_buf_free_space ) {
/* If the checksum will fit in the current buffer with space
- * left over, just write it directly into the buffer, and
- * touch up the ring buffer fields accordingly.
+ * left over, just write it directly into the buffer, and
+ * touch up the ring buffer fields accordingly.
*
- * This is the common case, so when we convert this function into
- * a macro, this will allow us to avoid a function call in the vast
+ * This is the common case, so when we convert this function into
+ * a macro, this will allow us to avoid a function call in the vast
* majority of cases.
*/
@@ -2799,21 +5543,38 @@ H5C2_jb_bjf__write_chksum(H5C2_jbrb_t * struct_ptr, hbool_t is_end_trans,
HDassert( p == ((uint8_t *)(struct_ptr->head + H5C2__CHECKSUM_SIZE)) );
- /* increment bufs_in_use as necessary */
- if(struct_ptr->bufs_in_use == 0 )
+ /* increment bufs_in_use as necessary -- do this differently
+ * for aio and sio.
+ */
+ if ( ( ( struct_ptr->bufs_in_use == 0 )
+ &&
+ ( ! struct_ptr->use_aio )
+ )
+ ||
+ ( ( struct_ptr->cur_buf_free_space == struct_ptr->buf_size )
+ &&
+ ( struct_ptr->use_aio )
+ )
+ ) {
+
struct_ptr->bufs_in_use++;
+ }
/* update head pointer */
struct_ptr->head = &(struct_ptr->head[H5C2__CHECKSUM_SIZE]);
- /* update rb_free_space */
- struct_ptr->rb_free_space -= H5C2__CHECKSUM_SIZE;
-
/* update current buffer usage */
struct_ptr->cur_buf_free_space -= H5C2__CHECKSUM_SIZE;
- /* update end of buffer space */
- struct_ptr->rb_space_to_rollover -= H5C2__CHECKSUM_SIZE;
+ /* update fields used only with SIO: */
+ if( ! struct_ptr->use_aio ) {
+
+ /* update rb_free_space */
+ struct_ptr->rb_free_space -= H5C2__CHECKSUM_SIZE;
+
+ /* update end of buffer space */
+ struct_ptr->rb_space_to_rollover -= H5C2__CHECKSUM_SIZE;
+ }
if(is_end_trans)
(*struct_ptr->trans_tracking)[struct_ptr->put] = trans_num;
@@ -2822,22 +5583,29 @@ H5C2_jb_bjf__write_chksum(H5C2_jbrb_t * struct_ptr, hbool_t is_end_trans,
} /* end if */
else {
+
uint8_t buf[H5C2__CHECKSUM_SIZE + 1];
/* Here, handle the case where the write will reach the edge
- * of a buffer. This gets a bit more complex, so for now at
- * least, we will construct a buffer containing a binary
- * representation of the checksum, and then call
- * H5C2_jb__write_to_buffer(). If this proves too costly,
+ * of a buffer. This gets a bit more complex, so for now at
+ * least, we will construct a buffer containing a binary
+ * representation of the checksum, and then call
+ * H5C2_jb__write_to_buffer(). If this proves too costly,
* further optimizations will be necessary.
*/
p = buf;
UINT32ENCODE(p, struct_ptr->msg_chksum);
HDassert( p == &(buf[H5C2__CHECKSUM_SIZE]) );
- if(H5C2_jb__write_to_buffer(struct_ptr, H5C2__CHECKSUM_SIZE,
- (const char *)buf, is_end_trans, trans_num) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, "H5C2_jb__write_to_buffer() failed.")
+ if ( H5C2_jb__write_to_buffer(struct_ptr,
+ H5C2__CHECKSUM_SIZE,
+ (const char *)buf,
+ is_end_trans,
+ trans_num) < 0 ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "H5C2_jb__write_to_buffer() failed.")
+ }
} /* end else */
/* re-set the checksum computation fields */
@@ -2845,9 +5613,11 @@ H5C2_jb_bjf__write_chksum(H5C2_jbrb_t * struct_ptr, hbool_t is_end_trans,
struct_ptr->msg_chksum = 0;
done:
+
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5C2_jb_bjf__write_chksum() */
+} /* H5C2_jb_bjf__write_chksum() */
+
/******************************************************************************
*
@@ -2856,15 +5626,15 @@ done:
* Programmer: John Mainzer
* 4/24/09
*
- * Purpose: Write a HDF5 file length to the ring buffer as
+ * Purpose: Write a HDF5 file length to the ring buffer as
* efficiently as possible.
*
- * If the space available in the current buffer in
- * the ring buffer is big enough, just encode the
- * lenght directly into the buffer and update its
- * fields accordingly.
+ * If the space available in the current buffer in
+ * the ring buffer is big enough, just encode the
+ * lenght directly into the buffer and update its
+ * fields accordingly.
*
- * If the binary representation of the length will
+ * If the binary representation of the length will
* touch buffer boundaries, create a buffer containing
* the binary representation of the length, and then
* call H5C2_jb__write_to_buffer() to handle the write.
@@ -2883,7 +5653,7 @@ done:
*
******************************************************************************/
-static herr_t
+static herr_t
H5C2_jb_bjf__write_length(H5C2_jbrb_t * struct_ptr,
size_t length,
hbool_t is_end_trans,
@@ -2897,7 +5667,7 @@ H5C2_jb_bjf__write_length(H5C2_jbrb_t * struct_ptr,
HDassert( struct_ptr != NULL );
HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
- HDassert( trans_num > 0 );
+ HDassert( trans_num > 0 );
/* is_end_trans must be FALSE if struct_ptr->chksum_cur_msg is TRUE.
* Throw an error if this invarient doesn't hold.
@@ -2909,20 +5679,20 @@ H5C2_jb_bjf__write_length(H5C2_jbrb_t * struct_ptr,
"is_end_trans and struct_ptr->chksum_cur_msg both true.")
}
- length_width = struct_ptr->length_width;
+ length_width = (size_t)(struct_ptr->length_width);
- HDassert( ( length_width == 2 ) ||
- ( length_width == 4 ) ||
+ HDassert( ( length_width == 2 ) ||
+ ( length_width == 4 ) ||
( length_width == 8 ) );
if ( length_width < struct_ptr->cur_buf_free_space ) {
/* If the offset will fit in the current buffer with space
- * left over, just write it directly into the buffer, and
- * touch up the ring buffer fields accordingly.
+ * left over, just write it directly into the buffer, and
+ * touch up the ring buffer fields accordingly.
*
- * This is the common case, so when we convert this function into
- * a macro, this will allow us to avoid a function call in the vast
+ * This is the common case, so when we convert this function into
+ * a macro, this will allow us to avoid a function call in the vast
* majority of cases.
*/
@@ -2952,8 +5722,19 @@ H5C2_jb_bjf__write_length(H5C2_jbrb_t * struct_ptr,
HDassert( p == ((uint8_t *)(struct_ptr->head + length_width)) );
- /* increment bufs_in_use as necessary */
- if ( ( struct_ptr->bufs_in_use == 0 ) ) {
+ /* increment bufs_in_use as necessary -- do this differently
+ * for aio and sio.
+ */
+ if ( ( ( struct_ptr->bufs_in_use == 0 )
+ &&
+ ( ! struct_ptr->use_aio )
+ )
+ ||
+ ( ( struct_ptr->cur_buf_free_space == struct_ptr->buf_size )
+ &&
+ ( struct_ptr->use_aio )
+ )
+ ) {
struct_ptr->bufs_in_use++;
}
@@ -2961,38 +5742,42 @@ H5C2_jb_bjf__write_length(H5C2_jbrb_t * struct_ptr,
/* Update the check sum if required */
if ( struct_ptr->chksum_cur_msg ) {
- struct_ptr->msg_chksum =
- H5_checksum_metadata((const void *)(struct_ptr->head),
- length_width,
+ struct_ptr->msg_chksum =
+ H5_checksum_metadata((const void *)(struct_ptr->head),
+ length_width,
struct_ptr->msg_chksum);
}
/* update head pointer */
struct_ptr->head = &(struct_ptr->head[length_width]);
- /* update rb_free_space */
- struct_ptr->rb_free_space -= length_width;
-
/* update current buffer usage */
struct_ptr->cur_buf_free_space -= length_width;
- /* update end of buffer space */
- struct_ptr->rb_space_to_rollover -= length_width;
+ /* update fields used only with SIO: */
+ if( ! struct_ptr->use_aio ) {
+
+ /* update rb_free_space */
+ struct_ptr->rb_free_space -= length_width;
+
+ /* update end of buffer space */
+ struct_ptr->rb_space_to_rollover -= length_width;
+ }
if ( is_end_trans == TRUE ) {
(*struct_ptr->trans_tracking)[struct_ptr->put] = trans_num;
- }
+ }
HDassert( struct_ptr->cur_buf_free_space > 0 );
} else {
/* Here, handle the case where the write will reach the edge
- * of a buffer. This gets a bit more complex, so for now at
- * least, we will construct a buffer containing a binary
- * representation of the offset, and then call
- * H5C2_jb__write_to_buffer(). If this proves too costly,
+ * of a buffer. This gets a bit more complex, so for now at
+ * least, we will construct a buffer containing a binary
+ * representation of the offset, and then call
+ * H5C2_jb__write_to_buffer(). If this proves too costly,
* further optimizations will be necessary.
*/
@@ -3014,27 +5799,38 @@ H5C2_jb_bjf__write_length(H5C2_jbrb_t * struct_ptr,
break;
default:
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, "length_width out of range (2).")
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "length_width out of range (2).")
break;
} /* end switch */
HDassert( p == &(buf[length_width]) );
- if(H5C2_jb__write_to_buffer(struct_ptr, length_width,
+
+ if ( H5C2_jb__write_to_buffer(struct_ptr, length_width,
(const char *)buf,
- is_end_trans, trans_num) != SUCCEED)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, "H5C2_jb__write_to_buffer() failed.")
+ is_end_trans,
+ trans_num) != SUCCEED ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "H5C2_jb__write_to_buffer() failed.")
+ }
/* Update the check sum if required */
- if(struct_ptr->chksum_cur_msg)
- struct_ptr->msg_chksum = H5_checksum_metadata((const void *)(buf),
- length_width,
- struct_ptr->msg_chksum);
+ if ( struct_ptr->chksum_cur_msg ) {
+
+ struct_ptr->msg_chksum =
+ H5_checksum_metadata((const void *)(buf),
+ length_width,
+ struct_ptr->msg_chksum);
+ }
} /* end else */
done:
+
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5C2_jb_bjf__write_length() */
+} /* H5C2_jb_bjf__write_length() */
+
/******************************************************************************
*
@@ -3043,15 +5839,15 @@ done:
* Programmer: John Mainzer
* 4/24/09
*
- * Purpose: Write a HDF5 file offset to the ring buffer as
+ * Purpose: Write a HDF5 file offset to the ring buffer as
* efficiently as possible.
*
- * If the space available in the current buffer in
- * the ring buffer is big enough, just encode the
- * offset directly into the buffer and update its
- * fields accordingly.
+ * If the space available in the current buffer in
+ * the ring buffer is big enough, just encode the
+ * offset directly into the buffer and update its
+ * fields accordingly.
*
- * If the binary representation of the offset will
+ * If the binary representation of the offset will
* touch buffer boundaries, create a buffer containing
* the binary representation of the offset, and then
* call H5C2_jb__write_to_buffer() to handle the write.
@@ -3070,7 +5866,7 @@ done:
*
******************************************************************************/
-static herr_t
+static herr_t
H5C2_jb_bjf__write_offset(H5C2_jbrb_t * struct_ptr,
haddr_t offset,
hbool_t is_end_trans,
@@ -3085,11 +5881,11 @@ H5C2_jb_bjf__write_offset(H5C2_jbrb_t * struct_ptr,
HDassert( struct_ptr != NULL );
HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
/* eoa messages can be written outside transactions -- so it is
- * possible that the trans_num will be 0. Since the trans_num is
+ * possible that the trans_num will be 0. Since the trans_num is
* not used unless is_end_trans is TRUE, we make an exception for
* the eoa message.
*/
- HDassert( ( ! is_end_trans ) || ( trans_num > 0 ) );
+ HDassert( ( ! is_end_trans ) || ( trans_num > 0 ) );
/* is_end_trans must be FALSE if struct_ptr->chksum_cur_msg is TRUE.
* Throw an error if this invarient doesn't hold.
@@ -3101,20 +5897,20 @@ H5C2_jb_bjf__write_offset(H5C2_jbrb_t * struct_ptr,
"is_end_trans and struct_ptr->chksum_cur_msg both true.")
}
- offset_width = struct_ptr->offset_width;
+ offset_width = (size_t)(struct_ptr->offset_width);
- HDassert( ( offset_width == 2 ) ||
- ( offset_width == 4 ) ||
+ HDassert( ( offset_width == 2 ) ||
+ ( offset_width == 4 ) ||
( offset_width == 8 ) );
if ( offset_width < struct_ptr->cur_buf_free_space ) {
/* If the offset will fit in the current buffer with space
- * left over, just write it directly into the buffer, and
- * touch up the ring buffer fields accordingly.
+ * left over, just write it directly into the buffer, and
+ * touch up the ring buffer fields accordingly.
*
- * This is the common case, so when we convert this function into
- * a macro, this will allow us to avoid a function call in the vast
+ * This is the common case, so when we convert this function into
+ * a macro, this will allow us to avoid a function call in the vast
* majority of cases.
*/
@@ -3144,8 +5940,19 @@ H5C2_jb_bjf__write_offset(H5C2_jbrb_t * struct_ptr,
HDassert( p == ((uint8_t *)(struct_ptr->head + offset_width)) );
- /* increment bufs_in_use as necessary */
- if ( ( struct_ptr->bufs_in_use == 0 ) ) {
+ /* increment bufs_in_use as necessary -- do this differently
+ * for aio and sio.
+ */
+ if ( ( ( struct_ptr->bufs_in_use == 0 )
+ &&
+ ( ! struct_ptr->use_aio )
+ )
+ ||
+ ( ( struct_ptr->cur_buf_free_space == struct_ptr->buf_size )
+ &&
+ ( struct_ptr->use_aio )
+ )
+ ) {
struct_ptr->bufs_in_use++;
}
@@ -3153,38 +5960,42 @@ H5C2_jb_bjf__write_offset(H5C2_jbrb_t * struct_ptr,
/* Update the check sum if required */
if ( struct_ptr->chksum_cur_msg ) {
- struct_ptr->msg_chksum =
- H5_checksum_metadata((const void *)(struct_ptr->head),
- offset_width,
+ struct_ptr->msg_chksum =
+ H5_checksum_metadata((const void *)(struct_ptr->head),
+ offset_width,
struct_ptr->msg_chksum);
}
/* update head pointer */
struct_ptr->head = &(struct_ptr->head[offset_width]);
- /* update rb_free_space */
- struct_ptr->rb_free_space -= offset_width;
-
/* update current buffer usage */
struct_ptr->cur_buf_free_space -= offset_width;
- /* update end of buffer space */
- struct_ptr->rb_space_to_rollover -= offset_width;
+ /* update fields used only with SIO: */
+ if( ! struct_ptr->use_aio ) {
+
+ /* update rb_free_space */
+ struct_ptr->rb_free_space -= offset_width;
+
+ /* update end of buffer space */
+ struct_ptr->rb_space_to_rollover -= offset_width;
+ }
if ( is_end_trans == TRUE ) {
(*struct_ptr->trans_tracking)[struct_ptr->put] = trans_num;
- }
+ }
HDassert( struct_ptr->cur_buf_free_space > 0 );
} else {
/* Here, handle the case where the write will reach the edge
- * of a buffer. This gets a bit more complex, so for now at
- * least, we will construct a buffer containing a binary
- * representation of the offset, and then call
- * H5C2_jb__write_to_buffer(). If this proves too costly,
+ * of a buffer. This gets a bit more complex, so for now at
+ * least, we will construct a buffer containing a binary
+ * representation of the offset, and then call
+ * H5C2_jb__write_to_buffer(). If this proves too costly,
* further optimizations will be necessary.
*/
@@ -3216,7 +6027,7 @@ H5C2_jb_bjf__write_offset(H5C2_jbrb_t * struct_ptr,
HDassert( p == &(buf[offset_width]) );
- if ( H5C2_jb__write_to_buffer(struct_ptr, offset_width,
+ if ( H5C2_jb__write_to_buffer(struct_ptr, offset_width,
(const char *)buf,
is_end_trans, trans_num) != SUCCEED ) {
@@ -3227,8 +6038,8 @@ H5C2_jb_bjf__write_offset(H5C2_jbrb_t * struct_ptr,
/* Update the check sum if required */
if ( struct_ptr->chksum_cur_msg ) {
- struct_ptr->msg_chksum = H5_checksum_metadata((const void *)(buf),
- offset_width,
+ struct_ptr->msg_chksum = H5_checksum_metadata((const void *)(buf),
+ offset_width,
struct_ptr->msg_chksum);
}
@@ -3239,7 +6050,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5C2_jb_bjf__write_offset() */
-
+
/******************************************************************************
*
@@ -3248,24 +6059,24 @@ done:
* Programmer: John Mainzer
* 4/24/09
*
- * Purpose: Write the signature and version of a binary journal
- * file message to the ring buffer as efficiently as
+ * Purpose: Write the signature and version of a binary journal
+ * file message to the ring buffer as efficiently as
* possible.
*
- * If there is space available in the current buffer in
- * the ring buffer is big enough, just memcpy the
- * signature and write the version directly into the
- * buffer and update its fields accordingly.
+ * If there is space available in the current buffer in
+ * the ring buffer is big enough, just memcpy the
+ * signature and write the version directly into the
+ * buffer and update its fields accordingly.
*
- * If the signature and version will cross buffer
- * boundaries, for now just call
+ * If the signature and version will cross buffer
+ * boundaries, for now just call
* H5C2_jb__write_to_buffer().
*
* In either case, if keep_chksum is TRUE, initialize
* struct_ptr->msg_chksum to 0, and set struct_ptr->
* chksum_cur_msg to TRUE.
*
- * Observe that the checksum does not include the
+ * Observe that the checksum does not include the
* signature and version.
*
* Note that this function will probably prove to be
@@ -3275,36 +6086,46 @@ done:
* Returns: SUCCEED on success.
* FAIL on failure.
*
+ * Changes: Updated function for slight differences in buffer
+ * management when aio is enabled.
+ * JRM -- 1/27/09
+ *
******************************************************************************/
-static herr_t
-H5C2_jb_bjf__write_sig_and_ver(H5C2_jbrb_t *struct_ptr, const char *sig_ptr,
- const uint8_t version, hbool_t keep_chksum, hbool_t is_end_trans,
- uint64_t trans_num)
+
+static herr_t
+H5C2_jb_bjf__write_sig_and_ver(H5C2_jbrb_t *struct_ptr,
+ const char *sig_ptr,
+ const uint8_t version,
+ hbool_t keep_chksum,
+ hbool_t is_end_trans,
+ uint64_t trans_num)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5C2_jb_bjf__write_sig_and_ver, FAIL)
- HDassert(struct_ptr);
- HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC);
- HDassert(sig_ptr);
- HDassert(H5C2_BJNL__SIG_LEN == HDstrlen(sig_ptr));
- HDassert(!is_end_trans);
- /* eoa messages can occur outside of transactions -- and thus it is
- * possible that we will have to process one before any transaction
+ HDassert( struct_ptr != NULL );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+ HDassert( sig_ptr != NULL );
+ HDassert( H5C2_BJNL__SIG_LEN == HDstrlen(sig_ptr) );
+ HDassert( ! is_end_trans );
+
+ /* eoa messages can occur outside of transactions -- and thus it is
+ * possible that we will have to process one before any transaction
* has started -- in which case trans_num will be 0. Since the trans_num
- * isn't used unless is_end_trans is TRUE, we carve a small exception
+ * isn't used unless is_end_trans is TRUE, we carve a small exception
* for the eoa message.
*/
HDassert((!is_end_trans) || (trans_num > 0));
- if((H5C2_BJNL__SIG_LEN + 1) < struct_ptr->cur_buf_free_space) {
- /* If the signature and version will fit in the current buffer
- * with space left over, just memcpy()/write it in and touch up
- * the ring bufferfields accordingly.
+ if ( (H5C2_BJNL__SIG_LEN + 1) < struct_ptr->cur_buf_free_space ) {
+
+ /* If the signature and version will fit in the current buffer
+ * with space left over, just memcpy()/write it in and touch up
+ * the ring bufferfields accordingly.
*
- * This is the common case, so when we convert this function into
- * a macro, this will allow us to avoid a function call in the vast
+ * This is the common case, so when we convert this function into
+ * a macro, this will allow us to avoid a function call in the vast
* majority of cases.
*/
@@ -3316,55 +6137,92 @@ H5C2_jb_bjf__write_sig_and_ver(H5C2_jbrb_t *struct_ptr, const char *sig_ptr,
/* update head pointer */
struct_ptr->head = &(struct_ptr->head[H5C2_BJNL__SIG_LEN + 1]);
- /* increment bufs_in_use as necessary */
- if(struct_ptr->bufs_in_use == 0)
- struct_ptr->bufs_in_use++;
+ /* increment bufs_in_use as necessary -- do this differently
+ * for aio and sio.
+ */
+ if ( ( ( struct_ptr->bufs_in_use == 0 )
+ &&
+ ( ! struct_ptr->use_aio )
+ )
+ ||
+ ( ( struct_ptr->cur_buf_free_space == struct_ptr->buf_size )
+ &&
+ ( struct_ptr->use_aio )
+ )
+ ) {
- /* update rb_free_space */
- struct_ptr->rb_free_space -= H5C2_BJNL__SIG_LEN + 1;
+ struct_ptr->bufs_in_use++;
+ }
/* update current buffer usage */
struct_ptr->cur_buf_free_space -= H5C2_BJNL__SIG_LEN + 1;
- /* update end of buffer space */
- struct_ptr->rb_space_to_rollover -= H5C2_BJNL__SIG_LEN + 1;
+ /* update fields used only with SIO: */
+ if( ! struct_ptr->use_aio ) {
+
+ /* update rb_free_space */
+ struct_ptr->rb_free_space -= H5C2_BJNL__SIG_LEN + 1;
+
+ /* update end of buffer space */
+ struct_ptr->rb_space_to_rollover -= H5C2_BJNL__SIG_LEN + 1;
+ }
- /* is_end_trans must be false in this call, so just throw an
+ /* is_end_trans must be false in this call, so just throw an
* error if it is TRUE.
*/
- if(is_end_trans)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, "is_end_trans TRUE when writing signiture.")
+ if ( is_end_trans ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "is_end_trans TRUE when writing signiture.")
+ }
HDassert( struct_ptr->cur_buf_free_space > 0 );
+
} /* end if */
else {
+
uint8_t buf[H5C2_BJNL__SIG_LEN + 2];
/* Here, handle the case where the write will reach the edge
- * of a buffer. This gets a bit more complex, so for now at
- * least, we will call H5C2_jb__write_to_buffer(). If this
+ * of a buffer. This gets a bit more complex, so for now at
+ * least, we will call H5C2_jb__write_to_buffer(). If this
* proves too costly, further optimizations will be necessary.
*/
+
HDmemcpy(buf, (const void *)sig_ptr, H5C2_BJNL__SIG_LEN);
+
buf[H5C2_BJNL__SIG_LEN] = version;
- if(H5C2_jb__write_to_buffer(struct_ptr, H5C2_BJNL__SIG_LEN + 1,
- (const char *)buf, is_end_trans, trans_num) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, "H5C2_jb__write_to_buffer() failed.")
+ if ( H5C2_jb__write_to_buffer(struct_ptr,
+ H5C2_BJNL__SIG_LEN + 1,
+ (const char *)buf,
+ is_end_trans,
+ trans_num) < 0 ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "H5C2_jb__write_to_buffer() failed.")
+ }
} /* end else */
- if(struct_ptr->chksum_cur_msg)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, "struct_ptr->chksum_cur_msg is already TRUE")
+ if ( struct_ptr->chksum_cur_msg ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "struct_ptr->chksum_cur_msg is already TRUE")
+ }
+
+ if ( keep_chksum ) {
- if(keep_chksum) {
struct_ptr->chksum_cur_msg = TRUE;
struct_ptr->msg_chksum = 0;
+
} /* end if */
done:
+
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5C2_jb_bjf__write_sig_and_ver() */
+} /* end H5C2_jb_bjf__write_sig_and_ver() */
+
/******************************************************************************
*
@@ -3373,17 +6231,17 @@ done:
* Programmer: John Mainzer
* 4/24/09
*
- * Purpose: Write the transaction number in a binary journal file
+ * Purpose: Write the transaction number in a binary journal file
* message to the ring buffer as efficiently as possible.
*
- * If the space available in the current buffer in
- * the ring buffer is big enough, just write the
- * transaction number directly into the buffer and
- * update its fields accordingly.
+ * If the space available in the current buffer in
+ * the ring buffer is big enough, just write the
+ * transaction number directly into the buffer and
+ * update its fields accordingly.
*
- * If the transaction will cross or touch buffer
- * boundaries, construct binary representation of the
- * transaction number in a buffer, and pass it to
+ * If the transaction will cross or touch buffer
+ * boundaries, construct binary representation of the
+ * transaction number in a buffer, and pass it to
* H5C2_jb__write_to_buffer().
*
* In either case, if struct_ptr->chksum_cur_msg is TRUE,
@@ -3400,7 +6258,7 @@ done:
*
******************************************************************************/
-static herr_t
+static herr_t
H5C2_jb_bjf__write_trans_num(H5C2_jbrb_t * struct_ptr,
hbool_t is_end_trans,
uint64_t trans_num)
@@ -3412,7 +6270,7 @@ H5C2_jb_bjf__write_trans_num(H5C2_jbrb_t * struct_ptr,
HDassert( struct_ptr != NULL );
HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
- HDassert( trans_num > 0 );
+ HDassert( trans_num > 0 );
/* is_end_trans must be FALSE if struct_ptr->chksum_cur_msg is TRUE.
* Throw an error if this invarient doesn't hold.
@@ -3427,11 +6285,11 @@ H5C2_jb_bjf__write_trans_num(H5C2_jbrb_t * struct_ptr,
if ( H5C2__TRANS_NUM_SIZE < struct_ptr->cur_buf_free_space ) {
/* If the transaction number will fit in the current buffer with space
- * left over, just write it directly into the buffer, and touch up the
- * ring buffer fields accordingly.
+ * left over, just write it directly into the buffer, and touch up the
+ * ring buffer fields accordingly.
*
- * This is the common case, so when we convert this function into
- * a macro, this will allow us to avoid a function call in the vast
+ * This is the common case, so when we convert this function into
+ * a macro, this will allow us to avoid a function call in the vast
* majority of cases.
*/
@@ -3441,8 +6299,19 @@ H5C2_jb_bjf__write_trans_num(H5C2_jbrb_t * struct_ptr,
HDassert( p == ((uint8_t *)(struct_ptr->head + H5C2__TRANS_NUM_SIZE)) );
- /* increment bufs_in_use as necessary */
- if ( ( struct_ptr->bufs_in_use == 0 ) ) {
+ /* increment bufs_in_use as necessary -- do this differently
+ * for aio and sio.
+ */
+ if ( ( ( struct_ptr->bufs_in_use == 0 )
+ &&
+ ( ! struct_ptr->use_aio )
+ )
+ ||
+ ( ( struct_ptr->cur_buf_free_space == struct_ptr->buf_size )
+ &&
+ ( struct_ptr->use_aio )
+ )
+ ) {
struct_ptr->bufs_in_use++;
}
@@ -3450,35 +6319,40 @@ H5C2_jb_bjf__write_trans_num(H5C2_jbrb_t * struct_ptr,
/* Update the check sum if required */
if ( struct_ptr->chksum_cur_msg ) {
- struct_ptr->msg_chksum =
- H5_checksum_metadata((const void *)(struct_ptr->head),
- H5C2__TRANS_NUM_SIZE,
+ struct_ptr->msg_chksum =
+ H5_checksum_metadata((const void *)(struct_ptr->head),
+ H5C2__TRANS_NUM_SIZE,
struct_ptr->msg_chksum);
}
/* update head pointer */
struct_ptr->head = &(struct_ptr->head[H5C2__TRANS_NUM_SIZE]);
- /* update rb_free_space */
- struct_ptr->rb_free_space -= H5C2__TRANS_NUM_SIZE;
-
/* update current buffer usage */
struct_ptr->cur_buf_free_space -= H5C2__TRANS_NUM_SIZE;
- /* update end of buffer space */
- struct_ptr->rb_space_to_rollover -= H5C2__TRANS_NUM_SIZE;
+ /* update fields used only with SIO: */
+ if( ! struct_ptr->use_aio ) {
+
+ /* update rb_free_space */
+ struct_ptr->rb_free_space -= H5C2__TRANS_NUM_SIZE;
+
+ /* update end of buffer space */
+ struct_ptr->rb_space_to_rollover -= H5C2__TRANS_NUM_SIZE;
+ }
+
if ( is_end_trans == TRUE ) {
(*struct_ptr->trans_tracking)[struct_ptr->put] = trans_num;
- }
+ }
HDassert( struct_ptr->cur_buf_free_space > 0 );
} else {
/* Here, handle the case where the write will reach the edge
- * of a buffer. This gets a bit more complex, so for now at
+ * of a buffer. This gets a bit more complex, so for now at
* least, we will construct a buffer containing a binary representation
* of the transaction number, and then call H5C2_jb__write_to_buffer().
* If this proves too costly, further optimizations will be necessary.
@@ -3492,9 +6366,11 @@ H5C2_jb_bjf__write_trans_num(H5C2_jbrb_t * struct_ptr,
HDassert( p == &(buf[H5C2__TRANS_NUM_SIZE]) );
- if ( H5C2_jb__write_to_buffer(struct_ptr, H5C2__TRANS_NUM_SIZE,
+ if ( H5C2_jb__write_to_buffer(struct_ptr,
+ H5C2__TRANS_NUM_SIZE,
(const char *)buf,
- is_end_trans, trans_num) != SUCCEED ) {
+ is_end_trans,
+ trans_num) != SUCCEED ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
"H5C2_jb__write_to_buffer() failed.")
@@ -3503,9 +6379,10 @@ H5C2_jb_bjf__write_trans_num(H5C2_jbrb_t * struct_ptr,
/* Update the check sum if required */
if ( struct_ptr->chksum_cur_msg ) {
- struct_ptr->msg_chksum = H5_checksum_metadata((const void *)(buf),
- H5C2__TRANS_NUM_SIZE,
- struct_ptr->msg_chksum);
+ struct_ptr->msg_chksum =
+ H5_checksum_metadata((const void *)(buf),
+ H5C2__TRANS_NUM_SIZE,
+ struct_ptr->msg_chksum);
}
}
@@ -3530,8 +6407,8 @@ done:
*
******************************************************************************/
-herr_t
-H5C2_jb__bin2hex(const uint8_t * buf,
+herr_t
+H5C2_jb__bin2hex(const uint8_t * buf,
char * hexdata,
size_t * hexlength,
size_t buf_size)
@@ -3540,7 +6417,7 @@ H5C2_jb__bin2hex(const uint8_t * buf,
size_t v; /* Local index variable */
uint8_t c;
char * t;
-
+
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5C2_jb__bin2hex)
t = hexdata;
@@ -3553,8 +6430,9 @@ H5C2_jb__bin2hex(const uint8_t * buf,
t[2] = ' ';
} /* end for */
+
t[3] = '\n';
- t[4] = 0;
+ t[4] = '\0';
* hexlength = v * 3 + 2;
@@ -3570,16 +6448,16 @@ H5C2_jb__bin2hex(const uint8_t * buf,
* Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
* Wednesday, February 6, 2008
*
- * Purpose: Insert the supplied comment in the journal file. This
- * call may be ignored if the journal file is machine
+ * Purpose: Insert the supplied comment in the journal file. This
+ * call may be ignored if the journal file is machine
* readable.
*
* Returns: SUCCEED on success.
*
* Changes: Turned this function into a switch board function,
- * calling either the human readable or the binary
- * journal file version of the function as indicated
- * by struct_ptr->human_readable.
+ * calling either the human readable or the binary
+ * journal file version of the function as indicated
+ * by struct_ptr->human_readable.
*
* The original version of this file has been renamed
* to H5C2_jb_hrjf__comment().
@@ -3588,14 +6466,14 @@ H5C2_jb__bin2hex(const uint8_t * buf,
*
******************************************************************************/
-herr_t
+herr_t
H5C2_jb__comment(H5C2_jbrb_t * struct_ptr,
const char * comment_ptr)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5C2_jb__comment, FAIL)
-
+
/* Check Arguments */
HDassert( struct_ptr != NULL );
HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
@@ -3632,7 +6510,7 @@ done:
* Wednesday, February 6, 2008
*
* Purpose: Verify that the supplied transaction is in progress,
- * and that at least one journal entry has been written
+ * and that at least one journal entry has been written
* under it. Then construct an end transaction message,
* and write it to the current journal buffer. Make note
* that the supplied transaction is closed, and that no
@@ -3641,9 +6519,9 @@ done:
* Returns: SUCCEED on success.
*
* Changes: Turned this function into a switch board function,
- * calling either the human readable or the binary
- * journal file version of the function as indicated
- * by struct_ptr->human_readable.
+ * calling either the human readable or the binary
+ * journal file version of the function as indicated
+ * by struct_ptr->human_readable.
*
* The original version of this file has been renamed
* to H5C2_jb_hrjf__end_transaction().
@@ -3680,8 +6558,10 @@ H5C2_jb__end_transaction(H5C2_jbrb_t * struct_ptr,
}
}
+ H5C2__JBRB__UPDATE_STATS_FOR_TRANS_COMPLETED(struct_ptr);
+
done:
-
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5C2_jb__end_transaction */
@@ -3699,9 +6579,9 @@ done:
* Returns: SUCCEED on success.
*
* Changes: Turned this function into a switch board function,
- * calling either the human readable or the binary
- * journal file version of the function as indicated
- * by struct_ptr->human_readable.
+ * calling either the human readable or the binary
+ * journal file version of the function as indicated
+ * by struct_ptr->human_readable.
*
* The original version of this file has been renamed
* to H5C2_jb_hrjf__eoa().
@@ -3710,14 +6590,14 @@ done:
*
******************************************************************************/
-herr_t
+herr_t
H5C2_jb__eoa(H5C2_jbrb_t * struct_ptr,
haddr_t eoa)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5C2_jb__eoa, FAIL)
-
+
/* Check Arguments */
HDassert( struct_ptr );
HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
@@ -3750,23 +6630,18 @@ done:
*
* Function: H5C2_jb__flush
*
- * Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
- * Wednesday, February 6, 2008
+ * Programmer: John Mainzer -- 1/14/10
*
- * Purpose: Verify that there is no transaction in progress. Then
- * flush all journal entries in the journal buffers to the
- * journal file. Do not return until all entries are on
- * disk.
+ * Purpose: Determine whether AIO is enabled, and then call the
+ * appropriate flush routine.
*
* Returns: SUCCEED on success.
*
******************************************************************************/
-herr_t
+herr_t
H5C2_jb__flush(H5C2_jbrb_t * struct_ptr)
{
- int result;
- int i;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5C2_jb__flush, FAIL)
@@ -3774,7 +6649,7 @@ H5C2_jb__flush(H5C2_jbrb_t * struct_ptr)
/* Check Arguments */
HDassert(struct_ptr);
HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC);
-
+
/* Check if transaction is in progress */
if (struct_ptr->trans_in_prog != FALSE) {
@@ -3783,257 +6658,77 @@ H5C2_jb__flush(H5C2_jbrb_t * struct_ptr)
"Attempt to flush buffers with transaction in progress.")
} /* end if */
- if (struct_ptr->get > struct_ptr->put) {
-
- /* write from get through end of buffer */
- result = HDwrite(struct_ptr->journal_file_fd,
- (*struct_ptr->buf)[struct_ptr->get],
- (struct_ptr->num_bufs - struct_ptr->get) * struct_ptr->buf_size);
-
- if ( result == -1 ) {
-
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
- "Journal file write failed(1).")
- }
-
- struct_ptr->bufs_in_use -= (struct_ptr->num_bufs - struct_ptr->get);
- struct_ptr->rb_free_space += (struct_ptr->num_bufs - struct_ptr->get) * struct_ptr->buf_size;
- struct_ptr->get = 0;
-
- } /* end if */
-
- if (struct_ptr->get < struct_ptr->put) {
+ if ( struct_ptr->use_aio ) {
- /* write from get up to, but not including, put */
- result = HDwrite(struct_ptr->journal_file_fd,
- (*struct_ptr->buf)[struct_ptr->get],
- (struct_ptr->put - struct_ptr->get) * struct_ptr->buf_size);
-
- if ( result == -1 ) {
-
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
- "Journal file write failed (2).")
- }
-
- struct_ptr->bufs_in_use -= (struct_ptr->put - struct_ptr->get);
- struct_ptr->rb_free_space += (struct_ptr->put - struct_ptr->get) * struct_ptr->buf_size;
- struct_ptr->get = struct_ptr->put;
-
- } /* end if */
-
- if ( struct_ptr->cur_buf_free_space != struct_ptr->buf_size ) {
-
- /* flush partially filled portion of current journal buffer to disk */
- result = HDwrite(struct_ptr->journal_file_fd,
- (*struct_ptr->buf)[struct_ptr->put],
- struct_ptr->buf_size - struct_ptr->cur_buf_free_space);
-
- if ( result == -1 ) {
-
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
- "Journal file write failed (3).")
- }
-
- struct_ptr->bufs_in_use--;
- struct_ptr->rb_free_space += (struct_ptr->buf_size - struct_ptr->cur_buf_free_space);
-
- } /* end if */
-
- HDassert(struct_ptr->bufs_in_use == 0);
- HDassert(struct_ptr->rb_free_space == struct_ptr->num_bufs * struct_ptr->buf_size);
-
- /* perform sync to ensure everything gets to disk before returning */
- /* Note: there is no HDfsync function, so for now, the standard
- fsync is being used. */
- if(fsync(struct_ptr->journal_file_fd) < 0)
- HGOTO_ERROR(H5E_IO, H5E_SYNCFAIL, FAIL, "Journal file sync failed.")
-
- /* record last transaction number that made it to disk */
- struct_ptr->last_trans_on_disk =
- (*struct_ptr->trans_tracking)[struct_ptr->put];
-
- /* MIKE: optimization note: don't reset to top of ring buffer.
- * instead, keep filling out current buffer so we can keep writes
- * on block boundaries.
- */
- struct_ptr->cur_buf_free_space = struct_ptr->buf_size;
- struct_ptr->rb_space_to_rollover = struct_ptr->num_bufs * struct_ptr->buf_size;
- struct_ptr->head = (*struct_ptr->buf)[0];
- struct_ptr->put = 0;
-
- /* Propogate the last transaction on in the buffers throughout the
- * transaction tracking array. */
- for(i = 0; i < struct_ptr->num_bufs; i++)
- (*struct_ptr->trans_tracking)[i] = struct_ptr->last_trans_on_disk;
-
- /* update get index */
- struct_ptr->get = struct_ptr->put;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5C2_jb__flush */
-
-
-/******************************************************************************
- *
- * Function: H5C2_jb__flush_full_buffers
- *
- * Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
- * Wednesday, February 6, 2008
- *
- * Purpose: Flush all the dirtied buffers in the ring buffer
- * starting with the buffer referenced by struct_ptr->get
- * and ending with the buffer right before the one
- * referenced by struct_ptr->put.
- *
- * Returns: SUCCEED on success.
- *
- ******************************************************************************/
-
-herr_t
-H5C2_jb__flush_full_buffers(H5C2_jbrb_t * struct_ptr)
-{
- int result;
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(H5C2_jb__flush_full_buffers, FAIL)
-
- /* this asserts that at least one buffer is in use */
- HDassert(struct_ptr->bufs_in_use > 0);
- /* write an assert to verify that at least one buffer is full */
- HDassert( (struct_ptr->put != struct_ptr->get) ||
- (struct_ptr->rb_free_space == 0) );
-
- /* flush all full, dirtied journal buffers to disk */
- if (struct_ptr->get < struct_ptr->put) {
-
- /* can write solid chunk from get up to, but not
- * including, put
- */
- result = HDwrite(struct_ptr->journal_file_fd,
- (*struct_ptr->buf)[struct_ptr->get],
- (struct_ptr->put - struct_ptr->get) *
- struct_ptr->buf_size);
-
- if ( result == -1 ) {
-
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
- "Journal file write failed (1).")
- }
-
- struct_ptr->bufs_in_use -= (struct_ptr->put - struct_ptr->get);
- struct_ptr->rb_free_space += (struct_ptr->put - struct_ptr->get) * struct_ptr->buf_size;
-
- } /* end if */
-
- else {
-
- /* write from get through end of buffer */
- result = HDwrite(struct_ptr->journal_file_fd,
- (*struct_ptr->buf)[struct_ptr->get],
- (struct_ptr->num_bufs - struct_ptr->get) * struct_ptr->buf_size);
-
- if ( result == -1 ) {
-
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
- "Journal file write failed (2).")
- }
-
- struct_ptr->bufs_in_use -= (struct_ptr->num_bufs - struct_ptr->get);
- struct_ptr->rb_free_space += (struct_ptr->num_bufs - struct_ptr->get) *
- struct_ptr->buf_size;
-
- /* if put = 0, then everything that needs to be flushed will have been
- * flushed, so we can stop here. Otherwise, need to flush all buffers
- * from the start of the ring buffer's allocated space up to, but not
- * including, the buffer indexed by put.
- */
- if (struct_ptr->put != 0) {
-
- result = HDwrite(struct_ptr->journal_file_fd,
- (*struct_ptr->buf)[0],
- (struct_ptr->put) * struct_ptr->buf_size);
-
- if ( result == -1 ) {
-
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
- "Journal file write failed(3).")
- } /* end if */
-
- struct_ptr->rb_free_space += (struct_ptr->put * struct_ptr->buf_size);
-
- } /* end if */
-
- struct_ptr->bufs_in_use -= struct_ptr->put;
-
- } /* end else */
-
- HDassert(struct_ptr->bufs_in_use <= 1);
-
- /* update get index */
- struct_ptr->get = struct_ptr->put;
-
- /* record last transaction number that made it to disk */
- if (struct_ptr->put == 0) {
-
- struct_ptr->last_trans_on_disk =
- (*struct_ptr->trans_tracking)[struct_ptr->num_bufs - 1];
+ ret_value = H5C2_jb_aio__flush(struct_ptr);
} else {
- struct_ptr->last_trans_on_disk =
- (*struct_ptr->trans_tracking)[struct_ptr->put - 1];
+ ret_value = H5C2_jb_sio__flush(struct_ptr);
}
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5C2_jb__flush_full_buffers */
+} /* H5C2_jb__flush() */
/******************************************************************************
*
* Function: H5C2_jb__get_last_transaction_on_disk
*
- * Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
- * Wednesday, February 6, 2008
+ * Programmer: JRM -- 1/20/10
*
- * Purpose: Lookup the number of the last transaction to have been
- * fully written to disk, and place its transaction
- * number in *trans_num_ptr. If no transaction has made
- * it to disk, load zero into *trans_num_ptr.
+ * Purpose: Determine whether we are using aio for journal
+ * entry writes, and then call the appropriate
+ * function.
*
* Returns: SUCCEED on success.
*
******************************************************************************/
-herr_t
+herr_t
H5C2_jb__get_last_transaction_on_disk(H5C2_jbrb_t * struct_ptr,
uint64_t * trans_num_ptr)
{
+ herr_t result;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5C2_jb__get_last_transaction_on_disk, FAIL)
-
+
/* Check Arguments */
HDassert( struct_ptr != NULL );
- HDassert( trans_num_ptr != NULL );
HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+ HDassert( trans_num_ptr != NULL );
- /* JRM: In machine readable version, lets check to see if a sync is
- * necessary, and call it only if it is.
- */
- /* perform a sync to ensure everything gets to disk before continuing */
- /* Note: there is no HDfsync function, so for now, the standard
- fsync is being used. */
- if(fsync(struct_ptr->journal_file_fd) < 0 )
- HGOTO_ERROR(H5E_IO, H5E_SYNCFAIL, FAIL, "Jounal file sync failed.")
+ if ( struct_ptr->use_aio ) {
- * trans_num_ptr = struct_ptr->last_trans_on_disk;
+ result = H5C2_jb_aio__get_last_transaction_on_disk(struct_ptr,
+ trans_num_ptr);
+
+ if ( result != SUCCEED ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_aio__get_last_transaction_on_disk failed")
+ }
+
+ } else {
+
+ result = H5C2_jb_sio__get_last_transaction_on_disk(struct_ptr,
+ trans_num_ptr);
+
+ if ( result != SUCCEED ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_sio__get_last_transaction_on_disk failed")
+ }
+ }
done:
+
FUNC_LEAVE_NOAPI(ret_value)
+
} /* end H5C2_jb__get_last_transaction_on_disk */
@@ -4044,19 +6739,19 @@ done:
* Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
* Wednesday, February 6, 2008
*
- * Purpose: Insert the supplied comment in the journal file. This
- * call may be ignored if the journal file is machine
+ * Purpose: Insert the supplied comment in the journal file. This
+ * call may be ignored if the journal file is machine
* readable.
*
* Returns: SUCCEED on success.
*
- * Changes: Renamed H5C2_jb__comment() to H5C2_jb_hrjf__comment().
+ * Changes: Renamed H5C2_jb__comment() to H5C2_jb_hrjf__comment().
*
* JRM -- 5/2/09
*
******************************************************************************/
-static herr_t
+static herr_t
H5C2_jb_hrjf__comment(H5C2_jbrb_t * struct_ptr,
const char * comment_ptr)
{
@@ -4065,15 +6760,15 @@ H5C2_jb_hrjf__comment(H5C2_jbrb_t * struct_ptr,
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5C2_jb_hrjf__comment, FAIL)
-
+
/* Check Arguments */
HDassert(struct_ptr);
HDassert(comment_ptr);
HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC);
HDassert(struct_ptr->hdf5_file_name);
- /* Verify that header message is present in journal file or ring buffer.
- * If not, write it.
+ /* Verify that header message is present in journal file or ring buffer.
+ * If not, write it.
*/
if ( struct_ptr->header_present == FALSE ) {
@@ -4086,21 +6781,39 @@ H5C2_jb_hrjf__comment(H5C2_jbrb_t * struct_ptr,
} /* end if */
temp_len = HDstrlen(comment_ptr) + 11;
- if(NULL == (temp = H5MM_malloc(temp_len + 1)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "allocation of temp buffer failed.")
+
+ if ( NULL == (temp = (char *)H5MM_malloc(temp_len + 1)) ) {
+
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \
+ "allocation of temp buffer failed.")
+ }
/* Write comment message */
HDsnprintf(temp, (temp_len + 1), "C comment %s\n", comment_ptr);
- HDassert(temp_len == HDstrlen(temp));
- if(H5C2_jb__write_to_buffer(struct_ptr, temp_len, temp, FALSE, struct_ptr->cur_trans) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, "H5C2_jb__write_to_buffer() failed.\n")
+ HDassert ( temp_len == HDstrlen(temp) );
+
+ if ( H5C2_jb__write_to_buffer(struct_ptr,
+ temp_len,
+ temp,
+ FALSE,
+ struct_ptr->cur_trans) < 0 ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "H5C2_jb__write_to_buffer() failed.\n")
+ }
done:
- if(NULL != temp) {
- temp = H5MM_xfree(temp);
- if(NULL != temp)
- HDONE_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "free of assembly buffer failed.")
+
+ if ( NULL != temp ) {
+
+ temp = (char *)H5MM_xfree(temp);
+
+ if ( NULL != temp ) {
+
+ HDONE_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \
+ "free of assembly buffer failed.")
+ }
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -4116,7 +6829,7 @@ done:
* Wednesday, February 6, 2008
*
* Purpose: Verify that the supplied transaction is in progress,
- * and that at least one journal entry has been written
+ * and that at least one journal entry has been written
* under it. Then construct an end transaction message,
* and write it to the current journal buffer. Make note
* that the supplied transaction is closed, and that no
@@ -4125,7 +6838,7 @@ done:
* Returns: SUCCEED on success.
*
* Changes: Renamed H5C2_jb__end_transaction() to
- * H5C2_jb_hrjf__end_transaction().
+ * H5C2_jb_hrjf__end_transaction().
* JRM -- 5/2/09
*
*****************************************************************************/
@@ -4142,7 +6855,7 @@ H5C2_jb_hrjf__end_transaction(H5C2_jbrb_t * struct_ptr,
/* Check Arguments */
HDassert(struct_ptr);
HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC);
-
+
/* Verify that the supplied transaction is in progress */
if ( ( struct_ptr->trans_in_prog != TRUE ) ||
( struct_ptr->cur_trans != trans_num ) ) {
@@ -4150,9 +6863,9 @@ H5C2_jb_hrjf__end_transaction(H5C2_jbrb_t * struct_ptr,
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"Transaction not in progress or bad transaction number.")
} /* end if */
-
- /* Verify that at least one journal entry has been written under
- * the current transaction
+
+ /* Verify that at least one journal entry has been written under
+ * the current transaction
*/
if ( struct_ptr->jentry_written != TRUE ) {
@@ -4165,15 +6878,15 @@ H5C2_jb_hrjf__end_transaction(H5C2_jbrb_t * struct_ptr,
HDsnprintf(temp, (size_t)25, "3 end_trans %llu\n", trans_num);
/* Write end transaction message */
- if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(temp), temp,
+ if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(temp), temp,
TRUE, trans_num ) < 0 ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
"H5C2_jb__write_to_buffer() failed.\n")
} /* end if */
- /* reset boolean flag indicating if at least one journal entry has
- * been written under transaction
+ /* reset boolean flag indicating if at least one journal entry has
+ * been written under transaction
*/
struct_ptr->jentry_written = FALSE;
@@ -4181,7 +6894,7 @@ H5C2_jb_hrjf__end_transaction(H5C2_jbrb_t * struct_ptr,
struct_ptr->trans_in_prog = FALSE;
done:
-
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5C2_jb_hrjf__end_transaction */
@@ -4198,12 +6911,12 @@ done:
*
* Returns: SUCCEED on success.
*
- * Changes: Renamed H5C2_jb__eoa() to H5C2_jb_hrjf__eoa().
+ * Changes: Renamed H5C2_jb__eoa() to H5C2_jb_hrjf__eoa().
* JRM -- 5/2/09
*
******************************************************************************/
-static herr_t
+static herr_t
H5C2_jb_hrjf__eoa(H5C2_jbrb_t * struct_ptr,
haddr_t eoa)
{
@@ -4212,26 +6925,38 @@ H5C2_jb_hrjf__eoa(H5C2_jbrb_t * struct_ptr,
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5C2_jb_hrjf__eoa, FAIL)
-
+
/* Check Arguments */
HDassert(struct_ptr);
HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC);
HDassert(struct_ptr->hdf5_file_name);
- /* Verify that header message is present in journal file or ring buffer.
- * If not, write it.
+ /* Verify that header message is present in journal file or ring buffer.
+ * If not, write it.
*/
- if(struct_ptr->header_present == FALSE ) {
- if(H5C2_jb__write_header_entry(struct_ptr) != SUCCEED)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, "H5C2_jb__write_header_entry() failed.\n")
+ if ( struct_ptr->header_present == FALSE ) {
+
+ if ( H5C2_jb__write_header_entry(struct_ptr) != SUCCEED ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "H5C2_jb__write_header_entry() failed.\n")
+ }
} /* end if */
/* Write EOA message */
HDsnprintf(temp, temp_len, "E eoa_value 0x%llx\n", eoa);
- HDassert(HDstrlen(temp) < temp_len);
- if(H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(temp), temp, FALSE, struct_ptr->cur_trans) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, "H5C2_jb__write_to_buffer() failed.\n")
+ HDassert ( HDstrlen(temp) < temp_len );
+
+ if ( H5C2_jb__write_to_buffer(struct_ptr,
+ HDstrlen(temp),
+ temp,
+ FALSE,
+ struct_ptr->cur_trans) < 0 ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "H5C2_jb__write_to_buffer() failed.\n")
+ }
done:
@@ -4254,13 +6979,13 @@ done:
*
* Returns: SUCCEED on success.
*
- * Changes: Renamed H5C2_jb__journal_entry() to
- * H5C2_jb_hrjf__journal_entry().
+ * Changes: Renamed H5C2_jb__journal_entry() to
+ * H5C2_jb_hrjf__journal_entry().
* JRM -- 5/2/09
*
******************************************************************************/
-static herr_t
+static herr_t
H5C2_jb_hrjf__journal_entry(H5C2_jbrb_t * struct_ptr,
uint64_t trans_num,
haddr_t base_addr,
@@ -4277,18 +7002,18 @@ H5C2_jb_hrjf__journal_entry(H5C2_jbrb_t * struct_ptr,
FUNC_ENTER_NOAPI(H5C2_jb_hrjf__journal_entry, FAIL)
/* Check Arguments */
- HDassert(struct_ptr);
+ HDassert(struct_ptr != NULL);
HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC);
/* Make a copy of body data */
- if ( (bodydata = H5MM_malloc(length)) == NULL ) {
+ if ( (bodydata = (uint8_t *)H5MM_malloc(length)) == NULL ) {
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \
"allocation of assembly buffer failed.");
}
HDmemcpy(bodydata, body, length);
-
+
/* Verify that the supplied transaction is in progress */
if ( ( struct_ptr->trans_in_prog != TRUE ) ||
( struct_ptr->cur_trans != trans_num ) ) {
@@ -4297,27 +7022,31 @@ H5C2_jb_hrjf__journal_entry(H5C2_jbrb_t * struct_ptr,
"Transaction not in progress or bad transaction number.")
} /* end if */
- if ( (temp = H5MM_malloc(length + 100)) == NULL ) {
+ if ( (temp = (char *)H5MM_malloc(length + 100)) == NULL ) {
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \
"allocation of assembly buffer failed.");
}
- if ( (hexdata = H5MM_malloc(length * 40)) == NULL ) {
+ if ( (hexdata = (char *)H5MM_malloc(length * 40)) == NULL ) {
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \
"allocation of assembly buffer failed.");
}
/* Write journal entry */
- HDsnprintf(temp,
+ HDsnprintf(temp,
(size_t)(length + 100),
- "2 trans_num %llu length %zu base_addr 0x%lx body ",
- trans_num,
- length,
+ "2 trans_num %llu length %zu base_addr 0x%lx body ",
+ trans_num,
+ length,
(unsigned long)base_addr);
- if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(temp), temp, FALSE, trans_num) < 0 ) {
+ if ( H5C2_jb__write_to_buffer(struct_ptr,
+ HDstrlen(temp),
+ temp,
+ FALSE,
+ trans_num) < 0 ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
"H5C2_jb__write_to_buffer() failed.\n")
@@ -4326,14 +7055,18 @@ H5C2_jb_hrjf__journal_entry(H5C2_jbrb_t * struct_ptr,
/* Convert data from binary to hex */
H5C2_jb__bin2hex(bodydata, hexdata, &hexlength, length);
- if ( H5C2_jb__write_to_buffer(struct_ptr, hexlength, hexdata, FALSE, trans_num) < 0 ) {
+ if ( H5C2_jb__write_to_buffer(struct_ptr,
+ hexlength,
+ hexdata,
+ FALSE,
+ trans_num) < 0 ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
"H5C2_jb__write_to_buffer() failed.\n")
} /* end if */
- /* Indicate that at least one journal entry has been written under
- * this transaction
+ /* Indicate that at least one journal entry has been written under
+ * this transaction
*/
if ( struct_ptr->jentry_written == FALSE ) {
@@ -4341,22 +7074,38 @@ H5C2_jb_hrjf__journal_entry(H5C2_jbrb_t * struct_ptr,
}
done:
- if(bodydata != NULL) {
- bodydata = H5MM_xfree(bodydata);
- if(bodydata != NULL)
- HDONE_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "free of assembly buffer failed.")
+
+ if ( bodydata != NULL ) {
+
+ bodydata = (uint8_t *)H5MM_xfree(bodydata);
+
+ if ( bodydata != NULL ) {
+
+ HDONE_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \
+ "free of assembly buffer failed.")
+ }
} /* end if */
- if(temp != NULL) {
- temp = H5MM_xfree(temp);
- if(temp != NULL)
- HDONE_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "free of assembly buffer failed.")
+ if ( temp != NULL ) {
+
+ temp = (char *)H5MM_xfree(temp);
+
+ if ( temp != NULL ) {
+
+ HDONE_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \
+ "free of assembly buffer failed.")
+ }
} /* end if */
- if(hexdata != NULL) {
- hexdata = H5MM_xfree(hexdata);
- if(hexdata != NULL)
- HDONE_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "free of assembly buffer failed.")
+ if ( hexdata != NULL ) {
+
+ hexdata = (char *)H5MM_xfree(hexdata);
+
+ if ( hexdata != NULL ) {
+
+ HDONE_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \
+ "free of assembly buffer failed.")
+ }
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -4372,21 +7121,21 @@ done:
* Wednesday, February 6, 2008
*
* Purpose: Verify that there is no transaction in progress, and
- * that the supplied transaction number greater than
- * the last. Then construct a start transaction message,
+ * that the supplied transaction number greater than
+ * the last. Then construct a start transaction message,
* and write it to the current journal buffer. Make note
* of the fact that the supplied transaction is in
* progress.
*
* Returns: SUCCEED on success.
*
- * Changes: Renamed H5C2_jb__start_transaction() to
- * H5C2_jb_hrjf__start_transaction().
+ * Changes: Renamed H5C2_jb__start_transaction() to
+ * H5C2_jb_hrjf__start_transaction().
* JRM -- 5/2/09
*
******************************************************************************/
-static herr_t
+static herr_t
H5C2_jb_hrjf__start_transaction(H5C2_jbrb_t * struct_ptr,
uint64_t trans_num)
@@ -4397,9 +7146,9 @@ H5C2_jb_hrjf__start_transaction(H5C2_jbrb_t * struct_ptr,
FUNC_ENTER_NOAPI(H5C2_jb_hrjf__start_transaction, FAIL)
/* Check Arguments */
- HDassert(struct_ptr);
- HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC);
-
+ HDassert( struct_ptr != NULL );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+
/* Verify that there is no transaction in progress */
if ( struct_ptr->trans_in_prog != FALSE ) {
@@ -4407,12 +7156,6 @@ H5C2_jb_hrjf__start_transaction(H5C2_jbrb_t * struct_ptr,
"Transaction already in progress.")
} /* end if */
- /* JRM: Heads up: we may relax this constraint to rquire that the
- * new transaction number is greater than the old, but possibly
- * not the next integer in sequence. Will this cause problems
- * with testing?
- */
-
/* Verify that the supplied transaction number greater than the last */
if ( (struct_ptr->cur_trans) >= trans_num ) {
@@ -4420,8 +7163,8 @@ H5C2_jb_hrjf__start_transaction(H5C2_jbrb_t * struct_ptr,
"New transaction out of sequence.")
} /* end if */
- /* Verify that header message is present in journal file or ring buffer.
- * If not, write it.
+ /* Verify that header message is present in journal file or ring buffer.
+ * If not, write it.
*/
if ( struct_ptr->header_present == FALSE ) {
@@ -4435,19 +7178,23 @@ H5C2_jb_hrjf__start_transaction(H5C2_jbrb_t * struct_ptr,
/* Write start transaction message */
HDsnprintf(temp, (size_t)150, "1 bgn_trans %llu\n", trans_num);
- if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(temp), temp,
- FALSE, trans_num) < 0 ) {
+
+ if ( H5C2_jb__write_to_buffer(struct_ptr,
+ HDstrlen(temp),
+ temp,
+ FALSE,
+ trans_num) < 0 ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
"H5C2_jb__write_to_buffer() failed.\n")
} /* end if */
-
+
/* Make note of the fact that supplied transaction is in progress */
struct_ptr->trans_in_prog = TRUE;
struct_ptr->cur_trans = trans_num;
done:
-
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5C2_jb_hrjf__start_transaction() */
@@ -4472,26 +7219,33 @@ done:
* Added the journal_magic parameter and related code.
*
* Also deleted code to write the header message.
- * Since the base address of the journal magic in
+ * Since the base address of the journal magic in
* the HDF5 file isn't available at this time, wait
* until our first real entry to write the header.
*
* JRM -- 4/16/09
* Added the sizeof_addr and sizeof_size parameters, and
- * associated code. These parameters must contain the
+ * associated code. These parameters must contain the
* values of the same name in the instance of H5F_file_t
* associated with the target file.
*
+ * JRM -- 12/7/09
+ * Added initialization for posix aio fields in
+ * H5C2_jbrb_t.
+ *
+ * JRM -- 2/21/10
+ * Added call to H5C2_jb_stats__reset();
+ *
******************************************************************************/
-herr_t
-H5C2_jb__init(H5C2_jbrb_t * struct_ptr,
+herr_t
+H5C2_jb__init(H5C2_jbrb_t * struct_ptr,
const int32_t journal_magic,
- const char * HDF5_file_name,
- const char * journal_file_name,
- size_t buf_size,
- int num_bufs,
- hbool_t use_aio,
+ const char * HDF5_file_name,
+ const char * journal_file_name,
+ size_t buf_size,
+ int num_bufs,
+ hbool_t use_aio,
hbool_t human_readable,
size_t sizeof_addr,
size_t sizeof_size)
@@ -4517,6 +7271,7 @@ H5C2_jb__init(H5C2_jbrb_t * struct_ptr,
struct_ptr->num_bufs = num_bufs;
struct_ptr->buf_size = buf_size;
struct_ptr->bufs_in_use = 0;
+ struct_ptr->writes_in_progress = 0;
struct_ptr->jvers = H5C2__JOURNAL_VERSION;
struct_ptr->get = 0;
struct_ptr->put = 0;
@@ -4529,6 +7284,8 @@ H5C2_jb__init(H5C2_jbrb_t * struct_ptr,
struct_ptr->msg_chksum = 0;
struct_ptr->journal_is_empty = TRUE;
struct_ptr->cur_trans = 0;
+ struct_ptr->last_trans_queued = 0;
+ struct_ptr->last_trans_written = 0;
struct_ptr->last_trans_on_disk = 0;
struct_ptr->trans_in_prog = FALSE;
struct_ptr->jname = HDstrdup(journal_file_name);
@@ -4537,7 +7294,7 @@ H5C2_jb__init(H5C2_jbrb_t * struct_ptr,
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \
"allocation of space for copy of journal_file_name failed.");
- }
+ }
struct_ptr->hdf5_file_name = HDstrdup(HDF5_file_name);
@@ -4545,40 +7302,57 @@ H5C2_jb__init(H5C2_jbrb_t * struct_ptr,
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \
"allocation of space for copy of HDF5_file_name failed.");
- }
+ }
struct_ptr->header_present = FALSE;
struct_ptr->cur_buf_free_space = buf_size;
- struct_ptr->rb_space_to_rollover = num_bufs * buf_size;
- struct_ptr->rb_free_space = num_bufs * buf_size;
+ struct_ptr->rb_space_to_rollover = (size_t)num_bufs * buf_size;
+ struct_ptr->rb_free_space = (size_t)num_bufs * buf_size;
struct_ptr->head = NULL;
struct_ptr->trans_tracking = NULL;
+ struct_ptr->aio_ctl_blks = NULL;
+ struct_ptr->aio_next_buf_offset = (off_t)0;
+#if 1
+ struct_ptr->use_aio_fsync = use_aio;
+#else
+ struct_ptr->use_aio_fsync = FALSE;
+#endif
+ struct_ptr->aio_sync_q_head = NULL;
+ struct_ptr->aio_sync_q_tail = NULL;
+ struct_ptr->aio_sync_q_len = 0;
struct_ptr->buf = NULL;
-
-
+
/* Open journal file */
- struct_ptr->journal_file_fd =
+#if 0 /* JRM */
+ HDfprintf(stdout, "%s: journal file name = %s.\n", FUNC, journal_file_name);
+#endif /* JRM */
+ struct_ptr->journal_file_fd =
HDopen(journal_file_name, O_WRONLY|O_CREAT|O_EXCL, 0777);
if ( struct_ptr->journal_file_fd == -1) {
+#if 0 /* JRM */
+ HDfprintf(stdout, "%s: errno = %d (%s).\n",
+ FUNC, errno, strerror(errno));
+#endif /* JRM */
HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL, \
"Can't create journal file. Does it already exist?")
} /* end if */
-
+
/* Allocate space for the ring buffer's journal buffer pointers */
- struct_ptr->buf = H5MM_malloc(struct_ptr->num_bufs * sizeof(char *));
+ struct_ptr->buf = (char *((*)[]))
+ H5MM_malloc((size_t)(struct_ptr->num_bufs) * sizeof(char *));
if ( struct_ptr->buf == NULL ) {
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \
"allocation of buf pointer array failed.");
} /* end if */
-
+
/* Allocate space for journal buffers */
- (*struct_ptr->buf)[0] =
- H5MM_malloc(struct_ptr->buf_size * struct_ptr->num_bufs);
+ (*struct_ptr->buf)[0] = (char *)
+ H5MM_malloc(struct_ptr->buf_size * (size_t)(struct_ptr->num_bufs));
if ( (*struct_ptr->buf)[0] == NULL ) {
@@ -4586,38 +7360,72 @@ H5C2_jb__init(H5C2_jbrb_t * struct_ptr,
"allocation of buffers failed.");
} /* end if */
- /* Allocate space for the purposes of tracking the last
- * transaction on disk
+ /* Allocate space for the purposes of tracking the last
+ * transaction on disk
*/
- struct_ptr->trans_tracking =
- H5MM_malloc(struct_ptr->num_bufs * sizeof(unsigned long));
+ struct_ptr->trans_tracking = (uint64_t (*)[])
+ H5MM_malloc((size_t)(struct_ptr->num_bufs) * sizeof(uint64_t));
if ( struct_ptr->trans_tracking == NULL ) {
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \
"allocation of trans_tracking failed.");
} /* end if */
-
+
/* Initialize the transaction tracking array */
for (i=0; i<struct_ptr->num_bufs; i++)
{
(*struct_ptr->trans_tracking)[i] = 0;
}
-
- /* Make journal buffer pointers point to the right location in
- * chunk of allocated memory above
+
+ /* Make journal buffer pointers point to the right location in
+ * chunk of allocated memory above
*/
for ( i = 1; i < struct_ptr->num_bufs; i++ )
{
- (*struct_ptr->buf)[i] =
- &((*struct_ptr->buf)[0])[i * struct_ptr->buf_size];
+ (*struct_ptr->buf)[i] =
+ &((*struct_ptr->buf)[0])[i * (int)(struct_ptr->buf_size)];
}
/* Define head pointer to point at where we are writing to in the buffer */
struct_ptr->head = (*struct_ptr->buf)[struct_ptr->put];
-done:
+ /* if we are using aio, allocate the array of struct aiocb used to manage
+ * and track the asychronous writes.
+ */
+ if ( struct_ptr->use_aio ) {
+
+ struct_ptr->aio_ctl_blks = (struct aiocb (*)[])
+ H5MM_malloc(sizeof(struct aiocb) *
+ (size_t)(struct_ptr->num_bufs));
+ if ( struct_ptr->aio_ctl_blks == NULL ) {
+
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \
+ "allocation of aio_ctl_blks failed.");
+ }
+
+ /* Set the aio_fildes field of each aio control block to -1. We
+ * use this value to indicate that no asynchronous write is currently
+ * in progress.
+ *
+ * Don't bother with zeroing out the blocks now -- we will do this
+ * to each block just prior to use.
+ */
+ for ( i = 0; i < struct_ptr->num_bufs; i++ )
+ {
+ ((*(struct_ptr->aio_ctl_blks))[i]).aio_fildes = -1;
+ }
+ }
+
+ if ( H5C2_jb_stats__reset(struct_ptr) != SUCCEED ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_stats__reset() failed.")
+ }
+
+done:
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5C2_jb__init */
@@ -4638,9 +7446,9 @@ done:
* Returns: SUCCEED on success.
*
* Changes: Turned this function into a switch board function,
- * calling either the human readable or the binary
- * journal file version of the function as indicated
- * by struct_ptr->human_readable.
+ * calling either the human readable or the binary
+ * journal file version of the function as indicated
+ * by struct_ptr->human_readable.
*
* The original version of this file has been renamed
* to H5C2_jb_hrjf__journal_entry().
@@ -4649,7 +7457,7 @@ done:
*
******************************************************************************/
-herr_t
+herr_t
H5C2_jb__journal_entry(H5C2_jbrb_t * struct_ptr,
uint64_t trans_num,
haddr_t base_addr,
@@ -4666,7 +7474,7 @@ H5C2_jb__journal_entry(H5C2_jbrb_t * struct_ptr,
if ( struct_ptr->human_readable ) {
- if ( H5C2_jb_hrjf__journal_entry(struct_ptr, trans_num, base_addr,
+ if ( H5C2_jb_hrjf__journal_entry(struct_ptr, trans_num, base_addr,
length, body) != SUCCEED ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
@@ -4691,14 +7499,796 @@ done:
/******************************************************************************
*
+ * Function: H5C2_jb_sio__flush
+ *
+ * Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
+ * Wednesday, February 6, 2008
+ *
+ * Purpose: Verify that there is no transaction in progress. Then
+ * flush all journal entries in the journal buffers to the
+ * journal file. Do not return until all entries are on
+ * disk.
+ *
+ * Returns: SUCCEED on success.
+ *
+ * Changes: Renamed function from H5C2_jb__flush() to
+ * H5C2_jb_sio__flush(). Added code to verify that
+ * SIO is selected.
+ *
+ * JRM -- 1/14/10
+ *
+ ******************************************************************************/
+
+static herr_t
+H5C2_jb_sio__flush(H5C2_jbrb_t * struct_ptr)
+{
+ int result;
+ int i;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5C2_jb_sio__flush, FAIL)
+
+ /* Check Arguments */
+ HDassert(struct_ptr);
+ HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC);
+ HDassert(struct_ptr->use_aio == FALSE);
+
+ /* Check if transaction is in progress */
+
+ if (struct_ptr->trans_in_prog != FALSE) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "Attempt to flush buffers with transaction in progress.")
+ } /* end if */
+
+ if (struct_ptr->get > struct_ptr->put) {
+
+ /* write from get through end of buffer */
+ result = HDwrite(struct_ptr->journal_file_fd,
+ (*struct_ptr->buf)[struct_ptr->get],
+ (size_t)(struct_ptr->num_bufs - struct_ptr->get) *
+ struct_ptr->buf_size);
+
+ if ( result == -1 ) {
+
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
+ "Journal file write failed(1).")
+ }
+
+ struct_ptr->bufs_in_use -= (struct_ptr->num_bufs - struct_ptr->get);
+ struct_ptr->rb_free_space +=
+ (size_t)(struct_ptr->num_bufs - struct_ptr->get) * struct_ptr->buf_size;
+ struct_ptr->get = 0;
+
+ } /* end if */
+
+ if (struct_ptr->get < struct_ptr->put) {
+
+ /* write from get up to, but not including, put */
+ result = HDwrite(struct_ptr->journal_file_fd,
+ (*struct_ptr->buf)[struct_ptr->get],
+ (size_t)(struct_ptr->put - struct_ptr->get) *
+ struct_ptr->buf_size);
+
+ if ( result == -1 ) {
+
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
+ "Journal file write failed (2).")
+ }
+
+ struct_ptr->bufs_in_use -= (struct_ptr->put - struct_ptr->get);
+ struct_ptr->rb_free_space +=
+ (size_t)(struct_ptr->put - struct_ptr->get) *
+ struct_ptr->buf_size;
+ struct_ptr->get = struct_ptr->put;
+
+ } /* end if */
+
+ if ( struct_ptr->cur_buf_free_space != struct_ptr->buf_size ) {
+
+ /* flush partially filled portion of current journal buffer to disk */
+ result = HDwrite(struct_ptr->journal_file_fd,
+ (*struct_ptr->buf)[struct_ptr->put],
+ struct_ptr->buf_size - struct_ptr->cur_buf_free_space);
+
+ if ( result == -1 ) {
+
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
+ "Journal file write failed (3).")
+ }
+
+ struct_ptr->bufs_in_use--;
+ struct_ptr->rb_free_space +=
+ (struct_ptr->buf_size - struct_ptr->cur_buf_free_space);
+
+ } /* end if */
+
+ HDassert(struct_ptr->bufs_in_use == 0);
+ HDassert(struct_ptr->rb_free_space ==
+ (size_t)(struct_ptr->num_bufs) * struct_ptr->buf_size);
+
+ /* perform sync to ensure everything gets to disk before returning
+ *
+ * Note: there is no HDfsync function, so for now, the standard
+ * fsync is being used.
+ */
+ if ( fsync(struct_ptr->journal_file_fd) < 0 ) {
+
+ HGOTO_ERROR(H5E_IO, H5E_SYNCFAIL, FAIL, "Journal file sync failed.")
+ }
+
+ H5C2__JBRB__UPDATE_STATS_FOR_CALL_TO_FSYNC(struct_ptr)
+
+ /* record last transaction number that made it to disk */
+ struct_ptr->last_trans_on_disk =
+ (*struct_ptr->trans_tracking)[struct_ptr->put];
+
+ /* MIKE: optimization note: don't reset to top of ring buffer.
+ * instead, keep filling out current buffer so we can keep writes
+ * on block boundaries.
+ */
+ struct_ptr->cur_buf_free_space = struct_ptr->buf_size;
+ struct_ptr->rb_space_to_rollover =
+ (size_t)(struct_ptr->num_bufs) * struct_ptr->buf_size;
+ struct_ptr->head = (*struct_ptr->buf)[0];
+ struct_ptr->put = 0;
+
+ /* Propogate the last transaction on in the buffers throughout the
+ * transaction tracking array. */
+ for ( i = 0; i < struct_ptr->num_bufs; i++ ) {
+
+ (*struct_ptr->trans_tracking)[i] = struct_ptr->last_trans_on_disk;
+ }
+
+ /* update get index */
+ struct_ptr->get = struct_ptr->put;
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5C2_jb_sio__flush */
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb_sio__flush_full_buffers
+ *
+ * Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
+ * Wednesday, February 6, 2008
+ *
+ * Purpose: Flush all the dirtied buffers in the ring buffer
+ * starting with the buffer referenced by struct_ptr->get
+ * and ending with the buffer right before the one
+ * referenced by struct_ptr->put.
+ *
+ * Returns: SUCCEED on success.
+ *
+ * Changes: Changed name from H5C2_jb__flush_full_buffers() to
+ * H5C2_jb_sio__flush_full_buffers().
+ *
+ * JRM -- 1/14/10
+ *
+ ******************************************************************************/
+
+static herr_t
+H5C2_jb_sio__flush_full_buffers(H5C2_jbrb_t * struct_ptr)
+{
+ int result;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5C2_jb_sio__flush_full_buffers, FAIL)
+
+ /* this asserts that at least one buffer is in use */
+ HDassert( struct_ptr->bufs_in_use > 0 );
+
+ /* write an assert to verify that at least one buffer is full */
+ HDassert( (struct_ptr->put != struct_ptr->get) ||
+ (struct_ptr->rb_free_space == 0) );
+
+ /* flush all full, dirtied journal buffers to disk */
+ if ( struct_ptr->get < struct_ptr->put ) {
+
+ /* can write solid chunk from get up to, but not
+ * including, put
+ */
+ result = HDwrite(struct_ptr->journal_file_fd,
+ (*struct_ptr->buf)[struct_ptr->get],
+ (size_t)(struct_ptr->put - struct_ptr->get) *
+ struct_ptr->buf_size);
+
+ if ( result == -1 ) {
+
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
+ "Journal file write failed (1).")
+ }
+
+ struct_ptr->bufs_in_use -= (struct_ptr->put - struct_ptr->get);
+ struct_ptr->rb_free_space +=
+ (size_t)(struct_ptr->put - struct_ptr->get) *
+ struct_ptr->buf_size;
+
+ } /* end if */
+
+ else {
+
+ /* write from get through end of buffer */
+ result = HDwrite(struct_ptr->journal_file_fd,
+ (*struct_ptr->buf)[struct_ptr->get],
+ (size_t)(struct_ptr->num_bufs - struct_ptr->get) *
+ struct_ptr->buf_size);
+
+ if ( result == -1 ) {
+
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
+ "Journal file write failed (2).")
+ }
+
+ struct_ptr->bufs_in_use -= (struct_ptr->num_bufs - struct_ptr->get);
+ struct_ptr->rb_free_space +=
+ (size_t)(struct_ptr->num_bufs - struct_ptr->get) *
+ struct_ptr->buf_size;
+
+ /* if put = 0, then everything that needs to be flushed will have been
+ * flushed, so we can stop here. Otherwise, need to flush all buffers
+ * from the start of the ring buffer's allocated space up to, but not
+ * including, the buffer indexed by put.
+ */
+ if (struct_ptr->put != 0) {
+
+ result = HDwrite(struct_ptr->journal_file_fd,
+ (*struct_ptr->buf)[0],
+ (size_t)(struct_ptr->put) * struct_ptr->buf_size);
+
+ if ( result == -1 ) {
+
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
+ "Journal file write failed(3).")
+ } /* end if */
+
+ struct_ptr->rb_free_space +=
+ ((size_t)(struct_ptr->put) * struct_ptr->buf_size);
+
+ } /* end if */
+
+ struct_ptr->bufs_in_use -= struct_ptr->put;
+
+ } /* end else */
+
+ HDassert(struct_ptr->bufs_in_use <= 1);
+
+ /* update get index */
+ struct_ptr->get = struct_ptr->put;
+
+ /* record last transaction number that made it to disk */
+ if (struct_ptr->put == 0) {
+
+ struct_ptr->last_trans_on_disk =
+ (*struct_ptr->trans_tracking)[struct_ptr->num_bufs - 1];
+
+ } else {
+
+ struct_ptr->last_trans_on_disk =
+ (*struct_ptr->trans_tracking)[struct_ptr->put - 1];
+ }
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5C2_jb_sio__flush_full_buffers */
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb_sio__get_last_transaction_on_disk
+ *
+ * Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
+ * Wednesday, February 6, 2008
+ *
+ * Purpose: Lookup the number of the last transaction to have been
+ * fully written to disk, and place its transaction
+ * number in *trans_num_ptr. If no transaction has made
+ * it to disk, load zero into *trans_num_ptr.
+ *
+ * Returns: SUCCEED on success.
+ *
+ * Changes: Renamed the function from
+ *
+ * H5C2_jb__get_last_transaction_on_disk()
+ *
+ * to
+ *
+ * H5C2_jb_sio__get_last_transaction_on_disk()
+ *
+ * and added some additional sanity checks.
+ *
+ * JRM -- 1/20/10
+ *
+ ******************************************************************************/
+
+static herr_t
+H5C2_jb_sio__get_last_transaction_on_disk(H5C2_jbrb_t * struct_ptr,
+ uint64_t * trans_num_ptr)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5C2_jb_sio__get_last_transaction_on_disk, FAIL)
+
+ /* Check Arguments */
+ HDassert( struct_ptr != NULL );
+ HDassert( trans_num_ptr != NULL );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+
+ /* JRM: In machine readable version, lets check to see if a sync is
+ * necessary, and call it only if it is.
+ */
+ /* perform a sync to ensure everything gets to disk before continuing */
+ /* Note: there is no HDfsync function, so for now, the standard
+ fsync is being used. */
+ if(fsync(struct_ptr->journal_file_fd) < 0 ) {
+
+ HGOTO_ERROR(H5E_IO, H5E_SYNCFAIL, FAIL, "Jounal file sync failed.")
+ }
+
+ H5C2__JBRB__UPDATE_STATS_FOR_CALL_TO_FSYNC(struct_ptr)
+
+ * trans_num_ptr = struct_ptr->last_trans_on_disk;
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5C2_jb_sio__get_last_transaction_on_disk */
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb_sio__write_to_buffer
+ *
+ * Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
+ * Wednesday, February 6, 2008
+ *
+ * Purpose: Put the contents of data into the journal buffers. This
+ * is done as follows: While the data to be written is
+ * larger than the amount of space left in the ring buffer,
+ * the ring buffer is filled to capacity with data and
+ * flushed. This repeats until the unwritten data remaining
+ * can fit in the ring buffer without having to loop around
+ * to the top.
+ *
+ * At this point, the rest of the data can just be written
+ * without having to break it up further. In the event
+ * the data covers more than one journal buffer, the get
+ * and put indices are updated to state this fact. Any
+ * journal buffers that were filled during the write are
+ * flushed.
+ *
+ * Returns: SUCCEED on success.
+ *
+ * Changes: Changed the name of the function from
+ * H5C2_jb__write_to_buffer() to
+ * H5C2_jb_sio__write_to_buffer(). Added assert to
+ * verify that struct_ptr->use_aio is FALSE.
+ *
+ * JRM -- 1/14/10
+ *
+ ******************************************************************************/
+
+static herr_t
+H5C2_jb_sio__write_to_buffer(H5C2_jbrb_t * struct_ptr,
+ size_t size,
+ const char * data,
+ hbool_t is_end_trans,
+ uint64_t trans_num)
+{
+ herr_t ret_value = SUCCEED;
+ uint64_t track_last_trans = 0;
+ int oldput = 0;
+ int i;
+
+ FUNC_ENTER_NOAPI(H5C2_jb_sio__write_to_buffer, FAIL)
+
+ /* Check Arguments */
+ HDassert(struct_ptr);
+ HDassert(data);
+ HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC);
+ HDassert(struct_ptr->use_aio == FALSE);
+ HDassert( ( struct_ptr->human_readable == FALSE ) ||
+ ( HDstrlen(data) == size ) );
+ HDassert(struct_ptr->rb_space_to_rollover <=
+ ((size_t)(struct_ptr->num_bufs)) * struct_ptr->buf_size);
+ HDassert(struct_ptr->rb_space_to_rollover > 0);
+
+ /* If the data size exceeds the bounds of the ring buffer's allocated
+ * memory, loop around to top
+ */
+ if (size >= struct_ptr->rb_space_to_rollover) {
+
+ while (size >= struct_ptr->rb_space_to_rollover) {
+
+ /* Assertions */
+ HDassert(size != 0);
+ HDassert( ( struct_ptr->human_readable == FALSE ) ||
+ ( HDstrlen(data) >= struct_ptr->rb_space_to_rollover ) );
+
+ /* fill up remaining space in the ring buffer */
+ HDmemcpy(struct_ptr->head, data, struct_ptr->rb_space_to_rollover);
+
+ /* move head to point to start of ring buffer */
+ struct_ptr->head = (*struct_ptr->buf)[0];
+
+ /* make note of last transaction on disk */
+ track_last_trans = (*struct_ptr->trans_tracking)[struct_ptr->put];
+
+ /* update rb_free_space */
+ struct_ptr->rb_free_space -= struct_ptr->rb_space_to_rollover;
+
+ /* Fill out the remainder of the trans_tracking array with
+ the most recent transaction in the array.*/
+ (*struct_ptr->trans_tracking)[0] = track_last_trans;
+ for (i=struct_ptr->put; i<struct_ptr->num_bufs; i++)
+ {
+ (*struct_ptr->trans_tracking)[i] = track_last_trans;
+ }
+
+ /* reset put index */
+ struct_ptr->put = 0;
+
+ /* update bufs_in_use as necessary */
+ struct_ptr->bufs_in_use = struct_ptr->num_bufs - struct_ptr->get;
+
+ /* check to see if trans_tracking needs to be updated. If so,
+ * then update it
+ */
+ if ((size == struct_ptr->rb_space_to_rollover) &&
+ (is_end_trans == TRUE)) {
+
+ (*struct_ptr->trans_tracking)[struct_ptr->num_bufs - 1]
+ = trans_num;
+ (*struct_ptr->trans_tracking)[0] = trans_num;
+ }
+
+ /* flush buffers */
+ if ( H5C2_jb_sio__flush_full_buffers(struct_ptr) < 0 ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "H5C2_jb_sio__flush_full_buffers() failed.\n")
+ }
+
+ /* update remaining size of data to be written */
+ size = size - struct_ptr->rb_space_to_rollover;
+
+ /* update the data pointer to point to the remaining data to be
+ * written
+ */
+ data = &data[struct_ptr->rb_space_to_rollover];
+
+ /* update the amount of space left at end of ring buffer */
+ struct_ptr->rb_space_to_rollover =
+ struct_ptr->buf_size * (size_t)(struct_ptr->num_bufs);
+
+ /* update the amount of space in the current buffer */
+ struct_ptr->cur_buf_free_space = struct_ptr->buf_size;
+
+ } /* end while */
+ } /* end if */
+
+ /* If the size of the data exceeds the bounds of a single journal
+ * buffer, will write into multiple
+ */
+ if (size > struct_ptr->cur_buf_free_space) {
+
+ HDassert(struct_ptr->cur_buf_free_space != 0);
+
+ /* write data into journal buffers */
+ HDmemcpy(struct_ptr->head, data, size);
+
+ /* update head pointer */
+ struct_ptr->head = &struct_ptr->head[size];
+
+ /* make note of last transaction on disk */
+ track_last_trans = (*struct_ptr->trans_tracking)[struct_ptr->put];
+ oldput = struct_ptr->put;
+
+ /* update rb_free_space */
+ struct_ptr->rb_free_space -= size;
+
+ /* update put index */
+ struct_ptr->put += (int)
+ ((size - struct_ptr->cur_buf_free_space)/(struct_ptr->buf_size) + 1);
+
+ /* Drag the last transaction in a filled buffer value residing in the
+ old put location through the trans_tracking array to the new
+ corresponding put position. */
+ for (i=oldput; i<struct_ptr->put+1; i++)
+ {
+ (*struct_ptr->trans_tracking)[i] = track_last_trans;
+ }
+
+ /* update current buffer usage */
+ struct_ptr->cur_buf_free_space =
+ struct_ptr->rb_space_to_rollover - size -
+ (((size_t)(struct_ptr->num_bufs)) - ((size_t)(struct_ptr->put + 1))) *
+ (struct_ptr->buf_size );
+
+ /* update bufs_in_use as necessary */
+ struct_ptr->bufs_in_use = struct_ptr->put - struct_ptr->get;
+ if (struct_ptr->cur_buf_free_space < struct_ptr->buf_size) {
+
+ struct_ptr->bufs_in_use++;
+ }
+
+ /* check to see if trans_tracking needs to be updated. If so,
+ * then update it
+ */
+ if ( is_end_trans == TRUE ) {
+
+ if ( struct_ptr->cur_buf_free_space == struct_ptr->buf_size ) {
+
+ (*struct_ptr->trans_tracking)[struct_ptr->put - 1] = trans_num;
+
+ } else {
+
+ (*struct_ptr->trans_tracking)[struct_ptr->put] = trans_num;
+ }
+
+ } /* end if */
+
+ /* flush buffers */
+ if ( H5C2_jb_sio__flush_full_buffers(struct_ptr) < 0 ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "H5C2_jb_siok__flush_full_buffers() failed.\n")
+ }
+
+ /* update space left at end of ring buffer */
+ struct_ptr->rb_space_to_rollover -= size;
+
+ } /* end if */
+
+ /* if the data can fit in the remaining space in the current journal
+ * buffer indexed by put
+ */
+ else if (size > 0) {
+
+ HDassert(size <= struct_ptr->cur_buf_free_space);
+
+ /* write data into journal buffer */
+ HDmemcpy(struct_ptr->head, data, size);
+
+ /* increment bufs_in_use as necessary */
+ if ( ( struct_ptr->bufs_in_use == 0 ) ) {
+
+ struct_ptr->bufs_in_use++;
+ }
+
+ /* update head pointer */
+ struct_ptr->head = &struct_ptr->head[size];
+
+ /* update rb_free_space */
+ struct_ptr->rb_free_space -= size;
+
+ /* update current buffer usage */
+ struct_ptr->cur_buf_free_space -= size;
+
+ /* update end of buffer space */
+ struct_ptr->rb_space_to_rollover -= size;
+
+ /* check to see if trans_tracking needs to be updated. If so,
+ then update it */
+ if (is_end_trans == TRUE) {
+
+ (*struct_ptr->trans_tracking)[struct_ptr->put]
+ = trans_num;
+ } /* end if */
+
+ /* if buffer is full, flush it, and loop to the top of the
+ * ring buffer if at the end.
+ */
+ if (struct_ptr->cur_buf_free_space == 0) {
+
+ if ( struct_ptr->put != (struct_ptr->num_bufs - 1) ) {
+ struct_ptr->put += 1;
+
+ /* Drag trans_tracking value into next buffer */
+ (*struct_ptr->trans_tracking)[struct_ptr->put] =
+ (*struct_ptr->trans_tracking)[struct_ptr->put - 1];
+
+ } /* end if */
+
+ else {
+
+ struct_ptr->put = 0;
+
+ /* Drag trans_tracking value into next buffer */
+ (*struct_ptr->trans_tracking)[0]
+ = (*struct_ptr->trans_tracking)[struct_ptr->num_bufs - 1];
+
+ /* reset head pointer and free space values */
+ struct_ptr->head = (*struct_ptr->buf)[0];
+ struct_ptr->rb_space_to_rollover =
+ struct_ptr->buf_size * (size_t)(struct_ptr->num_bufs);
+
+ } /* end else */
+
+ if ( H5C2_jb_sio__flush_full_buffers(struct_ptr) < 0 ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "H5C2_jb_sio__flush_full_buffers() failed.\n")
+ } /* end if */
+
+ struct_ptr->cur_buf_free_space = struct_ptr->buf_size;
+
+ } /* end if */
+
+ } /* end else */
+
+ HDassert(struct_ptr->bufs_in_use <= struct_ptr->num_bufs);
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5C2_jb_sio__write_to_buffer */
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb_stats__dump
+ *
+ * Programmer: JRM -- 2/21/20
+ *
+ * Purpose: If H5C2__JBRB__COLLECT_STATS is TRUE, dump the
+ * contents of the journal buffer ring buffer stats
+ * fields to stdout.
+ *
+ * If H5C2__JBRB__COLLECT_STATS is FALSE, do nothing.
+ *
+ * Returns: void
+ *
+ * Changes: None.
+ *
+ ******************************************************************************/
+
+herr_t
+H5C2_jb_stats__dump(H5C2_jbrb_t * struct_ptr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+#if H5C2__JBRB__COLLECT_STATS
+ double calls_to_aio_error_per_async_sync_await = 0.0;
+#endif /* H5C2__JBRB__COLLECT_STATS */
+
+ FUNC_ENTER_NOAPI(H5C2_jb_stats__dump, FAIL)
+
+ /* This would normally be an assert, but we need to use an HGOTO_ERROR
+ * call to shut up the compiler.
+ */
+ if ( ( struct_ptr == NULL ) ||
+ ( struct_ptr->magic != H5C2__H5C2_JBRB_T_MAGIC ) ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad struct_ptr on entry")
+ }
+
+#if H5C2__JBRB__COLLECT_STATS
+ if ( struct_ptr->async_syncs_completed_by_await > 0 ) {
+
+ calls_to_aio_error_per_async_sync_await =
+ (double)(struct_ptr->calls_to_aio_error_awaiting_sync) /
+ (double)(struct_ptr->async_syncs_completed_by_await);
+ }
+
+ HDfprintf(stdout,
+ "buf count/size = %lld/%lld, trans completed = %lld\n",
+ (long long)(struct_ptr->num_bufs),
+ (long long)(struct_ptr->buf_size),
+ (long long)(struct_ptr->transactions_completed));
+ HDfprintf(stdout,
+ "buf writes queued full/part/total = %lld/%lld/%lld\n",
+ (long long)(struct_ptr->full_buf_writes_queued),
+ (long long)(struct_ptr->partial_buf_writes_queued),
+ (long long)(struct_ptr->buf_writes_queued));
+
+ HDfprintf(stdout,
+ "buf writes completed by test/await/total = %lld/%lld/%lld\n",
+ (long long)(struct_ptr->buf_writes_completed_by_test),
+ (long long)(struct_ptr->buf_writes_completed_by_await),
+ (long long)(struct_ptr->buf_writes_completed));
+
+ HDfprintf(stdout,
+ "async syncs queued = %lld, max sync q len = %lld.\n",
+ (long long)(struct_ptr->async_syncs_queued),
+ (long long)(struct_ptr->max_sync_q_len));
+
+ HDfprintf(stdout,
+ "async syncs completed by test/await/total = %lld/%lld/%lld.\n",
+ (long long)(struct_ptr->async_syncs_completed_by_test),
+ (long long)(struct_ptr->async_syncs_completed_by_await),
+ (long long)(struct_ptr->async_syncs_completed));
+
+ HDfprintf(stdout,
+ "ave calls to aio_error() per aio_fsync() await = %f.\n",
+ calls_to_aio_error_per_async_sync_await);
+
+ HDfprintf(stdout, "calls to fsync() = %lld.\n",
+ (long long)(struct_ptr->calls_to_fsync));
+#endif /* H5C2__JBRB__COLLECT_STATS */
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C2_jb_stats__dump() */
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb_stats__reset
+ *
+ * Programmer: JRM -- 2/21/20
+ *
+ * Purpose: If H5C2__JBRB__COLLECT_STATS is TRUE, reset the
+ * stats fields in the instance of H5C2_jbrb_t
+ * pointed to by struct_ptr.
+ *
+ * If H5C2__JBRB__COLLECT_STATS is FALSE, do nothing.
+ *
+ * Returns: void
+ *
+ * Changes: None.
+ *
+ ******************************************************************************/
+
+herr_t
+H5C2_jb_stats__reset(H5C2_jbrb_t * struct_ptr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5C2_jb_stats__reset, FAIL)
+
+ /* This would normally be an assert, but we need to use an HGOTO_ERROR
+ * call to shut up the compiler.
+ */
+ if ( ( struct_ptr == NULL ) ||
+ ( struct_ptr->magic != H5C2__H5C2_JBRB_T_MAGIC ) ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad struct_ptr")
+ }
+
+#if H5C2__JBRB__COLLECT_STATS
+ struct_ptr->transactions_completed = 0;
+ struct_ptr->buf_writes_queued = 0;
+ struct_ptr->full_buf_writes_queued = 0;
+ struct_ptr->partial_buf_writes_queued = 0;
+ struct_ptr->buf_writes_completed = 0;
+ struct_ptr->buf_writes_completed_by_test = 0;
+ struct_ptr->buf_writes_completed_by_await = 0;
+ struct_ptr->async_syncs_queued = 0;
+ struct_ptr->async_syncs_completed = 0;
+ struct_ptr->async_syncs_completed_by_test = 0;
+ struct_ptr->async_syncs_completed_by_await = 0;
+ struct_ptr->calls_to_aio_error_awaiting_sync = 0;
+ struct_ptr->max_sync_q_len = 0;
+ struct_ptr->calls_to_fsync = 0;
+#endif /* H5C2__JBRB__COLLECT_STATS */
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C2_jb_stats__reset() */
+
+
+/******************************************************************************
+ *
* Function: H5C2_jb__start_transaction
*
* Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
* Wednesday, February 6, 2008
*
* Purpose: Verify that there is no transaction in progress, and
- * that the supplied transaction number greater than
- * the last. Then construct a start transaction message,
+ * that the supplied transaction number greater than
+ * the last. Then construct a start transaction message,
* and write it to the current journal buffer. Make note
* of the fact that the supplied transaction is in
* progress.
@@ -4706,9 +8296,9 @@ done:
* Returns: SUCCEED on success.
*
* Changes: Turned this function into a switch board function,
- * calling either the human readable or the binary
- * journal file version of the function as indicated
- * by struct_ptr->human_readable.
+ * calling either the human readable or the binary
+ * journal file version of the function as indicated
+ * by struct_ptr->human_readable.
*
* The original version of this file has been renamed
* to H5C2_jb_hrjf__start_transaction().
@@ -4717,7 +8307,7 @@ done:
*
******************************************************************************/
-herr_t
+herr_t
H5C2_jb__start_transaction(H5C2_jbrb_t * struct_ptr,
uint64_t trans_num)
@@ -4732,7 +8322,7 @@ H5C2_jb__start_transaction(H5C2_jbrb_t * struct_ptr,
if ( struct_ptr->human_readable ) {
- if ( H5C2_jb_hrjf__start_transaction(struct_ptr, trans_num)
+ if ( H5C2_jb_hrjf__start_transaction(struct_ptr, trans_num)
!= SUCCEED ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
@@ -4740,16 +8330,16 @@ H5C2_jb__start_transaction(H5C2_jbrb_t * struct_ptr,
}
} else {
- if ( H5C2_jb_bjf__start_transaction(struct_ptr, trans_num)
+ if ( H5C2_jb_bjf__start_transaction(struct_ptr, trans_num)
!= SUCCEED ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
"H5C2_jb_bjf__start_transaction() failed.")
}
}
-
+
done:
-
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5C2_jb__start_transaction() */
@@ -4765,31 +8355,49 @@ done:
* Purpose: Verify that the journal buffers are empty, and that the
* journal file has been truncated. Then close and delete
* the journal file associated with *struct_ptr, and free
- * all dynamically allocated memory associated with
+ * all dynamically allocated memory associated with
* *struct_ptr.
*
* Returns: SUCCEED on success.
*
+ * Changes: JRM -- 12/7/09
+ * Added code to free the aio control blocks if necessary.
+ *
+ * JRM -- 2/21/10
+ * Added call to H5C2_jb_stats__dump().
+ *
******************************************************************************/
-herr_t
+herr_t
H5C2_jb__takedown(H5C2_jbrb_t * struct_ptr)
{
herr_t ret_value = SUCCEED;
-
+
FUNC_ENTER_NOAPI(H5C2_jb__takedown, FAIL)
/* Check Arguments */
HDassert(struct_ptr);
HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC);
+ /* dump the stats before we start the takedown, as the dump
+ * routine may want to look at some of *struct_ptr's regular
+ * fields, as well as the stats fields.
+ */
+#if H5C2__JBRB__DUMP_STATS_ON_TAKEDOWN
+ if ( H5C2_jb_stats__dump(struct_ptr) != SUCCEED ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C2_jb_stats__dump() failed.")
+ }
+#endif /* H5C2__JBRB__DUMP_STATS_ON_TAKEDOWN */
+
/* Verify that the journal buffers are empty */
if ( struct_ptr->bufs_in_use != 0 ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"Attempt to takedown with non-empty buffers.")
- } /* end if */
+ } /* end if */
/* Verify that the journal file has been truncated */
if (struct_ptr->journal_is_empty != TRUE) {
@@ -4801,19 +8409,20 @@ H5C2_jb__takedown(H5C2_jbrb_t * struct_ptr)
/* Close and delete the journal file associated with struct_ptr */
if ( HDclose(struct_ptr->journal_file_fd) < 0 ) {
- HGOTO_ERROR(H5E_IO, H5E_CLOSEERROR, FAIL, "Jounal file close failed.")
+ HGOTO_ERROR(H5E_IO, H5E_CLOSEERROR, FAIL, "Journal file close failed.")
} /* end if */
if ( HDremove(struct_ptr->jname) < 0) {
- HGOTO_ERROR(H5E_IO, H5E_REMOVEFAIL, FAIL, "Jounal file close failed.")
+ HGOTO_ERROR(H5E_IO, H5E_REMOVEFAIL, FAIL, \
+ "Journal file close failed.")
} /* end if */
/* Free all memory associated with struct_ptr */
if ( struct_ptr->jname != NULL ) {
- struct_ptr->jname = H5MM_xfree(struct_ptr->jname);
+ struct_ptr->jname = (char *)H5MM_xfree(struct_ptr->jname);
if ( struct_ptr->jname != NULL ) {
@@ -4824,7 +8433,8 @@ H5C2_jb__takedown(H5C2_jbrb_t * struct_ptr)
if ( struct_ptr->hdf5_file_name != NULL ) {
- struct_ptr->hdf5_file_name = H5MM_xfree(struct_ptr->hdf5_file_name);
+ struct_ptr->hdf5_file_name =
+ (char *)H5MM_xfree(struct_ptr->hdf5_file_name);
if ( struct_ptr->hdf5_file_name != NULL ) {
@@ -4835,7 +8445,7 @@ H5C2_jb__takedown(H5C2_jbrb_t * struct_ptr)
if ( (*struct_ptr->buf)[0] != NULL ) {
- (*struct_ptr->buf)[0] = H5MM_xfree((*struct_ptr->buf)[0]);
+ (*struct_ptr->buf)[0] = (char *)H5MM_xfree((*struct_ptr->buf)[0]);
if ( (*struct_ptr->buf)[0] != NULL ) {
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \
@@ -4845,7 +8455,7 @@ H5C2_jb__takedown(H5C2_jbrb_t * struct_ptr)
if ( struct_ptr->buf != NULL ) {
- struct_ptr->buf = H5MM_xfree(struct_ptr->buf);
+ struct_ptr->buf = (char *((*)[]))H5MM_xfree(struct_ptr->buf);
if ( struct_ptr->buf != NULL ) {
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \
@@ -4855,7 +8465,8 @@ H5C2_jb__takedown(H5C2_jbrb_t * struct_ptr)
if ( struct_ptr->trans_tracking != NULL ) {
- struct_ptr->trans_tracking = H5MM_xfree(struct_ptr->trans_tracking);
+ struct_ptr->trans_tracking =
+ (uint64_t (*)[])H5MM_xfree(struct_ptr->trans_tracking);
if ( struct_ptr->trans_tracking != NULL ) {
@@ -4864,6 +8475,18 @@ H5C2_jb__takedown(H5C2_jbrb_t * struct_ptr)
}
}
+ if ( struct_ptr->aio_ctl_blks != NULL ) {
+
+ struct_ptr->aio_ctl_blks =
+ (struct aiocb (*)[])H5MM_xfree(struct_ptr->aio_ctl_blks);
+
+ if ( struct_ptr->aio_ctl_blks != NULL ) {
+
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \
+ "free of AIO control blocks array failed.");
+ }
+ }
+
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -4878,16 +8501,20 @@ done:
* Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
* Thursday, February 7, 2008
*
- * Purpose: Verify that there is no transaction in progress, and
+ * Purpose: Verify that there is no transaction in progress, and
* that the journal entry buffers are empty. Truncate
* the journal file. Does not return until the file
* is truncated on disk.
*
* Returns: SUCCEED on success.
*
+ * Changes: Added code to reset fields used exclusively by
+ * AIO.
+ * JRM -- 1/12/10
+ *
******************************************************************************/
-herr_t
+herr_t
H5C2_jb__trunc(H5C2_jbrb_t * struct_ptr)
{
@@ -4899,7 +8526,7 @@ H5C2_jb__trunc(H5C2_jbrb_t * struct_ptr)
/* Check Arguments */
HDassert(struct_ptr);
HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC);
-
+
/* Verify that there is no transaction in progress */
if ( struct_ptr->trans_in_prog != FALSE ) {
@@ -4912,7 +8539,7 @@ H5C2_jb__trunc(H5C2_jbrb_t * struct_ptr)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"Attempt to truncate with non-empty buffers.")
- } /* end if */
+ } /* end if */
/* Truncate the journal file */
if ( HDftruncate(struct_ptr->journal_file_fd, (off_t)0) < 0 ) {
@@ -4923,11 +8550,14 @@ H5C2_jb__trunc(H5C2_jbrb_t * struct_ptr)
/* Start back to top of journal buffer and journal file */
struct_ptr->header_present = FALSE;
struct_ptr->journal_is_empty = TRUE;
+ struct_ptr->aio_next_buf_offset = 0;
/* reset the transaction number fields */
struct_ptr->cur_trans = 0;
+ struct_ptr->last_trans_queued = 0;
+ struct_ptr->last_trans_written = 0;
struct_ptr->last_trans_on_disk = 0;
-
+
/* reset the transaction tracking array */
for (i=0; i<struct_ptr->num_bufs; i++)
{
@@ -4954,21 +8584,21 @@ done:
* 2/12/09
*
* Purpose: Write the header message to the journal file.
- *
+ *
* This message appear exactly once in every journal
* file, and is always the first message in the file.
- * It identifies the journal file, and contains
- * information required to run the journal, should
+ * It identifies the journal file, and contains
+ * information required to run the journal, should
* that be necessary.
*
* It is always in human readable format.
- *
+ *
* Returns: SUCCEED on success.
* FAIL on failure.
*
* Changes: JRM -- 3/21/09
- * Moved the entry tag strings into #defines.
- * Replaced all white space in the creation date
+ * Moved the entry tag strings into #defines.
+ * Replaced all white space in the creation date
* string with underscores.
*
* JRM -- 4/16/09
@@ -4977,7 +8607,7 @@ done:
*
******************************************************************************/
-herr_t
+herr_t
H5C2_jb__write_header_entry(H5C2_jbrb_t * struct_ptr)
{
@@ -4990,7 +8620,7 @@ H5C2_jb__write_header_entry(H5C2_jbrb_t * struct_ptr)
size_t file_name_len;
size_t buf_len;
time_t current_date;
-
+
FUNC_ENTER_NOAPI(H5C2_jb__write_header_entry, FAIL)
/* Check Arguments */
@@ -5005,16 +8635,16 @@ H5C2_jb__write_header_entry(H5C2_jbrb_t * struct_ptr)
HDassert( file_name_len > 0 );
buf_len = file_name_len + 256;
-
+
/* Allocate space for journal buffers */
- buf = H5MM_malloc(buf_len);
+ buf = (char *)H5MM_malloc(buf_len);
if ( buf == NULL ) {
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \
"buffer allocation failed.");
} /* end if */
-
+
/* Get the current date */
current_date = HDtime(NULL);
@@ -5030,7 +8660,7 @@ H5C2_jb__write_header_entry(H5C2_jbrb_t * struct_ptr)
} else {
- /* copy the string into time_buf, replacing white space with
+ /* copy the string into time_buf, replacing white space with
* underscores.
*
* Do this to make parsing the header easier.
@@ -5059,14 +8689,14 @@ H5C2_jb__write_header_entry(H5C2_jbrb_t * struct_ptr)
if ( struct_ptr->human_readable ) {
- chars_written =
- HDsnprintf(buf,
+ chars_written =
+ HDsnprintf(buf,
buf_len - 1,
"0 %s %ld %s %s %s %d %s %10.10s %s %d\n",
H5C2_JNL__VER_NUM_TAG,
- struct_ptr->jvers,
+ struct_ptr->jvers,
H5C2_JNL__TGT_FILE_NAME_TAG,
- struct_ptr->hdf5_file_name,
+ struct_ptr->hdf5_file_name,
H5C2_JNL__JNL_MAGIC_TAG,
(int)(struct_ptr->journal_magic),
H5C2_JNL__CREATION_DATE_TAG,
@@ -5076,24 +8706,24 @@ H5C2_jb__write_header_entry(H5C2_jbrb_t * struct_ptr)
} else {
- /* Only include the offset and length widths in header for a binary
- * journal file. Leave this data out of the human readable journal
+ /* Only include the offset and length widths in header for a binary
+ * journal file. Leave this data out of the human readable journal
* file header because:
*
- * 1) Everything is in ASCII so it isn't needed, and
+ * 1) Everything is in ASCII so it isn't needed, and
*
- * 2) If we included it anyway, we would have to update the
+ * 2) If we included it anyway, we would have to update the
* tests for the human readable journal file code.
*/
- chars_written =
- HDsnprintf(buf,
+ chars_written =
+ HDsnprintf(buf,
buf_len - 1,
"0 %s %ld %s %s %s %d %s %10.10s %s %d %s %d %s %d\n",
H5C2_JNL__VER_NUM_TAG,
- struct_ptr->jvers,
+ struct_ptr->jvers,
H5C2_JNL__TGT_FILE_NAME_TAG,
- struct_ptr->hdf5_file_name,
+ struct_ptr->hdf5_file_name,
H5C2_JNL__JNL_MAGIC_TAG,
(int)(struct_ptr->journal_magic),
H5C2_JNL__CREATION_DATE_TAG,
@@ -5107,7 +8737,7 @@ H5C2_jb__write_header_entry(H5C2_jbrb_t * struct_ptr)
}
- if ( chars_written >= buf_len - 1 ) {
+ if ( chars_written >= (int)(buf_len - 1) ) {
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCOPY, FAIL, \
"tried to overwrite buffer.");
@@ -5116,9 +8746,11 @@ H5C2_jb__write_header_entry(H5C2_jbrb_t * struct_ptr)
HDassert( HDstrlen(buf) < buf_len );
/* Write the header message into the ring buffer */
- if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(buf), buf, FALSE,
+ if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(buf), buf, FALSE,
(uint64_t)0) < 0) {
-
+#if 1 /* JRM */
+ HDfprintf(stdout, "%s: H5C2_jb__write_to_buffer() failed.\n", FUNC);
+#endif /* JRM */
HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
"H5C2_jb__write_to_buffer() failed.\n")
} /* end if */
@@ -5128,13 +8760,20 @@ H5C2_jb__write_header_entry(H5C2_jbrb_t * struct_ptr)
struct_ptr->journal_is_empty = FALSE;
done:
- if(buf != NULL) {
- buf = H5MM_xfree(buf);
- if(buf != NULL)
- HDONE_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "free of buf failed.")
+
+ if ( buf != NULL ) {
+
+ buf = (char *)H5MM_xfree(buf);
+
+ if ( buf != NULL ) {
+
+ HDONE_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \
+ "free of buf failed.")
+ }
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
+
} /* end H5C2_jb__write_header_entry() */
@@ -5142,273 +8781,55 @@ done:
*
* Function: H5C2_jb__write_to_buffer
*
- * Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
- * Wednesday, February 6, 2008
+ * Programmer: John Mainzer
+ * 1/14/10
*
- * Purpose: Put the contents of data into the journal buffers. This
- * is done as follows: While the data to be written is
- * larger than the amount of space left in the ring buffer,
- * the ring buffer is filled to capacity with data and
- * flushed. This repeats until the unwritten data remaining
- * can fit in the ring buffer without having to loop around
- * to the top.
+ * Purpose: Test to see whether AIO is enabled, and the
+ * call the appropriate version of the function.
*
- * At this point, the rest of the data can just be written
- * without having to break it up further. In the event
- * the data covers more than one journal buffer, the get
- * and put indices are updated to state this fact. Any
- * journal buffers that were filled during the write are
- * flushed.
+ * At some point we may wish to replace this switch
+ * function with a function pointer in struct H5C2_jbrb_t.
*
* Returns: SUCCEED on success.
*
******************************************************************************/
-herr_t
-H5C2_jb__write_to_buffer(H5C2_jbrb_t * struct_ptr,
- size_t size,
- const char * data,
- hbool_t is_end_trans,
- uint64_t trans_num)
+herr_t
+H5C2_jb__write_to_buffer(H5C2_jbrb_t * struct_ptr,
+ size_t size,
+ const char * data,
+ hbool_t is_end_trans,
+ uint64_t trans_num)
{
herr_t ret_value = SUCCEED;
- unsigned long track_last_trans = 0;
- int oldput = 0;
- int i;
-
+
FUNC_ENTER_NOAPI(H5C2_jb__write_to_buffer, FAIL)
/* Check Arguments */
- HDassert(struct_ptr);
- HDassert(data);
- HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC);
- HDassert( ( struct_ptr->human_readable == FALSE ) ||
- ( HDstrlen(data) == size ) );
- HDassert(struct_ptr->rb_space_to_rollover <=
- struct_ptr->num_bufs * struct_ptr->buf_size);
- HDassert(struct_ptr->rb_space_to_rollover > 0);
-
- /* If the data size exceeds the bounds of the ring buffer's allocated
- * memory, loop around to top
- */
- if (size >= struct_ptr->rb_space_to_rollover) {
-
- while (size >= struct_ptr->rb_space_to_rollover) {
-
- /* Assertions */
- HDassert(size != 0);
- HDassert( ( struct_ptr->human_readable == FALSE ) ||
- ( HDstrlen(data) >= struct_ptr->rb_space_to_rollover ) );
-
- /* fill up remaining space in the ring buffer */
- HDmemcpy(struct_ptr->head, data, struct_ptr->rb_space_to_rollover);
-
- /* move head to point to start of ring buffer */
- struct_ptr->head = (*struct_ptr->buf)[0];
-
- /* make note of last transaction on disk */
- track_last_trans = (*struct_ptr->trans_tracking)[struct_ptr->put];
-
- /* update rb_free_space */
- struct_ptr->rb_free_space -= struct_ptr->rb_space_to_rollover;
-
- /* Fill out the remainder of the trans_tracking array with
- the most recent transaction in the array.*/
- (*struct_ptr->trans_tracking)[0] = track_last_trans;
- for (i=struct_ptr->put; i<struct_ptr->num_bufs; i++)
- {
- (*struct_ptr->trans_tracking)[i] = track_last_trans;
- }
-
- /* reset put index */
- struct_ptr->put = 0;
-
- /* update bufs_in_use as necessary */
- struct_ptr->bufs_in_use = struct_ptr->num_bufs - struct_ptr->get;
-
- /* check to see if trans_tracking needs to be updated. If so,
- then update it */
- if ((size == struct_ptr->rb_space_to_rollover) &&
- (is_end_trans == TRUE)) {
-
- (*struct_ptr->trans_tracking)[struct_ptr->num_bufs - 1]
- = trans_num;
- (*struct_ptr->trans_tracking)[0] = trans_num;
- }
-
- /* flush buffers */
- if ( H5C2_jb__flush_full_buffers(struct_ptr) < 0 ) {
-
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "H5C2_jb__flush_full_buffers() failed.\n")
- }
-
- /* update remaining size of data to be written */
- size = size - struct_ptr->rb_space_to_rollover;
-
- /* update the data pointer to point to the remaining data to be
- * written
- */
- data = &data[struct_ptr->rb_space_to_rollover];
-
- /* update the amount of space left at end of ring buffer */
- struct_ptr->rb_space_to_rollover =
- struct_ptr->buf_size * struct_ptr->num_bufs;
-
- /* update the amount of space in the current buffer */
- struct_ptr->cur_buf_free_space = struct_ptr->buf_size;
-
- } /* end while */
- } /* end if */
-
- /* If the size of the data exceeds the bounds of a single journal
- * buffer, will write into multiple
- */
- if (size > struct_ptr->cur_buf_free_space) {
-
- HDassert(struct_ptr->cur_buf_free_space != 0);
-
- /* write data into journal buffers */
- HDmemcpy(struct_ptr->head, data, size);
-
- /* update head pointer */
- struct_ptr->head = &struct_ptr->head[size];
-
- /* make note of last transaction on disk */
- track_last_trans = (*struct_ptr->trans_tracking)[struct_ptr->put];
- oldput = struct_ptr->put;
-
- /* update rb_free_space */
- struct_ptr->rb_free_space -= size;
-
- /* update put index */
- struct_ptr->put +=
- (size-struct_ptr->cur_buf_free_space)/(struct_ptr->buf_size) + 1;
-
- /* Drag the last transaction in a filled buffer value residing in the
- old put location through the trans_tracking array to the new
- corresponding put position. */
- for (i=oldput; i<struct_ptr->put+1; i++)
- {
- (*struct_ptr->trans_tracking)[i] = track_last_trans;
- }
-
- /* update current buffer usage */
- struct_ptr->cur_buf_free_space =
- struct_ptr->rb_space_to_rollover - size -
- (struct_ptr->num_bufs - (struct_ptr->put + 1)) *
- (struct_ptr->buf_size );
-
- /* update bufs_in_use as necessary */
- struct_ptr->bufs_in_use = struct_ptr->put - struct_ptr->get;
- if (struct_ptr->cur_buf_free_space < struct_ptr->buf_size) {
-
- struct_ptr->bufs_in_use++;
- }
-
- /* check to see if trans_tracking needs to be updated. If so,
- then update it */
- if (is_end_trans == TRUE) {
-
- if (struct_ptr->cur_buf_free_space == struct_ptr->buf_size) {
- (*struct_ptr->trans_tracking)[struct_ptr->put - 1] = trans_num;
- }
- else {
- (*struct_ptr->trans_tracking)[struct_ptr->put] = trans_num;
- }
-
- } /* end if */
-
- /* flush buffers */
- if ( H5C2_jb__flush_full_buffers(struct_ptr) < 0 ) {
-
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "H5C2_jb__flush_full_buffers() failed.\n")
- }
+ if ( ( struct_ptr == NULL ) ||
+ ( struct_ptr->magic != H5C2__H5C2_JBRB_T_MAGIC ) ) {
- /* update space left at end of ring buffer */
- struct_ptr->rb_space_to_rollover -= size;
-
- } /* end if */
-
- /* if the data can fit in the remaining space in the current journal
- * buffer indexed by put
- */
- else if (size > 0) {
-
- HDassert(size <= struct_ptr->cur_buf_free_space);
-
- /* write data into journal buffer */
- HDmemcpy(struct_ptr->head, data, size);
-
- /* increment bufs_in_use as necessary */
- if ( ( struct_ptr->bufs_in_use == 0 ) ) {
-
- struct_ptr->bufs_in_use++;
- }
-
- /* update head pointer */
- struct_ptr->head = &struct_ptr->head[size];
-
- /* update rb_free_space */
- struct_ptr->rb_free_space -= size;
-
- /* update current buffer usage */
- struct_ptr->cur_buf_free_space -= size;
-
- /* update end of buffer space */
- struct_ptr->rb_space_to_rollover -= size;
-
- /* check to see if trans_tracking needs to be updated. If so,
- then update it */
- if (is_end_trans == TRUE) {
-
- (*struct_ptr->trans_tracking)[struct_ptr->put]
- = trans_num;
- } /* end if */
-
- /* if buffer is full, flush it, and loop to the top of the
- * ring buffer if at the end.
- */
- if (struct_ptr->cur_buf_free_space == 0) {
-
- if ( struct_ptr->put != (struct_ptr->num_bufs - 1) ) {
- struct_ptr->put += 1;
-
- /* Drag trans_tracking value into next buffer */
- (*struct_ptr->trans_tracking)[struct_ptr->put] =
- (*struct_ptr->trans_tracking)[struct_ptr->put - 1];
-
- } /* end if */
-
- else {
-
- struct_ptr->put = 0;
-
- /* Drag trans_tracking value into next buffer */
- (*struct_ptr->trans_tracking)[0]
- = (*struct_ptr->trans_tracking)[struct_ptr->num_bufs - 1];
-
- /* reset head pointer and free space values */
- struct_ptr->head = (*struct_ptr->buf)[0];
- struct_ptr->rb_space_to_rollover =
- struct_ptr->buf_size * struct_ptr->num_bufs;
-
- } /* end else */
-
- if ( H5C2_jb__flush_full_buffers(struct_ptr) < 0 ) {
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "bad struct_ptr on entry.")
+ }
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "H5C2_jb__flush_full_buffers() failed.\n")
- } /* end if */
+ if ( struct_ptr->use_aio ) {
- struct_ptr->cur_buf_free_space = struct_ptr->buf_size;
+ ret_value = H5C2_jb_aio__write_to_buffer(struct_ptr,
+ size,
+ data,
+ is_end_trans,
+ trans_num);
- } /* end if */
+ } else {
- } /* end else */
+ ret_value = H5C2_jb_sio__write_to_buffer(struct_ptr,
+ size,
+ data,
+ is_end_trans,
+ trans_num);
- HDassert(struct_ptr->bufs_in_use <= struct_ptr->num_bufs);
+ }
done:
diff --git a/src/H5C2pkg.h b/src/H5C2pkg.h
index 9909ca2..74fa64e 100644
--- a/src/H5C2pkg.h
+++ b/src/H5C2pkg.h
@@ -35,7 +35,6 @@
#ifndef _H5C2pkg_H
#define _H5C2pkg_H
-
/* Get package's private header */
#include "H5C2private.h"
@@ -46,6 +45,56 @@
/******************************************************************************
*
+ * Structure: H5C2_jbrb_sync_q_entry_t
+ *
+ * Programmer: John Mainzer
+ * 2/6/10
+ *
+ * Purpose: Instances of the H5C2_jbrb_sync_q_entry_t structure
+ * are used to maintain a queue of pending aio_fsync()
+ * operations.
+ *
+ * The basic idea is to issue a call to aio_fsync()
+ * after each transaction if that transaction has
+ * triggered a buffer write, and place the associated
+ * AIO control block on a queue of asynchronous syncs
+ * in progress. Then, whenever we are asked for the
+ * ID of the last transaction on disk, we simply scan
+ * this queue to see what if any syncs have completed,
+ * and update the last transaction on disk accordingly.
+ *
+ * The fields of this structure are discussed below:
+ *
+ *
+ * magic: Unsigned 32-bit integer always set to
+ * H5C2__H5C2_JBRB_SYNC_Q_T_MAGIC. This field is used
+ * to validate pointers to instances of
+ * H5C2_jbrb_sync_q_entry_t.
+ *
+ * last_trans_in_sync: ID of the last transaction that will be on disk
+ * when the associated aio_fsync() completes.
+ *
+ * clt_blk Instance of aiocb used in the associated call to
+ * aio_fsync().
+ *
+ * next: Pointer to the next instance of
+ * H5C2_jbrb_sync_q_entry_t in the list of same,
+ * or NULL if there is no next instance.
+ *
+ ******************************************************************************/
+
+#define H5C2__H5C2_JBRB_SYNC_Q_T_MAGIC (unsigned)0x00DA030
+
+struct H5C2_jbrb_sync_q_entry_t
+{
+ uint32_t magic;
+ uint64_t last_trans_in_sync;
+ struct aiocb ctl_blk;
+ struct H5C2_jbrb_sync_q_entry_t * next;
+};
+
+/******************************************************************************
+ *
* Structure: H5C2_jbrb_t
*
* Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
@@ -61,19 +110,19 @@
* The fields of this structure are discussed below:
*
*
- * magic: Unsigned 32-bit integer always set to
- * H5C2__H5C2_JBRB_T_MAGIC. This field is used to
+ * magic: Unsigned 32-bit integer always set to
+ * H5C2__H5C2_JBRB_T_MAGIC. This field is used to
* validate pointers to instances of H5C_jbrb_t.
*
* journal_magic: int32_t used to store a randomly selected integer
- * used to tag both the journal file and the
- * mdj_config_block. Should the journal ever be
- * run, we will check to see if the magic number
- * from the target HDF5 file matches that in the
+ * used to tag both the journal file and the
+ * mdj_config_block. Should the journal ever be
+ * run, we will check to see if the magic number
+ * from the target HDF5 file matches that in the
* journal, and refuse to run the journal if it does
* not.
*
- * journal_file_fd: File Descriptor of the journal file that is being
+ * journal_file_fd: File Descriptor of the journal file that is being
* written to from this ring buffer.
*
* num_bufs: The number of journal buffers in the ring buffer. This
@@ -82,21 +131,24 @@
* one for holding the last set of journal entries while
* they are being written to disk).
*
- * buf_size: The size of each journal buffer in the ring buffer. This
- * value is user specified, and will determine how much
- * data each journal buffer can hold before a move to
- * another journal buffer in the ring buffer is necessary.
- * Typically, this will be a multiple of the block size of
- * the underlying file system.
+ * buf_size: The size of each journal buffer in the ring buffer.
+ * This value is user specified, and will determine how
+ * much data each journal buffer can hold before a move
+ * to another journal buffer in the ring buffer is
+ * necessary. Typically, this will be a multiple of
+ * the block size of the underlying file system.
*
* bufs_in_use: This is the current number of dirty journal buffers
* in the ring buffer.
*
+ * writes_in_progress: Number of asynchronous writes in progress. Defined
+ * iff use_aio (see below) is TRUE.
+ *
* jvers: The journal version number. This is used to keep track
* of the formatting changes of the journal file.
*
* get: Number of the journal buffer that is next in line to
- * be written to disk. (i.e. the least recently dirtied
+ * be written to disk. (i.e. the least recently dirtied
* journal buffer).
*
* put: Number of the journal buffer that is currently being
@@ -111,25 +163,25 @@
* human_readable: Boolean flag that indicates whether the journal file
* is to be human readable or machine readable.
*
- * offset_width: If human_readable is FALSE, this field contains the
- * width of offsets in the HDF5 file in bytes (as
- * specified in the superblock -- sizeof_addr in
+ * offset_width: If human_readable is FALSE, this field contains the
+ * width of offsets in the HDF5 file in bytes (as
+ * specified in the superblock -- sizeof_addr in
* H5F_file_t).
*
* If human_readable is TRUE, this field is undefined.
*
* length_width: If human_readable is FALSE, this field contains the
- * width of lengths in the HDF5 file in bytes (as
- * specified in the super block -- sizeof_size in
+ * width of lengths in the HDF5 file in bytes (as
+ * specified in the super block -- sizeof_size in
* H5F_file_t).
*
* chksum_cur_msg: Boolean flag that is only defined if human_readable
* is false. It is used to indicate whether the current
- * journal message must be checksumed. If true, the
+ * journal message must be checksumed. If true, the
* message checksum to date is stored in the msg_chksum
* (discussed below).
*
- * If the journal message is being checksumed, this
+ * If the journal message is being checksumed, this
* field will be set back to FALSE when the checksum
* of the messages is written to buffer.
*
@@ -137,7 +189,7 @@
* journal file message. Note that not all messages
* are checksumed -- this field is only defined when
* chksum_cur_msg is TRUE.
- *
+ *
* journal_is_empty: Boolean flag that indicates if the journal file
* associated with the ring buffer is currently
* empty.
@@ -145,17 +197,29 @@
* cur_trans: Current transaction number, used to differentiate
* between differing journal entries in the journal file.
*
+ * last_trans_queued: Number of the last transaction that has been
+ * successfully queued (i.e. the associated aio_write()
+ * call has returned without error. At present, this
+ * field is only defined when use_aio (see above) is
+ * TRUE, and only used when use_aio_fsync (see below)
+ * is TRUE as well.
+ *
+ * last_trans_written: Number of the last transaction that has been
+ * successfully written. At present, this field is
+ * only defined when use_aio (see above) is TRUE.
+ *
* last_trans_on_disk: Number of the last transaction that has successfully
* made it to disk.
*
* trans_in_prog: Boolean flag that indicates if a transaction is in
* progress or not.
*
- * jname: Character array containing the name of the journal file.
+ * jname: Character array containing the name of the journal
+ * file.
*
* hdf5_file_name: Character array containing the name of the HDF5 file
* associated with this journal file.
- *
+ *
* header_present: Boolean flag that indicates if the header message has
* been written into the current journal file or journal
* buffer.
@@ -165,14 +229,14 @@
* ring buffer needs to switch to writing to the next
* journal buffer.
*
- * rb_space_to_rollover: The amount of space left at the end of the ring
+ * rb_space_to_rollover: The amount of space left at the end of the ring
* buffer, starting at the head pointer, and ending at
* the end of the ring buffer's allocate space. This
* is used to keep track of when a rollover to the start
* of the ring buffer must occur.
*
* rb_free_space: The amount of unused space in the ring buffer.
- *
+ *
* head: A pointer to the location in the active journal buffer
* that is to be written to.
*
@@ -181,16 +245,114 @@
* is used when the buffers are flushed to determine which
* is the last transaction successfully on disk.
*
+ * aio_ctl_blks An array of size num_bufs of instances of struct
+ * aiocb, or NULL if use_aio is FALSE.
+ *
+ * Each instance of struct aiocb is associated with
+ * the buffer at the same index in buf, and is used
+ * to manage posix aio for that buffer.
+ *
+ * Note that it is said to be good practice to zero
+ * out each instance of struct aiocb before each
+ * write.
+ *
+ * aio_next_buf_offset: Offset in the journal file at which to write the
+ * next buffer to the journal file. This field is
+ * undefined if use_aio is FALSE.
+ *
+ * use_aio_fsync: Boolean flag indicating whether we should attempt to
+ * use aio_fsync() to sync out journal writes. This
+ * field is initialized to TRUE whenever use_aio (see
+ * above) is set to TRUE, and then set to FALSE
+ * if we determine that aio_fsync() is not supported
+ * on the current host.
+ *
+ * aio_sync_q_head: Pointer to the first element in the aio sync queue,
+ * or NULL if that queue is empty.
+ *
+ * aio_sync_q_tail: Pointer to the last element in the aio sync queue,
+ * or NULL if that queue is empty.
+ *
+ * aio_sync_q_len: Number of elements on the aio sync queue. Note that
+ * aio_sync_q_head and aio_sync_q_tail must be NULL
+ * if this field contains zero, and may not be NULL if
+ * the sync queue length is greater than zero.
+ *
* buf: Array of char pointers to each journal buffer in the
- * ring buffer. This is allocated as a single chunk of
+ * ring buffer. This is allocated as a single chunk of
* memory, and thus data can be written past a buffer
* boundary provided it will not extend past the end
* of the total area allocated for the ring buffer.
*
+ * The following fields are used to collect statistics on the activities
+ * of the journal entry write code. These fields are only defined when
+ * H5C2__JBRB__COLLECT_STATS is TRUE. Descriptions of the individual
+ * stats collection fields follow:
+ *
+ * transactions_completed: uint64_t used to track the number of transactions
+ * completed. This is simply the number of calls to
+ * H5C2_jb__end_transaction().
+ *
+ * buf_writes_queued: uint64_t used to track the number of asynchronous
+ * buffer writes queued (via aio_write()).
+ *
+ * full_buf_writes_queued: uint64_t used to track the number of
+ * full asynchronous buffer writes queued
+ * (via aio_write()).
+ *
+ * partial_buf_writes_queued; uint64_t used to track the number of
+ * partial (i.e. writes of a buffer that isn't full)
+ * buffer writes queued (via aio_write()).
+ *
+ * buf_writes_completed: uint64_t used to track the total number of
+ * asynchronous buffer writes (queued via aio_write())
+ * that have completed.
+ *
+ * buf_writes_completed_by_test: uint64_t used to track the number of
+ * asynchronous buffer writes completed by test
+ * (i.e. the write was found to be complete in a
+ * routine check for completed writes without any
+ * waiting.)
+ *
+ * buf_writes_completed_by_await: uint64_t used to track the number of
+ * asynchronous buffer writes completed by await
+ * (i.e. the write was completed via a call to
+ * aio_suspend()) because processing could not
+ * continue until the write completed.
+ *
+ * async_syncs_queued: uint64_t used to track the number of asynchronous
+ * syncs queued (via aio_fsync()).
+ *
+ *
+ * async_syncs_completed: uin64_t used to track the number of asynchronous
+ * syncs completed.
+ *
+ * async_syncs_completed_by_test; uint64_t used to track the number of
+ * asynchronous syncs completed by test
+ * (i.e. the sync was found to be complete in a
+ * routine check for completed writes without any
+ * waiting.).
+ *
+ * async_syncs_completed_by_await; uint64_t used to track the number of
+ * asynchronous syncs completed by await
+ * (i.e. the sync was completed busy waiting
+ * with repeated calls to aio_error()).
+ *
+ * calls_to_aio_error_awaiting_sync: uint64_t used to track the number of
+ * calls to aio_error() made while busy waiting for
+ * the completion of aio_fsync()s.
+ *
+ * max_sync_q_len: uint64_t used to track the maximum value of
+ *
+ * calls_to_fsync: uint64_t used to track the number of calls to
+ * fsync().
+ *
******************************************************************************/
-#define H5C2__H5C2_JBRB_T_MAGIC (unsigned)0x00D0A03
-#define H5C2__JOURNAL_VERSION 1
+#define H5C2__H5C2_JBRB_T_MAGIC (unsigned)0x00D0A03
+#define H5C2__JOURNAL_VERSION 1
+#define H5C2__JBRB__COLLECT_STATS 0
+#define H5C2__JBRB__DUMP_STATS_ON_TAKEDOWN 0
/* tags used to mark entries in the journal file header */
#define H5C2_JNL__VER_NUM_TAG "ver_num"
@@ -201,7 +363,7 @@
#define H5C2_JNL__OFFSET_WIDTH_TAG "offset_width"
#define H5C2_JNL__LENGTH_WIDTH_TAG "length_width"
-/* signatures and versions used to mark the beginnings of journal file
+/* signatures and versions used to mark the beginnings of journal file
* messages in binary journal files.
*/
@@ -215,47 +377,74 @@
#define H5C2_BJNL__END_ADDR_SPACE_SIG "eoas"
#define H5C2_BJNL__END_ADDR_SPACE_VER ((uint8_t)(0))
-struct H5C2_jbrb_t
+struct H5C2_jbrb_t
{
- uint32_t magic;
- int32_t journal_magic;
- int journal_file_fd;
- int num_bufs;
- size_t buf_size;
- int bufs_in_use;
- unsigned long jvers;
- int get;
- int put;
- hbool_t jentry_written;
- hbool_t use_aio;
- hbool_t human_readable;
- int offset_width;
- int length_width;
- hbool_t chksum_cur_msg;
- uint32_t msg_chksum;
- hbool_t journal_is_empty;
- uint64_t cur_trans;
- uint64_t last_trans_on_disk;
- hbool_t trans_in_prog;
- const char * jname;
- const char * hdf5_file_name;
- hbool_t header_present;
- size_t cur_buf_free_space;
- size_t rb_space_to_rollover;
- size_t rb_free_space;
- char * head;
- unsigned long (*trans_tracking)[];
- char *((*buf)[]);
+ uint32_t magic;
+ int32_t journal_magic;
+ int journal_file_fd;
+ int num_bufs;
+ size_t buf_size;
+ int bufs_in_use;
+ int writes_in_progress;
+ unsigned long jvers;
+ int get;
+ int put;
+ hbool_t jentry_written;
+ hbool_t use_aio;
+ hbool_t human_readable;
+ int offset_width;
+ int length_width;
+ hbool_t chksum_cur_msg;
+ uint32_t msg_chksum;
+ hbool_t journal_is_empty;
+ uint64_t cur_trans;
+ uint64_t last_trans_queued;
+ uint64_t last_trans_written;
+ uint64_t last_trans_on_disk;
+ hbool_t trans_in_prog;
+ char * jname;
+ char * hdf5_file_name;
+ hbool_t header_present;
+ size_t cur_buf_free_space;
+ size_t rb_space_to_rollover;
+ size_t rb_free_space;
+ char * head;
+ uint64_t (*trans_tracking)[];
+ struct aiocb (*aio_ctl_blks)[];
+ off_t aio_next_buf_offset;
+ hbool_t use_aio_fsync;
+ struct H5C2_jbrb_sync_q_entry_t * aio_sync_q_head;
+ struct H5C2_jbrb_sync_q_entry_t * aio_sync_q_tail;
+ uint64_t aio_sync_q_len;
+ char *((*buf)[]);
+#if H5C2__JBRB__COLLECT_STATS
+ uint64_t transactions_completed;
+ uint64_t buf_writes_queued;
+ uint64_t full_buf_writes_queued;
+ uint64_t partial_buf_writes_queued;
+ uint64_t buf_writes_completed;
+ uint64_t buf_writes_completed_by_test;
+ uint64_t buf_writes_completed_by_await;
+ uint64_t async_syncs_queued;
+ uint64_t async_syncs_completed;
+ uint64_t async_syncs_completed_by_test;
+ uint64_t async_syncs_completed_by_await;
+ uint64_t calls_to_aio_error_awaiting_sync;
+ uint64_t max_sync_q_len;
+ uint64_t calls_to_fsync;
+#endif /* H5C2__JBRB__COLLECT_STATS */
};
-/* With the introduction of the fractal heap, it is now possible for
+/* With the introduction of the fractal heap, it is now possible for
* entries to be dirtied, resized, and/or renamed in the flush callbacks.
* As a result, on flushes, it may be necessary to make multiple passes
* through the slist before it is empty. The H5C2__MAX_PASSES_ON_FLUSH
* #define is used to set an upper limit on the number of passes.
- * The current value was obtained via personal communication with
+ * The current value was obtained via personal communication with
* Quincey. I have applied a fudge factor of 2.
+ *
+ * -- JRM
*/
#define H5C2__MAX_PASSES_ON_FLUSH 4
@@ -265,8 +454,8 @@ struct H5C2_jbrb_t
*
* structure H5C2_mdjsc_record_t
*
- * A dynamically allocate array of instances of H5C2_mdjsc_record_t is
- * used to record metadata journaling status change callbacks -- of which
+ * A dynamically allocate array of instances of H5C2_mdjsc_record_t is
+ * used to record metadata journaling status change callbacks -- of which
* there can be an arbitrary number.
*
* The fields in the structure are discussed individually below:
@@ -275,20 +464,20 @@ struct H5C2_jbrb_t
* to be called on metadata journaling start or stop. NULL
* if this record is not in use.
*
- * Note that the cache must be clean when this callback
+ * Note that the cache must be clean when this callback
* is called.
*
* data_ptr: Pointer to void. This value is supplied on registration,
- * and is passed to *fcn_ptr. NULL if this record is not
+ * and is passed to *fcn_ptr. NULL if this record is not
* in use.
*
* fl_next: Index of the next free entry in the metadata status change
- * callback table, or -1 if there is no next free entry or
+ * callback table, or -1 if there is no next free entry or
* if the entry is in use.
*
****************************************************************************/
-typedef struct H5C2_mdjsc_record_t
+typedef struct H5C2_mdjsc_record_t
{
H5C2_mdj_status_change_func_t fcn_ptr;
void * data_ptr;
@@ -334,11 +523,11 @@ typedef struct H5C2_mdjsc_record_t
*
* JRM - 9/26/05
*
- * magic: Unsigned 32 bit integer always set to H5C2__H5C2_T_MAGIC.
- * This field is used to validate pointers to instances of
+ * magic: Unsigned 32 bit integer always set to H5C2__H5C2_T_MAGIC.
+ * This field is used to validate pointers to instances of
* H5C2_t.
*
- * flush_in_progress: Boolean flag indicating whether a flush is in
+ * flush_in_progress: Boolean flag indicating whether a flush is in
* progress.
*
* trace_file_ptr: File pointer pointing to the trace file, which is used
@@ -347,7 +536,7 @@ typedef struct H5C2_mdjsc_record_t
* no trace file should be recorded.
*
* Since much of the code supporting the parallel metadata
- * cache is in H5AC, we don't write the trace file from
+ * cache is in H5AC, we don't write the trace file from
* H5C2. Instead, H5AC reads the trace_file_ptr as needed.
*
* When we get to using H5C2 in other places, we may add
@@ -420,10 +609,10 @@ typedef struct H5C2_mdjsc_record_t
* writes. The following field is used to implement this.
*
* evictions_enabled: Boolean flag that is initialized to TRUE. When
- * this flag is set to FALSE, the metadata cache will not
+ * this flag is set to FALSE, the metadata cache will not
* attempt to evict entries to make space for newly protected
* entries, and instead the will grow without limit.
- *
+ *
* Needless to say, this feature must be used with care.
*
*
@@ -494,7 +683,7 @@ typedef struct H5C2_mdjsc_record_t
* following two fields have been added. They are only compiled in when
* H5C2_DO_SANITY_CHECKS is TRUE.
*
- * slist_len_increase: Number of entries that have been added to the
+ * slist_len_increase: Number of entries that have been added to the
* slist since the last time this field was set to zero.
*
* slist_size_increase: Total size of all entries that have been added
@@ -817,39 +1006,39 @@ typedef struct H5C2_mdjsc_record_t
*
* Metadata journaling fields:
*
- * The following fields are used to support metadata journaling. The
+ * The following fields are used to support metadata journaling. The
* objective here is to journal all changes in metadata, so that we will
* 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
- * currently enabled. In general, the values of the
- * remaining fields in this section are undefined if
+ * 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.
+ * 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.
+ * 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
+ * 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
+ * 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_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.
+ * 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
@@ -858,21 +1047,21 @@ typedef struct H5C2_mdjsc_record_t
* file.
*
* jnl_magic: Randomly selected int32_t used to reduce the possibility
- * of running the wrong journal on an HDF5 file. The basic
- * idea is to pick a random number, store it in both the HDF5
- * file and the journal file, and then refuse to run the
+ * of running the wrong journal on an HDF5 file. The basic
+ * idea is to pick a random number, store it in both the HDF5
+ * file and the journal file, and then refuse to run the
* journal unless the numbers match.
*
* jnl_file_name_len: Length of the journal file name, or zero if the
* journal file name is undefined.
*
- * jnl_file_name: Array of char of length H5C2__MAX_JOURNAL_FILE_NAME_LEN
+ * jnl_file_name: Array of char of length H5C2__MAX_JOURNAL_FILE_NAME_LEN
* + 1 used to store the journal file path.
*
* 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
+ * 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:
@@ -883,56 +1072,56 @@ typedef struct H5C2_mdjsc_record_t
* 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
+ * 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
+ * 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
+ * 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
+ * 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
+ * until all the journal entries for the specified transaction reaches
* disk.
*
- * jwipl_len: Number of entries currently residing on the journal
+ * 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
+ * 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
+ * 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
+ * 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
+ * Entries on this list are linked by their next and prev
* fields.
*
* This field is NULL if the list is empty.
*
- * It is necessary to turn off some optimization while journaling is
+ * It is necessary to turn off some optimization while journaling is
* in progress, so as to avoid generating dirty metadata during a flush.
* The following fields are used to maintain a list of functions to be
* called when journaling is enabled or disabled. Note that the metadata
@@ -940,15 +1129,15 @@ typedef struct H5C2_mdjsc_record_t
*
* The metadata journaling status change callback table is initaly allocated
* with H5C2__MIN_MDJSC_CB_TBL_LEN entries. The table size is doubled
- * whenever an entry is added to a full table, and halved whenever the
- * active entries to total entries ratio drops below
- * H5C2__MDJSC_CB_TBL_MIN_ACTIVE_RATIO and the upper half of the table is
- * empty (Since entries are removed from the table by specifying the
+ * whenever an entry is added to a full table, and halved whenever the
+ * active entries to total entries ratio drops below
+ * H5C2__MDJSC_CB_TBL_MIN_ACTIVE_RATIO and the upper half of the table is
+ * empty (Since entries are removed from the table by specifying the
* index of the entry, we can't compress the table).
*
* mdjsc_cb_tbl: Base address of a dynamically allocated array of instances
- * of H5C2_mdjsc_record_t used to record an arbitrarily long
- * list of functions to call whenever journaling is enabled or
+ * of H5C2_mdjsc_record_t used to record an arbitrarily long
+ * list of functions to call whenever journaling is enabled or
* disabled.
*
* mdjsc_cb_tbl_len: Number of entries currently allocated in *mdjsc_cb_tbl.
@@ -960,7 +1149,7 @@ typedef struct H5C2_mdjsc_record_t
* or -1 if the table is full.
*
* mdjsc_cb_tbl_max_idx_in_use: Maximum of the indicies of metadata journaling
- * status change callback table entries in use, or -1 if the
+ * status change callback table entries in use, or -1 if the
* table is empty;
*
* Statistics collection fields:
@@ -979,23 +1168,23 @@ typedef struct H5C2_mdjsc_record_t
* equal to the array index has not been in cache when
* requested in the current epoch.
*
- * write_protects: Array of int64 of length H5C2__MAX_NUM_TYPE_IDS + 1. The
- * cells are used to record the number of times an entry with
- * type id equal to the array index has been write protected
+ * write_protects: Array of int64 of length H5C2__MAX_NUM_TYPE_IDS + 1. The
+ * cells are used to record the number of times an entry with
+ * type id equal to the array index has been write protected
* in the current epoch.
*
* Observe that (hits + misses) = (write_protects + read_protects).
*
- * read_protects: Array of int64 of length H5C2__MAX_NUM_TYPE_IDS + 1. The
- * cells are used to record the number of times an entry with
- * type id equal to the array index has been read protected in
+ * read_protects: Array of int64 of length H5C2__MAX_NUM_TYPE_IDS + 1. The
+ * cells are used to record the number of times an entry with
+ * type id equal to the array index has been read protected in
* the current epoch.
*
* Observe that (hits + misses) = (write_protects + read_protects).
*
- * max_read_protects: Array of int32 of length H5C2__MAX_NUM_TYPE_IDS + 1.
- * The cells are used to maximum number of simultaneous read
- * protects on any entry with type id equal to the array index
+ * max_read_protects: Array of int32 of length H5C2__MAX_NUM_TYPE_IDS + 1.
+ * The cells are used to maximum number of simultaneous read
+ * protects on any entry with type id equal to the array index
* in the current epoch.
*
* insertions: Array of int64 of length H5C2__MAX_NUM_TYPE_IDS + 1. The cells
@@ -1003,9 +1192,9 @@ typedef struct H5C2_mdjsc_record_t
* id equal to the array index has been inserted into the
* cache in the current epoch.
*
- * pinned_insertions: Array of int64 of length H5C2__MAX_NUM_TYPE_IDS + 1.
- * The cells are used to record the number of times an entry
- * with type id equal to the array index has been inserted
+ * pinned_insertions: Array of int64 of length H5C2__MAX_NUM_TYPE_IDS + 1.
+ * The cells are used to record the number of times an entry
+ * with type id equal to the array index has been inserted
* pinned into the cache in the current epoch.
*
* clears: Array of int64 of length H5C2__MAX_NUM_TYPE_IDS + 1. The cells
@@ -1028,13 +1217,13 @@ typedef struct H5C2_mdjsc_record_t
* id equal to the array index has been renamed in the current
* epoch.
*
- * entry_flush_renames: Array of int64 of length H5C2__MAX_NUM_TYPE_IDS + 1.
- * The cells are used to record the number of times an entry
+ * entry_flush_renames: Array of int64 of length H5C2__MAX_NUM_TYPE_IDS + 1.
+ * The cells are used to record the number of times an entry
* with type id equal to the array index has been renamed
* during its flush callback in the current epoch.
*
- * cache_flush_renames: Array of int64 of length H5C2__MAX_NUM_TYPE_IDS + 1.
- * The cells are used to record the number of times an entry
+ * cache_flush_renames: Array of int64 of length H5C2__MAX_NUM_TYPE_IDS + 1.
+ * The cells are used to record the number of times an entry
* with type id equal to the array index has been renamed
* during a cache flush in the current epoch.
*
@@ -1073,14 +1262,14 @@ typedef struct H5C2_mdjsc_record_t
* with type id equal to the array index has decreased in
* size in the current epoch.
*
- * entry_flush_size_changes: Array of int64 of length
- * H5C2__MAX_NUM_TYPE_IDS + 1. The cells are used to record
- * the number of times an entry with type id equal to the
+ * entry_flush_size_changes: Array of int64 of length
+ * H5C2__MAX_NUM_TYPE_IDS + 1. The cells are used to record
+ * the number of times an entry with type id equal to the
* array index has changed size while in its flush callback.
*
- * cache_flush_size_changes: Array of int64 of length
- * H5C2__MAX_NUM_TYPE_IDS + 1. The cells are used to record
- * the number of times an entry with type id equal to the
+ * cache_flush_size_changes: Array of int64 of length
+ * H5C2__MAX_NUM_TYPE_IDS + 1. The cells are used to record
+ * the number of times an entry with type id equal to the
* array index has changed size during a cache flush
*
* total_ht_insertions: Number of times entries have been inserted into the
@@ -1278,7 +1467,7 @@ struct H5C2_t
int64_t cache_hits;
int64_t cache_accesses;
-
+
hbool_t mdj_enabled;
hbool_t trans_in_progress;
char trans_api_name[H5C2__MAX_API_NAME_LEN];
@@ -1286,7 +1475,7 @@ struct H5C2_t
uint64_t last_trans_on_disk;
int32_t jnl_magic;
int32_t jnl_file_name_len;
- char jnl_file_name[H5C2__MAX_JOURNAL_FILE_NAME_LEN
+ char jnl_file_name[H5C2__MAX_JOURNAL_FILE_NAME_LEN
+ 1];
struct H5C2_jbrb_t mdj_jbrb;
int32_t tl_len;
@@ -1302,7 +1491,7 @@ struct H5C2_t
int32_t num_mdjsc_cbs;
int32_t mdjsc_cb_tbl_fl_head;
int32_t mdjsc_cb_tbl_max_idx_in_use;
-
+
#if H5C2_COLLECT_CACHE_STATS
/* stats fields */
@@ -1468,10 +1657,10 @@ struct H5C2_t
*
* 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
+ * - 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
+ * in the current transaction. At the end of the transaction, this
* list is used to generate the needed journal entries.
*
* JRM -- 3/27/08
@@ -1720,70 +1909,70 @@ if ( ( (entry_ptr) == NULL ) || \
#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)++; \
+ 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)++; \
+ 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; \
+ 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
@@ -1974,7 +2163,7 @@ if ( ( (entry_ptr) == NULL ) || \
* More pinned entry stats related updates.
*
* JRM -- 3/31/07
- * Updated H5C2__UPDATE_STATS_FOR_PROTECT() to keep stats on
+ * Updated H5C2__UPDATE_STATS_FOR_PROTECT() to keep stats on
* read and write protects.
*
***********************************************************************/
@@ -2010,22 +2199,22 @@ if ( ( (entry_ptr) == NULL ) || \
(((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])++; \
+ 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) \
@@ -2049,9 +2238,9 @@ if ( ( (entry_ptr) == NULL ) || \
#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)->accesses = 0; \
+ (entry_ptr)->clears = 0; \
+ (entry_ptr)->flushes = 0; \
(entry_ptr)->pins = 0;
#define H5C2__UPDATE_STATS_FOR_CLEAR(cache_ptr, entry_ptr) \
@@ -2277,100 +2466,100 @@ if ( ( (entry_ptr) == NULL ) || \
#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 ) || \
+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") \
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, fail_val, \
+ "Pre HT insert SC failed") \
}
-#define H5C2__PRE_HT_REMOVE_SC(cache_ptr, entry_ptr) \
+#define H5C2__PRE_HT_REMOVE_SC(cache_ptr, entry_ptr) \
if ( ( (cache_ptr) == NULL ) || \
- ( (cache_ptr)->magic != H5C2__H5C2_T_MAGIC ) || \
+ ( (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))] \
+ ( 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))] \
+ ( ( ((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))] == \
+ ( ( ((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) ) || \
+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") \
+ ( 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") \
+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") \
+ ( ((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__POST_HT_ENTRY_SIZE_CHANGE_SC(cache_ptr, old_size, new_size) \
+#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) > (cache_ptr)->index_size ) || \
+ ( (new_size) <= 0 ) || \
+ ( (old_size) > (cache_ptr)->index_size ) || \
+ ( (new_size) <= 0 ) || \
( ( (cache_ptr)->index_len == 1 ) && \
- ( (cache_ptr)->index_size != (new_size) ) ) ) { \
+ ( (cache_ptr)->index_size != (old_size) ) ) ) { \
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
- "Post HT entry size change SC failed") \
+ "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 */
@@ -2387,30 +2576,30 @@ if ( ( (cache_ptr) == NULL ) || \
#define H5C2__INSERT_IN_INDEX(cache_ptr, entry_ptr, fail_val) \
-{ \
- int k; \
+{ \
+ 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; \
+ 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) \
+#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); \
+ 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; \
@@ -2427,79 +2616,79 @@ if ( ( (cache_ptr) == 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) \
+ H5C2__UPDATE_STATS_FOR_HT_DELETION(cache_ptr) \
}
-#define H5C2__SEARCH_INDEX(cache_ptr, Addr, entry_ptr, fail_val) \
-{ \
- int k; \
- int depth = 0; \
+#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 ) \
- { \
+ 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); \
+ 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; \
+{ \
+ 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 ) \
- { \
+ 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); \
+ 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; \
+ (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) \
}
@@ -2553,12 +2742,12 @@ if ( ( (cache_ptr) == NULL ) || \
* JRM -- 8/25/06
* Added the H5C2_DO_SANITY_CHECKS version of the macro.
*
- * This version maintains the slist_len_increase and
+ * 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
+ * All this is needed as the fractal heap needs to be
+ * able to dirty, resize and/or rename entries during the
* flush.
*
*-------------------------------------------------------------------------
@@ -2566,10 +2755,10 @@ if ( ( (cache_ptr) == NULL ) || \
#if H5C2_DO_SANITY_CHECKS
-#define H5C2__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, fail_val) \
+#define H5C2__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, fail_val) \
{ \
HDassert( (cache_ptr) ); \
- HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
+ HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (entry_ptr) ); \
HDassert( (entry_ptr)->size > 0 ); \
HDassert( H5F_addr_defined((entry_ptr)->addr) ); \
@@ -2593,10 +2782,10 @@ if ( ( (cache_ptr) == NULL ) || \
#else /* H5C2_DO_SANITY_CHECKS */
-#define H5C2__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, fail_val) \
+#define H5C2__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, fail_val) \
{ \
HDassert( (cache_ptr) ); \
- HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
+ HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (entry_ptr) ); \
HDassert( (entry_ptr)->size > 0 ); \
HDassert( H5F_addr_defined((entry_ptr)->addr) ); \
@@ -2645,16 +2834,16 @@ if ( ( (cache_ptr) == NULL ) || \
* Switched over to using skip list routines.
*
* JRM -- 3/28/07
- * Updated sanity checks for the new is_read_only and
+ * 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) \
+#define H5C2__REMOVE_ENTRY_FROM_SLIST(cache_ptr, entry_ptr) \
{ \
HDassert( (cache_ptr) ); \
- HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
+ HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (entry_ptr) ); \
HDassert( !((entry_ptr)->is_protected) ); \
HDassert( !((entry_ptr)->is_read_only) ); \
@@ -2693,11 +2882,11 @@ if ( ( (cache_ptr) == NULL ) || \
* JRM -- 8/27/06
* Added the H5C2_DO_SANITY_CHECKS version of the macro.
*
- * This version maintains the slist_size_increase field
+ * 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
+ * All this is needed as the fractal heap needs to be
+ * able to dirty, resize and/or rename entries during the
* flush.
*
*-------------------------------------------------------------------------
@@ -2706,46 +2895,46 @@ if ( ( (cache_ptr) == NULL ) || \
#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) ) ); \
+{ \
+ 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) ) ); \
+{ \
+ 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 */
@@ -2788,7 +2977,7 @@ if ( ( (cache_ptr) == NULL ) || \
* to do if called for such an entry.
*
* JRM -- 3/28/07
- * Added sanity checks using the new is_read_only and
+ * Added sanity checks using the new is_read_only and
* ro_ref_count fields of struct H5C2_cache_entry_t.
*
* JRM -- 3/29/08
@@ -2801,99 +2990,99 @@ if ( ( (cache_ptr) == NULL ) || \
#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.\
- */ \
- \
+{ \
+ 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)) \
- \
+ (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 ) { \
+ (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)) \
- \
+ (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 { \
+ (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)) \
- \
+ (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. */ \
- } \
+ (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 \
- */ \
- \
+{ \
+ 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)) \
- \
+ (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. */ \
- } \
+ (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 */
@@ -2936,7 +3125,7 @@ if ( ( (cache_ptr) == NULL ) || \
* 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
+ * Added sanity checks for the new is_read_only and
* ro_ref_count fields of struct H5C2_cache_entry_t.
*
* JRM -- 3/29/08
@@ -2948,10 +3137,10 @@ if ( ( (cache_ptr) == NULL ) || \
#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS
-#define H5C2__UPDATE_RP_FOR_EVICTION(cache_ptr, entry_ptr, fail_val) \
+#define H5C2__UPDATE_RP_FOR_EVICTION(cache_ptr, entry_ptr, fail_val) \
{ \
HDassert( (cache_ptr) ); \
- HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
+ HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (entry_ptr) ); \
HDassert( !((entry_ptr)->is_protected) ); \
HDassert( !((entry_ptr)->is_read_only) ); \
@@ -2964,7 +3153,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
/* remove the entry from the LRU list. */ \
\
- H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ 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)) \
\
@@ -2976,12 +3165,12 @@ if ( ( (cache_ptr) == NULL ) || \
\
if ( (entry_ptr)->is_dirty ) { \
\
- H5C2__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->dLRU_head_ptr, \
+ 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, \
+ 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)) \
@@ -2991,10 +3180,10 @@ if ( ( (cache_ptr) == NULL ) || \
#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */
-#define H5C2__UPDATE_RP_FOR_EVICTION(cache_ptr, entry_ptr, fail_val) \
+#define H5C2__UPDATE_RP_FOR_EVICTION(cache_ptr, entry_ptr, fail_val) \
{ \
HDassert( (cache_ptr) ); \
- HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
+ HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (entry_ptr) ); \
HDassert( !((entry_ptr)->is_protected) ); \
HDassert( !((entry_ptr)->is_read_only) ); \
@@ -3007,7 +3196,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
/* remove the entry from the LRU list. */ \
\
- H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ 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)) \
\
@@ -3067,10 +3256,10 @@ if ( ( (cache_ptr) == NULL ) || \
#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS
-#define H5C2__UPDATE_RP_FOR_FLUSH(cache_ptr, entry_ptr, fail_val) \
+#define H5C2__UPDATE_RP_FOR_FLUSH(cache_ptr, entry_ptr, fail_val) \
{ \
HDassert( (cache_ptr) ); \
- HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
+ HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (entry_ptr) ); \
HDassert( !((entry_ptr)->is_protected) ); \
HDassert( !((entry_ptr)->is_read_only) ); \
@@ -3086,12 +3275,12 @@ if ( ( (cache_ptr) == NULL ) || \
* head. \
*/ \
\
- H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ 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, \
+ 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)) \
@@ -3108,18 +3297,18 @@ if ( ( (cache_ptr) == NULL ) || \
*/ \
\
if ( (entry_ptr)->is_dirty ) { \
- H5C2__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->dLRU_head_ptr, \
+ 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, \
+ 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, \
+ 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)) \
@@ -3130,10 +3319,10 @@ if ( ( (cache_ptr) == NULL ) || \
#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */
-#define H5C2__UPDATE_RP_FOR_FLUSH(cache_ptr, entry_ptr, fail_val) \
+#define H5C2__UPDATE_RP_FOR_FLUSH(cache_ptr, entry_ptr, fail_val) \
{ \
HDassert( (cache_ptr) ); \
- HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
+ HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (entry_ptr) ); \
HDassert( !((entry_ptr)->is_protected) ); \
HDassert( !((entry_ptr)->is_read_only) ); \
@@ -3149,12 +3338,12 @@ if ( ( (cache_ptr) == NULL ) || \
* head. \
*/ \
\
- H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ 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, \
+ 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)) \
@@ -3203,7 +3392,7 @@ if ( ( (cache_ptr) == NULL ) || \
* Inserted an assert to verify this.
*
* JRM - 8/9/06
- * Not any more. We must now allow insertion of pinned
+ * Not any more. We must now allow insertion of pinned
* entries. Updated macro to support this.
*
* JRM - 3/28/07
@@ -3211,13 +3400,13 @@ if ( ( (cache_ptr) == NULL ) || \
* 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
+ * 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
+ * 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.
*
@@ -3226,10 +3415,10 @@ if ( ( (cache_ptr) == NULL ) || \
#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS
-#define H5C2__UPDATE_RP_FOR_INSERTION(cache_ptr, entry_ptr, fail_val) \
+#define H5C2__UPDATE_RP_FOR_INSERTION(cache_ptr, entry_ptr, fail_val) \
{ \
HDassert( (cache_ptr) ); \
- HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
+ HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (entry_ptr) ); \
HDassert( !((entry_ptr)->is_protected) ); \
HDassert( !((entry_ptr)->is_read_only) ); \
@@ -3241,7 +3430,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
if ( (entry_ptr)->is_pinned ) { \
\
- H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->pel_head_ptr, \
+ 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)) \
@@ -3250,7 +3439,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
HDassert( (cache_ptr)->mdj_enabled ); \
HDassert( (cache_ptr)->trans_in_progress ); \
- H5C2__DLL_PREPEND((entry_ptr), \
+ H5C2__DLL_PREPEND((entry_ptr), \
((cache_ptr)->jwipl_head_ptr), \
((cache_ptr)->jwipl_tail_ptr), \
((cache_ptr)->jwipl_len), \
@@ -3262,7 +3451,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
/* insert the entry at the head of the LRU list. */ \
\
- H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ 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)) \
@@ -3272,12 +3461,12 @@ if ( ( (cache_ptr) == NULL ) || \
*/ \
\
if ( entry_ptr->is_dirty ) { \
- H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->dLRU_head_ptr, \
+ 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, \
+ 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)) \
@@ -3289,10 +3478,10 @@ if ( ( (cache_ptr) == NULL ) || \
#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */
-#define H5C2__UPDATE_RP_FOR_INSERTION(cache_ptr, entry_ptr, fail_val) \
+#define H5C2__UPDATE_RP_FOR_INSERTION(cache_ptr, entry_ptr, fail_val) \
{ \
HDassert( (cache_ptr) ); \
- HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
+ HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (entry_ptr) ); \
HDassert( !((entry_ptr)->is_protected) ); \
HDassert( !((entry_ptr)->is_read_only) ); \
@@ -3304,7 +3493,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
if ( (entry_ptr)->is_pinned ) { \
\
- H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->pel_head_ptr, \
+ 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)) \
@@ -3313,7 +3502,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
HDassert( (cache_ptr)->mdj_enabled ); \
HDassert( (cache_ptr)->trans_in_progress ); \
- H5C2__DLL_PREPEND((entry_ptr), \
+ H5C2__DLL_PREPEND((entry_ptr), \
((cache_ptr)->jwipl_head_ptr), \
((cache_ptr)->jwipl_tail_ptr), \
((cache_ptr)->jwipl_len), \
@@ -3325,7 +3514,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
/* insert the entry at the head of the LRU list. */ \
\
- H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ 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)) \
@@ -3341,13 +3530,13 @@ if ( ( (cache_ptr) == NULL ) || \
*
* 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
+ * 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
+ * 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
@@ -3371,11 +3560,11 @@ if ( ( (cache_ptr) == NULL ) || \
#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS
-#define H5C2__UPDATE_RP_FOR_JOURNAL_WRITE_COMPLETE(cache_ptr, entry_ptr, \
+#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)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (cache_ptr)->mdj_enabled ); \
HDassert( (entry_ptr) ); \
HDassert( !((entry_ptr)->is_protected) ); \
@@ -3386,7 +3575,7 @@ if ( ( (cache_ptr) == NULL ) || \
HDassert( (entry_ptr)->is_dirty ); \
HDassert( (entry_ptr)->last_trans == 0 ); \
\
- H5C2__DLL_REMOVE((entry_ptr), \
+ H5C2__DLL_REMOVE((entry_ptr), \
((cache_ptr)->jwipl_head_ptr), \
((cache_ptr)->jwipl_tail_ptr), \
((cache_ptr)->jwipl_len), \
@@ -3397,7 +3586,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
/* insert the entry at the head of the LRU list. */ \
\
- H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ 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)) \
@@ -3407,12 +3596,12 @@ if ( ( (cache_ptr) == NULL ) || \
*/ \
\
if ( entry_ptr->is_dirty ) { \
- H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->dLRU_head_ptr, \
+ 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, \
+ 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)) \
@@ -3424,11 +3613,11 @@ if ( ( (cache_ptr) == NULL ) || \
#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */
-#define H5C2__UPDATE_RP_FOR_JOURNAL_WRITE_COMPLETE(cache_ptr, entry_ptr, \
+#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)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (cache_ptr)->mdj_enabled ); \
HDassert( (entry_ptr) ); \
HDassert( !((entry_ptr)->is_protected) ); \
@@ -3439,7 +3628,7 @@ if ( ( (cache_ptr) == NULL ) || \
HDassert( (entry_ptr)->is_dirty ); \
HDassert( (entry_ptr)->last_trans == 0 ); \
\
- H5C2__DLL_REMOVE((entry_ptr), \
+ H5C2__DLL_REMOVE((entry_ptr), \
((cache_ptr)->jwipl_head_ptr), \
((cache_ptr)->jwipl_tail_ptr), \
((cache_ptr)->jwipl_len), \
@@ -3450,7 +3639,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
/* insert the entry at the head of the LRU list. */ \
\
- H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ 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)) \
@@ -3470,8 +3659,8 @@ if ( ( (cache_ptr) == NULL ) || \
* load from disk of the specified cache entry.
*
* Note that we update the replacement policy for load only
- * as a convenience -- the newly loaded entry will be
- * protected immediately. If this starts to eat up a
+ * as a convenience -- the newly loaded entry will be
+ * protected immediately. If this starts to eat up a
* significant number of cycles, we will have to re-work
* the code to avoid this step.
*
@@ -3497,10 +3686,10 @@ if ( ( (cache_ptr) == NULL ) || \
#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS
-#define H5C2__UPDATE_RP_FOR_LOAD(cache_ptr, entry_ptr, fail_val) \
+#define H5C2__UPDATE_RP_FOR_LOAD(cache_ptr, entry_ptr, fail_val) \
{ \
HDassert( (cache_ptr) ); \
- HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
+ HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (entry_ptr) ); \
HDassert( !((entry_ptr)->is_protected) ); \
HDassert( !((entry_ptr)->is_pinned) ); \
@@ -3513,7 +3702,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
/* insert the entry at the head of the LRU list. */ \
\
- H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ 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)) \
@@ -3523,12 +3712,12 @@ if ( ( (cache_ptr) == NULL ) || \
*/ \
\
if ( entry_ptr->is_dirty ) { \
- H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->dLRU_head_ptr, \
+ 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, \
+ 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)) \
@@ -3539,10 +3728,10 @@ if ( ( (cache_ptr) == NULL ) || \
#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */
-#define H5C2__UPDATE_RP_FOR_LOAD(cache_ptr, entry_ptr, fail_val) \
+#define H5C2__UPDATE_RP_FOR_LOAD(cache_ptr, entry_ptr, fail_val) \
{ \
HDassert( (cache_ptr) ); \
- HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
+ HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (entry_ptr) ); \
HDassert( !((entry_ptr)->is_protected) ); \
HDassert( !((entry_ptr)->is_pinned) ); \
@@ -3555,7 +3744,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
/* insert the entry at the head of the LRU list. */ \
\
- H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ 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)) \
@@ -3608,7 +3797,7 @@ if ( ( (cache_ptr) == NULL ) || \
* maintained by the replacement policy.
*
* JRM - 3/28/07
- * Added sanity checks based on the new is_read_only and
+ * 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
@@ -3620,10 +3809,10 @@ if ( ( (cache_ptr) == NULL ) || \
#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS
-#define H5C2__UPDATE_RP_FOR_PROTECT(cache_ptr, entry_ptr, fail_val) \
+#define H5C2__UPDATE_RP_FOR_PROTECT(cache_ptr, entry_ptr, fail_val) \
{ \
HDassert( (cache_ptr) ); \
- HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
+ HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (entry_ptr) ); \
HDassert( !((entry_ptr)->is_protected) ); \
HDassert( !((entry_ptr)->is_read_only) ); \
@@ -3632,7 +3821,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
if ( (entry_ptr)->is_pinned ) { \
\
- H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->pel_head_ptr, \
+ 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)) \
@@ -3641,7 +3830,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
HDassert( (cache_ptr)->mdj_enabled ); \
HDassert( (entry_ptr)->is_dirty ); \
- H5C2__DLL_REMOVE((entry_ptr), \
+ H5C2__DLL_REMOVE((entry_ptr), \
((cache_ptr)->jwipl_head_ptr), \
((cache_ptr)->jwipl_tail_ptr), \
((cache_ptr)->jwipl_len), \
@@ -3654,7 +3843,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
/* remove the entry from the LRU list. */ \
\
- H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ 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)) \
@@ -3665,14 +3854,14 @@ if ( ( (cache_ptr) == NULL ) || \
\
if ( (entry_ptr)->is_dirty ) { \
\
- H5C2__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->dLRU_head_ptr, \
+ 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, \
+ 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)) \
@@ -3685,7 +3874,7 @@ if ( ( (cache_ptr) == NULL ) || \
* pinned, now add the entry to the protected list. \
*/ \
\
- H5C2__DLL_APPEND((entry_ptr), (cache_ptr)->pl_head_ptr, \
+ 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)) \
@@ -3693,10 +3882,10 @@ if ( ( (cache_ptr) == NULL ) || \
#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */
-#define H5C2__UPDATE_RP_FOR_PROTECT(cache_ptr, entry_ptr, fail_val) \
+#define H5C2__UPDATE_RP_FOR_PROTECT(cache_ptr, entry_ptr, fail_val) \
{ \
HDassert( (cache_ptr) ); \
- HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
+ HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (entry_ptr) ); \
HDassert( !((entry_ptr)->is_protected) ); \
HDassert( !((entry_ptr)->is_read_only) ); \
@@ -3705,7 +3894,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
if ( (entry_ptr)->is_pinned ) { \
\
- H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->pel_head_ptr, \
+ 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)) \
@@ -3714,7 +3903,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
HDassert( (cache_ptr)->mdj_enabled ); \
HDassert( (entry_ptr)->is_dirty ); \
- H5C2__DLL_REMOVE((entry_ptr), \
+ H5C2__DLL_REMOVE((entry_ptr), \
((cache_ptr)->jwipl_head_ptr), \
((cache_ptr)->jwipl_tail_ptr), \
((cache_ptr)->jwipl_len), \
@@ -3727,7 +3916,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
/* remove the entry from the LRU list. */ \
\
- H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ 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)) \
@@ -3739,10 +3928,10 @@ if ( ( (cache_ptr) == NULL ) || \
* 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__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 */
@@ -3798,25 +3987,25 @@ if ( ( (cache_ptr) == NULL ) || \
* nothing to be done.
*
* JRM - 3/28/07
- * Added sanity checks using the new is_read_only and
+ * 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.
+ * 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, \
+#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( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (entry_ptr) ); \
HDassert( !((entry_ptr)->is_protected) ); \
HDassert( !((entry_ptr)->is_read_only) ); \
@@ -3837,7 +4026,7 @@ if ( ( (cache_ptr) == NULL ) || \
HDassert( (entry_ptr)->last_trans != 0 ); \
HDassert( was_dirty ); \
HDassert( (entry_ptr)->is_dirty ); \
- H5C2__DLL_REMOVE((entry_ptr), \
+ H5C2__DLL_REMOVE((entry_ptr), \
((cache_ptr)->jwipl_head_ptr), \
((cache_ptr)->jwipl_tail_ptr), \
((cache_ptr)->jwipl_len), \
@@ -3850,7 +4039,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
/* remove the entry from the LRU list */ \
\
- H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ 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)) \
@@ -3860,7 +4049,7 @@ if ( ( (cache_ptr) == NULL ) || \
*/ \
if ( was_dirty ) { \
\
- H5C2__AUX_DLL_REMOVE((entry_ptr), \
+ H5C2__AUX_DLL_REMOVE((entry_ptr), \
(cache_ptr)->dLRU_head_ptr, \
(cache_ptr)->dLRU_tail_ptr, \
(cache_ptr)->dLRU_list_len, \
@@ -3869,7 +4058,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
} else { \
\
- H5C2__AUX_DLL_REMOVE((entry_ptr), \
+ H5C2__AUX_DLL_REMOVE((entry_ptr), \
(cache_ptr)->cLRU_head_ptr, \
(cache_ptr)->cLRU_tail_ptr, \
(cache_ptr)->cLRU_list_len, \
@@ -3886,7 +4075,7 @@ if ( ( (cache_ptr) == NULL ) || \
HDassert( (cache_ptr)->mdj_enabled ); \
HDassert( (cache_ptr)->trans_in_progress ); \
HDassert( (entry_ptr)->is_dirty ); \
- H5C2__DLL_PREPEND((entry_ptr), \
+ H5C2__DLL_PREPEND((entry_ptr), \
((cache_ptr)->jwipl_head_ptr), \
((cache_ptr)->jwipl_tail_ptr), \
((cache_ptr)->jwipl_len), \
@@ -3896,7 +4085,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
/* begin modified LRU specific code */ \
\
- H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ 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)) \
@@ -3907,7 +4096,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
if ( (entry_ptr)->is_dirty ) { \
\
- H5C2__AUX_DLL_PREPEND((entry_ptr), \
+ H5C2__AUX_DLL_PREPEND((entry_ptr), \
(cache_ptr)->dLRU_head_ptr, \
(cache_ptr)->dLRU_tail_ptr, \
(cache_ptr)->dLRU_list_len, \
@@ -3916,7 +4105,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
} else { \
\
- H5C2__AUX_DLL_PREPEND((entry_ptr), \
+ H5C2__AUX_DLL_PREPEND((entry_ptr), \
(cache_ptr)->cLRU_head_ptr, \
(cache_ptr)->cLRU_tail_ptr, \
(cache_ptr)->cLRU_list_len, \
@@ -3931,11 +4120,11 @@ if ( ( (cache_ptr) == NULL ) || \
#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */
-#define H5C2__UPDATE_RP_FOR_RENAME(cache_ptr, entry_ptr, was_dirty, \
+#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( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (entry_ptr) ); \
HDassert( !((entry_ptr)->is_protected) ); \
HDassert( !((entry_ptr)->is_read_only) ); \
@@ -3956,7 +4145,7 @@ if ( ( (cache_ptr) == NULL ) || \
HDassert( (entry_ptr)->last_trans != 0 ); \
HDassert( was_dirty ); \
HDassert( (entry_ptr)->is_dirty ); \
- H5C2__DLL_REMOVE((entry_ptr), \
+ H5C2__DLL_REMOVE((entry_ptr), \
((cache_ptr)->jwipl_head_ptr), \
((cache_ptr)->jwipl_tail_ptr), \
((cache_ptr)->jwipl_len), \
@@ -3969,7 +4158,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
/* remove the entry from the LRU list */ \
\
- H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ 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)) \
@@ -3984,7 +4173,7 @@ if ( ( (cache_ptr) == NULL ) || \
HDassert( (cache_ptr)->mdj_enabled ); \
HDassert( (cache_ptr)->trans_in_progress ); \
HDassert( (entry_ptr)->is_dirty ); \
- H5C2__DLL_PREPEND((entry_ptr), \
+ H5C2__DLL_PREPEND((entry_ptr), \
((cache_ptr)->jwipl_head_ptr), \
((cache_ptr)->jwipl_tail_ptr), \
((cache_ptr)->jwipl_len), \
@@ -3994,7 +4183,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
/* begin modified LRU specific code */ \
\
- H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ 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)) \
@@ -4017,7 +4206,7 @@ if ( ( (cache_ptr) == NULL ) || \
* 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
+ * If it isn't pinned, the entry must handled by the
* replacement policy. Update the appropriate replacement
* policy data structures.
*
@@ -4033,13 +4222,13 @@ if ( ( (cache_ptr) == NULL ) || \
* Modifications:
*
* JRM -- 3/28/07
- * Added sanity checks based on the new is_read_only and
+ * 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
+ * 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.
*
@@ -4048,10 +4237,10 @@ if ( ( (cache_ptr) == NULL ) || \
#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS
-#define H5C2__UPDATE_RP_FOR_SIZE_CHANGE(cache_ptr, entry_ptr, new_size) \
+#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( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (entry_ptr) ); \
HDassert( !((entry_ptr)->is_protected) ); \
HDassert( !((entry_ptr)->is_read_only) ); \
@@ -4061,7 +4250,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
if ( (entry_ptr)->is_pinned ) { \
\
- H5C2__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->pel_len, \
+ H5C2__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->pel_len, \
(cache_ptr)->pel_size, \
(entry_ptr)->size, \
(new_size)); \
@@ -4070,7 +4259,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
HDassert( (cache_ptr)->mdj_enabled ); \
HDassert( (entry_ptr)->is_dirty ); \
- H5C2__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->jwipl_len, \
+ H5C2__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->jwipl_len, \
(cache_ptr)->jwipl_size, \
(entry_ptr)->size, \
(new_size)); \
@@ -4081,7 +4270,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
/* Update the size of the LRU list */ \
\
- H5C2__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->LRU_list_len, \
+ H5C2__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->LRU_list_len, \
(cache_ptr)->LRU_list_size, \
(entry_ptr)->size, \
(new_size)); \
@@ -4093,14 +4282,14 @@ if ( ( (cache_ptr) == NULL ) || \
\
if ( (entry_ptr)->is_dirty ) { \
\
- H5C2__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->dLRU_list_len, \
+ 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, \
+ H5C2__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->cLRU_list_len, \
(cache_ptr)->cLRU_list_size, \
(entry_ptr)->size, \
(new_size)); \
@@ -4113,10 +4302,10 @@ if ( ( (cache_ptr) == NULL ) || \
#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */
-#define H5C2__UPDATE_RP_FOR_SIZE_CHANGE(cache_ptr, entry_ptr, new_size) \
+#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( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (entry_ptr) ); \
HDassert( !((entry_ptr)->is_protected) ); \
HDassert( !((entry_ptr)->is_read_only) ); \
@@ -4126,7 +4315,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
if ( (entry_ptr)->is_pinned ) { \
\
- H5C2__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->pel_len, \
+ H5C2__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->pel_len, \
(cache_ptr)->pel_size, \
(entry_ptr)->size, \
(new_size)); \
@@ -4135,7 +4324,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
HDassert( (cache_ptr)->mdj_enabled ); \
HDassert( (entry_ptr)->is_dirty ); \
- H5C2__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->jwipl_len, \
+ H5C2__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->jwipl_len, \
(cache_ptr)->jwipl_size, \
(entry_ptr)->size, \
(new_size)); \
@@ -4146,7 +4335,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
/* Update the size of the LRU list */ \
\
- H5C2__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->LRU_list_len, \
+ H5C2__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr)->LRU_list_len, \
(cache_ptr)->LRU_list_size, \
(entry_ptr)->size, \
(new_size)); \
@@ -4182,11 +4371,11 @@ if ( ( (cache_ptr) == NULL ) || \
* Modifications:
*
* JRM -- 3/28/07
- * Added sanity checks based on the new is_read_only and
+ * 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
+ * Added code to place the newly unpinned entry on the
* journal write pending list if appropriate.
*
*-------------------------------------------------------------------------
@@ -4194,10 +4383,10 @@ if ( ( (cache_ptr) == NULL ) || \
#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS
-#define H5C2__UPDATE_RP_FOR_UNPIN(cache_ptr, entry_ptr, fail_val) \
+#define H5C2__UPDATE_RP_FOR_UNPIN(cache_ptr, entry_ptr, fail_val) \
{ \
HDassert( (cache_ptr) ); \
- HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
+ HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (entry_ptr) ); \
HDassert( !((entry_ptr)->is_protected) ); \
HDassert( !((entry_ptr)->is_read_only) ); \
@@ -4208,7 +4397,7 @@ if ( ( (cache_ptr) == NULL ) || \
/* Regardless of the replacement policy, remove the entry from the \
* pinned entry list. \
*/ \
- H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->pel_head_ptr, \
+ 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)) \
\
@@ -4217,7 +4406,7 @@ if ( ( (cache_ptr) == NULL ) || \
/* put the entry in the jwip list */ \
HDassert( (cache_ptr)->mdj_enabled ); \
HDassert( (entry_ptr)->is_dirty ); \
- H5C2__DLL_PREPEND((entry_ptr), \
+ H5C2__DLL_PREPEND((entry_ptr), \
((cache_ptr)->jwipl_head_ptr), \
((cache_ptr)->jwipl_tail_ptr), \
((cache_ptr)->jwipl_len), \
@@ -4229,7 +4418,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
/* insert the entry at the head of the LRU list. */ \
\
- H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ 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)) \
@@ -4240,7 +4429,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
if ( (entry_ptr)->is_dirty ) { \
\
- H5C2__AUX_DLL_PREPEND((entry_ptr), \
+ H5C2__AUX_DLL_PREPEND((entry_ptr), \
(cache_ptr)->dLRU_head_ptr, \
(cache_ptr)->dLRU_tail_ptr, \
(cache_ptr)->dLRU_list_len, \
@@ -4249,7 +4438,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
} else { \
\
- H5C2__AUX_DLL_PREPEND((entry_ptr), \
+ H5C2__AUX_DLL_PREPEND((entry_ptr), \
(cache_ptr)->cLRU_head_ptr, \
(cache_ptr)->cLRU_tail_ptr, \
(cache_ptr)->cLRU_list_len, \
@@ -4264,10 +4453,10 @@ if ( ( (cache_ptr) == NULL ) || \
#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */
-#define H5C2__UPDATE_RP_FOR_UNPIN(cache_ptr, entry_ptr, fail_val) \
+#define H5C2__UPDATE_RP_FOR_UNPIN(cache_ptr, entry_ptr, fail_val) \
{ \
HDassert( (cache_ptr) ); \
- HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
+ HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (entry_ptr) ); \
HDassert( !((entry_ptr)->is_protected) ); \
HDassert( !((entry_ptr)->is_read_only) ); \
@@ -4278,7 +4467,7 @@ if ( ( (cache_ptr) == NULL ) || \
/* Regardless of the replacement policy, remove the entry from the \
* pinned entry list. \
*/ \
- H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->pel_head_ptr, \
+ 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)) \
\
@@ -4287,7 +4476,7 @@ if ( ( (cache_ptr) == NULL ) || \
/* put the entry in the jwip list */ \
HDassert( (cache_ptr)->mdj_enabled ); \
HDassert( (entry_ptr)->is_dirty ); \
- H5C2__DLL_PREPEND((entry_ptr), \
+ H5C2__DLL_PREPEND((entry_ptr), \
((cache_ptr)->jwipl_head_ptr), \
((cache_ptr)->jwipl_tail_ptr), \
((cache_ptr)->jwipl_len), \
@@ -4299,7 +4488,7 @@ if ( ( (cache_ptr) == NULL ) || \
\
/* insert the entry at the head of the LRU list. */ \
\
- H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ 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)) \
@@ -4354,7 +4543,7 @@ if ( ( (cache_ptr) == NULL ) || \
* maintained by the replacement policy.
*
* JRM - 3/30/08
- * Modified macro to put un-pinned entries with pending
+ * Modified macro to put un-pinned entries with pending
* journal writes on the journal write in progress list.
*
*-------------------------------------------------------------------------
@@ -4362,10 +4551,10 @@ if ( ( (cache_ptr) == NULL ) || \
#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS
-#define H5C2__UPDATE_RP_FOR_UNPROTECT(cache_ptr, entry_ptr, fail_val) \
+#define H5C2__UPDATE_RP_FOR_UNPROTECT(cache_ptr, entry_ptr, fail_val) \
{ \
HDassert( (cache_ptr) ); \
- HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
+ HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (entry_ptr) ); \
HDassert( (entry_ptr)->is_protected); \
HDassert( (entry_ptr)->size > 0 ); \
@@ -4373,23 +4562,23 @@ if ( ( (cache_ptr) == NULL ) || \
/* Regardless of the replacement policy, remove the entry from the \
* protected list. \
*/ \
- H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->pl_head_ptr, \
+ 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)) \
+ 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), \
+ H5C2__DLL_PREPEND((entry_ptr), \
((cache_ptr)->jwipl_head_ptr), \
((cache_ptr)->jwipl_tail_ptr), \
((cache_ptr)->jwipl_len), \
@@ -4401,10 +4590,10 @@ if ( ( (cache_ptr) == NULL ) || \
\
/* 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)) \
+ 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. \
@@ -4412,17 +4601,17 @@ if ( ( (cache_ptr) == NULL ) || \
\
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)) \
+ 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)) \
+ 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. */ \
@@ -4432,10 +4621,10 @@ if ( ( (cache_ptr) == NULL ) || \
#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */
-#define H5C2__UPDATE_RP_FOR_UNPROTECT(cache_ptr, entry_ptr, fail_val) \
+#define H5C2__UPDATE_RP_FOR_UNPROTECT(cache_ptr, entry_ptr, fail_val) \
{ \
HDassert( (cache_ptr) ); \
- HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
+ HDassert( (cache_ptr)->magic == H5C2__H5C2_T_MAGIC ); \
HDassert( (entry_ptr) ); \
HDassert( (entry_ptr)->is_protected); \
HDassert( (entry_ptr)->size > 0 ); \
@@ -4443,13 +4632,13 @@ if ( ( (cache_ptr) == NULL ) || \
/* Regardless of the replacement policy, remove the entry from the \
* protected list. \
*/ \
- H5C2__DLL_REMOVE((entry_ptr), (cache_ptr)->pl_head_ptr, \
+ 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, \
+ 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)) \
@@ -4459,7 +4648,7 @@ if ( ( (cache_ptr) == NULL ) || \
/* put the entry in the jwip list */ \
HDassert( (cache_ptr)->mdj_enabled ); \
HDassert( (entry_ptr)->is_dirty ); \
- H5C2__DLL_PREPEND((entry_ptr), \
+ H5C2__DLL_PREPEND((entry_ptr), \
((cache_ptr)->jwipl_head_ptr), \
((cache_ptr)->jwipl_tail_ptr), \
((cache_ptr)->jwipl_len), \
@@ -4471,10 +4660,10 @@ if ( ( (cache_ptr) == NULL ) || \
\
/* 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)) \
+ 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. */ \
} \
@@ -4538,7 +4727,7 @@ if ( cache_ptr->mdj_enabled ) \
* 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
+ * list. If it is, remove it from the list, and set its
* last_trans field to zero.
*
* Return: N/A
@@ -4621,9 +4810,9 @@ if ( cache_ptr->mdj_enabled ) \
*
* Macro: H5C2__UPDATE_TL_FOR_ENTRY_SIZE_CHANGE
*
- * Purpose: Update the transaction list for a change in the size of
+ * Purpose: Update the transaction list for a change in the size of
* one of its constituents. Note that it is the callers
- * responsibility to verify that the entry is in the
+ * responsibility to verify that the entry is in the
* transaction list if it should be.
*
* Return: N/A
@@ -4647,5 +4836,84 @@ if ( ( (cache_ptr)->mdj_enabled ) && \
(old_size), (new_size)); \
} /* H5C2__UPDATE_TL_FOR_ENTRY_SIZE_CHANGE() */
-#endif /* _H5C2pkg_H */
+/*-------------------------------------------------------------------------
+ *
+ * Macro: H5C2__JBRB__UPDATE_STATS_FOR* macros
+ *
+ * Purpose: This set of macros exists to update the various journal
+ * buffer ring buffer stats fields when
+ * H5C2__JBRB__COLLECT_STATS is TRUE, and do nothing when
+ * it is false.
+ *
+ * Return: N/A
+ *
+ * Programmer: John Mainzer, 2/21/10
+ *
+ * Modifications:
+ *
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+
+#if H5C2__JBRB__COLLECT_STATS
+
+#define H5C2__JBRB__UPDATE_STATS_FOR_TRANS_COMPLETED(struct_ptr) \
+ ((struct_ptr)->transactions_completed)++;
+
+#define H5C2__JBRB__UPDATE_STATS_FOR_BUF_WRITE_QUEUED(struct_ptr, partial) \
+ ((struct_ptr)->buf_writes_queued)++; \
+ if ( partial ) { \
+ ((struct_ptr)->partial_buf_writes_queued)++; \
+ } else { \
+ ((struct_ptr)->full_buf_writes_queued)++; \
+ }
+
+#define H5C2__JBRB__UPDATE_STATS_FOR_BUF_WRITE_COMPLETE(struct_ptr, await) \
+ ((struct_ptr)->buf_writes_completed)++; \
+ if ( await ) { \
+ ((struct_ptr)->buf_writes_completed_by_await)++; \
+ } else { \
+ ((struct_ptr)->buf_writes_completed_by_test)++; \
+ }
+
+#define H5C2__JBRB__UPDATE_STATS_FOR_ASYNC_SYNCS_QUEUED(struct_ptr) \
+ ((struct_ptr)->async_syncs_queued)++; \
+ if (((struct_ptr)->max_sync_q_len) < ((struct_ptr)->aio_sync_q_len)) { \
+ (struct_ptr)->max_sync_q_len = (struct_ptr)->aio_sync_q_len; \
+ }
+
+#define H5C2__JBRB__UPDATE_STATS_FOR_ASYNC_SYNC_COMPLETED(struct_ptr, await) \
+ ((struct_ptr)->async_syncs_completed)++; \
+ if ( await ) { \
+ ((struct_ptr)->async_syncs_completed_by_await)++; \
+ } else { \
+ ((struct_ptr)->async_syncs_completed_by_test)++; \
+ }
+
+#define H5C2__JBRB__UPDATE_STATS_FOR_AIO_ERROR_CALL_AWAITING_SYNC(struct_ptr) \
+ ((struct_ptr)->calls_to_aio_error_awaiting_sync)++;
+
+#define H5C2__JBRB__UPDATE_STATS_FOR_CALL_TO_FSYNC(struct_ptr) \
+ ((struct_ptr)->calls_to_fsync)++;
+
+#else /* H5C2__JBRB__COLLECT_STATS */
+
+#define H5C2__JBRB__UPDATE_STATS_FOR_TRANS_COMPLETED(struct_ptr)
+
+#define H5C2__JBRB__UPDATE_STATS_FOR_BUF_WRITE_QUEUED(struct_ptr, partial)
+
+#define H5C2__JBRB__UPDATE_STATS_FOR_BUF_WRITE_COMPLETE(struct_ptr, await)
+
+#define H5C2__JBRB__UPDATE_STATS_FOR_ASYNC_SYNCS_QUEUED(struct_ptr)
+
+#define H5C2__JBRB__UPDATE_STATS_FOR_ASYNC_SYNC_COMPLETED(struct_ptr, await)
+
+#define H5C2__JBRB__UPDATE_STATS_FOR_AIO_ERROR_CALL_AWAITING_SYNC(struct_ptr)
+
+#define H5C2__JBRB__UPDATE_STATS_FOR_CALL_TO_FSYNC(struct_ptr)
+
+#endif /* H5C2__JBRB__COLLECT_STATS */
+#endif /* _H5C2pkg_H */
diff --git a/src/H5C2private.h b/src/H5C2private.h
index 0d053b0..5ac3748 100644
--- a/src/H5C2private.h
+++ b/src/H5C2private.h
@@ -107,13 +107,13 @@ typedef struct H5C2_t H5C2_t;
* name: Pointer to a string containing the name of the class of metadata
* cache entries.
*
- * mem_type: Instance of H5FD_mem_t, that is used to supply the
+ * mem_type: Instance of H5FD_mem_t, that is used to supply the
* mem type passed into H5F_block_read().
*
* deserialize: Pointer to the deserialize function.
*
* This function must be able to read an on disk image of a metadata
- * cache entry, allocate and load the equivalent in core representation,
+ * cache entry, allocate and load the equivalent in core representation,
* and return a pointer to that representation.
*
* The typedef for the deserialize callback is as follows:
@@ -140,8 +140,8 @@ typedef struct H5C2_t H5C2_t;
* mode, but the parameter may be unused when compiled in
* production mode.
*
- * image_ptr: Pointer to a buffer of length len containing the
- * contents of the file starting at addr and continuing
+ * image_ptr: Pointer to a buffer of length len containing the
+ * contents of the file starting at addr and continuing
* for len bytes.
*
* udata_ptr: Pointer to user data provided in the protect call, which
@@ -155,22 +155,22 @@ typedef struct H5C2_t H5C2_t;
* Processing in the deserialize function should proceed as follows:
*
* If the image contains valid data, and is of the correct length,
- * the deserialize function must allocate space for an in core
- * representation of that data, load the contents of the image into
- * the space allocated for the in core representation, and return
- * a pointer to the in core representation. Observe that an
- * instance of H5C2_cache_entry_t must be the first item in this
- * representation. It will have to be initialized appropriately
+ * the deserialize function must allocate space for an in core
+ * representation of that data, load the contents of the image into
+ * the space allocated for the in core representation, and return
+ * a pointer to the in core representation. Observe that an
+ * instance of H5C2_cache_entry_t must be the first item in this
+ * representation. It will have to be initialized appropriately
* after the callback returns.
*
* Note that the structure of the in core representation is otherwise
- * up to the cache client. All that is required is that the pointer
- * returned be sufficient for the clients purposes when it is returned
+ * up to the cache client. All that is required is that the pointer
+ * returned be sufficient for the clients purposes when it is returned
* on a protect call.
*
* If the deserialize function has to clean up file corruption
* left over from an old bug in the HDF5 library, it must set
- * *dirty_ptr to TRUE. If it doesn't, no action is needed as
+ * *dirty_ptr to TRUE. If it doesn't, no action is needed as
* *dirty_ptr will be set to FALSE before the deserialize call.
*
* If the operation fails for any reason (i.e. bad data in buffer, bad
@@ -214,18 +214,18 @@ typedef struct H5C2_t H5C2_t;
* serialize: Pointer to the serialize callback.
*
* The serialize callback is invoked by the metadata cache whenever
- * it needs a current on disk image of the metadata entry for purposes
+ * it needs a current on disk image of the metadata entry for purposes
* either constructing a journal or flushing the entry to disk.
*
- * At this point, one would think that the base address and length of
- * the length of the entry's image on disk would be well known.
- * However, that need not be the case as fractal heap blocks can
- * change size (and therefor possible location as well) on
- * serialization if compression is enabled. In the old H5C code,
- * this happened on a flush, and occasioned a rename in the midst
- * of the flush. To avoid this in H5C2, the serialize callback
- * will return the new base address, length, and image pointer to
- * the caller when necessary. The caller must then update the
+ * At this point, one would think that the base address and length of
+ * the length of the entry's image on disk would be well known.
+ * However, that need not be the case as fractal heap blocks can
+ * change size (and therefor possible location as well) on
+ * serialization if compression is enabled. In the old H5C code,
+ * this happened on a flush, and occasioned a rename in the midst
+ * of the flush. To avoid this in H5C2, the serialize callback
+ * will return the new base address, length, and image pointer to
+ * the caller when necessary. The caller must then update the
* metadata cache's internal structures accordingly.
*
* The typedef for the serialize callback is as follows:
@@ -237,19 +237,19 @@ typedef struct H5C2_t H5C2_t;
* void * image_ptr,
* void * thing,
* unsigned * flags_ptr,
- * haddr_t * new_addr_ptr,
- * size_t * new_len_ptr,
+ * haddr_t * new_addr_ptr,
+ * size_t * new_len_ptr,
* void ** new_image_ptr_ptr);
*
* The parameters of the serialize callback are as follows:
*
* f: File pointer -- needed if other metadata cache entries
- * must be modified in the process of serializing the
+ * must be modified in the process of serializing the
* target entry.
*
- * dxpl_id: dxpl_id passed with the file pointer to the cache, and
- * passed on to the callback. Necessary as some callbacks
- * revise the size and location of the target entry, or
+ * dxpl_id: dxpl_id passed with the file pointer to the cache, and
+ * passed on to the callback. Necessary as some callbacks
+ * revise the size and location of the target entry, or
* possibly other entries on serialize.
*
* addr: Base address in file of the entry to be serialized.
@@ -267,157 +267,157 @@ typedef struct H5C2_t H5C2_t;
* mode, but the parameter may be unused when compiled in
* production mode.
*
- * image_ptr: Pointer to a buffer of length len bytes into which a
- * serialized image of the target metadata cache entry is
+ * image_ptr: Pointer to a buffer of length len bytes into which a
+ * serialized image of the target metadata cache entry is
* to be written.
*
- * Note that this buffer will not in general be initialized
- * to any particular value. Thus the serialize function may
- * not assume any initial value and must set each byte in
+ * Note that this buffer will not in general be initialized
+ * to any particular value. Thus the serialize function may
+ * not assume any initial value and must set each byte in
* the buffer.
*
- * thing: Pointer to void containing the address of the in core
- * representation of the target metadata cache entry.
- * This is the same pointer returned by a protect of the
+ * thing: Pointer to void containing the address of the in core
+ * representation of the target metadata cache entry.
+ * This is the same pointer returned by a protect of the
* addr and len given above.
*
- * flags_ptr: Pointer to an unsigned integer used to return flags
- * indicating whether the resize function resized or renamed
- * the entry. If the entry was neither resized or renamed,
- * the serialize function must set *flags_ptr to zero.
- * H5C2__SERIALIZE_RESIZED_FLAG and H5C2__SERIALIZE_RENAMED_FLAG
+ * flags_ptr: Pointer to an unsigned integer used to return flags
+ * indicating whether the resize function resized or renamed
+ * the entry. If the entry was neither resized or renamed,
+ * the serialize function must set *flags_ptr to zero.
+ * H5C2__SERIALIZE_RESIZED_FLAG and H5C2__SERIALIZE_RENAMED_FLAG
* must be set to indicate a resize and a rename respectively.
*
- * If the H5C2__SERIALIZE_RESIZED_FLAG is set, the new length
- * and image pointer must be stored in *new_len_ptr and
- * *new_image_ptr_ptr respectively.
- *
- * If the H5C2__SERIALIZE_RENAMED_FLAG flag is also set, the
- * new image base address must be stored in *new_addr_ptr.
- * Observe that the H5C2__SERIALIZE_RENAMED_FLAG must not
- * appear without the H5C2__SERIALIZE_RESIZED_FLAG.
- *
- * Except as noted above, the locations pointed to by the
- * remaining parameters are undefined, and should be ignored
- * by the caller.
- *
- * new_addr_ptr: Pointer to haddr_t. If the entry is renamed by
- * the serialize function, the new on disk base address must
- * be stored in *new_addr_ptr. If the entry is not renamed
- * by the serialize function, *new_addr_ptr is undefined.
- *
- * new_len_ptr: Pointer to size_t. If the entry is resized by the
- * serialize function, the new length of the on disk image
- * must be stored in *new_len_ptr. If the entry is not
- * resized by the serialize function, *new_len_ptr is
- * undefined.
- *
- * new_image_ptr_ptr: Pointer to pointer to void. If the entry is
- * resized by the serialize function, the pointer to the
- * new buffer containing the on disk image must be stored
- * in *new_image_ptr_ptr. If the entry is not resized by
+ * If the H5C2__SERIALIZE_RESIZED_FLAG is set, the new length
+ * and image pointer must be stored in *new_len_ptr and
+ * *new_image_ptr_ptr respectively.
+ *
+ * If the H5C2__SERIALIZE_RENAMED_FLAG flag is also set, the
+ * new image base address must be stored in *new_addr_ptr.
+ * Observe that the H5C2__SERIALIZE_RENAMED_FLAG must not
+ * appear without the H5C2__SERIALIZE_RESIZED_FLAG.
+ *
+ * Except as noted above, the locations pointed to by the
+ * remaining parameters are undefined, and should be ignored
+ * by the caller.
+ *
+ * new_addr_ptr: Pointer to haddr_t. If the entry is renamed by
+ * the serialize function, the new on disk base address must
+ * be stored in *new_addr_ptr. If the entry is not renamed
+ * by the serialize function, *new_addr_ptr is undefined.
+ *
+ * new_len_ptr: Pointer to size_t. If the entry is resized by the
+ * serialize function, the new length of the on disk image
+ * must be stored in *new_len_ptr. If the entry is not
+ * resized by the serialize function, *new_len_ptr is
+ * undefined.
+ *
+ * new_image_ptr_ptr: Pointer to pointer to void. If the entry is
+ * resized by the serialize function, the pointer to the
+ * new buffer containing the on disk image must be stored
+ * in *new_image_ptr_ptr. If the entry is not resized by
* the serialize function, *new_image_ptr_ptr is undefined.
*
- * Processing in the serialize function should proceed as follows:
+ * Processing in the serialize function should proceed as follows:
*
- * The serialize function must examine the in core representation
- * indicated by the thing parameter, and write a serialized image
- * of its contents into the provided buffer.
+ * The serialize function must examine the in core representation
+ * indicated by the thing parameter, and write a serialized image
+ * of its contents into the provided buffer.
*
- * If the serialize function does not change the size or location
- * of the on disk image, it must set *flags_ptr to zero.
+ * If the serialize function does not change the size or location
+ * of the on disk image, it must set *flags_ptr to zero.
*
- * If the size of the on disk image must be changed, the serialize
- * function must free the old image buffer (base address in image_ptr),
- * allocate a new one, load the image into the new buffer, load the
- * base address of the new buffer into *new_image_ptr_ptr, load the
- * length of the new image into *new_len_ptr, and set the
- * H5C2__SERIALIZE_RESIZED_FLAG in *flags_ptr.
+ * If the size of the on disk image must be changed, the serialize
+ * function must free the old image buffer (base address in image_ptr),
+ * allocate a new one, load the image into the new buffer, load the
+ * base address of the new buffer into *new_image_ptr_ptr, load the
+ * length of the new image into *new_len_ptr, and set the
+ * H5C2__SERIALIZE_RESIZED_FLAG in *flags_ptr.
*
- * If in addition, the base address of the on disk image must
- * be changed, the serialize function must also set *new_addr_ptr
- * to the new base address, and set the H5C2__SERIALIZE_RENAMED_FLAG
+ * If in addition, the base address of the on disk image must
+ * be changed, the serialize function must also set *new_addr_ptr
+ * to the new base address, and set the H5C2__SERIALIZE_RENAMED_FLAG
* in *flags_ptr.
*
- * If it is successful, the function must return SUCCEED.
+ * If it is successful, the function must return SUCCEED.
*
* If it fails for any reason, the function must return FAIL and
- * push error information on the error stack with the error API
+ * push error information on the error stack with the error API
* routines.
*
*
* free_icr: Pointer to the free ICR Callback.
*
- * The free ICR callback is invoked by the metadata cache when it
- * wishes to evict an entry, and needs the client to free the memory
- * allocated for the in core representation.
+ * The free ICR callback is invoked by the metadata cache when it
+ * wishes to evict an entry, and needs the client to free the memory
+ * allocated for the in core representation.
*
- * The typedef for the free ICR callback is as follows:
+ * The typedef for the free ICR callback is as follows:
*
- * typedef herr_t (*N5C_free_icr_func_t)(haddr_t addr,
+ * typedef herr_t (*N5C_free_icr_func_t)(haddr_t addr,
* size_t len,
* void * thing);
+ *
+ * The parameters of the free ICR callback are as follows:
*
- * The parameters of the free ICR callback are as follows:
+ * addr: Base address in file of the entry being evicted.
*
- * addr: Base address in file of the entry being evicted.
+ * This parameter is supplied mainly for sanity checking.
+ * Sanity checks should be performed when compiled in debug
+ * mode, but the parameter may be unused when compiled in
+ * production mode.
*
- * This parameter is supplied mainly for sanity checking.
- * Sanity checks should be performed when compiled in debug
- * mode, but the parameter may be unused when compiled in
- * production mode.
+ * len: Length of the in file image of the entry being evicted
+ * in bytes.
*
- * len: Length of the in file image of the entry being evicted
- * in bytes.
+ * This parameter is supplied mainly for sanity checking.
+ * Sanity checks should be performed when compiled in debug
+ * mode, but the parameter may be unused when compiled in
+ * production mode.
*
- * This parameter is supplied mainly for sanity checking.
- * Sanity checks should be performed when compiled in debug
- * mode, but the parameter may be unused when compiled in
- * production mode.
+ * thing: Pointer to void containing the address of the in core
+ * representation of the target metadata cache entry. This
+ * is the same pointer that would be returned by a protect
+ * of the addr and len above.
*
- * thing: Pointer to void containing the address of the in core
- * representation of the target metadata cache entry. This
- * is the same pointer that would be returned by a protect
- * of the addr and len above.
+ * Processing in the free ICR function should proceed as follows:
*
- * Processing in the free ICR function should proceed as follows:
+ * The free ICR function must free all memory allocated to the
+ * in core representation.
*
- * The free ICR function must free all memory allocated to the
- * in core representation.
+ * If the function is successful, it must return SUCCEED.
*
- * If the function is successful, it must return SUCCEED.
+ * If it fails for any reason, the function must return FAIL and
+ * push error information on the error stack with the error API
+ * routines.
*
- * If it fails for any reason, the function must return FAIL and
- * push error information on the error stack with the error API
- * routines.
- *
- * At least when compiled with debug, it would be useful if the
- * free ICR call would fail if the in core representation has been
+ * At least when compiled with debug, it would be useful if the
+ * free ICR call would fail if the in core representation has been
* modified since the last serialize of clear callback.
*
*
* clear_dirty_bits: Pointer to the clear dirty bits callback.
*
- * For sanity checking purposes, it will be useful if cache clients
- * track whether an in core representation has been modified since
- * the last time it was serialized. This data is used to flag an
- * error if the cache attempts to free an in core representation
- * that has not been serialized since the last time it was modified.
+ * For sanity checking purposes, it will be useful if cache clients
+ * track whether an in core representation has been modified since
+ * the last time it was serialized. This data is used to flag an
+ * error if the cache attempts to free an in core representation
+ * that has not been serialized since the last time it was modified.
*
- * If this happens, either the client forgot to tell the cache that
- * an entry is dirty, or the cache forgot to flush a dirty entry
- * before evicting it. In either case we want to know before we
- * get file corruption complaints.
+ * If this happens, either the client forgot to tell the cache that
+ * an entry is dirty, or the cache forgot to flush a dirty entry
+ * before evicting it. In either case we want to know before we
+ * get file corruption complaints.
*
- * However, in some cases, we want to mark an entry as clean even
- * though it has not been flushed to disk -- most particularly in
- * the parallel case. Thus we need some way to tell the client
- * that a free of the associated ICR is OK even though it has
- * been modified since the last serialization. Hence the clear
- * dirty bits callback.
+ * However, in some cases, we want to mark an entry as clean even
+ * though it has not been flushed to disk -- most particularly in
+ * the parallel case. Thus we need some way to tell the client
+ * that a free of the associated ICR is OK even though it has
+ * been modified since the last serialization. Hence the clear
+ * dirty bits callback.
*
- * Since the clear dirty bits callback is purely for sanity checking,
- * it is called only when we compile with debug.
+ * Since the clear dirty bits callback is purely for sanity checking,
+ * it is called only when we compile with debug.
*
* The typedef for the clear callback is as follows:
*
@@ -425,27 +425,27 @@ typedef struct H5C2_t H5C2_t;
* size_t len,
* void * thing);
*
- * The parameters of the clear callback are as follows:
+ * The parameters of the clear callback are as follows:
*
- * addr: Base address in file of the entry whose dirty bits
- * are being cleared
+ * addr: Base address in file of the entry whose dirty bits
+ * are being cleared
*
- * len: Length in bytes of the in file image of the entry
- * whose dirty bits are being cleared.
+ * len: Length in bytes of the in file image of the entry
+ * whose dirty bits are being cleared.
*
- * thing: Pointer to void containing the address of the in
- * core representation of the target metadata cache entry.
- * This is the same pointer that would be returned by a
- * protect of the addr and len above.
+ * thing: Pointer to void containing the address of the in
+ * core representation of the target metadata cache entry.
+ * This is the same pointer that would be returned by a
+ * protect of the addr and len above.
*
- * Processing in the clear callback function should proceed as follows:
+ * Processing in the clear callback function should proceed as follows:
*
- * The function must clear any dirty bits associated with the ICR.
+ * The function must clear any dirty bits associated with the ICR.
*
- * If successful, the function must return SUCCEED.
+ * If successful, the function must return SUCCEED.
*
- * If it fails for any reason, the function must return FAIL and
- * push error information on the error stack with the error API
+ * If it fails for any reason, the function must return FAIL and
+ * push error information on the error stack with the error API
* routines.
*
***************************************************************************/
@@ -454,7 +454,7 @@ typedef void *(*H5C2_deserialize_func_t)(haddr_t addr,
const void * image_ptr,
void * udata_ptr,
hbool_t * dirty_ptr);
-
+
typedef herr_t (*H5C2_image_len_func_t)(const void *thing,
size_t *image_len_ptr);
@@ -467,12 +467,12 @@ typedef herr_t (*H5C2_serialize_func_t)(const H5F_t *f,
size_t len,
void * image_ptr,
void * thing,
- unsigned * flags_ptr,
- haddr_t * new_addr_ptr,
- size_t * new_len_ptr,
+ unsigned * flags_ptr,
+ haddr_t * new_addr_ptr,
+ size_t * new_len_ptr,
void ** new_image_ptr_ptr);
-typedef herr_t (*H5C2_free_icr_func_t)(haddr_t addr,
+typedef herr_t (*H5C2_free_icr_func_t)(haddr_t addr,
size_t len,
void * thing);
@@ -543,23 +543,23 @@ typedef herr_t (*H5C2_log_flush_func_t)(H5C2_t * cache_ptr,
*
* JRM - 4/26/04
*
- * magic: Unsigned 32 bit integer that must always be set to
+ * magic: Unsigned 32 bit integer that must always be set to
* H5C2__H5C2_CACHE_ENTRY_T_MAGIC when the entry is valid.
* The field must be set to H5C2__H5C2_CACHE_ENTRY_T_BAD_MAGIC
* just before the entry is freed.
*
- * This is necessary, as the LRU list can be changed out
+ * This is necessary, as the LRU list can be changed out
* from under H5C2_make_space_in_cache() by the serialize
* callback which may change the size of an existing entry,
* and/or load a new entry while serializing the target entry.
*
- * This in turn can cause a recursive call to
+ * This in turn can cause a recursive call to
* H5C2_make_space_in_cache() which may either flush or evict
* the next entry that the first invocation of that function
* was about to examine.
*
* The magic field allows H5C2_make_space_in_cache() to
- * detect this case, and re-start its scan from the bottom
+ * detect this case, and re-start its scan from the bottom
* of the LRU when this situation occurs.
*
* cache_ptr: Pointer to the cache that this entry is contained within.
@@ -580,8 +580,8 @@ typedef herr_t (*H5C2_log_flush_func_t)(H5C2_t * cache_ptr,
* block of memory on disk. The image of this block (i.e.
* the on disk image) is stored in *image_ptr (discussed below).
*
- * image_ptr: Pointer to void. When not NULL, this field points to a
- * dynamically allocated block of size bytes in which the
+ * image_ptr: Pointer to void. When not NULL, this field points to a
+ * dynamically allocated block of size bytes in which the
* on disk image of the metadata cache entry is stored.
*
* If the entry is dirty, the serialize callback must be used
@@ -645,20 +645,20 @@ typedef herr_t (*H5C2_log_flush_func_t)(H5C2_t * cache_ptr,
* Note that protected entries are removed from the LRU lists
* and inserted on the protected list.
*
- * is_read_only: Boolean flag that is only meaningful if is_protected is
- * TRUE. In this circumstance, it indicates whether the
+ * is_read_only: Boolean flag that is only meaningful if is_protected is
+ * TRUE. In this circumstance, it indicates whether the
* entry has been protected read only, or read/write.
*
* If the entry has been protected read only (i.e. is_protected
- * and is_read_only are both TRUE), we allow the entry to be
+ * and is_read_only are both TRUE), we allow the entry to be
* protected more than once.
*
- * In this case, the number of readers is maintained in the
+ * In this case, the number of readers is maintained in the
* ro_ref_count field (see below), and unprotect calls simply
* decrement that field until it drops to zero, at which point
* the entry is actually unprotected.
*
- * ro_ref_count: Integer field used to maintain a count of the number of
+ * ro_ref_count: Integer field used to maintain a count of the number of
* outstanding read only protects on this entry. This field
* must be zero whenever either is_protected or is_read_only
* are TRUE.
@@ -720,7 +720,7 @@ typedef herr_t (*H5C2_log_flush_func_t)(H5C2_t * cache_ptr,
* is in the process of being flushed. This allows the cache
* to detect when a call is the result of a flush callback.
*
- * destroy_in_progress: Boolean flag that is set to true iff the entry
+ * destroy_in_progress: Boolean flag that is set to true iff the entry
* is in the process of being flushed and destroyed.
*
*
@@ -811,24 +811,24 @@ typedef herr_t (*H5C2_log_flush_func_t)(H5C2_t * cache_ptr,
* the specified transaction has made it to disk, we will
* reset this field to zero as well.
*
- * We must maintain this field, as to avoid messages from
- * the future, we must not flush a dirty entry to disk
- * until the last transaction in which it was dirtied
+ * We must maintain this field, as to avoid messages from
+ * the future, we must not flush a dirty entry to disk
+ * until the last transaction in which it was dirtied
* has made it to disk in the journal file.
*
- * trans_next: Next pointer in the entries modified in the current
+ * trans_next: Next pointer in the entries modified in the current
* transaction list. This field should always be null
- * unless journaling is enabled, the entry is dirty,
+ * unless journaling is enabled, the entry is dirty,
* and last_trans field contains the current transaction
- * number. Even if all these conditions are fulfilled,
- * the field will still be NULL if this is the last
+ * number. Even if all these conditions are fulfilled,
+ * the field will still be NULL if this is the last
* entry on the list.
*
- * trans_prev: Previous pointer in the entries modified in the current
+ * trans_prev: Previous pointer in the entries modified in the current
* transaction list. This field should always be null
- * unless journaling is enabled, the entry is dirty,
+ * unless journaling is enabled, the entry is dirty,
* and last_trans field contains the current transaction
- * number. Even if all these conditions are fulfilled,
+ * number. Even if all these conditions are fulfilled,
* the field will still be NULL if this is the first
* entry on the list.
*
@@ -1045,7 +1045,7 @@ typedef struct H5C2_cache_entry_t
*
*
* With a little thought, it should be obvious that the above flash
- * cache size increase algorithm is not sufficient for all
+ * cache size increase algorithm is not sufficient for all
* circumstances -- for example, suppose the user round robins through
* (1/flash_threshold) +1 groups, adding one data set to each on each
* pass. Then all will increase in size at about the same time, requiring
@@ -1062,11 +1062,11 @@ typedef struct H5C2_cache_entry_t
* flash_incr_mode section. This field is ignored unless flash_incr_mode
* is H5C_flash_incr__add_space.
*
- * flash_threshold: Double containing the factor by which current max cache
- * size is multiplied to obtain the size threshold for the add_space
- * flash increment algorithm. The field is ignored unless
+ * flash_threshold: Double containing the factor by which current max cache
+ * size is multiplied to obtain the size threshold for the add_space
+ * flash increment algorithm. The field is ignored unless
* flash_incr_mode is H5C2_flash_incr__add_space.
- *
+ *
*
* Cache size decrease control fields:
*
@@ -1195,7 +1195,7 @@ typedef struct H5C2_cache_entry_t
#define H5C2__MAX_JBRB_BUF_SIZE ((size_t)(2 * 1024 * 1024))
#define H5C2__MIN_JBRB_NUM_BUFS 1
-#define H5C2__MAX_JBRB_NUM_BUFS 100
+#define H5C2__MAX_JBRB_NUM_BUFS 256
enum H5C2_resize_status
{
@@ -1273,14 +1273,14 @@ typedef struct H5C2_auto_size_ctl_t
*
* structure H5C2_mdj_config_t
*
- * H5C2_mdj_config_t is a structure intended for use in comminicating
- * metadata journaling configuration data to and from the metadata
- * cache.
+ * H5C2_mdj_config_t is a structure intended for use in comminicating
+ * metadata journaling configuration data to and from the metadata
+ * cache.
*
* In its initial incarnation, it is identical to the H5AC2_jnl_config_t
- * structure less ther version, and journal_recovered fields. However,
- * in the future we may support other types of journaling -- which will
- * likely require modification or replacement of the H5AC2_jnl_config_t
+ * structure less ther version, and journal_recovered fields. However,
+ * in the future we may support other types of journaling -- which will
+ * likely require modification or replacement of the H5AC2_jnl_config_t
* structure.
*
* The fields of the structure are discussed individually below. Note
@@ -1300,7 +1300,7 @@ typedef struct H5C2_auto_size_ctl_t
*
* At present, the length of the journal file path is restricted to
* no more than H5C2__MAX_JOURNAL_FILE_NAME_LEN (which must equal
- * H5AC2__MAX_JOURNAL_FILE_NAME_LEN).
+ * H5AC2__MAX_JOURNAL_FILE_NAME_LEN).
*
* jbrb_buf_size: size_t containing the size of each individual buffer
* in the journal buffer ring buffer. This size should be chosen
@@ -1589,6 +1589,18 @@ H5_DLL herr_t H5C2_update_for_new_last_trans_on_disk(H5C2_t * cache_ptr,
typedef struct H5C2_jbrb_t H5C2_jbrb_t;
+/* Note that H5C2_jb_aio_await_completion_of_all_async_fsyncs() and
+ * H5C2_jb_aio__await_completion_of_all_pending_writes() are declared
+ * in this header file purely for testing purposes -- they should not be
+ * called outside test/cache2_journal.c
+ */
+H5_DLL herr_t H5C2_jb_aio__await_completion_of_all_async_fsyncs(
+ H5C2_jbrb_t * struct_ptr);
+
+H5_DLL herr_t H5C2_jb_aio__await_completion_of_all_pending_writes(
+ H5C2_jbrb_t * struct_ptr);
+
+
H5_DLL herr_t H5C2_jb__bin2hex(const uint8_t * buf,
char * hexdata,
size_t * hexlength,
@@ -1606,10 +1618,9 @@ H5_DLL herr_t H5C2_jb__eoa(H5C2_jbrb_t * struct_ptr,
H5_DLL herr_t H5C2_jb__get_last_transaction_on_disk(H5C2_jbrb_t * struct_ptr,
uint64_t * trans_num_ptr);
-H5_DLL herr_t H5C2_jb__flush_full_buffers(H5C2_jbrb_t * struct_ptr);
-
H5_DLL herr_t H5C2_jb__flush(H5C2_jbrb_t * struct_ptr);
+
H5_DLL herr_t H5C2_jb__journal_entry(H5C2_jbrb_t * struct_ptr,
uint64_t trans_num,
haddr_t base_addr,
@@ -1636,13 +1647,12 @@ H5_DLL herr_t H5C2_jb__trunc(H5C2_jbrb_t * struct_ptr);
H5_DLL herr_t H5C2_jb__write_header_entry(H5C2_jbrb_t * struct_ptr);
-H5_DLL herr_t H5C2_jb__write_to_buffer(H5C2_jbrb_t * struct_ptr,
+H5_DLL herr_t H5C2_jb__write_to_buffer(H5C2_jbrb_t * struct_ptr,
size_t size,
const char * data,
hbool_t is_end_trans,
uint64_t trans_num);
-
/*****************************************************************************/
/***** superblock journaling message management function definitions: ********/
/*****************************************************************************/
diff --git a/src/H5MF.c b/src/H5MF.c
index 27b00cc..9882306 100644
--- a/src/H5MF.c
+++ b/src/H5MF.c
@@ -24,6 +24,8 @@
*-------------------------------------------------------------------------
*/
+#include <aio.h>
+
/****************/
/* Module Setup */
/****************/
diff --git a/src/H5private.h b/src/H5private.h
index ae71826..001e487 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -756,7 +756,11 @@ H5_DLL int HDfprintf (FILE *stream, const char *fmt, ...);
#define HDstat(S,B) stat64(S,B)
#endif /* HDstat */
typedef struct stat64 h5_stat_t;
+#if 1 /* Solaris */ /* JRM */
+ typedef off_t h5_stat_size_t;
+#else /* not Solaris */ /* JRM */
typedef off64_t h5_stat_size_t;
+#endif /* JRM */
#else /* H5_SIZEOF_OFF_T!=8 && ... */
#ifndef HDfstat
#define HDfstat(F,B) fstat(F,B)