diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/H5AC2.c | 2 | ||||
-rw-r--r-- | src/H5C2.c | 2 | ||||
-rw-r--r-- | src/H5C2journal.c | 5517 | ||||
-rw-r--r-- | src/H5C2pkg.h | 1556 | ||||
-rw-r--r-- | src/H5C2private.h | 396 | ||||
-rw-r--r-- | src/H5MF.c | 2 | ||||
-rw-r--r-- | src/H5private.h | 4 |
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 */ @@ -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: ********/ /*****************************************************************************/ @@ -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) |