From f9857027e327cac5b356da2c6c3ac94e3a773b29 Mon Sep 17 00:00:00 2001 From: John Mainzer Date: Tue, 20 May 2008 15:43:50 -0500 Subject: [svn-r15049] This is an interrim commit of metadata cache journaling mods. I now have substantial tests for this code -- enough (I hope) for Mike M. to get started. However, the code is my no means fully tested. I don't expect any obvious problems, but there are probably quite a few relatively subtle bugs remaining. I'll be chasing these in the next week. For an example of setting up the cache to journal, see setup_cache_for_journaling() in test/cache2_journal.c Warnings: 1) For now, only enable journaling at file creation time -- code to do this after the file is opened exists, but it hasn't been tested. 2) Right now the journal logging code is very inefficient, so expect things to run slowly until Mike M. checks in his changes to address this problem. 3) I have not checked in exemplar journal output files pending a fix another minor bug in the journal logging code. Until then, the journal tests create exemplars and then test against them -- a poor way to find errors. 4) The USE_CORE_DRIVER has been moved to cache2_common.h. 5) When USE_CORE_DRIVER is FALSE, cache2_journal runs VERY slowly on some system (i.e. 4 hours on Phoenix) -- but it runs fast on Kagiso (~10 minutes). Don't know why, but would guess that the quantity of RAM on the system has much to do with it. Tested serial debug on Phonenix, and parallel debug on Kagiso --- src/H5AC2.c | 3 +- src/H5C2.c | 511 +++++--- src/H5C2journal.c | 570 ++++++-- src/H5C2pkg.h | 200 ++- src/H5C2private.h | 14 + test/cache2_common.c | 213 ++- test/cache2_common.h | 6 + test/cache2_journal.c | 3485 ++++++++++++++++++++++++++++++++++++++++++++++++- 8 files changed, 4636 insertions(+), 366 deletions(-) diff --git a/src/H5AC2.c b/src/H5AC2.c index adda9b1..bf5400e 100644 --- a/src/H5AC2.c +++ b/src/H5AC2.c @@ -3003,6 +3003,7 @@ H5AC2_get_cache_auto_resize_config(H5AC2_t * cache_ptr, config_ptr->jbrb_human_readable = FALSE; result = H5C2_get_journal_config(cache_ptr, + NULL, &(config_ptr->enable_journaling), &(config_ptr->journal_file_path[0]), &(config_ptr->jbrb_buf_size), @@ -3345,7 +3346,7 @@ H5AC2_set_cache_auto_resize_config(const H5F_t * f, } result = H5C2_get_journal_config((H5C2_t *)cache_ptr, &mdj_enabled, - NULL, NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, NULL, NULL); if ( result < 0 ) { diff --git a/src/H5C2.c b/src/H5C2.c index 02b2a1d..4ea6158 100644 --- a/src/H5C2.c +++ b/src/H5C2.c @@ -601,6 +601,8 @@ H5C2_create(H5F_t * f, #endif /* NDEBUG */ ((cache_ptr->epoch_markers)[i]).addr = (haddr_t)i; ((cache_ptr->epoch_markers)[i]).size = (size_t)0; + ((cache_ptr->epoch_markers)[i]).image_ptr = NULL; + ((cache_ptr->epoch_markers)[i]).image_up_to_date = FALSE; ((cache_ptr->epoch_markers)[i]).type = &epoch_marker_class_2; ((cache_ptr->epoch_markers)[i]).is_dirty = FALSE; ((cache_ptr->epoch_markers)[i]).dirtied = FALSE; @@ -644,6 +646,15 @@ H5C2_create(H5F_t * f, cache_ptr->jwipl_head_ptr = NULL; cache_ptr->jwipl_tail_ptr = NULL; + cache_ptr->mdj_startup_pending = FALSE; + cache_ptr->mdj_startup_f = NULL; + cache_ptr->mdj_startup_dxpl_id = -1; + cache_ptr->mdj_startup_jrnl_file_name = NULL; + cache_ptr->mdj_startup_buf_size = 0; + cache_ptr->mdj_startup_num_bufs = 0; + cache_ptr->mdj_startup_use_aio = FALSE; + cache_ptr->mdj_startup_human_readable = FALSE; + if ( H5C2_reset_cache_hit_rate_stats(cache_ptr) != SUCCEED ) { @@ -1032,9 +1043,12 @@ done: * *cache_ptr), and one of the dxpl ids. * * JRM -- 4/3/08 - * I don't think we need to do anything on an expunge - * vis-a-vis journaling. Comment is here just to make - * note of the fact that I have reviewed this function. + * Added code to test to see if journaling is enabled, and + * if it is, test to see if entry_ptr->last_trans > zero. + * If so, must remove the entry from the transaction list + * (if it is present), remove the entry from the journal + * write in progress list, and set entry_ptr->last_trans to + * zero before calling H5C2_flush_single_entry(). * *------------------------------------------------------------------------- */ @@ -1083,17 +1097,43 @@ H5C2_expunge_entry(H5F_t * f, HDassert( entry_ptr->type == type ); if ( entry_ptr->is_protected ) { - +#if 0 /* JRM */ + HDfprintf(stdout, "%s: Target entry is protected.\n", FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTEXPUNGE, FAIL, \ "Target entry is protected.") } if ( entry_ptr->is_pinned ) { - +#if 0 /* JRM */ + HDfprintf(stdout, "%s: Target entry is pinned.\n", FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTEXPUNGE, FAIL, \ "Target entry is pinned.") } + /* H5C2_flush_single_entry() will choke if the last_trans field + * of the entry isn't zero, or if the entry is on the transaction + * list, or on the transaction write in progress list. Must tend + * to this before we we make the call. + */ + if ( cache_ptr->mdj_enabled ) { + + if ( cache_ptr->trans_num > 0 ) { + + /* remove the entry from the transaction list if it is there */ + H5C2__TRANS_DLL_REMOVE(entry_ptr, cache_ptr->tl_head_ptr, \ + cache_ptr->tl_tail_ptr, cache_ptr->tl_len, \ + cache_ptr->tl_size, FAIL); + + entry_ptr->last_trans = (uint64_t)0; + + H5C2__UPDATE_RP_FOR_JOURNAL_WRITE_COMPLETE(cache_ptr, \ + entry_ptr, \ + FAIL) + } + } + /* If we get this far, call H5C2_flush_single_entry() with the * H5C2__FLUSH_INVALIDATE_FLAG and the H5C2__FLUSH_CLEAR_ONLY_FLAG. * This will clear the entry, and then delete it from the cache. @@ -1109,7 +1149,9 @@ H5C2_expunge_entry(H5F_t * f, TRUE); if ( result < 0 ) { - +#if 0 /* JRM */ + HDfprintf(stdout, "%s: H5C2_flush_single_entry() failed.\n", FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTEXPUNGE, FAIL, \ "H5C2_flush_single_entry() failed.") } @@ -2385,6 +2427,9 @@ H5C2_insert_entry(H5F_t * f, entry_ptr->addr = addr; entry_ptr->type = type; + entry_ptr->image_ptr = NULL; + entry_ptr->image_up_to_date = FALSE; + /* newly inserted entries are assumed to be dirty */ entry_ptr->is_dirty = TRUE; @@ -2427,6 +2472,10 @@ H5C2_insert_entry(H5F_t * f, if ( result < 0 ) { +#if 0 /* JRM */ + HDfprintf(stdout, "%s: H5C2__flash_increase_cache_size failed.\n", + FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, \ "H5C2__flash_increase_cache_size failed.") } @@ -2448,6 +2497,9 @@ H5C2_insert_entry(H5F_t * f, if ( result < 0 ) { +#if 0 /* JRM */ + HDfprintf(stdout, "%s: Can't get write_permitted.\n", FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, \ "Can't get write_permitted") } @@ -2498,6 +2550,9 @@ H5C2_insert_entry(H5F_t * f, if ( result < 0 ) { +#if 0 /* JRM */ + HDfprintf(stdout, "%s: H5C2_make_space_in_cache() failed.\n", FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, \ "H5C2_make_space_in_cache failed.") } @@ -2513,6 +2568,9 @@ H5C2_insert_entry(H5F_t * f, if ( test_entry_ptr == entry_ptr ) { +#if 0 /* JRM */ + HDfprintf(stdout, "%s: entry already in cache.\n", FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, \ "entry already in cache.") @@ -2985,6 +3043,7 @@ H5C2_mark_pinned_entry_dirty(H5F_t * f, /* mark the entry as dirty if it isn't already */ entry_ptr->is_dirty = TRUE; + entry_ptr->image_up_to_date = FALSE; /* update for change in entry size if necessary */ if ( ( size_changed ) && ( entry_ptr->size != new_size ) ) { @@ -3136,6 +3195,7 @@ H5C2_mark_pinned_or_protected_entry_dirty(H5F_t * f, /* mark the entry as dirty if it isn't already */ entry_ptr->is_dirty = TRUE; + entry_ptr->image_up_to_date = FALSE; /* If journaling is enabled, must add the entry to the transaction * list, if it is not there already. @@ -3342,6 +3402,8 @@ H5C2_rename_entry(H5C2_t * cache_ptr, if ( ! ( entry_ptr->flush_in_progress ) ) { entry_ptr->is_dirty = TRUE; + /* This shouldn't be needed, but it keeps the test code happy */ + entry_ptr->image_up_to_date = FALSE; } H5C2__INSERT_IN_INDEX(cache_ptr, entry_ptr, FAIL) @@ -3471,6 +3533,7 @@ H5C2_resize_pinned_entry(H5F_t * f, * isn't already */ entry_ptr->is_dirty = TRUE; + entry_ptr->image_up_to_date = FALSE; /* update for change in entry size if necessary */ if ( entry_ptr->size != new_size ) { @@ -3514,6 +3577,13 @@ H5C2_resize_pinned_entry(H5F_t * f, (new_size)); } + /* if journaling is enabled, and the entry is already in the + * transaction list, update that list for the size change as well. + */ + H5C2__UPDATE_TL_FOR_ENTRY_SIZE_CHANGE((cache_ptr), (entry_ptr), \ + (entry_ptr->size), (new_size)); + + /* update statistics just before changing the entry size */ H5C2__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE((cache_ptr), (entry_ptr), \ (new_size)); @@ -3527,6 +3597,12 @@ H5C2_resize_pinned_entry(H5F_t * f, H5C2__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr, FAIL) } + /* if journaling is enabled, check to see if the entry is in the + * transaction list. If it isn't, insert it. If it is, move it to + * the head of the list. + */ + H5C2__UPDATE_TL_FOR_ENTRY_DIRTY(cache_ptr, entry_ptr, FAIL) + H5C2__UPDATE_STATS_FOR_DIRTY_PIN(cache_ptr, entry_ptr) done: @@ -3562,17 +3638,16 @@ done: * H5C2__UPDATE_STATS_FOR_UNPIN to call to * H5C2__UPDATE_STATS_FOR_PIN. * + * JRM -- 5/16/08 + * Undid change of 2/16/08, as we can use the f parameter + * in production mode. + * *------------------------------------------------------------------------- */ -#ifndef NDEBUG + herr_t H5C2_pin_protected_entry(H5F_t * f, void * thing) -#else -herr_t -H5C2_pin_protected_entry(H5F_t UNUSED * f, - void * thing) -#endif { H5C2_t * cache_ptr; herr_t ret_value = SUCCEED; /* Return value */ @@ -3788,6 +3863,9 @@ H5C2_protect(H5F_t * f, if ( thing == NULL ) { +#if 0 /* JRM */ + HDfprintf(stdout, "%s can't load entry.\n", FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "can't load entry") } @@ -3804,6 +3882,10 @@ H5C2_protect(H5F_t * f, if ( result < 0 ) { +#if 0 /* JRM */ + HDfprintf(stdout, + "%s H5C2__flash_increase_cache_size failed.\n", FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, NULL, \ "H5C2__flash_increase_cache_size failed.") } @@ -3828,6 +3910,10 @@ H5C2_protect(H5F_t * f, if ( result < 0 ) { +#if 0 /* JRM */ + HDfprintf(stdout, + "%s Can't get write_permitted 1.\n", FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, NULL, \ "Can't get write_permitted 1") @@ -3889,6 +3975,10 @@ H5C2_protect(H5F_t * f, if ( result < 0 ) { +#if 0 /* JRM */ + HDfprintf(stdout, + "%s H5C2_make_space_in_cache failed 1.\n", FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, NULL, \ "H5C2_make_space_in_cache failed 1.") } @@ -3917,12 +4007,18 @@ H5C2_protect(H5F_t * f, H5C2__INSERT_ENTRY_IN_TL(cache_ptr, entry_ptr, NULL); } - /* insert the entry in the data structures used by the replacement - * policy. We are just going to take it out again when we update - * the replacement policy for a protect, but this simplifies the - * code. If we do this often enough, we may want to optimize this. - */ - H5C2__UPDATE_RP_FOR_INSERTION(cache_ptr, entry_ptr, NULL) + /* load the entry into the data structures used by the replacement + * policy. We are just going to take it out again when we update + * the replacement policy for a protect, but this simplifies the + * code. If we do this often enough, we may want to optimize this. + * + * Note that we used to do an update for insertion here, but + * that confused the journaling code -- the update for load is + * just a simplified version of update for insertion that + * avoids the problem. + */ + + H5C2__UPDATE_RP_FOR_LOAD(cache_ptr, entry_ptr, NULL) } HDassert( entry_ptr->addr == addr ); @@ -3938,6 +4034,10 @@ H5C2_protect(H5F_t * f, } else { +#if 0 /* JRM */ + HDfprintf(stdout, + "%s Target already protected & not read only?!?\n", FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, NULL, \ "Target already protected & not read only?!?.") } @@ -4007,6 +4107,10 @@ H5C2_protect(H5F_t * f, write_permitted); if ( result != SUCCEED ) { +#if 0 /* JRM */ + HDfprintf(stdout, + "%s Cache auto-resize failed.?!?\n", FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, NULL, \ "Cache auto-resize failed.") } @@ -4032,6 +4136,10 @@ H5C2_protect(H5F_t * f, if ( result < 0 ) { +#if 0 /* JRM */ + HDfprintf(stdout, + "%s H5C2_make_space_in_cache failed 2.\n", FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, NULL, \ "H5C2_make_space_in_cache failed 2.") } @@ -4044,7 +4152,6 @@ done: #if H5C2_DO_EXTREME_SANITY_CHECKS if ( H5C2_validate_lru_list(cache_ptr) < 0 ) { - HDassert(0); HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, NULL, \ "LRU sanity check failed.\n"); } @@ -5484,7 +5591,13 @@ H5C2_unprotect(H5F_t * f, } /* mark the entry as dirty if appropriate */ - entry_ptr->is_dirty = ( (entry_ptr->is_dirty) || dirtied ); + if ( dirtied ) { + + entry_ptr->is_dirty = ( (entry_ptr->is_dirty) || dirtied ); + entry_ptr->image_up_to_date = FALSE; + + H5C2__UPDATE_TL_FOR_ENTRY_DIRTY(cache_ptr, entry_ptr, FAIL) + } /* update for change in entry size if necessary */ if ( ( size_changed ) && ( entry_ptr->size != new_size ) ) { @@ -5529,6 +5642,13 @@ H5C2_unprotect(H5F_t * f, (new_size)); } + /* if journaling is enabled, and the entry is on the transaction + * list, update that list for the size changed. + */ + H5C2__UPDATE_TL_FOR_ENTRY_SIZE_CHANGE((cache_ptr), (entry_ptr), \ + (entry_ptr->size), \ + (new_size)); + /* update statistics just before changing the entry size */ H5C2__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE((cache_ptr), (entry_ptr), \ (new_size)); @@ -5621,6 +5741,9 @@ H5C2_unprotect(H5F_t * f, HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "Can't flush.") } + + /* delete the entry from the transaction list if appropriate */ + H5C2__UPDATE_TL_FOR_ENTRY_CLEAR((cache_ptr), (entry_ptr), FAIL) } #ifdef H5_HAVE_PARALLEL else if ( clear_entry ) { @@ -5650,6 +5773,9 @@ H5C2_unprotect(H5F_t * f, HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "Can't clear.") } + + /* delete the entry from the transaction list if appropriate */ + H5C2__UPDATE_TL_FOR_ENTRY_CLEAR((cache_ptr), (entry_ptr), FAIL) } #endif /* H5_HAVE_PARALLEL */ } @@ -8001,7 +8127,7 @@ H5C2_flush_single_entry(H5F_t * f, } } } -#if 1 +#if 0 /* this should be useful for debugging from time to time. * lets leave it in for now. -- JRM 12/15/04 */ @@ -8016,6 +8142,7 @@ H5C2_flush_single_entry(H5F_t * f, if ( ( entry_ptr != NULL ) && ( entry_ptr->is_protected ) ) { + /* Attempt to flush a protected entry -- scream and die. */ HGOTO_ERROR(H5E_CACHE, H5E_PROTECT, FAIL, \ "Attempt to flush a protected entry.") @@ -8245,6 +8372,7 @@ H5C2_flush_single_entry(H5F_t * f, H5C2__UPDATE_RP_FOR_EVICTION(cache_ptr, entry_ptr, FAIL) } else { + /* If journaling is enabled, the target entry is being cleared, * and it is on the transaction list, remove it from the transaction * list and set its last_trans field to zero. @@ -8273,6 +8401,7 @@ H5C2_flush_single_entry(H5F_t * f, } } + /* Clear the dirty flag only, if requested */ if ( clear_only ) { @@ -8329,172 +8458,184 @@ H5C2_flush_single_entry(H5F_t * f, } } - if ( entry_ptr->type->serialize(entry_ptr->addr, - entry_ptr->size, - entry_ptr->image_ptr, - (void *)entry_ptr, - &serialize_flags, - &new_addr, - &new_len, - &new_image_ptr) != SUCCEED ) - { - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ - "unable to serialize entry") - } + if ( ! ( entry_ptr->image_up_to_date ) ) { - if ( serialize_flags != 0 ) - { - if ( destroy ) - { - if ( cache_ptr->mdj_enabled ) { + if ( entry_ptr->type->serialize(entry_ptr->addr, + entry_ptr->size, + entry_ptr->image_ptr, + (void *)entry_ptr, + &serialize_flags, + &new_addr, + &new_len, + &new_image_ptr) != SUCCEED ) + { - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "rename/resize on destroy when journaling enabled."); - } + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "unable to serialize entry") + } - /* We have already removed the entry from the - * cache's data structures, so no need to update - * them for the re-size and/or rename. All we need - * to do is update the cache entry so we will have - * the correct values when we actually write the - * image of the entry to disk. - * - * Note that if the serialize function changes the - * size of the disk image of the entry, it must - * deallocate the old image, and allocate a new. - */ + if ( serialize_flags != 0 ) + { + if ( destroy ) + { + if ( cache_ptr->mdj_enabled ) { - switch ( serialize_flags ) - { - case H5C2__SERIALIZE_RESIZED_FLAG: - H5C2__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE(cache_ptr, - entry_ptr, - new_len) - entry_ptr->size = new_len; - entry_ptr->image_ptr = new_image_ptr; - break; + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "rename/resize on destroy when journaling enabled."); + } + + /* We have already removed the entry from the + * cache's data structures, so no need to update + * them for the re-size and/or rename. All we need + * to do is update the cache entry so we will have + * the correct values when we actually write the + * image of the entry to disk. + * + * Note that if the serialize function changes the + * size of the disk image of the entry, it must + * deallocate the old image, and allocate a new. + */ + + switch ( serialize_flags ) + { + case H5C2__SERIALIZE_RESIZED_FLAG: + H5C2__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE( \ + cache_ptr, \ + entry_ptr, \ + new_len) + entry_ptr->size = new_len; + entry_ptr->image_ptr = new_image_ptr; + break; - case (H5C2__SERIALIZE_RESIZED_FLAG | - H5C2__SERIALIZE_RENAMED_FLAG): - H5C2__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE(cache_ptr, - entry_ptr, - new_len) - entry_ptr->addr = new_addr; - entry_ptr->size = new_len; - entry_ptr->image_ptr = new_image_ptr; - break; + case (H5C2__SERIALIZE_RESIZED_FLAG | + H5C2__SERIALIZE_RENAMED_FLAG): + H5C2__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE( \ + cache_ptr, \ + entry_ptr, \ + new_len) + entry_ptr->addr = new_addr; + entry_ptr->size = new_len; + entry_ptr->image_ptr = new_image_ptr; + break; - default: - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ - "unexpected serialize flag(s)") - break; + default: + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "unexpected serialize flag(s)") + break; + } } - } - else - { - if ( cache_ptr->mdj_enabled ) { + else + { + if ( cache_ptr->mdj_enabled ) { - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ "rename/resize on flush when journaling enabled."); - } - - /* The entry is not being destroyed, and thus has not - * been removed from the cache's data structures. - * - * Thus, in addition to updating the entry for the - * re-size and/or rename, we must also update the - * cache data structures. - */ + } - switch ( serialize_flags ) - { - case H5C2__SERIALIZE_RESIZED_FLAG: - H5C2__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE(cache_ptr, - entry_ptr, - new_len) - /* The replacement policy code thinks the - * entry is already clean, so modify is_dirty - * to meet this expectation. - */ - entry_ptr->is_dirty = FALSE; - - /* update the hash table for the size change*/ - H5C2__UPDATE_INDEX_FOR_SIZE_CHANGE((cache_ptr), \ + /* The entry is not being destroyed, and thus has not + * been removed from the cache's data structures. + * + * Thus, in addition to updating the entry for the + * re-size and/or rename, we must also update the + * cache data structures. + */ + + switch ( serialize_flags ) + { + case H5C2__SERIALIZE_RESIZED_FLAG: + H5C2__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE( \ + cache_ptr, \ + entry_ptr, \ + new_len) + /* The replacement policy code thinks the + * entry is already clean, so modify is_dirty + * to meet this expectation. + */ + entry_ptr->is_dirty = FALSE; + + /* update the hash table for the size change*/ + H5C2__UPDATE_INDEX_FOR_SIZE_CHANGE( \ + (cache_ptr), \ (entry_ptr->size),\ (new_len)); - /* The entry can't be protected since we are in - * the process of flushing it. Thus we must - * update the replacement policy data structures - * for the size change. The macro deals with - * the pinned case. - */ - H5C2__UPDATE_RP_FOR_SIZE_CHANGE(cache_ptr, \ - entry_ptr, \ - new_len); - - /* The entry can't be in the slist, so no need - * to update the slist for the size change. - */ - - /* finally, set is_dirty to TRUE again, and - * update the size and image_ptr. - */ - entry_ptr->is_dirty = TRUE; - entry_ptr->size = new_len; - entry_ptr->image_ptr = new_image_ptr; - break; + /* The entry can't be protected since we are + * in the process of flushing it. Thus we must + * update the replacement policy data + * structures for the size change. The macro + * deals with the pinned case. + */ + H5C2__UPDATE_RP_FOR_SIZE_CHANGE(cache_ptr, \ + entry_ptr, \ + new_len); + + /* The entry can't be in the slist, so no need + * to update the slist for the size change. + */ + + /* finally, set is_dirty to TRUE again, and + * update the size and image_ptr. + */ + entry_ptr->is_dirty = TRUE; + entry_ptr->size = new_len; + entry_ptr->image_ptr = new_image_ptr; + break; - case (H5C2__SERIALIZE_RESIZED_FLAG | - H5C2__SERIALIZE_RENAMED_FLAG): - H5C2__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE(cache_ptr, - entry_ptr, - new_len) - /* The replacement policy code thinks the - * entry is already clean, so modify is_dirty - * to meet this expectation. - */ - entry_ptr->is_dirty = FALSE; - - /* first update the hash table for the rename */ - H5C2__DELETE_FROM_INDEX(cache_ptr, entry_ptr) - entry_ptr->addr = new_addr; - H5C2__INSERT_IN_INDEX(cache_ptr, entry_ptr, FAIL) - - /* update the hash table for the size change */ - H5C2__UPDATE_INDEX_FOR_SIZE_CHANGE((cache_ptr), \ + case (H5C2__SERIALIZE_RESIZED_FLAG | + H5C2__SERIALIZE_RENAMED_FLAG): + H5C2__UPDATE_STATS_FOR_ENTRY_SIZE_CHANGE( \ + cache_ptr, \ + entry_ptr, \ + new_len) + /* The replacement policy code thinks the + * entry is already clean, so modify is_dirty + * to meet this expectation. + */ + entry_ptr->is_dirty = FALSE; + + /* first update the hash table for the rename */ + H5C2__DELETE_FROM_INDEX(cache_ptr, entry_ptr) + entry_ptr->addr = new_addr; + H5C2__INSERT_IN_INDEX(cache_ptr, entry_ptr, \ + FAIL) + + /* update the hash table for the size change */ + H5C2__UPDATE_INDEX_FOR_SIZE_CHANGE( \ + (cache_ptr), \ (entry_ptr->size),\ (new_len)); - /* The entry can't be protected since we are in - * the process of flushing it. Thus we must - * update the replacement policy data structures - * for the size change. The macro deals with - * the pinned case. - */ - H5C2__UPDATE_RP_FOR_SIZE_CHANGE(cache_ptr, \ - entry_ptr, \ - new_len); - - /* The entry can't be in the slist, so no need - * to update the slist for the size change. - */ - - /* finally, set is_dirty to TRUE again, and - * update the size and image_ptr. - */ - entry_ptr->is_dirty = TRUE; - - entry_ptr->size = new_len; - entry_ptr->image_ptr = new_image_ptr; - break; + /* The entry can't be protected since we are + * in the process of flushing it. Thus we must + * update the replacement policy data + * structures for the size change. The macro + * deals with the pinned case. + */ + H5C2__UPDATE_RP_FOR_SIZE_CHANGE(cache_ptr, \ + entry_ptr, \ + new_len); + + /* The entry can't be in the slist, so no need + * to update the slist for the size change. + */ + + /* finally, set is_dirty to TRUE again, and + * update the size and image_ptr. + */ + entry_ptr->is_dirty = TRUE; + + entry_ptr->size = new_len; + entry_ptr->image_ptr = new_image_ptr; + break; - default: - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ - "unexpected serialize flag(s)") - break; + default: + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "unexpected serialize flag(s)") + break; + } } - } + } + entry_ptr->image_up_to_date = TRUE; } /* now write the image to disk */ @@ -8507,6 +8648,10 @@ H5C2_flush_single_entry(H5F_t * f, } #ifdef H5_HAVE_PARALLEL + /* note that we initialized the serialize_flags to 0, so if + * the image was up to date on entry, serialize_flags should + * still be 0 at this point. + */ if ( serialize_flags != 0 ) { /* In the parallel case, resizes and renames in @@ -8571,6 +8716,7 @@ H5C2_flush_single_entry(H5F_t * f, if ( type_ptr->free_icr(entry_ptr->addr, entry_ptr->size, (void *)entry_ptr) != SUCCEED ) { + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ "free_icr callback failed.") } @@ -8681,12 +8827,19 @@ H5C2_load_entry(H5F_t * f, if ( image_ptr == NULL ) { +#if 0 /* JRM */ + HDfprintf(stdout, + "memory allocation failed for on disk image buffer.\n"); +#endif /* JRM */ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, \ "memory allocation failed for on disk image buffer.") } if ( H5F_block_read(f, type->mem_type, addr, len, dxpl_id, image_ptr) < 0 ) { +#if 0 /* JRM */ + HDfprintf(stdout, "can't read image.\n."); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "Can't read image") } @@ -8694,6 +8847,9 @@ H5C2_load_entry(H5F_t * f, if ( thing == NULL ) { +#if 0 /* JRM */ + HDfprintf(stdout, "can't deserialize image.\n."); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "Can't deserialize image") } @@ -8701,15 +8857,24 @@ H5C2_load_entry(H5F_t * f, { if ( type->image_len(thing, &new_len) != SUCCEED ) { - HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "image_len() failed") +#if 0 /* JRM */ + HDfprintf(stdout, "image_len() failed.\n."); +#endif /* JRM */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "image_len() failed.\n"); } else if ( new_len > len ) { - HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "new_len > len") +#if 0 /* JRM */ + HDfprintf(stdout, "new_len > len.\n."); +#endif /* JRM */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "new_len > len.\n"); } else if ( new_len <= 0 ) { - HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "new_len <= 0") +#if 0 /* JRM */ + HDfprintf(stdout, "new_len <= 0.\n."); +#endif /* JRM */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "new_len <= 0.\n") } else if ( new_len < len ) { @@ -8717,6 +8882,9 @@ H5C2_load_entry(H5F_t * f, if ( thing == NULL ) { +#if 0 /* JRM */ + HDfprintf(stdout, "thing null after H5MM_realloc().\n"); +#endif /* JRM */ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, \ "thing null after H5MM_realloc().") } @@ -8756,6 +8924,7 @@ H5C2_load_entry(H5F_t * f, entry_ptr->addr = addr; entry_ptr->size = len; entry_ptr->image_ptr = image_ptr; + entry_ptr->image_up_to_date = TRUE; entry_ptr->type = type; entry_ptr->is_dirty = dirty; entry_ptr->dirtied = FALSE; diff --git a/src/H5C2journal.c b/src/H5C2journal.c index 53d0d71..3445c4f 100644 --- a/src/H5C2journal.c +++ b/src/H5C2journal.c @@ -79,9 +79,10 @@ H5C2_begin_journaling(H5F_t * f, herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5C2_begin_journaling, FAIL) - +#if 0 /* JRM */ + HDfprintf(stdout, "%s entering.\n", FUNC); +#endif /* JRM */ HDassert( f != NULL ); - HDassert( f->name != NULL ); HDassert( cache_ptr != NULL ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); HDassert( cache_ptr->mdj_enabled == FALSE ); @@ -102,34 +103,91 @@ H5C2_begin_journaling(H5F_t * f, if ( cache_ptr->mdj_enabled ) { + HDfprintf(stdout, "%s: metadata journaling already enabled on entry.\n", + FUNC); HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ "metadata journaling already enabled on entry.") } - result = H5C2_jb__init(&(cache_ptr->mdj_jbrb), - f->name, - journal_file_name_ptr, - buf_size, - num_bufs, - use_aio, - human_readable); +#if 0 /* JRM */ + HDfprintf(stdout, "%s Finished initial sanity checks.\n", FUNC); +#endif /* JRM */ - if ( result != SUCCEED ) { + if ( f->name == NULL ) { - HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, "H5C2_jb__init() failed.") - } +#if 0 /* JRM */ + HDfprintf(stdout, "%s Queueing startup.\n", FUNC); +#endif /* JRM */ - result = H5C2_mark_journaling_in_progress(f, - dxpl_id, - journal_file_name_ptr); + if ( cache_ptr->mdj_startup_pending ) { - if ( result != SUCCEED ) { + HDfprintf(stdout, + "%s: metadata journaling startup already pending.\n", + FUNC); + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "metadata journaling startup already pending.") + } - HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ - "H5C2_mark_journaling_in_progress() failed.") + result = H5C2_queue_begin_journaling(f, dxpl_id, cache_ptr, + journal_file_name_ptr, buf_size, + num_bufs, use_aio, human_readable); + + if ( result < 0 ) { + + HDfprintf(stdout, "%s: H5C2_queue_begin_journaling() failed.\n", + FUNC); + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_queue_begin_journaling() failed.") + } + +#if 0 /* JRM */ + HDfprintf(stdout, "%s Queueing startup -- done.\n", FUNC); +#endif /* JRM */ + } else { + +#if 0 /* JRM */ + HDfprintf(stdout, "%s calling H5C2_jb__init().\n", FUNC); +#endif /* JRM */ + + result = H5C2_jb__init(&(cache_ptr->mdj_jbrb), + f->name, + journal_file_name_ptr, + buf_size, + num_bufs, + use_aio, + human_readable); + + if ( result != SUCCEED ) { + + HDfprintf(stdout, "%s: H5C2_jb__init() failed.\n", FUNC); + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__init() failed.") + } + +#if 0 /* JRM */ + HDfprintf(stdout, "%s calling H5C2_mark_journaling_in_progress().\n", + FUNC); +#endif /* JRM */ + + result = H5C2_mark_journaling_in_progress(f, + dxpl_id, + journal_file_name_ptr); + + if ( result != SUCCEED ) { + + HDfprintf(stdout, + "%s: H5C2_mark_journaling_in_progress() failed.\n", FUNC); + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_mark_journaling_in_progress() failed.") + } + + cache_ptr->mdj_enabled = TRUE; + cache_ptr->mdj_startup_pending = FALSE; } - cache_ptr->mdj_enabled = TRUE; +#if 0 /* JRM */ + HDfprintf(stdout, "%s exiting.\n", FUNC); +#endif /* JRM */ done: @@ -160,9 +218,15 @@ H5C2_begin_transaction(H5C2_t * cache_ptr, const char * api_call_name) { herr_t ret_value = SUCCEED; /* Return value */ + herr_t result; FUNC_ENTER_NOAPI(H5C2_begin_transaction, FAIL) - +#if 0 /* JRM */ + HDfprintf(stdout, "%s entering -- call name = \"%s\".\n", + FUNC, api_call_name); + HDfprintf(stdout, "%s cache_ptr->mdj_enabled = %d.\n", + FUNC, (int)(cache_ptr->mdj_enabled)); +#endif /* JRM */ HDassert( cache_ptr != NULL ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); HDassert( cache_ptr->tl_len == 0 ); @@ -173,17 +237,51 @@ H5C2_begin_transaction(H5C2_t * cache_ptr, HDassert( api_call_name != NULL ); HDassert( HDstrlen(api_call_name) <= H5C2__MAX_API_NAME_LEN ); + if ( cache_ptr->mdj_startup_pending ) { +#if 0 /* JRM */ + HDfprintf(stdout, "%s calling H5C2_begin_journaling()...", FUNC); + fflush(stdout); +#endif /* JRM */ + result = H5C2_begin_journaling(cache_ptr->mdj_startup_f, + cache_ptr->mdj_startup_dxpl_id, + cache_ptr, + cache_ptr->mdj_startup_jrnl_file_name, + cache_ptr->mdj_startup_buf_size, + cache_ptr->mdj_startup_num_bufs, + cache_ptr->mdj_startup_use_aio, + cache_ptr->mdj_startup_human_readable); + + if ( result < 0 ) { + + HDfprintf(stdout, "%s H5C2_begin_journaling() failed.\n", FUNC); + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "H5C2_begin_journaling() failed.") + } + + if ( cache_ptr->mdj_startup_jrnl_file_name != NULL ) { + + cache_ptr->mdj_startup_jrnl_file_name = (char *) + H5MM_xfree((void *)(cache_ptr->mdj_startup_jrnl_file_name)); + } +#if 0 /* JRM */ + HDfprintf(stdout, "done.\n"); + fflush(stdout); +#endif /* JRM */ + } + if ( cache_ptr->mdj_enabled ) { if ( cache_ptr->trans_in_progress ) { + HDfprintf(stdout, "%s transaction already in progress.\n", FUNC); HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ "transaction already in progress?.") } - HDstrncpy(cache_ptr->trans_api_name, api_call_name, + HDstrncpy(cache_ptr->trans_api_name, api_call_name, (size_t)H5C2__MAX_API_NAME_LEN); - cache_ptr->trans_num++; + + (cache_ptr->trans_num)++; *trans_num_ptr = cache_ptr->trans_num; @@ -191,7 +289,10 @@ H5C2_begin_transaction(H5C2_t * cache_ptr, } done: - +#if 0 /* JRM */ + HDfprintf(stdout, "%s exiting -- cache_ptr->trans_num = %lld.\n", + FUNC, cache_ptr->trans_num); +#endif /* JRM */ FUNC_LEAVE_NOAPI(ret_value) } /* H5C2_begin_transaction() */ @@ -235,7 +336,7 @@ H5C2_end_journaling(H5F_t * f, HDassert( f != NULL ); HDassert( cache_ptr != NULL ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); - HDassert( cache_ptr->mdj_enabled == TRUE ); + /* HDassert( cache_ptr->mdj_enabled == TRUE ); */ HDassert( cache_ptr->trans_in_progress == FALSE ); HDassert( cache_ptr->tl_len == 0 ); HDassert( cache_ptr->tl_size == 0 ); @@ -253,7 +354,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.") } result = H5C2_unmark_journaling_in_progress(f, dxpl_id, cache_ptr); @@ -307,7 +408,10 @@ H5C2_end_transaction(H5F_t * f, herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5C2_end_transaction, FAIL) - +#if 0 /* JRM */ + HDfprintf(stdout, "%s call = \"%s\", trans_num = %lld, tl_len = %d.\n", + FUNC, api_call_name, trans_num, (int)(cache_ptr->tl_len)); +#endif /* JRM */ HDassert( cache_ptr != NULL ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); HDassert( api_call_name != NULL ); @@ -318,13 +422,20 @@ H5C2_end_transaction(H5F_t * f, if ( cache_ptr->mdj_enabled ) { if ( ! ( cache_ptr->trans_in_progress ) ) { - +#if 0 /* JRM */ + HDfprintf(stdout, "%s: transaction not in progress?!?!\n", FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ "transaction not in progress?!?!") } if ( cache_ptr->trans_num != trans_num ) { +#if 0 /* JRM */ + HDfprintf(stdout, "%s: trans_num mis-match (%lld/%lld)\n", + FUNC, (long long)(trans_num), + (long long)(cache_ptr->trans_num)); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "trans_num mis-match?!?!") } @@ -337,11 +448,18 @@ H5C2_end_transaction(H5F_t * f, if ( result != SUCCEED ) { +#if 0 /* JRM */ + HDfprintf(stdout, "%s: H5C2_journal_transaction() failed.\n", + FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ "H5C2_journal_transaction() failed.") } } - +#if 0 /* JRM */ + HDfprintf(stdout, "%s: setting cache_ptr->trans_in_progress = FALSE.\n", + FUNC); +#endif /* JRM */ cache_ptr->trans_in_progress = FALSE; /* Get the last transaction on disk. If it has changed, remove @@ -353,6 +471,11 @@ H5C2_end_transaction(H5F_t * f, &new_last_trans_on_disk); if ( result != SUCCEED ) { +#if 0 /* JRM */ + HDfprintf(stdout, + "%s: H5C2_jb__get_last_transaction_on_disk() failed.\n", + FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ "H5C2_jb__get_last_transaction_on_disk() failed.") } @@ -364,6 +487,11 @@ H5C2_end_transaction(H5F_t * f, if ( result != SUCCEED ) { +#if 0 /* JRM */ + HDfprintf(stdout, + "%s: H5C2_update_for_new_last_trans_on_disk() failed.\n", + FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ "H5C2_update_for_new_last_trans_on_disk() failed.") } @@ -427,12 +555,20 @@ done: * Programmer: John Mainzer * April 13, 2008 * + * Changes: + * + * John Mainzer -- 4/2/08 + * Modified function to report the pending journaling + * status if journaling has been enabled, but not yet + * configured. + * *------------------------------------------------------------------------- */ herr_t H5C2_get_journal_config(H5C2_t * cache_ptr, hbool_t * journaling_enabled_ptr, + hbool_t * startup_pending_ptr, char * journal_file_path_ptr, size_t * jbrb_buf_size_ptr, int * jbrb_num_bufs_ptr, @@ -457,6 +593,11 @@ H5C2_get_journal_config(H5C2_t * cache_ptr, *journaling_enabled_ptr = TRUE; + if ( startup_pending_ptr != NULL ) { + + *startup_pending_ptr = FALSE; + } + if ( journal_file_path_ptr != NULL ) { HDsnprintf(journal_file_path_ptr, @@ -485,6 +626,43 @@ H5C2_get_journal_config(H5C2_t * cache_ptr, *jbrb_human_readable_ptr = (cache_ptr->mdj_jbrb).human_readable; } + } else if ( cache_ptr->mdj_startup_pending ) { + + *journaling_enabled_ptr = TRUE; + + if ( startup_pending_ptr != NULL ) { + + *startup_pending_ptr = TRUE; + } + + if ( journal_file_path_ptr != NULL ) { + + HDsnprintf(journal_file_path_ptr, + H5AC2__MAX_JOURNAL_FILE_NAME_LEN, + "%s", + cache_ptr->mdj_startup_jrnl_file_name); + } + + if ( jbrb_buf_size_ptr != NULL ) { + + *jbrb_buf_size_ptr = cache_ptr->mdj_startup_buf_size; + } + + if ( jbrb_num_bufs_ptr != NULL ) { + + *jbrb_num_bufs_ptr = cache_ptr->mdj_startup_num_bufs; + } + + if ( jbrb_use_aio_ptr != NULL ) { + + *jbrb_use_aio_ptr = cache_ptr->mdj_startup_use_aio; + } + + if ( jbrb_human_readable_ptr ) { + + *jbrb_human_readable_ptr = cache_ptr->mdj_startup_human_readable; + } + } else { *journaling_enabled_ptr = FALSE; @@ -617,7 +795,7 @@ H5C2_journal_pre_flush(H5C2_t * cache_ptr) HDassert( cache_ptr->mdj_enabled ); if ( cache_ptr->trans_in_progress ) { - + HDassert(0); HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ "Transaction in progress during flush?!?!?.") } @@ -684,6 +862,8 @@ H5C2_journal_transaction(H5F_t * f, { char buf[H5C2__MAX_API_NAME_LEN + 128]; + hbool_t resized; + hbool_t renamed; H5C2_cache_entry_t * entry_ptr = NULL; unsigned serialize_flags = 0; haddr_t new_addr; @@ -708,6 +888,9 @@ H5C2_journal_transaction(H5F_t * f, if ( result != SUCCEED ) { +#if 0 /* JRM */ + HDfprintf(stdout, "%s: H5C2_jb__comment() failed.\n", FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ "H5C2_jb__comment() failed.") } @@ -717,6 +900,9 @@ H5C2_journal_transaction(H5F_t * f, if ( result != SUCCEED ) { +#if 0 /* JRM */ + HDfprintf(stdout, "%s: H5C2_jb__start_transaction() failed.\n", FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ "H5C2_jb__start_transaction() failed.") } @@ -727,9 +913,16 @@ H5C2_journal_transaction(H5F_t * f, HDassert( entry_ptr->is_dirty ); HDassert( entry_ptr->last_trans == cache_ptr->trans_num ); + resized = FALSE; + renamed = FALSE; + if ( entry_ptr->is_protected ) { +#if 0 /* JRM */ + HDfprintf(stdout, + "%s: Protected entry in TL at transaction close.\n", FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ "Protected entry in TL at transaction close.") } @@ -741,91 +934,126 @@ H5C2_journal_transaction(H5F_t * f, if ( entry_ptr->image_ptr == NULL ) { +#if 0 /* JRM */ + HDfprintf(stdout, + "%s: memory allocation failed for on disk image buffer.\n", + FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ "memory allocation failed for on disk image buffer.") } } - result = entry_ptr->type->serialize(entry_ptr->addr, - entry_ptr->size, - entry_ptr->image_ptr, - (void *)entry_ptr, - &serialize_flags, - &new_addr, - &new_len, - &new_image_ptr); - if ( result != SUCCEED ) - { - HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ - "unable to serialize entry") - } - - if ( serialize_flags != 0 ) - { - /* if the serialize_flags are not zero, the entry has been - * modified as a result of the serialize. Pass these changes - * on to the cache, and don't bother to write a journal entry - * at this time -- the protect/unprotect/rename will move the - * entry to the head of the transaction list, where we will - * handle it later. - */ - hbool_t resized; - hbool_t renamed; - - resized = (serialize_flags & H5C2__SERIALIZE_RESIZED_FLAG) != 0; - renamed = (serialize_flags & H5C2__SERIALIZE_RENAMED_FLAG) != 0; - - if ( ( renamed ) && ( ! resized ) ) + /* 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). + */ + if ( ! ( entry_ptr->image_up_to_date ) ) { + + result = entry_ptr->type->serialize(entry_ptr->addr, + entry_ptr->size, + entry_ptr->image_ptr, + (void *)entry_ptr, + &serialize_flags, + &new_addr, + &new_len, + &new_image_ptr); + if ( result != SUCCEED ) { +#if 0 /* JRM */ + HDfprintf(stdout, "%s: unable to serialize entry.\n", FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ - "entry renamed but not resized?!?!") + "unable to serialize entry") } - if ( resized ) + if ( serialize_flags != 0 ) { - /* in the following protect/unprotect, use default - * dxpl_id as we know that the entry is in cache, - * and thus no I/O will take place. + /* if the serialize_flags are not zero, the entry has been + * modified as a result of the serialize. Pass these changes + * on to the cache, and don't bother to write a journal entry + * at this time -- the protect/unprotect/rename will move the + * entry to the head of the transaction list, where we will + * handle it later. */ - thing = H5C2_protect(f, H5P_DATASET_XFER_DEFAULT, - entry_ptr->type, entry_ptr->addr, - entry_ptr->size, NULL, - H5C2__NO_FLAGS_SET); - if ( thing == NULL ) + resized = (serialize_flags & H5C2__SERIALIZE_RESIZED_FLAG) != 0; + renamed = (serialize_flags & H5C2__SERIALIZE_RENAMED_FLAG) != 0; + + if ( ( renamed ) && ( ! resized ) ) { +#if 0 /* JRM */ + HDfprintf(stdout, "%s: entry renamed but not resized.\n", + FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ - "H5C2_protect() failed.") + "entry renamed but not resized?!?!") } - result = H5C2_unprotect(f, H5P_DATASET_XFER_DEFAULT, - entry_ptr->type, entry_ptr->addr, - thing, H5C2__SIZE_CHANGED_FLAG, - new_len); - - if ( result < 0 ) + if ( resized ) { - HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ - "H5C2_unprotect() failed.") + /* in the following protect/unprotect, use default + * dxpl_id as we know that the entry is in cache, + * and thus no I/O will take place. + */ + thing = H5C2_protect(f, H5P_DATASET_XFER_DEFAULT, + entry_ptr->type, entry_ptr->addr, + entry_ptr->size, NULL, + H5C2__NO_FLAGS_SET); + + if ( thing == NULL ) + { +#if 0 /* JRM */ + HDfprintf(stdout, "%s: H5C2_protect() failed.\n", + FUNC); +#endif /* JRM */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_protect() failed.") + } + + result = H5C2_unprotect(f, H5P_DATASET_XFER_DEFAULT, + entry_ptr->type, entry_ptr->addr, + thing, H5C2__SIZE_CHANGED_FLAG, + new_len); + + if ( result < 0 ) + { +#if 0 /* JRM */ + HDfprintf(stdout, "%s: H5C2_unprotect() failed.\n", + FUNC); +#endif /* JRM */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_unprotect() failed.") + } + + entry_ptr->image_ptr = new_image_ptr; } - entry_ptr->image_ptr = new_image_ptr; - } - - if ( renamed ) - { - result = H5C2_rename_entry(cache_ptr, entry_ptr->type, - entry_ptr->addr, new_addr); - - if ( result < 0 ) + if ( renamed ) { - HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ - "H5C2_rename_entr() failed.") + result = H5C2_rename_entry(cache_ptr, entry_ptr->type, + entry_ptr->addr, new_addr); + + if ( result < 0 ) + { +#if 0 /* JRM */ + HDfprintf(stdout, "%s: H5C2_rename_entr() failed.\n", + FUNC); +#endif /* JRM */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_rename_entr() failed.") + } } } + + entry_ptr->image_up_to_date = TRUE; } - else /* generate the journal entry & remove from transaction list */ - { + + /* if the entry hasn't been either resized or renamed, generate + * 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, @@ -834,6 +1062,10 @@ H5C2_journal_transaction(H5F_t * f, if ( result != SUCCEED ) { +#if 0 /* JRM */ + HDfprintf(stdout, "%s: H5C2_jb__journal_entry() failed.\n", + FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ "H5C2_jb__journal_entry() failed.") } @@ -850,6 +1082,9 @@ H5C2_journal_transaction(H5F_t * f, if ( result != SUCCEED ) { +#if 0 /* JRM */ + HDfprintf(stdout, "%s: H5C2_jb__end_transaction() failed.\n", FUNC); +#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ "H5C2_jb__end_transaction() failed.") } @@ -862,6 +1097,93 @@ done: /*------------------------------------------------------------------------- + * Function: H5C2_queue_begin_journaling() + * + * Purpose: Verify that the HDF5 file name is not available. + * + * Then make note of the information needed to begin + * journaling once the file is fully open. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: John Mainzer + * 5/1/08 + * + *------------------------------------------------------------------------- + */ + +herr_t +H5C2_queue_begin_journaling(H5F_t * f, + hid_t dxpl_id, + H5C2_t * cache_ptr, + char * journal_file_name_ptr, + size_t buf_size, + int num_bufs, + hbool_t use_aio, + hbool_t human_readable) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5C2_queue_begin_journaling, FAIL) + + HDassert( f != NULL ); + HDassert( cache_ptr != NULL ); + HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); + HDassert( cache_ptr->mdj_enabled == FALSE ); + HDassert( cache_ptr->mdj_startup_pending == FALSE ); + HDassert( cache_ptr->trans_in_progress == FALSE ); + HDassert( cache_ptr->trans_num == 0 ); + HDassert( cache_ptr->last_trans_on_disk == 0 ); + HDassert( cache_ptr->tl_len == 0 ); + HDassert( cache_ptr->tl_size == 0 ); + HDassert( cache_ptr->tl_head_ptr == NULL ); + HDassert( cache_ptr->tl_tail_ptr == NULL ); + HDassert( cache_ptr->jwipl_len == 0 ); + HDassert( cache_ptr->jwipl_size == 0 ); + HDassert( cache_ptr->jwipl_head_ptr == NULL ); + HDassert( cache_ptr->jwipl_tail_ptr == NULL ); + HDassert( buf_size > 0 ); + HDassert( num_bufs > 0 ); + HDassert( journal_file_name_ptr != NULL ); + + if ( cache_ptr->mdj_enabled ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "metadata journaling already enabled on entry.") + } + + cache_ptr->mdj_startup_jrnl_file_name = + (char *)H5MM_malloc(strlen(journal_file_name_ptr) + 1); + + if ( cache_ptr->mdj_startup_jrnl_file_name == NULL ) { + + if ( cache_ptr->mdj_startup_jrnl_file_name == NULL ) { + + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ + "memory allocation failed for jrnl file name buffer.") + } + } + + HDstrcpy(cache_ptr->mdj_startup_jrnl_file_name, journal_file_name_ptr); + + cache_ptr->mdj_startup_f = f; + cache_ptr->mdj_startup_dxpl_id = dxpl_id; + cache_ptr->mdj_startup_buf_size = buf_size; + cache_ptr->mdj_startup_num_bufs = num_bufs; + cache_ptr->mdj_startup_use_aio = use_aio; + cache_ptr->mdj_startup_human_readable = human_readable; + + cache_ptr->mdj_startup_pending = TRUE; + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5C2_queue_begin_journaling() */ + + +/*------------------------------------------------------------------------- * Function: H5C2_update_for_new_last_trans_on_disk() * * Purpose: Update the journal write in progress list for a change in @@ -875,6 +1197,13 @@ done: * set their last_trans fields to zero, and insert then into * the eviction policy data structures. * + * Similarly, scan the pinned entry list for entries whose + * 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 + * ceases to be the case, we will have re-visit this case. + * * Return: Success: SUCCEED * Failure: FAIL * @@ -907,9 +1236,10 @@ H5C2_update_for_new_last_trans_on_disk(H5C2_t * cache_ptr, while ( entry_ptr != NULL ) { - prev_entry_ptr = entry_ptr->next; + prev_entry_ptr = entry_ptr->prev; HDassert( entry_ptr->last_trans > 0 ); + HDassert( entry_ptr->is_dirty ); if ( entry_ptr->last_trans <= cache_ptr->last_trans_on_disk ) { @@ -921,6 +1251,24 @@ H5C2_update_for_new_last_trans_on_disk(H5C2_t * cache_ptr, entry_ptr = prev_entry_ptr; } + + /* now scan the pinned entry list */ + + entry_ptr = cache_ptr->pel_head_ptr; + + while ( entry_ptr != NULL ) { + + if ( entry_ptr->last_trans > 0 ) { + + HDassert( entry_ptr->is_dirty ); + + if ( entry_ptr->last_trans <= cache_ptr->last_trans_on_disk ) { + + entry_ptr->last_trans = 0; + } + } + entry_ptr = entry_ptr->next; + } } done: @@ -1493,7 +1841,10 @@ H5C2_mark_journaling_in_progress(H5F_t * f, HDassert( cache_ptr->mdj_conf_block_ptr == NULL ); HDassert( cache_ptr->mdj_file_name_ptr == NULL ); HDassert( journal_file_name_ptr != NULL ); - +#if 0 + /* Unfortunately, the flags may not be set yet -- thus we can't + * check for this error. + */ /* Can't journal a read only file, so verify that we are * opened read/write and fail if we are not. */ @@ -1502,7 +1853,7 @@ H5C2_mark_journaling_in_progress(H5F_t * f, HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ "File is opened read only.") } - +#endif /* first, create a metadata journaling configuration block */ result = H5C2_create_journal_config_block(f, dxpl_id, @@ -1897,7 +2248,7 @@ H5C2_jb__flush(H5C2_jbrb_t * struct_ptr) /* 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 ) { + if ( fsync(struct_ptr->journal_file_fd) != 0 ) { HGOTO_ERROR(H5E_IO, H5E_SYNCFAIL, FAIL, "Journal file sync failed.") } /* end if */ @@ -2252,9 +2603,11 @@ H5C2_jb__init(H5C2_jbrb_t * struct_ptr, /* Open journal file */ struct_ptr->journal_file_fd = HDopen(journal_file_name, O_WRONLY|O_CREAT|O_EXCL, 0777); - if ( struct_ptr->journal_file_fd == -1) { + HDfprintf(stdout, + "%s: Can't create journal file \"%s\". Does it already exist?\n", + FUNC, journal_file_name); HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL, \ "Can't create journal file. Does it already exist?") } /* end if */ @@ -2284,6 +2637,9 @@ H5C2_jb__init(H5C2_jbrb_t * struct_ptr, if ( struct_ptr->buf == NULL ) { + HDfprintf(stdout, + "%s: allocation of buf pointer array failed.\n", + FUNC); HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ "allocation of buf pointer array failed."); } /* end if */ @@ -2294,6 +2650,9 @@ H5C2_jb__init(H5C2_jbrb_t * struct_ptr, if ( (*struct_ptr->buf)[0] == NULL ) { + HDfprintf(stdout, + "%s: allocation of buffers failed.\n", + FUNC); HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ "allocation of buffers failed."); } /* end if */ @@ -2306,6 +2665,9 @@ H5C2_jb__init(H5C2_jbrb_t * struct_ptr, if ( struct_ptr->trans_tracking == NULL ) { + HDfprintf(stdout, + "%s: allocation of trans_tracking failed.\n", + FUNC); HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ "allocation of trans_tracking failed."); } /* end if */ @@ -2341,6 +2703,9 @@ H5C2_jb__init(H5C2_jbrb_t * struct_ptr, if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(temp), temp, FALSE, (uint64_t)0) < 0) { + HDfprintf(stdout, + "%s: H5C2_jb__write_to_buffer() failed.\n", + FUNC); HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ "H5C2_jb__write_to_buffer() failed.\n") } /* end if */ @@ -2383,7 +2748,9 @@ H5C2_jb__start_transaction(H5C2_jbrb_t * struct_ptr, herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(H5C2_jb__start_transaction, FAIL) - +#if 0 /* JRM */ + HDfprintf(stdout, "%s trans_num = %lld.\n", FUNC, trans_num); +#endif /* JRM */ /* Check Arguments */ HDassert(struct_ptr); HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC); @@ -2482,7 +2849,10 @@ H5C2_jb__journal_entry(H5C2_jbrb_t * struct_ptr, herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(H5C2_jb__journal_entry, FAIL) - +#if 0 /* JRM */ + HDfprintf(stdout, "%s trans_num = %lld, base_addr = %d, length = %ld.\n", + FUNC, trans_num, (int)base_addr, (int)length); +#endif /* JRM */ /* Check Arguments */ HDassert(struct_ptr); HDassert(body); @@ -2591,7 +2961,9 @@ H5C2_jb__end_transaction(H5C2_jbrb_t * struct_ptr, herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(H5C2_jb__end_transaction, FAIL) - +#if 0 /* JRM */ + HDfprintf(stdout, "%s trans_num = %lld.\n", FUNC, trans_num); +#endif /* JRM */ /* Check Arguments */ HDassert(struct_ptr); HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC); diff --git a/src/H5C2pkg.h b/src/H5C2pkg.h index 637e5e9..5245ce6 100644 --- a/src/H5C2pkg.h +++ b/src/H5C2pkg.h @@ -805,6 +805,38 @@ struct H5C2_jbrb_t * mdj_jbrb: Instance of H5C2_jbrb_t used to manage logging of journal * entries to the journal file. * + * If journaling is requested at file creation time, we must make note of + * the request, and delay implementing it until receipt of the first + * begin transaction message. This is necessary as the file structure will + * not have been fully initialized at the point the request is received. + * + * The following fields support this facility. + * + * mdj_startup_pending: Boolean flag used to indicate that we must + * do setup for journaling on the next begin transaction + * call. + * + * mdj_startup_f: Pointer to the instance of H5F_t used in the metadata + * journaling startup. + * + * mdj_startup_dxpl_id: dxpl_id used in the metadata journaling startup. + * + * mdj_startup_jrnl_file_name: Pointer to a string containing the name of + * the journal file. + * + * mdj_startup_buf_size: Size of the buffers used in the metadata journal + * buffer ring buffer. + * + * mdj_startup_num_bufs: Number of buffers in the metadata journal buffer + * ring buffer. + * + * mdj_startup_use_aio: use_aio parameter used when setting up metadata + * journaling. + * + * mdj_startup_human_readable: human_readable parameter used when setting + * up metadata journaling. + * + * * 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 @@ -1206,6 +1238,15 @@ struct H5C2_t size_t jwipl_size; H5C2_cache_entry_t * jwipl_head_ptr; H5C2_cache_entry_t * jwipl_tail_ptr; + + hbool_t mdj_startup_pending; + H5F_t * mdj_startup_f; + hid_t mdj_startup_dxpl_id; + char * mdj_startup_jrnl_file_name; + size_t mdj_startup_buf_size; + int mdj_startup_num_bufs; + hbool_t mdj_startup_use_aio; + hbool_t mdj_startup_human_readable; #if H5C2_COLLECT_CACHE_STATS @@ -1712,6 +1753,26 @@ if ( ( (hd_ptr) == NULL ) || \ ) \ ) \ ) { \ + HDfprintf(stdout, "%s: TRANS DLL pre remove SC failed.\n", FUNC); \ + /* JRM */ /* Debugging code -- remove eventually */ \ + if ( (hd_ptr) == NULL ) HDfprintf(stdout, "( (hd_ptr) == NULL ).\n" );\ + if ( (tail_ptr) == NULL ) HDfprintf(stdout, "(tail_ptr) == NULL\n");\ + if ( (entry_ptr) == NULL ) HDfprintf(stdout, "(entry_ptr) == NULL\n");\ + if ( (len) <= 0 ) HDfprintf(stdout, "( (len) <= 0 )\n");\ + if ( (Size) < (entry_ptr)->size ) \ + HDfprintf(stdout,"( (Size) < (entry_ptr)->size )\n");\ + if ( ( (Size) == (entry_ptr)->size ) && ( ! ( (len) == 1 ) ) ) \ + HDfprintf(stdout, "(((Size)==(entry_ptr)->size)&&(!((len) == 1)))\n");\ + if ( ( (entry_ptr)->trans_prev == NULL ) && ( (hd_ptr) != (entry_ptr) ) ) \ + HDfprintf(stdout,"(((entry_ptr)->trans_prev==NULL)&&((hd_ptr)!=(entry_ptr)))\n");\ + if ( ((entry_ptr)->trans_next == NULL) && ((tail_ptr) != (entry_ptr)) ) \ + HDfprintf(stdout,"(((entry_ptr)->trans_next==NULL)&&((tail_ptr)!=(entry_ptr)))\n"); \ + if ( ( (len) == 1 ) && \ + ( ! ( ( (hd_ptr) == (entry_ptr) ) && ( (tail_ptr) == (entry_ptr) ) && \ + ( (entry_ptr)->trans_next == NULL ) && \ + ( (entry_ptr)->trans_prev == NULL ) && \ + ( (Size) == (entry_ptr)->size ) ) ) ) \ + HDfprintf(stdout,"long condition failed\n"); \ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (fv), "TRANS DLL pre remove SC failed") \ } @@ -3134,11 +3195,11 @@ if ( ( (cache_ptr) == NULL ) || \ \ HDassert( (cache_ptr)->mdj_enabled ); \ HDassert( (cache_ptr)->trans_in_progress ); \ - H5C2__TRANS_DLL_PREPEND((entry_ptr), \ - ((cache_ptr)->jwipl_head_ptr), \ - ((cache_ptr)->jwipl_tail_ptr), \ - ((cache_ptr)->jwipl_len), \ - ((cache_ptr)->jwipl_size), fail_val) \ + H5C2__DLL_PREPEND((entry_ptr), \ + ((cache_ptr)->jwipl_head_ptr), \ + ((cache_ptr)->jwipl_tail_ptr), \ + ((cache_ptr)->jwipl_len), \ + ((cache_ptr)->jwipl_size), fail_val) \ \ } else { \ \ @@ -3197,11 +3258,11 @@ if ( ( (cache_ptr) == NULL ) || \ \ HDassert( (cache_ptr)->mdj_enabled ); \ HDassert( (cache_ptr)->trans_in_progress ); \ - H5C2__TRANS_DLL_PREPEND((entry_ptr), \ - ((cache_ptr)->jwipl_head_ptr), \ - ((cache_ptr)->jwipl_tail_ptr), \ - ((cache_ptr)->jwipl_len), \ - ((cache_ptr)->jwipl_size), (fail_val)) \ + H5C2__DLL_PREPEND((entry_ptr), \ + ((cache_ptr)->jwipl_head_ptr), \ + ((cache_ptr)->jwipl_tail_ptr), \ + ((cache_ptr)->jwipl_len), \ + ((cache_ptr)->jwipl_size), (fail_val)) \ \ } else { \ \ @@ -3348,6 +3409,110 @@ if ( ( (cache_ptr) == NULL ) || \ /*------------------------------------------------------------------------- * + * Macro: H5C2__UPDATE_RP_FOR_LOAD + * + * Purpose: Update the replacement policy data structures for a + * 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 + * significant number of cycles, we will have to re-work + * the code to avoid this step. + * + * At present, we only support the modified LRU policy, so + * this function deals with that case unconditionally. If + * we ever support other replacement policies, the function + * should switch on the current policy and act accordingly. + * + * In theory, the loaded entry should be clean, but due + * to a bug fix, it is possible that we will dirty it during + * the load. + * + * Return: N/A + * + * Programmer: John Mainzer, 5/02/08 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +#if H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS + +#define H5C2__UPDATE_RP_FOR_LOAD(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_pinned) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( (entry_ptr)->size > 0 ); \ + HDassert( (entry_ptr)->last_trans == 0 ); \ + \ + /* modified LRU specific code */ \ + \ + /* insert the entry at the head of the LRU list. */ \ + \ + H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* insert the entry at the head of the clean or dirty LRU list as \ + * appropriate. \ + */ \ + \ + if ( entry_ptr->is_dirty ) { \ + H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ + (cache_ptr)->dLRU_tail_ptr, \ + (cache_ptr)->dLRU_list_len, \ + (cache_ptr)->dLRU_list_size, (fail_val)) \ + } else { \ + H5C2__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ + (cache_ptr)->cLRU_tail_ptr, \ + (cache_ptr)->cLRU_list_len, \ + (cache_ptr)->cLRU_list_size, (fail_val)) \ + } \ + \ + /* End modified LRU specific code. */ \ +} + +#else /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + +#define H5C2__UPDATE_RP_FOR_LOAD(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_pinned) ); \ + HDassert( !((entry_ptr)->is_read_only) ); \ + HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \ + HDassert( (entry_ptr)->size > 0 ); \ + HDassert( (entry_ptr)->last_trans == 0 ); \ + \ + /* modified LRU specific code */ \ + \ + /* insert the entry at the head of the LRU list. */ \ + \ + H5C2__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, \ + (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* End modified LRU specific code. */ \ +} + +#endif /* H5C2_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ + + +/*------------------------------------------------------------------------- + * * Macro: H5C2__UPDATE_RP_FOR_PROTECT * * Purpose: Update the replacement policy data structures for a @@ -4403,9 +4568,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 - * one of its constituents. Note that it is the caller's + * one of its constituents. Note that it is the callers * responsibility to verify that the entry is in the - * transaction list. + * transaction list if it should be. * * Return: N/A * @@ -4420,13 +4585,12 @@ if ( cache_ptr->mdj_enabled ) \ #define H5C2__UPDATE_TL_FOR_ENTRY_SIZE_CHANGE(cache_ptr, entry_ptr, \ old_size, new_size) \ -if ( (cache_ptr)->mdj_enabled ) { \ +if ( ( (cache_ptr)->mdj_enabled ) && \ + ( (entry_ptr)->last_trans == (cache_ptr)->trans_num ) ) { \ HDassert( (cache_ptr)->trans_in_progress ); \ - if ( (entry_ptr)->last_trans == (cache_ptr)->trans_num ) { \ - H5C2__DLL_UPDATE_FOR_SIZE_CHANGE(((cache_ptr)->tl_len), \ - ((cache_ptr)->tl_size), \ - (old_size), (new_size)); \ - } \ + H5C2__DLL_UPDATE_FOR_SIZE_CHANGE(((cache_ptr)->tl_len), \ + ((cache_ptr)->tl_size), \ + (old_size), (new_size)); \ } /* H5C2__UPDATE_TL_FOR_ENTRY_SIZE_CHANGE() */ #endif /* _H5C2pkg_H */ diff --git a/src/H5C2private.h b/src/H5C2private.h index 4f42927..7806337 100644 --- a/src/H5C2private.h +++ b/src/H5C2private.h @@ -572,6 +572,9 @@ typedef herr_t (*H5C2_log_flush_func_t)(H5C2_t * cache_ptr, * If the entry is dirty, the serialize callback must be used * to update this image before it is written to disk * + * image_up_to_date: Boolean flag that is set to TRUE when *image_ptr + * is up to date, and set to false when the entry is dirtied. + * * type: Pointer to the instance of H5C2_class_t containing pointers * to the methods for cache entries of the current type. This * field should be NULL when the instance of H5C2_cache_entry_t @@ -848,6 +851,7 @@ typedef struct H5C2_cache_entry_t haddr_t addr; size_t size; void * image_ptr; + hbool_t image_up_to_date; const H5C2_class_t * type; hbool_t is_dirty; hbool_t dirtied; @@ -1477,6 +1481,7 @@ H5_DLL herr_t H5C2_end_transaction(H5F_t * f, H5_DLL herr_t H5C2_get_journal_config(H5C2_t * cache_ptr, hbool_t * journaling_enabled_ptr, + hbool_t * startup_pending_ptr, char * journal_file_path_ptr, size_t * jbrb_buf_size_ptr, int * jbrb_num_bufs_ptr, @@ -1491,6 +1496,15 @@ H5_DLL herr_t H5C2_journal_pre_flush(H5C2_t * cache_ptr); H5_DLL herr_t H5C2_journal_transaction(H5F_t * f, H5C2_t * cache_ptr); +H5_DLL herr_t H5C2_queue_begin_journaling(H5F_t * f, + hid_t dxpl_id, + H5C2_t * cache_ptr, + char * journal_file_name_ptr, + size_t buf_size, + int num_bufs, + hbool_t use_aio, + hbool_t human_readable); + H5_DLL herr_t H5C2_update_for_new_last_trans_on_disk(H5C2_t * cache_ptr, uint64_t new_last_trans_on_disk); diff --git a/test/cache2_common.c b/test/cache2_common.c index d0571ed..b8716f1 100644 --- a/test/cache2_common.c +++ b/test/cache2_common.c @@ -27,8 +27,6 @@ #include "H5MMprivate.h" #include "cache2_common.h" -#define USE_CORE_DRIVER FALSE - /* global variable declarations: */ const char *FILENAME[] = { @@ -989,6 +987,7 @@ serialize(haddr_t addr, void ** new_image_ptr_ptr) { const char * fcn_name = "serialize()"; + char * char_ptr; hbool_t verbose = FALSE; herr_t ret_val = SUCCEED; int32_t i; @@ -1049,6 +1048,12 @@ serialize(haddr_t addr, entry_ptr->num_flush_ops = 0; entry_ptr->flush_op_self_resize_in_progress = FALSE; + /* This looks wrong, but it isn't -- *flags_ptr will be modified + * by execute_flush_op2() only if the target is this entry -- + * and the flags set will accumulate over the set of calls in + * the for loop. + */ + if ( ( pass2 ) && ( ((*flags_ptr) & H5C2__SERIALIZE_RESIZED_FLAG) != 0 ) ) { @@ -1082,6 +1087,7 @@ serialize(haddr_t addr, *new_image_ptr_ptr = image_ptr; *new_len_ptr = entry_ptr->size; + len = entry_ptr->size; } } @@ -1097,6 +1103,14 @@ serialize(haddr_t addr, } } + /* null out the image to avoid spurious failures */ + char_ptr = (char *)image_ptr; + for ( i = 0; (size_t)i < len; i++ ) + { + *char_ptr = '\0'; + char_ptr++; + } + if ( ( type == PICO_ENTRY_TYPE ) || ( type == VARIABLE_ENTRY_TYPE ) ) { HDassert( entry_ptr->size >= PICO_ENTRY_SIZE ); @@ -1344,7 +1358,6 @@ free_icr(haddr_t addr, HDassert( entry_ptr->header.size == entry_ptr->size ); HDassert( ( entry_ptr->type == VARIABLE_ENTRY_TYPE ) || ( entry_ptr->size == entry_sizes2[entry_ptr->type] ) ); - HDassert( !(entry_ptr->is_dirty) ); HDassert( !(entry_ptr->header.is_dirty) ); @@ -2181,6 +2194,7 @@ resize_pinned_entry2(H5F_t * file_ptr, result = H5C2_resize_pinned_entry(file_ptr, (void *)entry_ptr, new_size); + entry_ptr->is_dirty = TRUE; if ( result != SUCCEED ) { @@ -2625,6 +2639,8 @@ setup_cache2(size_t max_cache_size, HDfprintf(stdout, "%s() - %0d -- pass2 = %d\n", fcn_name, mile_stone++, (int)pass2); + saved_fid = -1; + #if 0 /* This debugging code is useful from time to time -- keep it for now */ HDfprintf(stdout, "PICO_BASE_ADDR = 0x%lx, PICO_ALT_BASE_ADDR = 0x%lx.\n", (long)PICO_BASE_ADDR, (long)PICO_ALT_BASE_ADDR); @@ -2693,6 +2709,8 @@ setup_cache2(size_t max_cache_size, fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id); + saved_fid = fid; + if ( fid < 0 ) { pass2 = FALSE; @@ -2713,7 +2731,6 @@ setup_cache2(size_t max_cache_size, } else { - saved_fid = fid; file_ptr = H5I_object_verify(fid, H5I_FILE); if ( file_ptr == NULL ) { @@ -2919,7 +2936,7 @@ takedown_cache2(H5F_t * file_ptr, saved_fid = -1; } -#if ! USE_CORE_DRIVER +#if ( USE_CORE_DRIVER == FALSE ) if ( h5_fixname(FILENAME[0], H5P_DEFAULT, filename, sizeof(filename)) == NULL ) { @@ -3176,7 +3193,7 @@ insert_entry2(H5F_t * file_ptr, pass2 = FALSE; failure_mssg2 = "error in H5C2_insert()."; -#if 0 /* This is useful debugging code. Lets keep it around. */ +#if 1 /* This is useful debugging code. Lets keep it around. */ HDfprintf(stdout, "result = %d\n", (int)result); HDfprintf(stdout, "entry_ptr->header.is_protected = %d\n", @@ -3427,6 +3444,9 @@ mark_pinned_or_protected_entry_dirty2(H5F_t * file_ptr, * Updated code to reflect the fact that renames automatically * dirty entries. * + * JRM -- 5/16/08 + * Updated code to do nothing if pass2 is FALSE on entry. + * *------------------------------------------------------------------------- */ @@ -3436,6 +3456,7 @@ rename_entry2(H5C2_t * cache_ptr, int32_t idx, hbool_t main_addr) { + const char * fcn_name = "rename_entry2()"; herr_t result; hbool_t done = TRUE; /* will set to FALSE if we have work to do */ haddr_t old_addr = HADDR_UNDEF; @@ -3443,74 +3464,168 @@ rename_entry2(H5C2_t * cache_ptr, test_entry_t * base_addr; test_entry_t * entry_ptr; - HDassert( cache_ptr ); - HDassert( ( 0 <= type ) && ( type < NUMBER_OF_ENTRY_TYPES ) ); - HDassert( ( 0 <= idx ) && ( idx <= max_indices2[type] ) ); + if ( pass2 ) { - base_addr = entries2[type]; - entry_ptr = &(base_addr[idx]); + HDassert( cache_ptr ); + HDassert( ( 0 <= type ) && ( type < NUMBER_OF_ENTRY_TYPES ) ); + HDassert( ( 0 <= idx ) && ( idx <= max_indices2[type] ) ); - HDassert( entry_ptr->index == idx ); - HDassert( entry_ptr->type == type ); - HDassert( entry_ptr == entry_ptr->self ); - HDassert( entry_ptr->cache_ptr == cache_ptr ); - HDassert( !(entry_ptr->is_protected) ); - HDassert( !(entry_ptr->header.is_protected) ); + base_addr = entries2[type]; + entry_ptr = &(base_addr[idx]); + HDassert( entry_ptr->index == idx ); + HDassert( entry_ptr->type == type ); + HDassert( entry_ptr == entry_ptr->self ); + HDassert( entry_ptr->cache_ptr == cache_ptr ); + HDassert( !(entry_ptr->is_protected) ); + HDassert( !(entry_ptr->header.is_protected) ); - if ( entry_ptr->at_main_addr && !main_addr ) { - /* rename to alt addr */ + if ( entry_ptr->at_main_addr && !main_addr ) { - HDassert( entry_ptr->addr == entry_ptr->main_addr ); + /* rename to alt addr */ - done = FALSE; - old_addr = entry_ptr->addr; - new_addr = entry_ptr->alt_addr; + HDassert( entry_ptr->addr == entry_ptr->main_addr ); - } else if ( !(entry_ptr->at_main_addr) && main_addr ) { + done = FALSE; + old_addr = entry_ptr->addr; + new_addr = entry_ptr->alt_addr; - /* rename to main addr */ + } else if ( !(entry_ptr->at_main_addr) && main_addr ) { - HDassert( entry_ptr->addr == entry_ptr->alt_addr ); + /* rename to main addr */ - done = FALSE; - old_addr = entry_ptr->addr; - new_addr = entry_ptr->main_addr; - } + HDassert( entry_ptr->addr == entry_ptr->alt_addr ); + + done = FALSE; + old_addr = entry_ptr->addr; + new_addr = entry_ptr->main_addr; + } + + if ( ! done ) { + + entry_ptr->is_dirty = TRUE; + + result = H5C2_rename_entry(cache_ptr, &(types2[type]), + old_addr, new_addr); + } - if ( ! done ) { + if ( ! done ) { + + if ( ( result < 0 ) || + ( ( ! ( entry_ptr->header.destroy_in_progress ) ) && + ( entry_ptr->header.addr != new_addr ) ) ) { + +#if 1 /* JRM */ + if ( result < 0 ) { + HDfprintf(stdout, "%s: H5C2_rename_entry() failed.\n", + fcn_name); + } + if ( ( ! ( entry_ptr->header.destroy_in_progress ) ) && + ( entry_ptr->header.addr != new_addr ) ) { + HDfprintf(stdout, "%s: ( ( ! ( entry_ptr->header.destroy_in_progress ) ) && ( entry_ptr->header.addr != new_addr ) ).\n", + fcn_name); + } + HDassert(FALSE); +#endif /* JRM */ + pass2 = FALSE; + failure_mssg2 = "error in H5C2_rename_entry()."; - entry_ptr->is_dirty = TRUE; + } else { + + entry_ptr->addr = new_addr; + entry_ptr->at_main_addr = main_addr; + } + } - result = H5C2_rename_entry(cache_ptr, &(types2[type]), - old_addr, new_addr); + HDassert( ((entry_ptr->header).type)->id == type ); + + HDassert( entry_ptr->header.is_dirty ); + HDassert( entry_ptr->is_dirty ); } - if ( ! done ) { + return; - if ( ( result < 0 ) || - ( ( ! ( entry_ptr->header.destroy_in_progress ) ) && - ( entry_ptr->header.addr != new_addr ) ) ) { +} /* rename_entry2() */ - pass2 = FALSE; - failure_mssg2 = "error in H5C2_rename_entry()."; + +/*------------------------------------------------------------------------- + * Function: pin_protected_entry2() + * + * Purpose: Pin the specified protected entry. + * + * Do nothing if pass2 is FALSE on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 5/17/06 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ - } else { +void +pin_protected_entry2(H5F_t * file_ptr, + int32_t type, + int32_t idx) +{ + /* const char * fcn_name = "pin_protected_entry2()"; */ +#ifndef NDEBUG + H5C2_t * cache_ptr = file_ptr->shared->cache2; +#endif /* NDEBUG */ + herr_t result; + test_entry_t * base_addr; + test_entry_t * entry_ptr; + + if ( pass2 ) { + + HDassert( cache_ptr ); + HDassert( ( 0 <= type ) && ( type < NUMBER_OF_ENTRY_TYPES ) ); + HDassert( ( 0 <= idx ) && ( idx <= max_indices2[type] ) ); + + base_addr = entries2[type]; + entry_ptr = &(base_addr[idx]); + + HDassert( entry_ptr->index == idx ); + HDassert( entry_ptr->type == type ); + HDassert( entry_ptr == entry_ptr->self ); + HDassert( entry_ptr->cache_ptr == cache_ptr ); + HDassert( entry_ptr->header.is_protected ); + HDassert( ! entry_ptr->header.is_pinned ); + + result = H5C2_pin_protected_entry(file_ptr, (void *)entry_ptr); + + if ( ( result < 0 ) + || + ( ! (entry_ptr->header.is_protected) ) + || + ( ! (entry_ptr->header.is_pinned) ) + || + ( entry_ptr->header.type != &(types2[type]) ) + || + ( entry_ptr->size != entry_ptr->header.size ) + || + ( entry_ptr->addr != entry_ptr->header.addr ) ) { + + pass2 = FALSE; + failure_mssg2 = + "error in H5C2_pin_protected_entry()."; - entry_ptr->addr = new_addr; - entry_ptr->at_main_addr = main_addr; } - } - HDassert( ((entry_ptr->header).type)->id == type ); + entry_ptr->is_pinned = TRUE; - HDassert( entry_ptr->header.is_dirty ); - HDassert( entry_ptr->is_dirty ); + HDassert( ((entry_ptr->header).type)->id == type ); + + } return; -} /* rename_entry2() */ +} /* pinned_protected_entry2() */ /*------------------------------------------------------------------------- @@ -3590,7 +3705,7 @@ protect_entry2(H5F_t * file_ptr, ( entry_ptr->size != entry_ptr->header.size ) || ( entry_ptr->addr != entry_ptr->header.addr ) ) { -#if 0 +#if 1 /* I've written the following debugging code several times * now. Lets keep it around so I don't have to write it * again. diff --git a/test/cache2_common.h b/test/cache2_common.h index d8ee4fe..60cf697 100644 --- a/test/cache2_common.h +++ b/test/cache2_common.h @@ -33,6 +33,8 @@ #define NO_CHANGE -1 +#define USE_CORE_DRIVER 0 + /* with apologies for the abuse of terminology... */ #define PICO_ENTRY_TYPE 0 @@ -672,6 +674,10 @@ void rename_entry2(H5C2_t * cache_ptr, int32_t idx, hbool_t main_addr); +void pin_protected_entry2(H5F_t * file_ptr, + int32_t type, + int32_t idx); + void protect_entry2(H5F_t * file_ptr, int32_t type, int32_t idx); diff --git a/test/cache2_journal.c b/test/cache2_journal.c index 7789ced..4b4860a 100644 --- a/test/cache2_journal.c +++ b/test/cache2_journal.c @@ -26,6 +26,7 @@ #include "H5Eprivate.h" #include "H5Iprivate.h" #include "H5MMprivate.h" /* Memory management */ +#include "H5MFprivate.h" #include "H5AC2private.h" #include "cache2_common.h" #include "H5Fpkg.h" @@ -38,49 +39,3470 @@ const char *FILENAMES[] = { "cache_test", "cache_journal_test", "cache_sb_test", + "journal_file", NULL }; /* private function declarations: */ +/* utility functions */ + +static void begin_trans(H5C2_t * cache_ptr, + hbool_t verbose, + uint64_t expected_trans_num, + const char * trans_name); + +static void copy_file(const char * input_file, + const char * output_file); + +static void end_trans(H5F_t * file_ptr, + H5C2_t * cache_ptr, + hbool_t verbose, + uint64_t trans_num, + const char * trans_name); + +static void flush_journal(H5C2_t * cache_ptr); + +static void jrnl_col_major_scan_backward2(H5F_t * file_ptr, + int32_t max_index, + int32_t lag, + hbool_t verbose, + hbool_t reset_stats, + hbool_t display_stats, + hbool_t display_detailed_stats, + hbool_t do_inserts, + hbool_t dirty_inserts, + int dirty_unprotects, + uint64_t trans_num); + +static void jrnl_col_major_scan_forward2(H5F_t * file_ptr, + int32_t max_index, + int32_t lag, + hbool_t verbose, + hbool_t reset_stats, + hbool_t display_stats, + hbool_t display_detailed_stats, + hbool_t do_inserts, + hbool_t dirty_inserts, + int dirty_unprotects, + uint64_t trans_num); +#if 0 /* JRM */ +/* these functions are in-op at present */ +static void jrnl_row_major_scan_backward2(H5F_t * file_ptr, + int32_t max_index, + int32_t lag, + hbool_t verbose, + hbool_t reset_stats, + hbool_t display_stats, + hbool_t display_detailed_stats, + hbool_t do_inserts, + hbool_t dirty_inserts, + hbool_t do_renames, + hbool_t rename_to_main_addr, + hbool_t do_destroys, + hbool_t do_mult_ro_protects, + int dirty_destroys, + int dirty_unprotects, + uint64_t trans_num); + +static void jrnl_row_major_scan_forward2(H5F_t * file_ptr, + int32_t max_index, + int32_t lag, + hbool_t verbose, + hbool_t reset_stats, + hbool_t display_stats, + hbool_t display_detailed_stats, + hbool_t do_inserts, + hbool_t dirty_inserts, + hbool_t do_renames, + hbool_t rename_to_main_addr, + hbool_t do_destroys, + hbool_t do_mult_ro_protects, + int dirty_destroys, + int dirty_unprotects, + uint64_t trans_num); +#endif /* JRM */ +static void setup_cache_for_journaling(const char * hdf_file_name, + const char * journal_file_name, + hid_t * file_id_ptr, + H5F_t ** file_ptr_ptr, + H5C2_t ** cache_ptr_ptr); + +static void takedown_cache_after_journaling(hid_t file_id, + const char * filename, + const char * journal_filename); + +static void verify_journal_contents(const char * journal_file_path_ptr, + const char * expected_file_path_ptr); + +static void verify_journal_empty(const char * journal_file_path_ptr); + +/* test functions */ + static void check_buffer_writes(void); -static void write_flush_verify(H5C2_jbrb_t * struct_ptr, - int size, - char * data, - FILE * readback); +static void write_flush_verify(H5C2_jbrb_t * struct_ptr, + int size, + char * data, + FILE * readback); + +static void write_noflush_verify(H5C2_jbrb_t * struct_ptr, + int size, + char * data, + FILE * readback, + int repeats); + +static void check_mdj_config_block_IO(void); + +static void test_mdj_conf_blk_read_write_discard(H5F_t * file_ptr, + const char * jrnl_file_path); + +static void check_superblock_extensions(void); + +static void check_message_format(void); + +static void check_legal_calls(void); + +static void check_transaction_tracking(void); + +static void mdj_smoke_check_00(void); + +static void mdj_smoke_check_01(void); + +static void write_verify_trans_num(H5C2_jbrb_t * struct_ptr, + uint64_t trans_num, + uint64_t verify_val); + + + +/**************************************************************************/ +/**************************************************************************/ +/********************************* tests: *********************************/ +/**************************************************************************/ +/**************************************************************************/ + +/*** metadata journaling test utility functions ***/ + +/*------------------------------------------------------------------------- + * Function: begin_trans() + * + * Purpose: If pass2 is true on entry, attempt to begin a transaction. + * If the operation fails, or if it returns an unexpected + * transaction number, set passw2 to FALSE, and set failure_mssg2 + * to point to an appropriate failure message. + * + * Do nothing if pass2 is FALSE on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 5/15/08 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +static void +begin_trans(H5C2_t * cache_ptr, + hbool_t verbose, + uint64_t expected_trans_num, + const char * trans_name) +{ + const char * fcn_name = "begin_trans()"; + herr_t result; + uint64_t trans_num = 0; + + if ( pass2 ) { + + result = H5C2_begin_transaction(cache_ptr, &trans_num, trans_name); + + if ( result < 0 ) { + + if ( verbose ) { + + HDfprintf(stdout, "%s: H5C2_begin_transaction(%s) failed.\n", + fcn_name, trans_name); + } + pass2 = FALSE; + failure_mssg2 = "H5C2_begin_transaction() failed.\n"; + + } else if ( trans_num != expected_trans_num ) { + + if ( verbose ) { + + HDfprintf(stdout, "%s: actual/expected trans num = %lld/%lld.\n", + fcn_name, (long long)trans_num, + (long long)expected_trans_num); + } + pass2 = FALSE; + failure_mssg2 = "begin_trans() issued unexpected trans_num.\n"; + } + } + + return; + +} /* begin_trans() */ + + +/*------------------------------------------------------------------------- + * Function: copy_file() + * + * Purpose: If pass2 is true, copy the input file to the output file. + * Set pass2 to FALSE and set failure_mssg2 to point to an + * appropriate error message on failure. + * + * Do nothing if pass2 is false on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 5/15/08 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +static void +copy_file(const char * input_file, + const char * output_file) +{ + const char * fcn_name = "copy_file()"; + char buffer[(8 * 1024) + 1]; + hbool_t verbose = FALSE; + size_t cur_buf_len; + const size_t max_buf_len = (8 * 1024); + size_t input_len; + size_t input_remainder; + ssize_t result; + int input_file_fd = -1; + int output_file_fd = -1; + struct stat buf; + + if ( pass2 ) { + + if ( input_file == NULL ) { + + failure_mssg2 = "input_file NULL on entry?!?", + pass2 = FALSE; + + } else if ( output_file == NULL ) { + + failure_mssg2 = "output_file NULL on entry?!?", + pass2 = FALSE; + + } + } + + /* get the length of the input file */ + if ( pass2 ) { + + if ( HDstat(input_file, &buf) != 0 ) { + + if ( verbose ) { + + HDfprintf(stdout, "%s: HDstat() failed with errno = %d.\n", + fcn_name, errno); + } + failure_mssg2 = "stat() failed on journal file."; + pass2 = FALSE; + + } else { + + if ( (buf.st_size) == 0 ) { + + failure_mssg2 = "input file empty?!?"; + pass2 = FALSE; + + } else { + + input_len = (size_t)(buf.st_size); + input_remainder = input_len; + + if ( verbose ) { + + HDfprintf(stdout, "%s: input_len = %d.\n", + fcn_name, (int)input_len); + } + } + } + } + + /* open the input file */ + if ( pass2 ) { + + if ( (input_file_fd = HDopen(input_file, O_RDONLY, 0777)) == -1 ) { + + if ( verbose ) { + + HDfprintf(stdout, "%s: HDopen(i) failed with errno = %d.\n", + fcn_name, errno); + } + failure_mssg2 = "Can't open input file."; + pass2 = FALSE; + } + } + + /* open the output file */ + if ( pass2 ) { + + if ( (output_file_fd = HDopen(output_file, O_WRONLY|O_CREAT|O_TRUNC, 0777)) + == -1 ) { + + if ( verbose ) { + + HDfprintf(stdout, "%s: HDopen(i) failed with errno = %d.\n", + fcn_name, errno); + } + failure_mssg2 = "Can't open output file."; + pass2 = FALSE; + } + } + + while ( ( pass2 ) && + ( input_remainder > 0 ) ) + { + if ( input_remainder > max_buf_len ) { + + cur_buf_len = max_buf_len; + input_remainder -= max_buf_len; + + } else { + + cur_buf_len = input_remainder; + input_remainder = 0; + } + + result = HDread(input_file_fd, buffer, cur_buf_len); + + if ( result != (int)cur_buf_len ) { + + if ( verbose ) { + + HDfprintf(stdout, + "%s: HDread() failed. result = %d, errno = %d.\n", + fcn_name, (int)result, errno); + } + failure_mssg2 = "error reading input file."; + pass2 = FALSE; + } + + buffer[cur_buf_len] = '\0'; + + if ( pass2 ) { + + result = HDwrite(output_file_fd, buffer, cur_buf_len); + + if ( result != (int)cur_buf_len ) { + + if ( verbose ) { + + HDfprintf(stdout, + "%s: HDwrite() failed. result = %d, errno = %d.\n", + fcn_name, (int)result, errno); + } + failure_mssg2 = "error writing output file."; + pass2 = FALSE; + } + } + } + + if ( input_file_fd != -1 ) { + + if ( HDclose(input_file_fd) != 0 ) { + + if ( verbose ) { + + HDfprintf(stdout, "%s: HDclose(i) failed with errno = %d.\n", + fcn_name, errno); + } + + if ( pass2 ) { + + failure_mssg2 = "Can't close input file."; + pass2 = FALSE; + } + } + } + + if ( output_file_fd != -1 ) { + + if ( HDclose(output_file_fd) != 0 ) { + + if ( verbose ) { + + HDfprintf(stdout, "%s: HDclose(o) failed with errno = %d.\n", + fcn_name, errno); + } + + if ( pass2 ) { + + failure_mssg2 = "Can't close output file."; + pass2 = FALSE; + } + } + } + + return; + +} /* copy_file() */ + + +/*------------------------------------------------------------------------- + * Function: end_trans() + * + * Purpose: If pass2 is true on entry, attempt to end the current + * transaction. If the operation fails, set pass2 to FALSE, + * and set failure_mssg2 to point to an appropriate failure + * message. + * + * Do nothing if pass2 is FALSE on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 5/15/08 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +static void +end_trans(H5F_t * file_ptr, + H5C2_t * cache_ptr, + hbool_t verbose, + uint64_t trans_num, + const char * trans_name) +{ + const char * fcn_name = "end_trans()"; + herr_t result; + + if ( pass2 ) { + + result = H5C2_end_transaction(file_ptr, cache_ptr, trans_num, trans_name); + + if ( result < 0 ) { + + if ( verbose ) { + HDfprintf(stdout, + "%s: H5C2_end_transaction(%lld, \"%s\") failed.\n", + fcn_name, (long long)trans_num, trans_name); + } + pass2 = FALSE; + failure_mssg2 = "H5C2_end_transaction() failed.\n"; + } + } + + return; + +} /* end_trans() */ + + +/*------------------------------------------------------------------------- + * Function: flush_journal() + * + * Purpose: If pass2 is true on entry, attempt to flush the journal. + * If the operation fails, set pass2 to FALSE, and set + * failure_mssg2 to point to an appropriate failure message. + * + * Do nothing if pass2 is FALSE on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 5/15/08 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +static void +flush_journal(H5C2_t * cache_ptr) +{ + if ( pass2 ) { + + if ( H5C2_jb__flush(&(cache_ptr->mdj_jbrb)) < 0 ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__flush() reports failure."; + } + } + + return; + +} /* flush_journal() */ + + +/*------------------------------------------------------------------------- + * Function: jrnl_col_major_scan_backward2() + * + * Purpose: Do a sequence of inserts, protects, and unprotects + * broken into a sequence of transactions while scanning + * backwards through the set of entries. + * + * If pass2 is false on entry, do nothing. + * + * Note tht this function is an adaption of + * col_major_scan_backward2() + * + * Return: void + * + * Programmer: John Mainzer + * 5/20/08 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +void +jrnl_col_major_scan_backward2(H5F_t * file_ptr, + int32_t max_index, + int32_t lag, + hbool_t verbose, + hbool_t reset_stats, + hbool_t display_stats, + hbool_t display_detailed_stats, + hbool_t do_inserts, + hbool_t dirty_inserts, + int dirty_unprotects, + uint64_t trans_num) +{ + const char * fcn_name = "jrnl_col_major_scan_backward2()"; + H5C2_t * cache_ptr = file_ptr->shared->cache2; + int i; + int mile_stone = 1; + int32_t type; + int32_t idx; + int32_t local_max_index[NUMBER_OF_ENTRY_TYPES]; + + if ( verbose ) + HDfprintf(stdout, "%s: entering.\n", fcn_name); + + for ( i = 0; i < NUMBER_OF_ENTRY_TYPES; i++ ) + { + local_max_index[i] = MIN(max_index, max_indices2[i]); + } + + HDassert( lag > 5 ); + + if ( ( pass2 ) && ( reset_stats ) ) { + + H5C2_stats__reset(cache_ptr); + } + + idx = local_max_index[NUMBER_OF_ENTRY_TYPES - 1] + lag; + + if ( verbose ) /* 1 */ + HDfprintf(stdout, "%s: point %d.\n", fcn_name, mile_stone++); + + + while ( ( pass2 ) && ( (idx + lag) >= 0 ) ) + { + type = NUMBER_OF_ENTRY_TYPES - 1; + + trans_num++; + + begin_trans(cache_ptr, verbose, trans_num, + "jrnl_col_major_scan_backward outer loop"); + + if ( verbose ) { + + HDfprintf(stdout, "begin trans %lld, idx = %d.\n", trans_num, idx); + } + + while ( ( pass2 ) && ( type >= 0 ) ) + { + if ( verbose ) { + + HDfprintf(stdout, "%d:%d: ", type, idx); + } + + if ( ( pass2 ) && ( do_inserts) && ( (idx - lag) >= 0 ) && + ( (idx - lag) <= local_max_index[type] ) && + ( ((idx - lag) % 3) == 0 ) && + ( ! entry_in_cache2(cache_ptr, type, (idx - lag)) ) ) { + + if ( verbose ) + HDfprintf(stdout, "(i, %d, %d) ", type, (idx - lag)); + + insert_entry2(file_ptr, type, (idx - lag), dirty_inserts, + H5C2__NO_FLAGS_SET); + } + + if ( ( pass2 ) && + ( idx >= 0 ) && + ( idx <= local_max_index[type] ) ) { + + if ( verbose ) + HDfprintf(stdout, "(p, %d, %d) ", type, idx); + + protect_entry2(file_ptr, type, idx); + } + + if ( ( pass2 ) && ( (idx + lag) >= 0 ) && + ( (idx + lag) <= local_max_index[type] ) ) { + + if ( verbose ) + HDfprintf(stdout, "(u, %d, %d) ", type, (idx + lag)); + + unprotect_entry2(file_ptr, type, idx + lag, + dirty_unprotects, H5C2__NO_FLAGS_SET); + } + + if ( verbose ) + HDfprintf(stdout, "\n"); + + type--; + } + + end_trans(file_ptr, cache_ptr, verbose, trans_num, + "jrnl_col_major_scan_backward outer loop"); + + if ( verbose ) { + + HDfprintf(stdout, "end trans %lld, idx = %d.\n", trans_num, idx); + } + + if ( ( verbose ) && ( ! pass2 ) ) { + + HDfprintf(stdout, "pass2 == FALSE, failure mssg = \"%s\".\n", + failure_mssg2); + } + + idx--; + } + + if ( verbose ) /* 2 */ + HDfprintf(stdout, "%s: point %d.\n", fcn_name, mile_stone++); + + if ( ( pass2 ) && ( display_stats ) ) { + + H5C2_stats(cache_ptr, "test cache", display_detailed_stats); + } + + if ( verbose ) + HDfprintf(stdout, "%s: exiting.\n", fcn_name); + + return; + +} /* jrnl_col_major_scan_backward2() */ + + +/*------------------------------------------------------------------------- + * Function: jrnl_col_major_scan_forward2() + * + * Purpose: Do a sequence of inserts, protects, and unprotects + * broken into a sequence of transactions while scanning + * through the set of entries. + * + * Note that this function is an adaption of + * col_major_scan_forward2(). + * + * If pass2 is false on entry, do nothing. + * + * Return: void + * + * Programmer: John Mainzer + * 5/20/08 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +void +jrnl_col_major_scan_forward2(H5F_t * file_ptr, + int32_t max_index, + int32_t lag, + hbool_t verbose, + hbool_t reset_stats, + hbool_t display_stats, + hbool_t display_detailed_stats, + hbool_t do_inserts, + hbool_t dirty_inserts, + int dirty_unprotects, + uint64_t trans_num) +{ + const char * fcn_name = "jrnl_col_major_scan_forward2()"; + H5C2_t * cache_ptr = file_ptr->shared->cache2; + int i; + int32_t type; + int32_t idx; + int32_t local_max_index[NUMBER_OF_ENTRY_TYPES]; + + if ( verbose ) + HDfprintf(stdout, "%s: entering.\n", fcn_name); + + for ( i = 0; i < NUMBER_OF_ENTRY_TYPES; i++ ) + { + local_max_index[i] = MIN(max_index, max_indices2[i]); + } + + HDassert( lag > 5 ); + + type = 0; + + if ( ( pass2 ) && ( reset_stats ) ) { + + H5C2_stats__reset(cache_ptr); + } + + idx = -lag; + + while ( ( pass2 ) && ( (idx - lag) <= MAX_ENTRIES ) ) + { + type = 0; + + trans_num++; + + begin_trans(cache_ptr, verbose, trans_num, + "jrnl_col_major_scan_forward outer loop"); + + if ( verbose ) { + + HDfprintf(stdout, "begin trans %lld, idx = %d.\n", trans_num, idx); + } + + while ( ( pass2 ) && ( type < NUMBER_OF_ENTRY_TYPES ) ) + { + if ( verbose ) { + + HDfprintf(stdout, "%d:%d: ", type, idx); + } + + if ( ( pass2 ) && ( do_inserts ) && ( (idx + lag) >= 0 ) && + ( (idx + lag) <= local_max_index[type] ) && + ( ((idx + lag) % 3) == 0 ) && + ( ! entry_in_cache2(cache_ptr, type, (idx + lag)) ) ) { + + if ( verbose ) + HDfprintf(stdout, "(i, %d, %d) ", type, (idx + lag)); + + insert_entry2(file_ptr, type, (idx + lag), dirty_inserts, + H5C2__NO_FLAGS_SET); + } + + if ( ( pass2 ) && + ( idx >= 0 ) && + ( idx <= local_max_index[type] ) ) { + + if ( verbose ) + HDfprintf(stdout, "(p, %d, %d) ", type, idx); + + protect_entry2(file_ptr, type, idx); + } + + if ( ( pass2 ) && ( (idx - lag) >= 0 ) && + ( (idx - lag) <= local_max_index[type] ) ) { + + if ( verbose ) + HDfprintf(stdout, "(u, %d, %d) ", type, (idx - lag)); + + unprotect_entry2(file_ptr, type, idx - lag, + dirty_unprotects, H5C2__NO_FLAGS_SET); + } + + if ( verbose ) + HDfprintf(stdout, "\n"); + + type++; + } + + end_trans(file_ptr, cache_ptr, verbose, trans_num, + "jrnl_col_major_scan_forward outer loop"); + + if ( verbose ) { + + HDfprintf(stdout, "end trans %lld, idx = %d.\n", trans_num, idx); + } + + if ( ( verbose ) && ( ! pass2 ) ) { + + HDfprintf(stdout, "pass2 == FALSE, failure mssg = \"%s\".\n", + failure_mssg2); + } + + idx++; + } + + if ( ( pass2 ) && ( display_stats ) ) { + + H5C2_stats(cache_ptr, "test cache", display_detailed_stats); + } + + return; + +} /* jrnl_col_major_scan_forward2() */ + +#if 0 /* JRM */ +/* this code commented out as it is in-op at present */ + +/*------------------------------------------------------------------------- + * Function: jrnl_row_major_scan_backward2() + * + * Purpose: Do a sequence of inserts, protects, unprotects, renames, + * destroys broken into transactions while scanning backwards + * through the set of entries. + * + * If pass2 is false on entry, do nothing. + * + * Note that this function is an adaption of + * row_major_scan_backward2() + * + * Return: void + * + * Programmer: John Mainzer + * 5/20/08 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +void +jrnl_row_major_scan_backward2(H5F_t * file_ptr, + int32_t max_index, + int32_t lag, + hbool_t verbose, + hbool_t reset_stats, + hbool_t display_stats, + hbool_t display_detailed_stats, + hbool_t do_inserts, + hbool_t dirty_inserts, + hbool_t do_renames, + hbool_t rename_to_main_addr, + hbool_t do_destroys, + hbool_t do_mult_ro_protects, + int dirty_destroys, + int dirty_unprotects, + uint64_t trans_num) +{ + const char * fcn_name = "jrnl_row_major_scan_backward2"; + H5C2_t * cache_ptr = file_ptr->shared->cache2; + int32_t type; + int32_t idx; + int32_t local_max_index; + + if ( verbose ) + HDfprintf(stdout, "%s(): Entering.\n", fcn_name); + + HDassert( lag >= 10 ); + + type = NUMBER_OF_ENTRY_TYPES - 1; + + if ( ( pass2 ) && ( reset_stats ) ) { + + H5C2_stats__reset(cache_ptr); + } + + while ( ( pass2 ) && ( type >= 0 ) ) + { + local_max_index = MIN(max_index, max_indices2[type]); + + idx = local_max_index + lag; + + while ( ( pass2 ) && ( idx >= -lag ) ) + { + trans_num++; + + begin_trans(cache_ptr, verbose, trans_num, + "jrnl_row_major_scan_backward inner loop"); + + if ( verbose ) { + + HDfprintf(stdout, "%lld:%d:%d: ", trans_num, type, idx); + } + + if ( ( pass2 ) && ( do_inserts ) && ( (idx - lag) >= 0 ) && + ( (idx - lag) <= local_max_index ) && + ( ((idx - lag) % 2) == 1 ) && + ( ! entry_in_cache2(cache_ptr, type, (idx - lag)) ) ) { + + if ( verbose ) + HDfprintf(stdout, "(i, %d, %d) ", type, (idx - lag)); + + insert_entry2(file_ptr, type, (idx - lag), dirty_inserts, + H5C2__NO_FLAGS_SET); + } + + + if ( ( pass2 ) && ( (idx - lag + 1) >= 0 ) && + ( (idx - lag + 1) <= local_max_index ) && + ( ( (idx - lag + 1) % 3 ) == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "(p, %d, %d) ", type, (idx - lag + 1)); + + protect_entry2(file_ptr, type, (idx - lag + 1)); + } + + if ( ( pass2 ) && ( (idx - lag + 2) >= 0 ) && + ( (idx - lag + 2) <= local_max_index ) && + ( ( (idx - lag + 2) % 3 ) == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "(u, %d, %d) ", type, (idx - lag + 2)); + + unprotect_entry2(file_ptr, type, idx-lag+2, NO_CHANGE, + H5C2__NO_FLAGS_SET); + } + + + if ( ( pass2 ) && ( do_renames ) && ( (idx - lag + 2) >= 0 ) && + ( (idx - lag + 2) <= local_max_index ) && + ( ( (idx - lag + 2) % 3 ) == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "(r, %d, %d, %d) ", + type, (idx + lag + 2), (int)rename_to_main_addr); + + rename_entry2(cache_ptr, type, (idx - lag + 2), + rename_to_main_addr); + } + + + if ( ( pass2 ) && ( (idx - lag + 3) >= 0 ) && + ( (idx - lag + 3) <= local_max_index ) && + ( ( (idx - lag + 3) % 5 ) == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "(p, %d, %d) ", type, (idx - lag + 3)); + + protect_entry2(file_ptr, type, (idx - lag + 3)); + } + + if ( ( pass2 ) && ( (idx - lag + 5) >= 0 ) && + ( (idx - lag + 5) <= local_max_index ) && + ( ( (idx - lag + 5) % 5 ) == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "(u, %d, %d) ", type, (idx - lag + 5)); + + unprotect_entry2(file_ptr, type, idx-lag+5, NO_CHANGE, + H5C2__NO_FLAGS_SET); + } + + if ( do_mult_ro_protects ) + { + if ( ( pass2 ) && ( (idx - lag + 5) >= 0 ) && + ( (idx - lag + 5) < local_max_index ) && + ( (idx - lag + 5) % 9 == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "(p-ro, %d, %d) ", type, + (idx - lag + 5)); + + protect_entry_ro2(file_ptr, type, (idx - lag + 5)); + } + + if ( ( pass2 ) && ( (idx - lag + 6) >= 0 ) && + ( (idx - lag + 6) < local_max_index ) && + ( (idx - lag + 6) % 11 == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "(p-ro, %d, %d) ", type, + (idx - lag + 6)); + + protect_entry_ro2(file_ptr, type, (idx - lag + 6)); + } + + if ( ( pass2 ) && ( (idx - lag + 7) >= 0 ) && + ( (idx - lag + 7) < local_max_index ) && + ( (idx - lag + 7) % 13 == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "(p-ro, %d, %d) ", type, + (idx - lag + 7)); + + protect_entry_ro2(file_ptr, type, (idx - lag + 7)); + } + + if ( ( pass2 ) && ( (idx - lag + 7) >= 0 ) && + ( (idx - lag + 7) < local_max_index ) && + ( (idx - lag + 7) % 9 == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "(u-ro, %d, %d) ", type, + (idx - lag + 7)); + + unprotect_entry2(file_ptr, type, (idx - lag + 7), + FALSE, H5C2__NO_FLAGS_SET); + } + + if ( ( pass2 ) && ( (idx - lag + 8) >= 0 ) && + ( (idx - lag + 8) < local_max_index ) && + ( (idx - lag + 8) % 11 == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "(u-ro, %d, %d) ", type, + (idx - lag + 8)); + + unprotect_entry2(file_ptr, type, (idx - lag + 8), + FALSE, H5C2__NO_FLAGS_SET); + } + + if ( ( pass2 ) && ( (idx - lag + 9) >= 0 ) && + ( (idx - lag + 9) < local_max_index ) && + ( (idx - lag + 9) % 13 == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "(u-ro, %d, %d) ", type, + (idx - lag + 9)); + + unprotect_entry2(file_ptr, type, (idx - lag + 9), + FALSE, H5C2__NO_FLAGS_SET); + } + } /* if ( do_mult_ro_protects ) */ + + if ( ( pass2 ) && ( idx >= 0 ) && ( idx <= local_max_index ) ) { + + if ( verbose ) + HDfprintf(stdout, "(p, %d, %d) ", type, idx); + + protect_entry2(file_ptr, type, idx); + } + + + if ( ( pass2 ) && ( (idx + lag - 2) >= 0 ) && + ( (idx + lag - 2) <= local_max_index ) && + ( ( (idx + lag - 2) % 7 ) == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "(u, %d, %d) ", type, (idx + lag - 2)); + + unprotect_entry2(file_ptr, type, idx+lag-2, NO_CHANGE, + H5C2__NO_FLAGS_SET); + } + + if ( ( pass2 ) && ( (idx + lag - 1) >= 0 ) && + ( (idx + lag - 1) <= local_max_index ) && + ( ( (idx + lag - 1) % 7 ) == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "(p, %d, %d) ", type, (idx + lag - 1)); + + protect_entry2(file_ptr, type, (idx + lag - 1)); + } + + + if ( do_destroys ) { + + if ( ( pass2 ) && ( (idx + lag) >= 0 ) && + ( ( idx + lag) <= local_max_index ) ) { + + switch ( (idx + lag) %4 ) { + + case 0: + if ( (entries2[type])[idx+lag].is_dirty ) { + + unprotect_entry2(file_ptr, type, idx + lag, + NO_CHANGE, H5C2__NO_FLAGS_SET); + } else { + + unprotect_entry2(file_ptr, type, idx + lag, + dirty_unprotects, + H5C2__NO_FLAGS_SET); + } + break; + + case 1: /* we just did an insert */ + unprotect_entry2(file_ptr, type, idx + lag, + NO_CHANGE, H5C2__NO_FLAGS_SET); + break; + + case 2: + if ( (entries2[type])[idx + lag].is_dirty ) { + + unprotect_entry2(file_ptr, type, idx + lag, + NO_CHANGE, H5C2__DELETED_FLAG); + } else { + + unprotect_entry2(file_ptr, type, idx + lag, + dirty_destroys, + H5C2__DELETED_FLAG); + } + break; + + case 3: /* we just did an insrt */ + unprotect_entry2(file_ptr, type, idx + lag, + NO_CHANGE, H5C2__DELETED_FLAG); + break; + + default: + HDassert(0); /* this can't happen... */ + break; + } + } + } else { + + if ( ( pass2 ) && ( (idx + lag) >= 0 ) && + ( ( idx + lag) <= local_max_index ) ) { + + if ( verbose ) + HDfprintf(stdout, "(u, %d, %d) ", type, (idx + lag)); + + unprotect_entry2(file_ptr, type, idx + lag, + dirty_unprotects, H5C2__NO_FLAGS_SET); + } + } + + end_trans(file_ptr, cache_ptr, verbose, trans_num, + "jrnl_row_major_scan_backward inner loop"); + + if ( verbose ) + HDfprintf(stdout, "\n"); + + idx--; + } + type--; + } + + if ( ( pass2 ) && ( display_stats ) ) { + + H5C2_stats(cache_ptr, "test cache", display_detailed_stats); + } + + return; + +} /* jrnl_row_major_scan_backward2() */ + +#endif /* JRM */ + +#if 0 /* JRM */ +/* this code commented out as it is in-op at present */ + +/*------------------------------------------------------------------------- + * Function: jrnl_row_major_scan_forward2() + * + * Purpose: Do a sequence of inserts, protects, unprotects, renames, + * and destroys broken into transactions while scanning + * through the set of entries. + * + * If pass2 is false on entry, do nothing. + * + * Note that this function is an adaption of + * row_major_scan_forward2(). + * + * Return: void + * + * Programmer: John Mainzer + * 5/20/08 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +void +jrnl_row_major_scan_forward2(H5F_t * file_ptr, + int32_t max_index, + int32_t lag, + hbool_t verbose, + hbool_t reset_stats, + hbool_t display_stats, + hbool_t display_detailed_stats, + hbool_t do_inserts, + hbool_t dirty_inserts, + hbool_t do_renames, + hbool_t rename_to_main_addr, + hbool_t do_destroys, + hbool_t do_mult_ro_protects, + int dirty_destroys, + int dirty_unprotects, + uint64_t trans_num) +{ + const char * fcn_name = "jrnl_row_major_scan_forward2"; + H5C2_t * cache_ptr = file_ptr->shared->cache2; + int32_t type; + int32_t idx; + int32_t local_max_index; + + if ( verbose ) + HDfprintf(stdout, "%s(): entering.\n", fcn_name); + + HDassert( lag >= 10 ); + + type = 0; + + if ( ( pass2 ) && ( reset_stats ) ) { + + H5C2_stats__reset(cache_ptr); + } + + while ( ( pass2 ) && ( type < NUMBER_OF_ENTRY_TYPES ) ) + { + idx = -lag; + + local_max_index = MIN(max_index, max_indices2[type]); + + while ( ( pass2 ) && ( idx <= (local_max_index + lag) ) ) + { + trans_num++; + + begin_trans(cache_ptr, verbose, trans_num, + "jrnl_row_major_scan_forward inner loop"); + + if ( verbose ) { + + HDfprintf(stdout, "%lld:%d:%d: ", trans_num, type, idx); + } + + if ( ( pass2 ) && ( do_inserts ) && ( (idx + lag) >= 0 ) && + ( (idx + lag) <= local_max_index ) && + ( ((idx + lag) % 2) == 0 ) && + ( ! entry_in_cache2(cache_ptr, type, (idx + lag)) ) ) { + + if ( verbose ) + HDfprintf(stdout, "1(i, %d, %d) ", type, (idx + lag)); + + insert_entry2(file_ptr, type, (idx + lag), dirty_inserts, + H5C2__NO_FLAGS_SET); + } + + + if ( ( pass2 ) && ( (idx + lag - 1) >= 0 ) && + ( (idx + lag - 1) <= local_max_index ) && + ( ( (idx + lag - 1) % 3 ) == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "2(p, %d, %d) ", type, (idx + lag - 1)); + + protect_entry2(file_ptr, type, (idx + lag - 1)); + } + + if ( ( pass2 ) && ( (idx + lag - 2) >= 0 ) && + ( (idx + lag - 2) <= local_max_index ) && + ( ( (idx + lag - 2) % 3 ) == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "3(u, %d, %d) ", type, (idx + lag - 2)); + + unprotect_entry2(file_ptr, type, idx+lag-2, NO_CHANGE, + H5C2__NO_FLAGS_SET); + } + + + if ( ( pass2 ) && ( do_renames ) && ( (idx + lag - 2) >= 0 ) && + ( (idx + lag - 2) <= local_max_index ) && + ( ( (idx + lag - 2) % 3 ) == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "4(r, %d, %d, %d) ", + type, (idx + lag - 2), (int)rename_to_main_addr); + + rename_entry2(cache_ptr, type, (idx + lag - 2), + rename_to_main_addr); + } + + + if ( ( pass2 ) && ( (idx + lag - 3) >= 0 ) && + ( (idx + lag - 3) <= local_max_index ) && + ( ( (idx + lag - 3) % 5 ) == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "5(p, %d, %d) ", type, (idx + lag - 3)); + + protect_entry2(file_ptr, type, (idx + lag - 3)); + } + + if ( ( pass2 ) && ( (idx + lag - 5) >= 0 ) && + ( (idx + lag - 5) <= local_max_index ) && + ( ( (idx + lag - 5) % 5 ) == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "6(u, %d, %d) ", type, (idx + lag - 5)); + + unprotect_entry2(file_ptr, type, idx+lag-5, NO_CHANGE, + H5C2__NO_FLAGS_SET); + } + + if ( do_mult_ro_protects ) + { + if ( ( pass2 ) && ( (idx + lag - 5) >= 0 ) && + ( (idx + lag - 5) < local_max_index ) && + ( (idx + lag - 5) % 9 == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "7(p-ro, %d, %d) ", type, + (idx + lag - 5)); + + protect_entry_ro2(file_ptr, type, (idx + lag - 5)); + } + + if ( ( pass2 ) && ( (idx + lag - 6) >= 0 ) && + ( (idx + lag - 6) < local_max_index ) && + ( (idx + lag - 6) % 11 == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "8(p-ro, %d, %d) ", type, + (idx + lag - 6)); + + protect_entry_ro2(file_ptr, type, (idx + lag - 6)); + } + + if ( ( pass2 ) && ( (idx + lag - 7) >= 0 ) && + ( (idx + lag - 7) < local_max_index ) && + ( (idx + lag - 7) % 13 == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "9(p-ro, %d, %d) ", type, + (idx + lag - 7)); + + protect_entry_ro2(file_ptr, type, (idx + lag - 7)); + } + + if ( ( pass2 ) && ( (idx + lag - 7) >= 0 ) && + ( (idx + lag - 7) < local_max_index ) && + ( (idx + lag - 7) % 9 == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "10(u-ro, %d, %d) ", type, + (idx + lag - 7)); + + unprotect_entry2(file_ptr, type, (idx + lag - 7), + FALSE, H5C2__NO_FLAGS_SET); + } + + if ( ( pass2 ) && ( (idx + lag - 8) >= 0 ) && + ( (idx + lag - 8) < local_max_index ) && + ( (idx + lag - 8) % 11 == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "11(u-ro, %d, %d) ", type, + (idx + lag - 8)); + + unprotect_entry2(file_ptr, type, (idx + lag - 8), + FALSE, H5C2__NO_FLAGS_SET); + } + + if ( ( pass2 ) && ( (idx + lag - 9) >= 0 ) && + ( (idx + lag - 9) < local_max_index ) && + ( (idx + lag - 9) % 13 == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "12(u-ro, %d, %d) ", type, + (idx + lag - 9)); + + unprotect_entry2(file_ptr, type, (idx + lag - 9), + FALSE, H5C2__NO_FLAGS_SET); + } + } /* if ( do_mult_ro_protects ) */ + + if ( ( pass2 ) && ( idx >= 0 ) && ( idx <= local_max_index ) ) { + + if ( verbose ) + HDfprintf(stdout, "13(p, %d, %d) ", type, idx); + + protect_entry2(file_ptr, type, idx); + } + + if ( ( pass2 ) && ( (idx - lag + 2) >= 0 ) && + /*( (idx - lag + 2) <= max_indices2[type] ) && */ + ( (idx - lag + 2) <= local_max_index ) && + ( ( (idx - lag + 2) % 7 ) == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "14(u, %d, %d) ", type, (idx - lag + 2)); + + unprotect_entry2(file_ptr, type, idx-lag+2, NO_CHANGE, + H5C2__NO_FLAGS_SET); + } + + if ( ( pass2 ) && ( (idx - lag + 1) >= 0 ) && + /*( (idx - lag + 1) <= max_indices2[type] ) && */ + ( (idx - lag + 1) <= local_max_index ) && + ( ( (idx - lag + 1) % 7 ) == 0 ) ) { + + if ( verbose ) + HDfprintf(stdout, "15(p, %d, %d) ", type, (idx - lag + 1)); + + protect_entry2(file_ptr, type, (idx - lag + 1)); + } + + + if ( do_destroys ) { + + if ( ( pass2 ) && ( (idx - lag) >= 0 ) && + ( ( idx - lag) <= local_max_index ) ) { + + switch ( (idx - lag) %4 ) { + + case 0: /* we just did an insert */ + + if ( verbose ) + HDfprintf(stdout, + "16(u, %d, %d) ", type, (idx - lag)); + + unprotect_entry2(file_ptr, type, idx - lag, + NO_CHANGE, H5C2__NO_FLAGS_SET); + break; + + case 1: + if ( (entries2[type])[idx-lag].is_dirty ) { + + if ( verbose ) + HDfprintf(stdout, + "17(u, %d, %d) ", type, (idx - lag)); + + unprotect_entry2(file_ptr, type, idx - lag, + NO_CHANGE, H5C2__NO_FLAGS_SET); + } else { + + if ( verbose ) + HDfprintf(stdout, + "18(u, %d, %d) ", type, (idx - lag)); + + unprotect_entry2(file_ptr, type, idx - lag, + dirty_unprotects, + H5C2__NO_FLAGS_SET); + } + break; + + case 2: /* we just did an insrt */ + + if ( verbose ) + HDfprintf(stdout, + "19(u-del, %d, %d) ", type, (idx - lag)); + + unprotect_entry2(file_ptr, type, idx - lag, + NO_CHANGE, H5C2__DELETED_FLAG); + break; + + case 3: + if ( (entries2[type])[idx-lag].is_dirty ) { + + if ( verbose ) + HDfprintf(stdout, + "20(u-del, %d, %d) ", + type, (idx - lag)); + + unprotect_entry2(file_ptr, type, idx - lag, + NO_CHANGE, H5C2__DELETED_FLAG); + } else { + + if ( verbose ) + HDfprintf(stdout, + "21(u-del, %d, %d) ", + type, (idx - lag)); + + unprotect_entry2(file_ptr, type, idx - lag, + dirty_destroys, + H5C2__DELETED_FLAG); + } + break; + + default: + HDassert(0); /* this can't happen... */ + break; + } + } + + } else { + + if ( ( pass2 ) && ( (idx - lag) >= 0 ) && + ( ( idx - lag) <= local_max_index ) ) { + + if ( verbose ) + HDfprintf(stdout, "22(u, %d, %d) ", type, (idx - lag)); + + unprotect_entry2(file_ptr, type, idx - lag, + dirty_unprotects, H5C2__NO_FLAGS_SET); + } + } + + end_trans(file_ptr, cache_ptr, verbose, trans_num, + "jrnl_row_major_scan_forward inner loop"); + + if ( verbose ) + HDfprintf(stdout, "\n"); + + idx++; + } + type++; + } + + if ( ( pass2 ) && ( display_stats ) ) { + + H5C2_stats(cache_ptr, "test cache", display_detailed_stats); + } + + return; + +} /* jrnl_row_major_scan_forward2() */ + +#endif /* JRM */ + + +/*------------------------------------------------------------------------- + * Function: setup_cache_for_journaling() + * + * Purpose: If pass2 is true on entry, create a HDF5 file with + * journaling enabled and journal file with the specified name. + * Return pointers to the cache data structure and file data + * structures. and verify that it contains the expected data. + * + * On failure, set pass2 to FALSE, and set failure_mssg2 + * to point to an appropriate failure message. + * + * Do nothing if pass2 is FALSE on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 5/13/08 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +static void +setup_cache_for_journaling(const char * hdf_file_name, + const char * journal_file_name, + hid_t * file_id_ptr, + H5F_t ** file_ptr_ptr, + H5C2_t ** cache_ptr_ptr) +{ + const char * fcn_name = "setup_cache_for_journaling()"; + hbool_t show_progress = FALSE; + hbool_t verbose = FALSE; + int cp = 0; + herr_t result; + H5AC2_cache_config_t mdj_config = + { + /* int version = */ H5C2__CURR_AUTO_SIZE_CTL_VER, + /* hbool_t rpt_fcn_enabled = */ FALSE, + /* hbool_t open_trace_file = */ FALSE, + /* hbool_t close_trace_file = */ FALSE, + /* char trace_file_name[] = */ "", + /* hbool_t evictions_enabled = */ TRUE, + /* hbool_t set_initial_size = */ TRUE, + /* size_t initial_size = */ ( 64 * 1024 ), + /* double min_clean_fraction = */ 0.5, + /* size_t max_size = */ (16 * 1024 * 1024 ), + /* size_t min_size = */ ( 8 * 1024 ), + /* long int epoch_length = */ 50000, + /* enum H5C2_cache_incr_mode incr_mode = */ H5C2_incr__off, + /* double lower_hr_threshold = */ 0.9, + /* double increment = */ 2.0, + /* hbool_t apply_max_increment = */ TRUE, + /* size_t max_increment = */ (4 * 1024 * 1024), + /* enum H5C2_cache_flash_incr_mode */ + /* flash_incr_mode = */ H5C2_flash_incr__off, + /* double flash_multiple = */ 1.0, + /* double flash_threshold = */ 0.25, + /* enum H5C2_cache_decr_mode decr_mode = */ H5C2_decr__off, + /* double upper_hr_threshold = */ 0.999, + /* double decrement = */ 0.9, + /* hbool_t apply_max_decrement = */ TRUE, + /* size_t max_decrement = */ (1 * 1024 * 1024), + /* int epochs_before_eviction = */ 3, + /* hbool_t apply_empty_reserve = */ TRUE, + /* double empty_reserve = */ 0.1, + /* int dirty_bytes_threshold = */ (8 * 1024), + /* hbool_t enable_journaling = */ TRUE, + /* char journal_file_path[] = */ "", + /* hbool_t journal_recovered = */ FALSE, + /* size_t jbrb_buf_size = */ (8 * 1024), + /* int jbrb_num_bufs = */ 2, + /* hbool_t jbrb_use_aio = */ FALSE, + /* hbool_t jbrb_human_readable = */ TRUE + }; + hid_t fapl_id = -1; + hid_t file_id; + haddr_t actual_base_addr; + H5F_t * file_ptr; + H5C2_t * cache_ptr; + + if ( pass2 ) + { + if ( ( hdf_file_name == NULL ) || + ( journal_file_name == NULL ) || + ( file_id_ptr == NULL ) || + ( file_ptr_ptr == NULL ) || + ( cache_ptr_ptr == NULL ) ) { + + failure_mssg2 = + "Bad param(s) on entry to setup_cache_for_journaling().\n"; + pass2 = FALSE; + } + else if ( strlen(journal_file_name) > H5AC2__MAX_JOURNAL_FILE_NAME_LEN ) { + + failure_mssg2 = "journal file name too long.\n"; + pass2 = FALSE; + + } else { + + strcpy(mdj_config.journal_file_path, journal_file_name); + + if ( verbose ) { + + HDfprintf(stdout, "%s: HDF file name = \"%s\".\n", + fcn_name, hdf_file_name); + HDfprintf(stdout, "%s: journal file name = \"%s\".\n", + fcn_name, journal_file_name); + } + } + } + + if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + /* create a file access propertly list. */ + if ( pass2 ) { + + fapl_id = H5Pcreate(H5P_FILE_ACCESS); + + if ( fapl_id < 0 ) { + + pass2 = FALSE; + failure_mssg2 = "H5Pcreate() failed.\n"; + } + } + + if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + /* call H5Pset_latest_format() on the fapl_id */ + if ( pass2 ) { + + if ( H5Pset_latest_format(fapl_id, TRUE) < 0 ) { + + pass2 = FALSE; + failure_mssg2 = "H5Pset_latest_format() failed.\n"; + } + } + + if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + if ( pass2 ) { + + result = H5Pset_mdc_config(fapl_id, (H5AC_cache_config_t *)&mdj_config); + + if ( result < 0 ) { + + pass2 = FALSE; + failure_mssg2 = "H5Pset_mdc_config() failed.\n"; + } + } + + if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + +#if USE_CORE_DRIVER + if ( pass2 ) { + + if ( H5Pset_fapl_core(fapl_id, 64 * 1024 * 1024, FALSE) < 0 ) { + + pass2 = FALSE; + failure_mssg2 = "H5P_set_fapl_core() failed.\n"; + } + } +#endif /* USE_CORE_DRIVER */ + + if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + + /**************************************/ + /* Create a file with the fapl above. */ + /**************************************/ + + /* create the file using fapl_id */ + if ( pass2 ) { + + file_id = H5Fcreate(hdf_file_name, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id); + + if ( file_id < 0 ) { + + pass2 = FALSE; + failure_mssg2 = "H5Fcreate() failed.\n"; + + } else { + + file_ptr = H5I_object_verify(file_id, H5I_FILE); + + if ( file_ptr == NULL ) { + + pass2 = FALSE; + failure_mssg2 = "Can't get file_ptr."; + + if ( verbose ) { + HDfprintf(stdout, "%s: Can't get file_ptr.\n", fcn_name); + } + } + } + } + + if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + if ( pass2 ) { /* allocate space for test entries */ + + actual_base_addr = H5MF_alloc(file_ptr, H5FD_MEM_DEFAULT, H5P_DEFAULT, + (hsize_t)(ADDR_SPACE_SIZE + BASE_ADDR)); + + if ( actual_base_addr == HADDR_UNDEF ) { + + pass2 = FALSE; + failure_mssg2 = "H5MF_alloc() failed."; + + if ( verbose ) { + HDfprintf(stdout, "%s: H5MF_alloc() failed.\n", fcn_name); + } + + } else if ( actual_base_addr > BASE_ADDR ) { + + /* If this happens, must increase BASE_ADDR so that the + * actual_base_addr is <= BASE_ADDR. This should only happen + * if the size of the superblock is increase. + */ + pass2 = FALSE; + failure_mssg2 = "actual_base_addr > BASE_ADDR"; + + if ( verbose ) { + HDfprintf(stdout, "%s: actual_base_addr > BASE_ADDR.\n", fcn_name); + } + } + } + + if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + /* get a pointer to the files internal data structure and then + * to the cache structure + */ + if ( pass2 ) { + + if ( file_ptr->shared->cache2 == NULL ) { + + pass2 = FALSE; + failure_mssg2 = "can't get cache2 pointer(1).\n"; + + } else { + + cache_ptr = file_ptr->shared->cache2; + } + } + + if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + reset_entries2(); + + if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + if ( pass2 ) { + + *file_id_ptr = file_id; + *file_ptr_ptr = file_ptr; + *cache_ptr_ptr = cache_ptr; + } + + if ( show_progress ) + HDfprintf(stdout, "%s: cp = %d -- exiting.\n", fcn_name, cp++); + + return; + +} /* setup_cache_for_journaling() */ + + +/*------------------------------------------------------------------------- + * Function: takedown_cache_after_journaling() + * + * Purpose: If file_id >= 0, close the associated file, and then delete + * it and the associated journal file (if it exists). + * + * Return: void + * + * Programmer: John Mainzer + * 5/13/08 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +static void +takedown_cache_after_journaling(hid_t file_id, + const char * filename, + const char * journal_filename) +{ + hbool_t verbose = TRUE; + int error; + + if ( file_id >= 0 ) { + + if ( H5Fclose(file_id) ) { + + if ( pass2 ) { + + pass2 = FALSE; + failure_mssg2 = "file close failed."; + } +#if ! USE_CORE_DRIVER + } else if ( (error = HDremove(filename)) != 0 ) { + + if ( verbose ) { + HDfprintf(stdout, + "HDremove(\"%s\") failed, returned %d, errno = %d = %s.\n", + filename, error, errno, strerror(errno)); + } + + if ( pass2 ) { + + pass2 = FALSE; + failure_mssg2 = "HDremove() failed (1).\n"; + } +#endif + } else if ( HDremove(journal_filename) != 0 ) { + + if ( pass2 ) { + + pass2 = FALSE; + failure_mssg2 = "HDremove() failed (2).\n"; + } + } + } + + return; + +} /* takedown_cache_after_journaling() */ + + +/*------------------------------------------------------------------------- + * Function: verify_journal_contents() + * + * Purpose: If pass2 is true on entry, verify that the contents of the + * journal file matches that of the expected file. If + * differences are detected, or if any other error is detected, + * set pass2 to FALSE and set failure_mssg2 to point to an + * appropriate error message. + * + * Do nothing if pass2 is FALSE on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 5/06/08 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +static void +verify_journal_contents(const char * journal_file_path_ptr, + const char * expected_file_path_ptr) +{ + const char * fcn_name = "verify_journal_contents()"; + char ch; + char journal_buf[(8 * 1024) + 1]; + char expected_buf[(8 * 1024) + 1]; + hbool_t verbose = FALSE; + size_t cur_buf_len; + const size_t max_buf_len = (8 * 1024); + size_t journal_len; + size_t expected_len; + size_t first_line_len; + size_t journal_remainder_len; + size_t expected_remainder_len; + ssize_t read_result; + int journal_file_fd = -1; + int expected_file_fd = -1; + struct stat buf; + + if ( pass2 ) { + + if ( journal_file_path_ptr == NULL ) { + + failure_mssg2 = "journal_file_path_ptr NULL on entry?!?", + pass2 = FALSE; + + } else if ( expected_file_path_ptr == NULL ) { + + failure_mssg2 = "expected_file_path_ptr NULL on entry?!?", + pass2 = FALSE; + + } + } + + /* get the actual length of the journal file */ + if ( pass2 ) { + + if ( HDstat(journal_file_path_ptr, &buf) != 0 ) { + + if ( verbose ) { + + HDfprintf(stdout, "%s: HDstat(j) failed with errno = %d.\n", + fcn_name, errno); + } + failure_mssg2 = "stat() failed on journal file."; + pass2 = FALSE; + + } else { + + if ( (buf.st_size) == 0 ) { + + failure_mssg2 = "Journal file empty?!?"; + pass2 = FALSE; + + } else { + + journal_len = (size_t)(buf.st_size); + + if ( verbose ) { + + HDfprintf(stdout, "%s: journal_len = %d.\n", + fcn_name, (int)journal_len); + } + } + } + } + + /* get the actual length of the expected file */ + if ( pass2 ) { + + if ( HDstat(expected_file_path_ptr, &buf) != 0 ) { + + if ( verbose ) { + + HDfprintf(stdout, "%s: HDstat(e) failed with errno = %d.\n", + fcn_name, errno); + } + failure_mssg2 = "stat() failed on expected file."; + pass2 = FALSE; + + } else { + + if ( (buf.st_size) == 0 ) { + + failure_mssg2 = "Expected file empty?!?"; + pass2 = FALSE; + + } else { + + expected_len = (size_t)(buf.st_size); + + } + } + } + + /* open the journal file */ + if ( pass2 ) { + + if ( (journal_file_fd = HDopen(journal_file_path_ptr, O_RDONLY, 0777)) + == -1 ) { + + if ( verbose ) { + + HDfprintf(stdout, "%s: HDopen(j) failed with errno = %d.\n", + fcn_name, errno); + } + failure_mssg2 = "Can't open journal file."; + pass2 = FALSE; + } + } + + /* open the expected file */ + if ( pass2 ) { + + if ( (expected_file_fd = HDopen(expected_file_path_ptr, O_RDONLY, 0777)) + == -1 ) { + + if ( verbose ) { + + HDfprintf(stdout, "%s: HDopen(e) failed with errno = %d.\n", + fcn_name, errno); + } + failure_mssg2 = "Can't open expected file."; + pass2 = FALSE; + } + } + + /* The first lines of the journal and expected files will usually differ + * in creation date. We could look at everything else on the line, but + * for now we will just skip past it, and compute the length of the remainder + * of the journal and expected files as we do so. + * + * Do this by reading the file one character at a time until we hit a newline. + * This is very inefficient, but this is test code, and the first line + * can't be very long. + */ + if ( pass2 ) { + + first_line_len = 1; + read_result = read(journal_file_fd, &ch, 1); + + while ( ( ch != '\n' ) && + ( first_line_len < 128 ) && + ( read_result == 1 ) ) { + + first_line_len++; + read_result = read(journal_file_fd, &ch, 1); + } + + if ( ch != '\n' ) { + + failure_mssg2 = "error skipping first line of journal file."; + pass2 = FALSE; + + } else if ( first_line_len > journal_len ) { + + failure_mssg2 = "first_line_len > journal_len?!?"; + pass2 = FALSE; + + } else { + + journal_remainder_len = journal_len - first_line_len; + } + } + + if ( pass2 ) { + + first_line_len = 1; + read_result = read(expected_file_fd, &ch, 1); + + while ( ( ch != '\n' ) && + ( first_line_len < 128 ) && + ( read_result == 1 ) ) { + + first_line_len++; + read_result = read(expected_file_fd, &ch, 1); + } + + if ( ch != '\n' ) { + + failure_mssg2 = "error skipping first line of expected file."; + pass2 = FALSE; + + } else if ( first_line_len > expected_len ) { + + failure_mssg2 = "first_line_len > expected_len?!?"; + pass2 = FALSE; + + } else { + + expected_remainder_len = expected_len - first_line_len; + } + } + + if ( pass2 ) { + + if ( journal_remainder_len != expected_remainder_len ) { + + failure_mssg2 = "Unexpected journal file contents(1)."; + pass2 = FALSE; + } + } + + /* If we get this far without an error, the lengths of the actual + * and expected files (after skipping the first line) are identical. + * Thus we have to go and compare the actual data. + */ + while ( ( pass2 ) && + ( journal_remainder_len > 0 ) ) + { + HDassert( journal_remainder_len == expected_remainder_len ); + + if ( journal_remainder_len > max_buf_len ) { + + cur_buf_len = max_buf_len; + journal_remainder_len -= max_buf_len; + expected_remainder_len -= max_buf_len; + + } else { + + cur_buf_len = journal_remainder_len; + journal_remainder_len = 0; + expected_remainder_len = 0; + } + + read_result = HDread(journal_file_fd, journal_buf, cur_buf_len); + + if ( read_result != (int)cur_buf_len ) { + + if ( verbose ) { + + HDfprintf(stdout, + "%s: HDread(j) failed. result = %d, errno = %d.\n", + fcn_name, (int)read_result, errno); + } + failure_mssg2 = "error reading journal file."; + pass2 = FALSE; + } + + journal_buf[cur_buf_len] = '\0'; + + if ( pass2 ) { + + read_result = HDread(expected_file_fd, expected_buf, cur_buf_len); + + if ( read_result != (int)cur_buf_len ) { + + if ( verbose ) { + + HDfprintf(stdout, + "%s: HDread(e) failed. result = %d, errno = %d.\n", + fcn_name, (int)read_result, errno); + } + failure_mssg2 = "error reading expected file."; + pass2 = FALSE; + } + + expected_buf[cur_buf_len] = '\0'; + } + + if ( pass2 ) { + + if ( HDstrcmp(journal_buf, expected_buf) != 0 ) { + + failure_mssg2 = "Unexpected journal file contents(2)."; + pass2 = FALSE; + } + } + } + + if ( journal_file_fd != -1 ) { + + if ( HDclose(journal_file_fd) != 0 ) { + + if ( verbose ) { + + HDfprintf(stdout, "%s: HDclose(j) failed with errno = %d.\n", + fcn_name, errno); + } + + if ( pass2 ) { + + failure_mssg2 = "Can't close journal file."; + pass2 = FALSE; + } + } + } + + if ( expected_file_fd != -1 ) { + + if ( HDclose(expected_file_fd) != 0 ) { + + if ( verbose ) { + + HDfprintf(stdout, "%s: HDclose(e) failed with errno = %d.\n", + fcn_name, errno); + } + + if ( pass2 ) { + + failure_mssg2 = "Can't close expected file."; + pass2 = FALSE; + } + } + } + + return; + +} /* verify_journal_contents() */ + + +/*------------------------------------------------------------------------- + * Function: verify_journal_empty() + * + * Purpose: If pass2 is true on entry, stat the target journal file, + * and verify that it has length zero. If it is not, set + * pass2 to FALSE, and set failure_mssg2 to point to an + * appropriate failure message. Similarly, if any errors + * are detected in this process, set pass2 to FALSE and set + * failure_mssg2 to point to an appropriate error message. + * + * Do nothing if pass2 is FALSE on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 5/06/08 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +static void +verify_journal_empty(const char * journal_file_path_ptr) +{ + const char * fcn_name = "verify_journal_empty()"; + hbool_t verbose = FALSE; + struct stat buf; + + if ( pass2 ) { + + if ( journal_file_path_ptr == NULL ) { + + failure_mssg2 = "journal_file_path_ptr NULL on entry?!?", + pass2 = FALSE; + } + } + + if ( pass2 ) { + + if ( HDstat(journal_file_path_ptr, &buf) != 0 ) { + + if ( verbose ) { + + HDfprintf(stdout, "%s: HDstat() failed with errno = %d.\n", + fcn_name, errno); + } + failure_mssg2 = "stat() failed on journal file."; + pass2 = FALSE; + + } else { + + if ( (buf.st_size) > 0 ) { + + failure_mssg2 = "Empty journal file expected."; + pass2 = FALSE; + } + } + } + + return; + +} /* verify_journal_empty() */ + + +/*** metadata journaling smoke checks ***/ + +/*------------------------------------------------------------------------- + * Function: mdj_smoke_check_00() + * + * Purpose: Run a basic smoke check on the metadata journaling + * facilities of the metadata cache. Proceed as follows: + * + * 1) Create a file with journaling enabled. Verify that + * journal file is created. + * + * 2) Using the test entries, simulate a selection of + * transactions, which exercise the full range of + * metadata cache API which can generate journal entries. + * Verify that these transactions are reflected correctly + * in the journal. + * + * 3) Close and delete the file. + * + * Return: void + * + * Programmer: John Mainzer + * 3/11/08 + * + * Changes: None. + * + *------------------------------------------------------------------------- + */ + +static void +mdj_smoke_check_00(void) +{ + const char * fcn_name = "mdj_smoke_check_00()"; + const char * testfiles[] = + { + "testfiles/cache2_journal_sc00_000.jnl", + "testfiles/cache2_journal_sc00_001.jnl", + "testfiles/cache2_journal_sc00_002.jnl", + "testfiles/cache2_journal_sc00_003.jnl", + "testfiles/cache2_journal_sc00_004.jnl", + "testfiles/cache2_journal_sc00_005.jnl", + "testfiles/cache2_journal_sc00_006.jnl", + "testfiles/cache2_journal_sc00_007.jnl", + "testfiles/cache2_journal_sc00_008.jnl", + "testfiles/cache2_journal_sc00_009.jnl", + "testfiles/cache2_journal_sc00_010.jnl", + "testfiles/cache2_journal_sc00_011.jnl", + "testfiles/cache2_journal_sc00_012.jnl", + "testfiles/cache2_journal_sc00_013.jnl", + "testfiles/cache2_journal_sc00_014.jnl", + "testfiles/cache2_journal_sc00_015.jnl", + "testfiles/cache2_journal_sc00_016.jnl", + NULL + }; + char filename[512]; + char journal_filename[H5AC2__MAX_JOURNAL_FILE_NAME_LEN + 1]; + hbool_t show_progress = FALSE; + hbool_t verbose = FALSE; + hbool_t update_architypes = TRUE; + int cp = 0; + hid_t file_id = -1; + H5F_t * file_ptr = NULL; + H5C2_t * cache_ptr = NULL; + + TESTING("mdj smoke check 00 -- general coverage"); + + pass2 = TRUE; + + /***********************************************************************/ + /* 1) Create a file with cache configuration set to enable journaling. */ + /***********************************************************************/ + + /* setup the file name */ + if ( pass2 ) { + + if ( h5_fixname(FILENAMES[1], H5P_DEFAULT, filename, sizeof(filename)) + == NULL ) { + + pass2 = FALSE; + failure_mssg2 = "h5_fixname() failed (1).\n"; + } + } + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + if ( verbose ) { + HDfprintf(stdout, "%s: filename = \"%s\".\n", fcn_name, filename); + } + + /* setup the journal file name */ + if ( pass2 ) { + + if ( h5_fixname(FILENAMES[3], H5P_DEFAULT, journal_filename, + sizeof(journal_filename)) == NULL ) { + + pass2 = FALSE; + failure_mssg2 = "h5_fixname() failed (2).\n"; + } + else if ( strlen(journal_filename) >= + H5AC2__MAX_JOURNAL_FILE_NAME_LEN ) { + + pass2 = FALSE; + failure_mssg2 = "journal file name too long.\n"; + } + } + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + if ( verbose ) { + HDfprintf(stdout, "%s: journal filename = \"%s\".\n", + fcn_name, journal_filename); + } + + setup_cache_for_journaling(filename, journal_filename, &file_id, + &file_ptr, &cache_ptr); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + + /********************************************************************/ + /* 2) Using the test entries, simulate a selection of transactions, */ + /* which exercise the full range of metadata cache API calls */ + /* that can generate journal entries. Verify that these */ + /* transactions are reflected correctly in the journal. */ + /********************************************************************/ + + /* a) First a quick check to see if we can do anything */ + + begin_trans(cache_ptr, verbose, (uint64_t)1, "transaction 1.0"); + + insert_entry2(file_ptr, 0, 1, FALSE, H5C2__NO_FLAGS_SET); + protect_entry2(file_ptr, 0, 0); + unprotect_entry2(file_ptr, 0, 0, TRUE, H5C2__NO_FLAGS_SET); + + end_trans(file_ptr, cache_ptr, verbose, (uint64_t)1, "transaction 1.0"); + + flush_journal(cache_ptr); + + if ( update_architypes ) { + + copy_file(journal_filename, testfiles[0]); + } + + verify_journal_contents(journal_filename, testfiles[0]); + + flush_cache2(file_ptr, FALSE, FALSE, FALSE); /* resets transaction number */ + + verify_journal_empty(journal_filename); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + + /* b) Verify that a sequence of cache operation that do not dirty + * any entry do not result in any journal activity. + */ + + begin_trans(cache_ptr, verbose, (uint64_t)1, "transaction 1.1"); + + protect_entry2(file_ptr, TINY_ENTRY_TYPE, 0); + protect_entry2(file_ptr, TINY_ENTRY_TYPE, 1); + protect_entry2(file_ptr, TINY_ENTRY_TYPE, 2); + unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 2, FALSE, H5C2__NO_FLAGS_SET); + unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 1, FALSE, H5C2__NO_FLAGS_SET); + unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 0, FALSE, H5C2__NO_FLAGS_SET); + + protect_entry_ro2(file_ptr, TINY_ENTRY_TYPE, 3); + protect_entry_ro2(file_ptr, TINY_ENTRY_TYPE, 3); + protect_entry_ro2(file_ptr, TINY_ENTRY_TYPE, 3); + unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 3, FALSE, H5C2__NO_FLAGS_SET); + unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 3, FALSE, H5C2__NO_FLAGS_SET); + unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 3, FALSE, H5C2__NO_FLAGS_SET); + + end_trans(file_ptr, cache_ptr, verbose, (uint64_t)1, "transaction 1.1"); + + flush_journal(cache_ptr); + + verify_journal_empty(journal_filename); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + + /* c) Verify that the most recently dirtied entry get to the head of + * the transaction list (and thus appears as the last entry in the + * transaction). + */ + + begin_trans(cache_ptr, verbose, (uint64_t)2, "transaction 2.1"); + + protect_entry2(file_ptr, TINY_ENTRY_TYPE, 0); + unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 0, FALSE, H5C2__NO_FLAGS_SET); + protect_entry2(file_ptr, TINY_ENTRY_TYPE, 1); + unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 1, TRUE, H5C2__NO_FLAGS_SET); + protect_entry2(file_ptr, TINY_ENTRY_TYPE, 2); + unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 2, FALSE, H5C2__NO_FLAGS_SET); + protect_entry2(file_ptr, TINY_ENTRY_TYPE, 3); + unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 3, TRUE, H5C2__NO_FLAGS_SET); + protect_entry2(file_ptr, TINY_ENTRY_TYPE, 4); + unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 4, FALSE, H5C2__NO_FLAGS_SET); + protect_entry2(file_ptr, TINY_ENTRY_TYPE, 5); + unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 5, TRUE, H5C2__NO_FLAGS_SET); + protect_entry2(file_ptr, TINY_ENTRY_TYPE, 3); + unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 3, TRUE, H5C2__NO_FLAGS_SET); + protect_entry2(file_ptr, TINY_ENTRY_TYPE, 1); + unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 1, FALSE, H5C2__NO_FLAGS_SET); + + end_trans(file_ptr, cache_ptr, verbose, (uint64_t)2, "transaction 2.1"); + + flush_journal(cache_ptr); + + if ( update_architypes ) { + + copy_file(journal_filename, testfiles[1]); + } + + verify_journal_contents(journal_filename, testfiles[1]); + + flush_cache2(file_ptr, FALSE, FALSE, FALSE); /* resets transaction number */ + + verify_journal_empty(journal_filename); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + + /* d) Mix up some protect/unprotect calls with renames. Do this with + * different orders to make things interesting. + */ + + begin_trans(cache_ptr, verbose, (uint64_t)1, "transaction 1.2"); + + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 0); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 0, FALSE, H5C2__NO_FLAGS_SET); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 1); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 1, TRUE, H5C2__NO_FLAGS_SET); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 2); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 2, FALSE, H5C2__NO_FLAGS_SET); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 2); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 2, TRUE, H5C2__NO_FLAGS_SET); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 3); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 3, FALSE, H5C2__NO_FLAGS_SET); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 4); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 4, TRUE, H5C2__NO_FLAGS_SET); + + rename_entry2(cache_ptr, MICRO_ENTRY_TYPE, 2, FALSE); + rename_entry2(cache_ptr, MICRO_ENTRY_TYPE, 3, FALSE); + + end_trans(file_ptr, cache_ptr, verbose, (uint64_t)1, "transaction 1.2"); + + flush_journal(cache_ptr); + + if ( update_architypes ) { + + copy_file(journal_filename, testfiles[2]); + } + + verify_journal_contents(journal_filename, testfiles[2]); + + + + begin_trans(cache_ptr, verbose, (uint64_t)2, "transaction 2.2"); + + rename_entry2(cache_ptr, MICRO_ENTRY_TYPE, 3, TRUE); + rename_entry2(cache_ptr, MICRO_ENTRY_TYPE, 2, TRUE); + + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 0); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 0, FALSE, H5C2__NO_FLAGS_SET); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 1); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 1, TRUE, H5C2__NO_FLAGS_SET); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 2); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 2, FALSE, H5C2__NO_FLAGS_SET); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 3); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 3, TRUE, H5C2__NO_FLAGS_SET); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 4); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 4, FALSE, H5C2__NO_FLAGS_SET); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 5); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 5, TRUE, H5C2__NO_FLAGS_SET); + + end_trans(file_ptr, cache_ptr, verbose, (uint64_t)2, "transaction 2.2"); + + flush_journal(cache_ptr); + + if ( update_architypes ) { + + copy_file(journal_filename, testfiles[3]); + } + + verify_journal_contents(journal_filename, testfiles[3]); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + + + /* e-1) Start by pinning a selection of entries... */ + + begin_trans(cache_ptr, verbose, (uint64_t)3, "transaction 3.2"); + + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 0); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 0, FALSE, H5C2__NO_FLAGS_SET); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 1); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 1, TRUE, H5C2__NO_FLAGS_SET); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 2); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 2, FALSE, H5C2__PIN_ENTRY_FLAG); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 3); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 3, TRUE, H5C2__PIN_ENTRY_FLAG); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 4); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 4, FALSE, H5C2__PIN_ENTRY_FLAG); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 5); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 5, TRUE, H5C2__PIN_ENTRY_FLAG); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 6); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 6, FALSE, H5C2__PIN_ENTRY_FLAG); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 7); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 7, TRUE, H5C2__PIN_ENTRY_FLAG); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 8); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 8, FALSE, H5C2__NO_FLAGS_SET); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 9); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 9, TRUE, H5C2__NO_FLAGS_SET); + + end_trans(file_ptr, cache_ptr, verbose, (uint64_t)3, "transaction 3.2"); + + flush_journal(cache_ptr); + + if ( update_architypes ) { + + copy_file(journal_filename, testfiles[4]); + } + + verify_journal_contents(journal_filename, testfiles[4]); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + + /* e-2) ... then use the H5C2_mark_pinned_or_protected_entry_dirty() + * call to mark a variety of protected, pinned, and pinned and + * protected entries dirty. Also rename some pinned entries. + */ + + begin_trans(cache_ptr, verbose, (uint64_t)4, "transaction 4.2"); + + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 0); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 1); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 6); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 7); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 8); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 9); + + mark_pinned_or_protected_entry_dirty2(file_ptr, MICRO_ENTRY_TYPE, 0); + mark_pinned_or_protected_entry_dirty2(file_ptr, MICRO_ENTRY_TYPE, 1); + mark_pinned_or_protected_entry_dirty2(file_ptr, MICRO_ENTRY_TYPE, 2); + mark_pinned_or_protected_entry_dirty2(file_ptr, MICRO_ENTRY_TYPE, 3); + mark_pinned_or_protected_entry_dirty2(file_ptr, MICRO_ENTRY_TYPE, 6); + mark_pinned_or_protected_entry_dirty2(file_ptr, MICRO_ENTRY_TYPE, 7); + + rename_entry2(cache_ptr, MICRO_ENTRY_TYPE, 4, FALSE); + rename_entry2(cache_ptr, MICRO_ENTRY_TYPE, 5, FALSE); + + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 0, FALSE, H5C2__NO_FLAGS_SET); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 1, TRUE, H5C2__NO_FLAGS_SET); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 6, FALSE, H5C2__NO_FLAGS_SET); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 7, TRUE, H5C2__NO_FLAGS_SET); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 8, FALSE, H5C2__NO_FLAGS_SET); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 9, TRUE, H5C2__NO_FLAGS_SET); + + end_trans(file_ptr, cache_ptr, verbose, (uint64_t)4, "transaction 4.2"); + + flush_journal(cache_ptr); + + if ( update_architypes ) { + + copy_file(journal_filename, testfiles[5]); + } + + verify_journal_contents(journal_filename, testfiles[5]); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + + /* e-3) ...finally, upin all the pinned entries, with an undo of the + * previous rename in the middle. + */ + + begin_trans(cache_ptr, verbose, (uint64_t)5, "transaction 5.2"); + + unpin_entry2(file_ptr, MICRO_ENTRY_TYPE, 2); + unpin_entry2(file_ptr, MICRO_ENTRY_TYPE, 3); + unpin_entry2(file_ptr, MICRO_ENTRY_TYPE, 4); + + rename_entry2(cache_ptr, MICRO_ENTRY_TYPE, 4, TRUE); + rename_entry2(cache_ptr, MICRO_ENTRY_TYPE, 5, TRUE); + + unpin_entry2(file_ptr, MICRO_ENTRY_TYPE, 5); + unpin_entry2(file_ptr, MICRO_ENTRY_TYPE, 6); + unpin_entry2(file_ptr, MICRO_ENTRY_TYPE, 7); + + end_trans(file_ptr, cache_ptr, verbose, (uint64_t)5, "transaction 5.2"); + + flush_journal(cache_ptr); + + if ( update_architypes ) { + + copy_file(journal_filename, testfiles[6]); + } + + verify_journal_contents(journal_filename, testfiles[6]); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + + + /* f-1) Pin a bunch more entries -- make them variable size, as we need + * to test resizing. In passing, pin some of the entries using + * the H5C2_pin_ptrotected_entry() call. + */ + + begin_trans(cache_ptr, verbose, (uint64_t)6, "transaction 6.2"); + + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 0); + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 1); + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 2); + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 3); + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 4); + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 5); + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 6); + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 7); + + pin_protected_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 2); + pin_protected_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 3); + + unprotect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 0, FALSE, H5C2__NO_FLAGS_SET); + unprotect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 1, TRUE, H5C2__NO_FLAGS_SET); + unprotect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 2, FALSE, H5C2__NO_FLAGS_SET); + unprotect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 3, TRUE, H5C2__NO_FLAGS_SET); + unprotect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 4, FALSE, H5C2__PIN_ENTRY_FLAG); + unprotect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 5, TRUE, H5C2__PIN_ENTRY_FLAG); + unprotect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 6, FALSE, H5C2__PIN_ENTRY_FLAG); + unprotect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 7, TRUE, H5C2__PIN_ENTRY_FLAG); + + end_trans(file_ptr, cache_ptr, verbose, (uint64_t)6, "transaction 6.2"); + + flush_journal(cache_ptr); + + if ( update_architypes ) { + + copy_file(journal_filename, testfiles[7]); + } + + verify_journal_contents(journal_filename, testfiles[7]); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + + + /* f-2) Now resize a selection of pinned and unpinned entries via + * protect/unprotect pairs, H5C2_resize_pinned_entry() and + * H5C2_mark_pinned_entry_dirty(). + */ + + + begin_trans(cache_ptr, verbose, (uint64_t)7, "transaction 7.2"); + + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 0); + unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 0, + H5C2__SIZE_CHANGED_FLAG, + ((VARIABLE_ENTRY_SIZE / 16) * 15)); + + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 1); + unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 1, + H5C2__SIZE_CHANGED_FLAG|H5C2__DIRTIED_FLAG, + ((VARIABLE_ENTRY_SIZE / 16) * 14)); + + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 2); + unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 2, + H5C2__SIZE_CHANGED_FLAG, + ((VARIABLE_ENTRY_SIZE / 16) * 13)); + + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 3); + unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 3, + H5C2__SIZE_CHANGED_FLAG|H5C2__DIRTIED_FLAG, + ((VARIABLE_ENTRY_SIZE / 16) * 12)); + + resize_pinned_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 4, + ((VARIABLE_ENTRY_SIZE / 16) * 11)); + + resize_pinned_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 5, + ((VARIABLE_ENTRY_SIZE / 16) * 10)); + + mark_pinned_entry_dirty2(file_ptr, VARIABLE_ENTRY_TYPE, 6, TRUE, + ((VARIABLE_ENTRY_SIZE / 16) * 9)); + + mark_pinned_entry_dirty2(file_ptr, VARIABLE_ENTRY_TYPE, 7, TRUE, + ((VARIABLE_ENTRY_SIZE / 16) * 8)); + + end_trans(file_ptr, cache_ptr, verbose, (uint64_t)7, "transaction 7.2"); + + flush_journal(cache_ptr); + + if ( update_architypes ) { + + copy_file(journal_filename, testfiles[8]); + } + + verify_journal_contents(journal_filename, testfiles[8]); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + + + /* f-3) Now put all the sizes back, and also rename all the entries. */ + + + begin_trans(cache_ptr, verbose, (uint64_t)8, "transaction 8.2"); + + rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 0, FALSE); + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 0); + unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 0, + H5C2__SIZE_CHANGED_FLAG, + VARIABLE_ENTRY_SIZE); + + rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 1, FALSE); + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 1); + unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 1, + H5C2__SIZE_CHANGED_FLAG|H5C2__DIRTIED_FLAG, + VARIABLE_ENTRY_SIZE); + + rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 2, FALSE); + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 2); + unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 2, + H5C2__SIZE_CHANGED_FLAG, + VARIABLE_ENTRY_SIZE); + + rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 3, FALSE); + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 3); + unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 3, + H5C2__SIZE_CHANGED_FLAG|H5C2__DIRTIED_FLAG, + VARIABLE_ENTRY_SIZE); + + rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 4, FALSE); + resize_pinned_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 4, VARIABLE_ENTRY_SIZE); + + rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 5, FALSE); + resize_pinned_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 5, VARIABLE_ENTRY_SIZE); + + rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 6, FALSE); + mark_pinned_entry_dirty2(file_ptr, VARIABLE_ENTRY_TYPE, 6, TRUE, + VARIABLE_ENTRY_SIZE); + + rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 7, FALSE); + mark_pinned_entry_dirty2(file_ptr, VARIABLE_ENTRY_TYPE, 7, TRUE, + VARIABLE_ENTRY_SIZE); + + end_trans(file_ptr, cache_ptr, verbose, (uint64_t)8, "transaction 8.2"); + + flush_journal(cache_ptr); + + if ( update_architypes ) { + + copy_file(journal_filename, testfiles[9]); + } + + verify_journal_contents(journal_filename, testfiles[9]); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + + + /* f-4) Finally, rename all the entries back to their original locations, + * and unpin all the pinned entries. + */ + + begin_trans(cache_ptr, verbose, (uint64_t)9, "transaction 9.2"); + + rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 0, TRUE); + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 0); + unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 0, + H5C2__SIZE_CHANGED_FLAG, VARIABLE_ENTRY_SIZE); + + rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 1, TRUE); + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 1); + unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 1, + H5C2__SIZE_CHANGED_FLAG|H5C2__DIRTIED_FLAG, + VARIABLE_ENTRY_SIZE); + + rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 2, TRUE); + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 2); + unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 2, + H5C2__SIZE_CHANGED_FLAG|H5C2__UNPIN_ENTRY_FLAG, + VARIABLE_ENTRY_SIZE); + + rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 3, TRUE); + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 3); + unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 3, + H5C2__SIZE_CHANGED_FLAG|H5C2__DIRTIED_FLAG|H5C2__UNPIN_ENTRY_FLAG, + VARIABLE_ENTRY_SIZE); + + rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 4, TRUE); + resize_pinned_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 4, VARIABLE_ENTRY_SIZE); + unpin_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 4); + + rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 5, TRUE); + resize_pinned_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 5, VARIABLE_ENTRY_SIZE); + unpin_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 5); + + rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 6, TRUE); + mark_pinned_entry_dirty2(file_ptr, VARIABLE_ENTRY_TYPE, 6, TRUE, + VARIABLE_ENTRY_SIZE); + unpin_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 6); + + rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 7, TRUE); + mark_pinned_entry_dirty2(file_ptr, VARIABLE_ENTRY_TYPE, 7, TRUE, + VARIABLE_ENTRY_SIZE); + unpin_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 7); + + end_trans(file_ptr, cache_ptr, verbose, (uint64_t)9, "transaction 9.2"); + + flush_journal(cache_ptr); + + if ( update_architypes ) { + + copy_file(journal_filename, testfiles[10]); + } + + verify_journal_contents(journal_filename, testfiles[10]); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + flush_cache2(file_ptr, FALSE, FALSE, FALSE); /* resets transaction number */ + + verify_journal_empty(journal_filename); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + + + /* g) verify that the journaling code handles a cascade of changes + * caused when the serialization of an entry causes dirties, resizes, + * and/or resizes of other entries. + * + * g-1) Load several entries of VARIABLE_ENTRY_TYPE into the cache, and + * set their sizes to values less than the maximum. + */ + + begin_trans(cache_ptr, verbose, (uint64_t)1, "transaction 1.3"); + + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 10); + unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 10, + H5C2__SIZE_CHANGED_FLAG, + ((VARIABLE_ENTRY_SIZE / 4) * 1)); + + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 11); + unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 11, + H5C2__SIZE_CHANGED_FLAG, + ((VARIABLE_ENTRY_SIZE / 4) * 2)); -static void write_noflush_verify(H5C2_jbrb_t * struct_ptr, - int size, - char * data, - FILE * readback, - int repeats); + protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 12); + unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 12, + H5C2__SIZE_CHANGED_FLAG, + ((VARIABLE_ENTRY_SIZE / 4) * 3)); -static void check_mdj_config_block_IO(void); + end_trans(file_ptr, cache_ptr, verbose, (uint64_t)1, "transaction 1.3"); -static void test_mdj_conf_blk_read_write_discard(H5F_t * file_ptr, - const char * jrnl_file_path); + flush_journal(cache_ptr); -static void check_superblock_extensions(void); + if ( update_architypes ) { -static void check_message_format(void); + copy_file(journal_filename, testfiles[11]); + } -static void check_legal_calls(void); + verify_journal_contents(journal_filename, testfiles[11]); -static void check_transaction_tracking(void); -static void write_verify_trans_num(H5C2_jbrb_t * struct_ptr, - uint64_t trans_num, - uint64_t verify_val); + /* g-2) Now setup flush operations on some entries to dirty, resize, + * and/or rename other entries. When these entries are dirtied + * in a transaction, the associated flush operations should be + * triggered and appear in the journal. + * + * In case you need a score card, in what follows, I set up the + * following dependencies: + * + * (MICRO_ENTRY_TYPE, 20) dirties (MICRO_ENTRY_TYPE, 30) + * + * (MICRO_ENTRY_TYPE, 21) renames, resizes, and dirties: + * (VARIABLE_ENTRY_TYPE, 10) + * (VARIABLE_ENTRY_TYPE, 13) + * + * (MICRO_ENTRY_TYPE, 22) resizes (VARIABLE_ENTRY_TYPE, 11) + * (VARIABLE_ENTRY_TYPE, 12) + * + * (MICRO_ENTRY_TYPE, 23) renames (VARIABLE_ENTRY_TYPE, 10) + * (VARIABLE_ENTRY_TYPE, 13) + * to their original locations + * + * (MICRO_ENTRY_TYPE, 24) dirties (MICRO_ENTRY_TYPE, 21) + * + * (MICRO_ENTRY_TYPE, 25) dirties (MICRO_ENTRY_TYPE, 22) + * (MICRO_ENTRY_TYPE, 23) + * + */ + add_flush_op2(MICRO_ENTRY_TYPE, 20, + FLUSH_OP__DIRTY, MICRO_ENTRY_TYPE, 30, FALSE, 0); - -/**************************************************************************/ -/**************************************************************************/ -/********************************* tests: *********************************/ -/**************************************************************************/ -/**************************************************************************/ + + add_flush_op2(MICRO_ENTRY_TYPE, 21, + FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 10, FALSE, VARIABLE_ENTRY_SIZE); + add_flush_op2(MICRO_ENTRY_TYPE, 21, + FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 10, FALSE, 0); + add_flush_op2(MICRO_ENTRY_TYPE, 21, + FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 10, FALSE, 0); + + add_flush_op2(MICRO_ENTRY_TYPE, 21, + FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 13, FALSE, VARIABLE_ENTRY_SIZE/4); + add_flush_op2(MICRO_ENTRY_TYPE, 21, + FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 13, FALSE, 0); + add_flush_op2(MICRO_ENTRY_TYPE, 21, + FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 13, FALSE, 0); + + + add_flush_op2(MICRO_ENTRY_TYPE, 22, + FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 11, FALSE, VARIABLE_ENTRY_SIZE); + + add_flush_op2(MICRO_ENTRY_TYPE, 22, + FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 12, FALSE, VARIABLE_ENTRY_SIZE); + + + add_flush_op2(MICRO_ENTRY_TYPE, 23, + FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 10, TRUE, 0); + + add_flush_op2(MICRO_ENTRY_TYPE, 23, + FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 13, TRUE, 0); + + + add_flush_op2(MICRO_ENTRY_TYPE, 24, + FLUSH_OP__DIRTY, MICRO_ENTRY_TYPE, 21, FALSE, 0); + + + add_flush_op2(MICRO_ENTRY_TYPE, 25, + FLUSH_OP__DIRTY, MICRO_ENTRY_TYPE, 22, FALSE, 0); + + add_flush_op2(MICRO_ENTRY_TYPE, 25, + FLUSH_OP__DIRTY, MICRO_ENTRY_TYPE, 23, FALSE, 0); + + + /* g-3) Start with a simple check -- dirty (MICRO_ENTRY_TYPE, 20), + * which should also dirty (MICRO_ENTRY_TYPE, 30) when + * (MICRO_ENTRY_TYPE, 20) is serialized at transaction close. + */ + + begin_trans(cache_ptr, verbose, (uint64_t)2, "transaction 2.3"); + + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 20); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 20, TRUE, H5C2__NO_FLAGS_SET); + + end_trans(file_ptr, cache_ptr, verbose, (uint64_t)2, "transaction 2.3"); + + flush_journal(cache_ptr); + + if ( update_architypes ) { + + copy_file(journal_filename, testfiles[12]); + } + + verify_journal_contents(journal_filename, testfiles[12]); + + + /* g-4) Now dirty (MICRO_ENTRY_TYPE, 24), which dirties + * (MICRO_ENTRY_TYPE, 21), which dirties, resizes, and + * renames (VARIABLE_ENTRY_TYPE, 10) and (VARIABLE_ENTRY_TYPE, 13) + */ + + begin_trans(cache_ptr, verbose, (uint64_t)3, "transaction 3.3"); + + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 24); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 24, TRUE, H5C2__NO_FLAGS_SET); + + end_trans(file_ptr, cache_ptr, verbose, (uint64_t)3, "transaction 3.3"); + + flush_journal(cache_ptr); + + if ( update_architypes ) { + + copy_file(journal_filename, testfiles[13]); + } + + verify_journal_contents(journal_filename, testfiles[13]); + + + /* g-4) Now dirty (MICRO_ENTRY_TYPE, 25), which dirties + * (MICRO_ENTRY_TYPE, 22) and (MICRO_ENTRY_TYPE, 23), which + * in turn resize (VARIABLE_ENTRY_TYPE, 11) and + * (VARIABLE_ENTRY_TYPE, 12), and rename (VARIABLE_ENTRY_TYPE, 10) + * and (VARIABLE_ENTRY_TYPE, 13) back to their original locations. + */ + + begin_trans(cache_ptr, verbose, (uint64_t)4, "transaction 4.3"); + + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 25); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 25, TRUE, H5C2__NO_FLAGS_SET); + + end_trans(file_ptr, cache_ptr, verbose, (uint64_t)4, "transaction 4.3"); + + flush_journal(cache_ptr); + + if ( update_architypes ) { + + copy_file(journal_filename, testfiles[14]); + } + + verify_journal_contents(journal_filename, testfiles[14]); + + flush_cache2(file_ptr, FALSE, FALSE, FALSE); /* resets transaction number */ + + verify_journal_empty(journal_filename); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + + + /* h) Dirty an entry, and then expunge it. Entry should not appear + * in the journal. Do this twice -- first with only the expunge + * entry in the transaction, and a second time with other entries + * involved. + * + * Note that no journal file will be written until the first + * entry, so start with a transaction that generates some data. + */ + + begin_trans(cache_ptr, verbose, (uint64_t)1, "transaction 1.4"); + + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 39); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 39, TRUE, H5C2__NO_FLAGS_SET); + + end_trans(file_ptr, cache_ptr, verbose, (uint64_t)1, "transaction 1.4"); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + + begin_trans(cache_ptr, verbose, (uint64_t)2, "transaction 2.4"); + + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 40); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 40, TRUE, H5C2__NO_FLAGS_SET); + + expunge_entry2(file_ptr, MICRO_ENTRY_TYPE, 40); + + end_trans(file_ptr, cache_ptr, verbose, (uint64_t)2, "transaction 2.4"); + + flush_journal(cache_ptr); + + if ( update_architypes ) { + + copy_file(journal_filename, testfiles[15]); + } + + verify_journal_contents(journal_filename, testfiles[15]); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + + + begin_trans(cache_ptr, verbose, (uint64_t)3, "transaction 3.4"); + + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 41); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 41, TRUE, H5C2__NO_FLAGS_SET); + expunge_entry2(file_ptr, MICRO_ENTRY_TYPE, 41); + protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 42); + unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 42, TRUE, H5C2__NO_FLAGS_SET); + + end_trans(file_ptr, cache_ptr, verbose, (uint64_t)3, "transaction 3.4"); + + flush_journal(cache_ptr); + + if ( update_architypes ) { + + copy_file(journal_filename, testfiles[16]); + } + + verify_journal_contents(journal_filename, testfiles[16]); + + + /*******************************************************/ + /* 3) Close and discard the file and the journal file. */ + /*******************************************************/ + + takedown_cache_after_journaling(file_id, filename, journal_filename); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + if ( pass2 ) { PASSED(); } else { H5_FAILED(); } + + if ( ! pass2 ) { + + failures2++; + HDfprintf(stdout, "%s: failure_mssg2 = \"%s\".\n", + fcn_name, failure_mssg2); + } + + return; + +} /* mdj_smoke_check_00() */ + + +/*------------------------------------------------------------------------- + * Function: mdj_smoke_check_01() + * + * Purpose: Run a cut down version of smoke_check_1 in cache2.c, with + * journaling enabled. Check the journal files generated, + * and verify that the journal output matches the architype + * test files. Skip the test if these architypes are not + * present. + * + * Return: void + * + * Programmer: John Mainzer + * 5/19/08 + * + * Changes: None. + * + *------------------------------------------------------------------------- + */ + +static void +mdj_smoke_check_01(void) +{ + const char * fcn_name = "mdj_smoke_check_01()"; + const char * testfiles[] = + { + "testfiles/cache2_journal_sc01_000.jnl", + "testfiles/cache2_journal_sc01_001.jnl", + NULL + }; + char filename[512]; + char journal_filename[H5AC2__MAX_JOURNAL_FILE_NAME_LEN + 1]; + hbool_t show_progress = FALSE; + hbool_t dirty_inserts = FALSE; + hbool_t verbose = FALSE; + hbool_t update_architypes = TRUE; + int dirty_unprotects = FALSE; + int dirty_destroys = FALSE; + hbool_t display_stats = FALSE; + int32_t lag = 10; + int cp = 0; + int32_t max_index = 128; + uint64_t trans_num = 0; + hid_t file_id = -1; + H5F_t * file_ptr = NULL; + H5C2_t * cache_ptr = NULL; + + TESTING("mdj smoke check 01 -- jrnl ins, prot, unprot"); + + pass2 = TRUE; + + /********************************************************************/ + /* Create a file with cache configuration set to enable journaling. */ + /********************************************************************/ + + /* setup the file name */ + if ( pass2 ) { + + if ( h5_fixname(FILENAMES[1], H5P_DEFAULT, filename, sizeof(filename)) + == NULL ) { + + pass2 = FALSE; + failure_mssg2 = "h5_fixname() failed (1).\n"; + } + } + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + if ( verbose ) { + HDfprintf(stdout, "%s: filename = \"%s\".\n", fcn_name, filename); + } + + /* setup the journal file name */ + if ( pass2 ) { + + if ( h5_fixname(FILENAMES[3], H5P_DEFAULT, journal_filename, + sizeof(journal_filename)) == NULL ) { + + pass2 = FALSE; + failure_mssg2 = "h5_fixname() failed (2).\n"; + } + else if ( strlen(journal_filename) >= + H5AC2__MAX_JOURNAL_FILE_NAME_LEN ) { + + pass2 = FALSE; + failure_mssg2 = "journal file name too long.\n"; + } + } + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + if ( verbose ) { + HDfprintf(stdout, "%s: journal filename = \"%s\".\n", + fcn_name, journal_filename); + } + + setup_cache_for_journaling(filename, journal_filename, &file_id, + &file_ptr, &cache_ptr); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + + /******************************************/ + /* Run a small, fairly simple stress test */ + /******************************************/ + + trans_num = 0; +#if 0 /* JRM */ /* this section is in-op at present */ + jrnl_row_major_scan_forward2(/* file_ptr */ file_ptr, + /* max_index */ max_index, + /* lag */ lag, + /* verbose */ verbose, + /* reset_stats */ TRUE, + /* display_stats */ display_stats, + /* display_detailed_stats */ FALSE, + /* do_inserts */ TRUE, + /* dirty_inserts */ dirty_inserts, + /* do_renames */ TRUE, + /* rename_to_main_addr */ FALSE, + /* do_destroys */ TRUE, + /* do_mult_ro_protects */ TRUE, + /* dirty_destroys */ dirty_destroys, + /* dirty_unprotects */ dirty_unprotects, + /* trans_num */ trans_num); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + flush_journal(cache_ptr); + + if ( update_architypes ) { + + copy_file(journal_filename, testfiles[0]); + } + + verify_journal_contents(journal_filename, testfiles[0]); + + flush_cache2(file_ptr, FALSE, FALSE, FALSE); /* resets transaction number */ + + verify_journal_empty(journal_filename); + + trans_num = 0; + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + jrnl_row_major_scan_backward2(/* file_ptr */ file_ptr, + /* max_index */ max_index, + /* lag */ lag, + /* verbose */ verbose, + /* reset_stats */ TRUE, + /* display_stats */ display_stats, + /* display_detailed_stats */ FALSE, + /* do_inserts */ FALSE, + /* dirty_inserts */ dirty_inserts, + /* do_renames */ TRUE, + /* rename_to_main_addr */ TRUE, + /* do_destroys */ FALSE, + /* do_mult_ro_protects */ TRUE, + /* dirty_destroys */ dirty_destroys, + /* dirty_unprotects */ dirty_unprotects, + /* trans_num */ trans_num); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + flush_journal(cache_ptr); + + if ( update_architypes ) { + + copy_file(journal_filename, testfiles[1]); + } + + verify_journal_contents(journal_filename, testfiles[1]); + + flush_cache2(file_ptr, FALSE, FALSE, FALSE); /* resets transaction number */ + + verify_journal_empty(journal_filename); + + trans_num = 0; + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + jrnl_row_major_scan_forward2(/* file_ptr */ file_ptr, + /* max_index */ max_index, + /* lag */ lag, + /* verbose */ verbose, + /* reset_stats */ TRUE, + /* display_stats */ display_stats, + /* display_detailed_stats */ FALSE, + /* do_inserts */ TRUE, + /* dirty_inserts */ dirty_inserts, + /* do_renames */ TRUE, + /* rename_to_main_addr */ FALSE, + /* do_destroys */ TRUE, + /* do_mult_ro_protects */ TRUE, + /* dirty_destroys */ dirty_destroys, + /* dirty_unprotects */ dirty_unprotects, + /* trans_num */ trans_num); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + flush_journal(cache_ptr); + + if ( update_architypes ) { + + copy_file(journal_filename, testfiles[2]); + } + + verify_journal_contents(journal_filename, testfiles[2]); + + flush_cache2(file_ptr, FALSE, FALSE, FALSE); /* resets transaction number */ + + verify_journal_empty(journal_filename); +#endif /* JRM */ + trans_num = 0; + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + jrnl_col_major_scan_forward2(/* file_ptr */ file_ptr, + /* max_index */ max_index, + /* lag */ lag, + /* verbose */ verbose, + /* reset_stats */ TRUE, + /* display_stats */ display_stats, + /* display_detailed_stats */ TRUE, + /* do_inserts */ TRUE, + /* dirty_inserts */ dirty_inserts, + /* dirty_unprotects */ dirty_unprotects, + /* trans_num */ trans_num); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + flush_journal(cache_ptr); + + if ( update_architypes ) { + + copy_file(journal_filename, testfiles[0]); + } + + verify_journal_contents(journal_filename, testfiles[0]); + + flush_cache2(file_ptr, FALSE, FALSE, FALSE); /* resets transaction number */ + + verify_journal_empty(journal_filename); + + trans_num = 0; + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + jrnl_col_major_scan_backward2(/* file_ptr */ file_ptr, + /* max_index */ max_index, + /* lag */ lag, + /* verbose */ verbose, + /* reset_stats */ TRUE, + /* display_stats */ display_stats, + /* display_detailed_stats */ TRUE, + /* do_inserts */ TRUE, + /* dirty_inserts */ dirty_inserts, + /* dirty_unprotects */ dirty_unprotects, + /* trans_num */ trans_num); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + flush_journal(cache_ptr); + + if ( update_architypes ) { + + copy_file(journal_filename, testfiles[1]); + } + + verify_journal_contents(journal_filename, testfiles[1]); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + /****************************************************/ + /* Close and discard the file and the journal file. */ + /****************************************************/ + + takedown_cache_after_journaling(file_id, filename, journal_filename); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + verify_clean2(); + verify_unprotected2(); + + if ( show_progress ) + HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + + if ( pass2 ) { PASSED(); } else { H5_FAILED(); } + + if ( ! pass2 ) { + + failures2++; + HDfprintf(stdout, "%s: failure_mssg2 = \"%s\".\n", + fcn_name, failure_mssg2); + } + + return; + +} /* mdj_smoke_check_01() */ /*** metatada journaling config block I/O test code ***/ @@ -1970,7 +5392,7 @@ check_message_format(void) fgets(from_journal[i], 300, readback); if ( HDstrcmp(verify[i], from_journal[i]) != 0) { - + pass2 = FALSE; failure_mssg2 = "journal file not written correctly"; @@ -3345,7 +6767,6 @@ write_verify_trans_num(H5C2_jbrb_t * struct_ptr, } /* end write_verify_trans_num */ - /*------------------------------------------------------------------------- * Function: main @@ -3374,7 +6795,14 @@ main(void) H5open(); express_test = GetTestExpress(); - + +#if 1 + mdj_smoke_check_00(); +#endif +#if 1 + mdj_smoke_check_01(); +#endif +#if 1 check_buffer_writes(); check_legal_calls(); check_message_format(); @@ -3382,6 +6810,7 @@ main(void) check_superblock_extensions(); check_mdj_config_block_IO(); +#endif return(failures2); -- cgit v0.12