From 077aed74b57de2d7b0f8647b87061277ea051c52 Mon Sep 17 00:00:00 2001 From: John Mainzer Date: Wed, 10 Jun 2009 21:39:27 -0500 Subject: [svn-r17028] Added binary journal file support and related tests. Removed a bunch of debug code. Other minor changes. Did only limited testing -- just build and test on Phoenix (AMD64 linux with debug). --- src/H5AC.c | 2 +- src/H5AC2.c | 15 +- src/H5C2.c | 138 +- src/H5C2journal.c | 3184 +++++++++++++---- src/H5C2pkg.h | 47 + src/H5C2private.h | 4 +- test/cache2.c | 6 +- test/cache2_api.c | 65 +- test/cache2_common.c | 45 +- test/cache2_jnl_file_marking.c | 2 - test/cache2_journal.c | 1813 ++++++++-- test/testfiles/cache2_journal_bsc00_000.jnl.gz | Bin 0 -> 217 bytes test/testfiles/cache2_journal_bsc00_001.jnl.gz | Bin 0 -> 237 bytes test/testfiles/cache2_journal_bsc00_002.jnl.gz | Bin 0 -> 252 bytes test/testfiles/cache2_journal_bsc00_003.jnl.gz | Bin 0 -> 309 bytes test/testfiles/cache2_journal_bsc00_004.jnl.gz | Bin 0 -> 370 bytes test/testfiles/cache2_journal_bsc00_005.jnl.gz | Bin 0 -> 466 bytes test/testfiles/cache2_journal_bsc00_006.jnl.gz | Bin 0 -> 492 bytes test/testfiles/cache2_journal_bsc00_007.jnl.gz | Bin 0 -> 672 bytes test/testfiles/cache2_journal_bsc00_008.jnl.gz | Bin 0 -> 933 bytes test/testfiles/cache2_journal_bsc00_009.jnl.gz | Bin 0 -> 1163 bytes test/testfiles/cache2_journal_bsc00_010.jnl.gz | Bin 0 -> 1389 bytes test/testfiles/cache2_journal_bsc00_011.jnl.gz | Bin 0 -> 289 bytes test/testfiles/cache2_journal_bsc00_012.jnl.gz | Bin 0 -> 339 bytes test/testfiles/cache2_journal_bsc00_013.jnl.gz | Bin 0 -> 442 bytes test/testfiles/cache2_journal_bsc00_014.jnl.gz | Bin 0 -> 614 bytes test/testfiles/cache2_journal_bsc00_015.jnl.gz | Bin 0 -> 202 bytes test/testfiles/cache2_journal_bsc00_016.jnl.gz | Bin 0 -> 227 bytes test/testfiles/cache2_journal_bsc00_017.jnl.gz | Bin 0 -> 206 bytes test/testfiles/cache2_journal_bsc00_018.jnl.gz | Bin 0 -> 225 bytes test/testfiles/cache2_journal_bsc01_000.jnl.gz | Bin 0 -> 4818 bytes test/testfiles/cache2_journal_bsc01_001.jnl.gz | Bin 0 -> 4699 bytes test/testfiles/cache2_journal_bsc01_002.jnl.gz | Bin 0 -> 4172 bytes test/testfiles/cache2_journal_bsc01_003.jnl.gz | Bin 0 -> 12769 bytes test/testfiles/cache2_journal_bsc01_004.jnl.gz | Bin 0 -> 11939 bytes test/testfiles/cache2_journal_bsc02_000.jnl.gz | Bin 0 -> 6932 bytes test/testfiles/cache2_journal_bsc02_001.jnl.gz | Bin 0 -> 12318 bytes test/testfiles/cache2_journal_bsc02_002.jnl.gz | Bin 0 -> 12468 bytes test/testfiles/cache2_journal_bsc02_003.jnl.gz | Bin 0 -> 49627 bytes test/testfiles/cache2_journal_bsc02_004.jnl.gz | Bin 0 -> 48362 bytes tools/h5recover/h5recover.c | 4558 ++++++++++++++++++++---- tools/h5recover/testh5recover.sh.in | 18 +- tools/h5recover/trecover.h | 2 +- tools/h5recover/trecover_main.c | 30 +- tools/h5recover/trecover_writer.c | 4 +- 45 files changed, 7914 insertions(+), 2019 deletions(-) create mode 100755 test/testfiles/cache2_journal_bsc00_000.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc00_001.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc00_002.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc00_003.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc00_004.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc00_005.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc00_006.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc00_007.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc00_008.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc00_009.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc00_010.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc00_011.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc00_012.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc00_013.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc00_014.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc00_015.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc00_016.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc00_017.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc00_018.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc01_000.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc01_001.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc01_002.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc01_003.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc01_004.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc02_000.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc02_001.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc02_002.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc02_003.jnl.gz create mode 100755 test/testfiles/cache2_journal_bsc02_004.jnl.gz diff --git a/src/H5AC.c b/src/H5AC.c index b5f8af6..fc4ea4d 100644 --- a/src/H5AC.c +++ b/src/H5AC.c @@ -3131,7 +3131,7 @@ H5AC_validate_config(H5AC_cache_config_t * config_ptr) if ( ( config_ptr->evictions_enabled == FALSE ) && ( ( config_ptr->incr_mode != H5C_incr__off ) || ( config_ptr->flash_incr_mode != H5C_flash_incr__off ) || - ( config_ptr->incr_mode != H5C_decr__off ) ) ) { + ( config_ptr->decr_mode != H5C_decr__off ) ) ) { HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, \ "Can't disable evictions while auto-resize is enabled.") diff --git a/src/H5AC2.c b/src/H5AC2.c index 95d78e2..5a12dea 100644 --- a/src/H5AC2.c +++ b/src/H5AC2.c @@ -4154,20 +4154,7 @@ H5AC2_validate_jnl_config(const H5AC2_jnl_config_t *config_ptr) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL config_ptr on entry.") if ( config_ptr->version != H5AC2__CURR_JNL_CONFIG_VER ) { -#if 0 /* JRM */ - HDfprintf(stdout, "version = %d(%d).\n", config_ptr->version, - H5AC2__CURR_JNL_CONFIG_VER); - HDfprintf(stdout, "enable_journaling = %d.\n", - (int)(config_ptr->enable_journaling)); - HDfprintf(stdout, "journal_recovered = %d\n", - (int)(config_ptr->journal_recovered)); - HDfprintf(stdout, "jbrb_buf_size = %ld\n", - (long)(config_ptr->jbrb_buf_size)); - HDfprintf(stdout, "jbrb_num_bufs = %d\n", config_ptr->jbrb_num_bufs); - HDfprintf(stdout, "jbrb_use_aio = %d\n", (int)(config_ptr->jbrb_use_aio)); - HDfprintf(stdout, "jbrb_human_readable = %d\n", - (int)(config_ptr->jbrb_human_readable)); -#endif /* JRM */ + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Unknown config version.") } diff --git a/src/H5C2.c b/src/H5C2.c index 2115d92..0c5323d 100644 --- a/src/H5C2.c +++ b/src/H5C2.c @@ -1167,17 +1167,13 @@ 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.") } @@ -1219,9 +1215,7 @@ 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.") } @@ -2585,10 +2579,6 @@ 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.") } @@ -2610,9 +2600,6 @@ 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") } @@ -2663,9 +2650,6 @@ 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.") } @@ -2681,9 +2665,6 @@ 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.") @@ -3333,9 +3314,9 @@ H5C2_mark_pinned_or_protected_entry_dirty(void * thing) #endif /* JRM */ if ( entry_ptr->is_protected ) { -#if 0 /* JRM - uncomment this when possible */ + HDassert( ! ((entry_ptr)->is_read_only) ); -#endif + /* set the dirtied flag */ entry_ptr->dirtied = TRUE; @@ -4076,9 +4057,6 @@ 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") } @@ -4095,10 +4073,6 @@ 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.") } @@ -4123,10 +4097,6 @@ 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") @@ -4188,10 +4158,6 @@ 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.") } @@ -4247,10 +4213,6 @@ 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?!?.") } @@ -4320,10 +4282,6 @@ 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.") } @@ -4349,10 +4307,6 @@ 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.") } @@ -4779,6 +4733,7 @@ H5C2_set_evictions_enabled(const H5F_t * f, */ if ( ( evictions_enabled != TRUE ) && ( ( cache_ptr->resize_ctl.incr_mode != H5C2_incr__off ) || + ( cache_ptr->resize_ctl.flash_incr_mode != H5C2_flash_incr__off ) || ( cache_ptr->resize_ctl.decr_mode != H5C2_decr__off ) ) ) { HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ @@ -9004,10 +8959,7 @@ H5C2_flush_single_entry(const H5F_t * f, entry_ptr->magic = H5C2__H5C2_CACHE_ENTRY_T_BAD_MAGIC; #endif /* NDEBUG */ entry_ptr->cache_ptr = NULL; -#if 0 /* JRM */ - HDfprintf(stdout, "%s: calling free_icr(%d -- %s).\n", FUNC, - type_ptr->id, type_ptr->name); -#endif /* JRM */ + if ( type_ptr->free_icr(entry_ptr->addr, entry_ptr->size, (void *)entry_ptr) != SUCCEED ) { @@ -9155,34 +9107,21 @@ H5C2_load_entry(H5F_t * f, image_ptr = H5MM_malloc(len); - if ( image_ptr == NULL ) - { -#if 0 /* JRM */ - HDfprintf(stdout, - "memory allocation failed for on disk image buffer.\n"); -#endif /* JRM */ + if ( image_ptr == NULL ) { + 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."); - HDfprintf(stdout, "%s: addr = 0X%llx, len = %d.\n", - FUNC, (long long)addr, (int)len); - fflush(stdout); -#endif /* JRM */ + if ( H5F_block_read(f, type->mem_type, addr, len, dxpl_id, image_ptr) < 0 ) { + HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "Can't read image*") } thing = type->deserialize(addr, len, image_ptr, udata_ptr, &dirty); - if ( thing == NULL ) - { -#if 0 /* JRM */ - HDfprintf(stdout, "can't deserialize image.\n."); -#endif /* JRM */ + if ( thing == NULL ) { + HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "Can't deserialize image") } @@ -9191,34 +9130,27 @@ H5C2_load_entry(H5F_t * f, { size_t new_len; - if ( type->image_len(thing, &new_len) != SUCCEED ) - { -#if 0 /* JRM */ - HDfprintf(stdout, "image_len() failed.\n."); -#endif /* JRM */ + if ( type->image_len(thing, &new_len) != SUCCEED ) { + HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "image_len() failed.\n"); - } - else if ( new_len == 0 ) - { -#if 0 /* JRM */ - HDfprintf(stdout, "new_len == 0\n."); -#endif /* JRM */ + + } else if ( new_len == 0 ) { + HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "new_len == 0\n") } else if ( new_len != len) { image_ptr = H5MM_realloc(image_ptr, new_len); - if ( image_ptr == NULL ) - { -#if 0 /* JRM */ - HDfprintf(stdout, "image_ptr null after H5MM_realloc().\n"); -#endif /* JRM */ + if ( image_ptr == NULL ) { + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, \ "image_ptr null after H5MM_realloc().") } - /* If the thing's image needs to be bigger, free the thing and retry with new length */ + /* If the thing's image needs to be bigger, free the thing + * and retry with new length + */ if ( new_len > len) { if ( type->free_icr(addr, len, thing) != SUCCEED ) @@ -9227,22 +9159,20 @@ H5C2_load_entry(H5F_t * f, "free_icr callback failed.") } - if ( H5F_block_read(f, type->mem_type, addr, new_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") + if ( H5F_block_read(f, type->mem_type, addr, new_len, + dxpl_id, image_ptr) < 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, \ + "Can't read image") } - thing = type->deserialize(addr, new_len, image_ptr, udata_ptr, &dirty); + thing = type->deserialize(addr, new_len, image_ptr, + udata_ptr, &dirty); - 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") + if ( thing == NULL ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, \ + "Can't deserialize image") } } diff --git a/src/H5C2journal.c b/src/H5C2journal.c index e5c338d..223a5ec 100644 --- a/src/H5C2journal.c +++ b/src/H5C2journal.c @@ -67,12 +67,82 @@ static herr_t H5C2_call_mdjsc_callbacks(H5C2_t * cache_ptr, hid_t dxpl_id, H5C2_mdj_config_t * config_ptr); +static herr_t H5C2_get_journaling_in_progress(const H5F_t * f, + H5C2_t * cache_ptr); + static herr_t H5C2_grow_mdjsc_callback_table(H5C2_t * cache_ptr); +static herr_t H5C2_jb_bjf__comment(H5C2_jbrb_t * struct_ptr, + const char * comment_ptr); + +static herr_t H5C2_jb_bjf__end_transaction(H5C2_jbrb_t * struct_ptr, + uint64_t trans_num); + +static herr_t H5C2_jb_bjf__eoa(H5C2_jbrb_t * struct_ptr, + haddr_t eoa); + +static herr_t H5C2_jb_bjf__journal_entry(H5C2_jbrb_t * struct_ptr, + uint64_t trans_num, + haddr_t base_addr, + size_t length, + const uint8_t * body); + +static herr_t H5C2_jb_bjf__start_transaction(H5C2_jbrb_t * struct_ptr, + uint64_t trans_num); + +static herr_t H5C2_jb_bjf__write_buffer(H5C2_jbrb_t * struct_ptr, + size_t buf_size, + const char * buf_ptr, + hbool_t is_end_trans, + uint64_t trans_num); + +static herr_t H5C2_jb_bjf__write_chksum(H5C2_jbrb_t * struct_ptr, + hbool_t is_end_trans, + uint64_t trans_num); + +static herr_t H5C2_jb_bjf__write_length(H5C2_jbrb_t * struct_ptr, + size_t length, + hbool_t is_end_trans, + uint64_t trans_num); + +static herr_t H5C2_jb_bjf__write_offset(H5C2_jbrb_t * struct_ptr, + haddr_t offset, + hbool_t is_end_trans, + uint64_t trans_num); + +static herr_t H5C2_jb_bjf__write_sig_and_ver(H5C2_jbrb_t * struct_ptr, + size_t sig_size, + const char * sig_ptr, + const uint8_t version, + hbool_t keep_chksum, + hbool_t is_end_trans, + uint64_t trans_num); + +static herr_t H5C2_jb_bjf__write_trans_num(H5C2_jbrb_t * struct_ptr, + hbool_t is_end_trans, + uint64_t trans_num); + +static herr_t H5C2_jb_hrjf__comment(H5C2_jbrb_t * struct_ptr, + const char * comment_ptr); + +static herr_t H5C2_jb_hrjf__end_transaction(H5C2_jbrb_t * struct_ptr, + uint64_t trans_num); + +static herr_t H5C2_jb_hrjf__eoa(H5C2_jbrb_t * struct_ptr, + haddr_t eoa); + +static herr_t H5C2_jb_hrjf__journal_entry(H5C2_jbrb_t * struct_ptr, + uint64_t trans_num, + haddr_t base_addr, + size_t length, + const uint8_t * body); + +static herr_t H5C2_jb_hrjf__start_transaction(H5C2_jbrb_t * struct_ptr, + uint64_t trans_num); + + static herr_t H5C2_shrink_mdjsc_callback_table(H5C2_t * cache_ptr); -static herr_t H5C2_get_journaling_in_progress(const H5F_t * f, - H5C2_t * cache_ptr); /**************************************************************************/ @@ -122,11 +192,12 @@ H5C2_begin_journaling(H5F_t * f, H5C2_mdj_config_t config; 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( f->shared != NULL ); + HDassert( f->shared->sizeof_addr > 0 ); + HDassert( f->shared->sizeof_size > 0 ); HDassert( cache_ptr != NULL ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); HDassert( cache_ptr->mdj_enabled == FALSE ); @@ -152,10 +223,6 @@ H5C2_begin_journaling(H5F_t * f, "metadata journaling already enabled on entry.") } -#if 0 /* JRM */ - HDfprintf(stdout, "%s Finished initial sanity checks.\n", FUNC); -#endif /* JRM */ - result = H5C2_flush_cache(f, dxpl_id, H5C2__NO_FLAGS_SET); if ( result < 0 ) { @@ -164,20 +231,8 @@ H5C2_begin_journaling(H5F_t * f, "H5C2_flush_cache() failed.") } -#if 0 /* JRM */ - HDfprintf(stdout, "%s Finished flushing the cache.\n", FUNC); -#endif /* JRM */ - journal_magic = (int32_t)HDrand(); -#if 0 /* JRM */ - HDfprintf(stdout, "%s journal_magic = %d.\n", FUNC, (int)journal_magic); -#endif /* JRM */ - -#if 0 /* JRM */ - HDfprintf(stdout, "%s calling H5C2_jb__init().\n", FUNC); -#endif /* JRM */ - result = H5C2_jb__init(&(cache_ptr->mdj_jbrb), journal_magic, f->name, @@ -185,30 +240,22 @@ H5C2_begin_journaling(H5F_t * f, config_ptr->jbrb_buf_size, config_ptr->jbrb_num_bufs, config_ptr->jbrb_use_aio, - config_ptr->jbrb_human_readable); + config_ptr->jbrb_human_readable, + f->shared->sizeof_addr, + f->shared->sizeof_size); if ( result != SUCCEED ) { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: H5C2_jb__init() failed.\n", FUNC); -#endif /* JRM */ + 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 */ - /* Note that this call flushes the HDF5 file in passing */ result = H5C2_mark_journaling_in_progress(f, dxpl_id, journal_magic, config_ptr->journal_file_path); if ( result != SUCCEED ) { -#if 0 /* JRM */ - HDfprintf(stdout, - "%s: H5C2_mark_journaling_in_progress() failed.\n", FUNC); -#endif /* JRM */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ "H5C2_mark_journaling_in_progress() failed.") } @@ -231,10 +278,6 @@ H5C2_begin_journaling(H5F_t * f, "H5C2_call_mdjsc_callbacks() failed.") } -#if 0 /* JRM */ - HDfprintf(stdout, "%s exiting.\n", FUNC); -#endif /* JRM */ - done: FUNC_LEAVE_NOAPI(ret_value) @@ -266,12 +309,7 @@ H5C2_begin_transaction(H5C2_t * cache_ptr, herr_t ret_value = SUCCEED; /* Return value */ 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 ); @@ -301,10 +339,7 @@ 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() */ @@ -350,19 +385,13 @@ H5C2_end_journaling(H5F_t * f, H5C2_mdj_config_t config; FUNC_ENTER_NOAPI(H5C2_end_journaling, FAIL) -#if 0 /* JRM */ - HDfprintf(stdout, "%s: entering.\n", FUNC); -#endif /* JRM */ + HDassert( f != NULL ); HDassert( cache_ptr != NULL ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); if ( cache_ptr->mdj_enabled ) { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: taking down journaling.\n", FUNC); -#endif /* JRM */ - HDassert( cache_ptr->mdj_enabled ); HDassert( cache_ptr->trans_in_progress == FALSE ); HDassert( cache_ptr->tl_len == 0 ); @@ -426,10 +455,6 @@ H5C2_end_journaling(H5F_t * f, done: -#if 0 /* JRM */ - HDfprintf(stdout, "%s: exiting.\n", FUNC); -#endif /* JRM */ - FUNC_LEAVE_NOAPI(ret_value) } /* H5C2_end_journaling() */ @@ -462,10 +487,7 @@ 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 ); @@ -476,20 +498,13 @@ 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?!?!") } @@ -502,18 +517,11 @@ 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 @@ -523,13 +531,9 @@ H5C2_end_transaction(H5F_t * f, result = H5C2_jb__get_last_transaction_on_disk(&(cache_ptr->mdj_jbrb), &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.") } @@ -541,11 +545,6 @@ 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.") } @@ -871,9 +870,6 @@ 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.") } @@ -883,9 +879,6 @@ 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.") } @@ -902,10 +895,6 @@ H5C2_journal_transaction(H5F_t * f, 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.") } @@ -917,11 +906,6 @@ 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.") } @@ -943,17 +927,15 @@ H5C2_journal_transaction(H5F_t * f, &new_addr, &new_len, &new_image_ptr); - if ( result != SUCCEED ) - { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: unable to serialize entry.\n", FUNC); -#endif /* JRM */ + + if ( result != SUCCEED ) { + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ "unable to serialize entry") } - if ( serialize_flags != 0 ) - { + 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 @@ -965,12 +947,8 @@ H5C2_journal_transaction(H5F_t * f, 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 */ + if ( ( renamed ) && ( ! resized ) ) { + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ "entry renamed but not resized?!?!") } @@ -986,12 +964,8 @@ H5C2_journal_transaction(H5F_t * f, entry_ptr->size, NULL, H5C2__NO_FLAGS_SET); - if ( thing == NULL ) - { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: H5C2_protect() failed.\n", - FUNC); -#endif /* JRM */ + if ( thing == NULL ) { + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ "H5C2_protect() failed.") } @@ -1001,12 +975,8 @@ H5C2_journal_transaction(H5F_t * f, thing, H5C2__SIZE_CHANGED_FLAG, new_len); - if ( result < 0 ) - { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: H5C2_unprotect() failed.\n", - FUNC); -#endif /* JRM */ + if ( result < 0 ) { + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ "H5C2_unprotect() failed.") } @@ -1014,17 +984,13 @@ H5C2_journal_transaction(H5F_t * f, entry_ptr->image_ptr = new_image_ptr; } - if ( renamed ) - { + if ( renamed ) { + 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 */ + if ( result < 0 ) { + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ "H5C2_rename_entr() failed.") } @@ -1047,10 +1013,6 @@ 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.") } @@ -1067,9 +1029,6 @@ 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.") } @@ -1225,10 +1184,6 @@ H5C2_check_for_journaling(H5F_t * f, FUNC_ENTER_NOAPI(H5C2_check_for_journaling, FAIL) -#if 0 /* JRM */ - HDfprintf(stdout, "%s: entering.\n", FUNC); -#endif /* JRM */ - HDassert( f ); HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); @@ -1245,12 +1200,8 @@ H5C2_check_for_journaling(H5F_t * f, "H5C2_get_journaling_in_progress() failed.") } - if ( cache_ptr->jnl_file_name_len > 0 ) /* journaling was in */ - /* progress */ - { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: journaling was in progress.\n", FUNC); -#endif /* JRM */ + if ( cache_ptr->jnl_file_name_len > 0 ) { /* journaling was in */ + /* progress */ if ( journal_recovered ) { @@ -1259,7 +1210,9 @@ H5C2_check_for_journaling(H5F_t * f, * we were. */ - result = H5C2_unmark_journaling_in_progress(f, dxpl_id, cache_ptr); + result = H5C2_unmark_journaling_in_progress(f, + dxpl_id, + cache_ptr); if ( result != SUCCEED ) { @@ -1284,16 +1237,8 @@ H5C2_check_for_journaling(H5F_t * f, } } -#if 0 /* JRM */ - HDfprintf(stdout, "%s: done.\n", FUNC); -#endif /* JRM */ - done: -#if 0 /* JRM */ - HDfprintf(stdout, "%s: exiting.\n", FUNC); -#endif /* JRM */ - FUNC_LEAVE_NOAPI(ret_value) } /* H5C2_check_for_journaling() */ @@ -1346,21 +1291,12 @@ H5C2_get_journaling_in_progress(const H5F_t * f, FUNC_ENTER_NOAPI_NOINIT(H5C2_get_journaling_in_progress) -#if 0 /* JRM */ - HDfprintf(stdout, "%s: entering.\n", FUNC); -#endif /* JRM */ - HDassert( f ); HDassert( f->shared != NULL ); HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC ); HDassert( cache_ptr->jnl_file_name_len == 0 ); -#if 0 /* JRM */ - HDfprintf(stdout, "%s: f->shared->mdc_jnl_enabled = %d.\n", FUNC, - (int)(f->shared->mdc_jnl_enabled)); -#endif /* JRM */ - if ( f->shared->mdc_jnl_enabled == TRUE ) { if ( f->shared->mdc_jnl_file_name_len <= 0 ) { @@ -1392,16 +1328,8 @@ H5C2_get_journaling_in_progress(const H5F_t * f, } } -#if 0 /* JRM */ - HDfprintf(stdout, "%s: done.\n"); -#endif /* JRM */ - done: -#if 0 /* JRM */ - HDfprintf(stdout, "%s: exiting.\n"); -#endif /* JRM */ - FUNC_LEAVE_NOAPI(ret_value) } /* H5C2_get_journaling_in_progress() */ @@ -1448,9 +1376,7 @@ H5C2_mark_journaling_in_progress(H5F_t * f, herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5C2_mark_journaling_in_progress, FAIL) -#if 0 /* JRM */ - HDfprintf(stdout, "%s: Entering.\n", FUNC); -#endif /* JRM */ + HDassert( f != NULL ); HDassert( f->shared != NULL ); HDassert( ! f->shared->mdc_jnl_enabled ); @@ -1501,39 +1427,19 @@ H5C2_mark_journaling_in_progress(H5F_t * f, journal_file_name_ptr, (size_t)(cache_ptr->jnl_file_name_len + 1)); -#if 0 /* JRM */ - HDfprintf(stdout, "%s: writing superblock extension.\n", FUNC); -#endif /* JRM */ - if ( H5F_super_write_mdj_msg(f, dxpl_id) < 0 ) { HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ "H5F_super_write_mdj_msg() failed.") } -#if 0 /* JRM */ - HDfprintf(stdout, "%s: finished writing superblock extension.\n", FUNC); -#endif /* JRM */ - /* Finally, flush the file to ensure that changes made it to disk. */ -#if 0 /* JRM */ - HDfprintf(stdout, "%s: calling H5F_flush().\n", FUNC); -#endif /* JRM */ - if ( H5F_flush(f, dxpl_id, H5F_SCOPE_GLOBAL, H5F_FLUSH_NONE) < 0 ) { HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, "H5F_flush() failed.") } -#if 0 /* JRM */ - HDfprintf(stdout, "%s: H5F_flush() returns.\n", FUNC); -#endif /* JRM */ - -#if 0 /* JRM */ - HDfprintf(stdout, "%s: Exiting.\n", FUNC); -#endif /* JRM */ - done: FUNC_LEAVE_NOAPI(ret_value) @@ -1585,10 +1491,7 @@ H5C2_unmark_journaling_in_progress(H5F_t * f, herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5C2_unmark_journaling_in_progress, FAIL) -#if 0 /* JRM */ - HDfprintf(stdout, "%s: entering.\n", FUNC); - HDfflush(stdout); -#endif /* JRM */ + HDassert( f != NULL ); HDassert( f->shared != NULL ); HDassert( f->shared->mdc_jnl_enabled ); @@ -1629,28 +1532,13 @@ H5C2_unmark_journaling_in_progress(H5F_t * f, /* Finally, flush the file to ensure that changes made it to disk. */ -#if 0 /* JRM */ - HDfprintf(stdout, "%s: calling H5F_flush().\n", FUNC); - HDfflush(stdout); -#endif /* JRM */ - if ( H5F_flush(f, dxpl_id, H5F_SCOPE_GLOBAL, H5F_FLUSH_NONE) < 0 ) { HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, "H5F_flush() failed.") } -#if 0 /* JRM */ - HDfprintf(stdout, "%s: done.\n", FUNC); - HDfflush(stdout); -#endif /* JRM */ - done: -#if 0 /* JRM */ - HDfprintf(stdout, "%s: exiting.\n", FUNC); - HDfflush(stdout); -#endif /* JRM */ - FUNC_LEAVE_NOAPI(ret_value) } /* H5C2_unmark_journaling_in_progress() */ @@ -1780,16 +1668,10 @@ H5C2_deregister_mdjsc_callback(H5C2_t * cache_ptr, double fraction_in_use; FUNC_ENTER_NOAPI(H5C2_deregister_mdjsc_callback, FAIL) -#if 0 /* JRM */ - HDfprintf(stdout, "entering %s: idx = %d.\n", FUNC, idx); -#endif /* JRM */ if ( ( cache_ptr == NULL ) || ( cache_ptr->magic != H5C2__H5C2_T_MAGIC ) ) { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: cache_ptr corrupt?!?\n", FUNC); -#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ "cache_ptr corrupt?!?"); } @@ -1808,25 +1690,11 @@ H5C2_deregister_mdjsc_callback(H5C2_t * cache_ptr, ( ( cache_ptr->mdjsc_cb_tbl_max_idx_in_use < 0 ) && ( cache_ptr->num_mdjsc_cbs > 0 ) ) ) { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: mdjsc_cb_tbl corrupt(1)?!?!\n", FUNC); - HDfprintf(stdout, "mdjsc_cb_tbl_len = %d\n", - cache_ptr->mdjsc_cb_tbl_len); - HDfprintf(stdout, "num_mdjsc_cbs = %d\n", - cache_ptr->num_mdjsc_cbs); - HDfprintf(stdout, "mdjsc_cb_tbl_fl_head = %d\n", - cache_ptr->mdjsc_cb_tbl_fl_head); - HDfprintf(stdout, "mdjsc_cb_tbl_max_idx_in_use = %d\n", - cache_ptr->mdjsc_cb_tbl_max_idx_in_use); -#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "mdjsc_cb_tbl corrupt(1)?!?!"); } if ( cache_ptr->num_mdjsc_cbs <= 0 ) { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: mdjsc_cb_tbl empty(1)?!?!\n", FUNC); -#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "mdjsc_cb_tbl empty(1)!?!"); } @@ -1834,29 +1702,15 @@ H5C2_deregister_mdjsc_callback(H5C2_t * cache_ptr, ( idx >= cache_ptr->mdjsc_cb_tbl_len ) || ( idx > cache_ptr->mdjsc_cb_tbl_max_idx_in_use ) ) { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: bad fcn_ptr/data_ptr/idx?!?\n", FUNC); - HDfprintf(stdout, "%s: idx = %d.\n", FUNC, idx); - HDfprintf(stdout, "%s: cache_ptr->mdjsc_cb_tbl_len = %d.\n", - FUNC, cache_ptr->mdjsc_cb_tbl_len); - HDfprintf(stdout, "%s: cache_ptr->mdjsc_cb_tbl_max_idx_in_use = %d.\n", - FUNC, cache_ptr->mdjsc_cb_tbl_max_idx_in_use); -#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "bad idx?!?"); } else if ( ((cache_ptr->mdjsc_cb_tbl)[idx]).fcn_ptr == NULL ) { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: callback already deregistered\n", FUNC); -#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ "callback already deregistered"); } else if ( ((cache_ptr->mdjsc_cb_tbl)[idx]).fl_next != -1 ) { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: free list corrupted\n", FUNC); -#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "free list corrupted."); } @@ -1884,9 +1738,6 @@ H5C2_deregister_mdjsc_callback(H5C2_t * cache_ptr, if ( i < 0 ) { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: mdjsc_cb_tbl empty(2)!?!\n", FUNC); -#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ "mdjsc_cb_tbl empty(2)!?!"); } @@ -1912,9 +1763,6 @@ H5C2_deregister_mdjsc_callback(H5C2_t * cache_ptr, ) ) { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: mdjsc_cb_tbl corrupt(2)?!?!\n", FUNC); -#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "mdjsc_cb_tbl corrupt(2)?!?!"); } @@ -1931,10 +1779,6 @@ H5C2_deregister_mdjsc_callback(H5C2_t * cache_ptr, if ( result != SUCCEED ) { -#if 0 /* JRM */ - HDfprintf(stdout, - "%s: H5C2_shrink_mdjsc_callback_table() failed.\n", FUNC); -#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ "H5C2_shrink_mdjsc_callback_table() failed."); } @@ -2065,55 +1909,37 @@ H5C2_register_mdjsc_callback(H5C2_t * cache_ptr, FUNC_ENTER_NOAPI(H5C2_register_mdjsc_callback, FAIL) if ( ( cache_ptr == NULL ) || - ( cache_ptr->magic != H5C2__H5C2_T_MAGIC ) ) - { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: bad cache_ptr on entry.\n", FUNC); -#endif /* JRM */ + ( cache_ptr->magic != H5C2__H5C2_T_MAGIC ) ) { + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "bad cache_ptr on entry"); } - if ( cache_ptr->mdjsc_cb_tbl == NULL ) - { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: cache_ptr->mdjsc_cb_tbl == NULL.\n", FUNC); -#endif /* JRM */ + if ( cache_ptr->mdjsc_cb_tbl == NULL ) { + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ "cache_ptr->mdjsc_cb_tbl == NULL") } - if ( cache_ptr->mdjsc_cb_tbl_len < H5C2__MIN_MDJSC_CB_TBL_LEN ) - { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: cache_ptr->mdjsc_cb_tbl_len too small.\n", FUNC); -#endif /* JRM */ + if ( cache_ptr->mdjsc_cb_tbl_len < H5C2__MIN_MDJSC_CB_TBL_LEN ) { + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ "cache_ptr->mdjsc_cb_tbl_len too small") } if ( ( cache_ptr->mdjsc_cb_tbl_fl_head == -1 ) && - ( cache_ptr->num_mdjsc_cbs < cache_ptr->mdjsc_cb_tbl_len ) ) - { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: mdjsc callback table corrupt?\n", FUNC); -#endif /* JRM */ + ( cache_ptr->num_mdjsc_cbs < cache_ptr->mdjsc_cb_tbl_len ) ) { + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ "mdjsc callback table corrupt?") } - if ( fcn_ptr == NULL ) - { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: fcn_ptr NULL on entry\n", FUNC); -#endif /* JRM */ + if ( fcn_ptr == NULL ) { + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "fcn_ptr NULL on entry") } - if ( idx_ptr == NULL ) - { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: idx_ptr NULL on entry\n", FUNC); -#endif /* JRM */ + if ( idx_ptr == NULL ) { + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "idx_ptr NULL on entry") } @@ -2122,10 +1948,7 @@ H5C2_register_mdjsc_callback(H5C2_t * cache_ptr, result = H5C2_grow_mdjsc_callback_table(cache_ptr); if ( result != SUCCEED ) { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: H5C2_grow_mdjsc_callback_table() failed.\n", - FUNC); -#endif /* JRM */ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ "H5C2_grow_mdjsc_callback_table() failed."); } @@ -2135,16 +1958,6 @@ H5C2_register_mdjsc_callback(H5C2_t * cache_ptr, ( cache_ptr->mdjsc_cb_tbl_fl_head >= cache_ptr->mdjsc_cb_tbl_len ) || ( cache_ptr->num_mdjsc_cbs >= cache_ptr->mdjsc_cb_tbl_len ) ) { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: mdjsc_cb_tbl corrupt(1)?!?!.\n", - FUNC); - HDfprintf(stdout, "%s: cache_ptr->mdjsc_cb_tbl_fl_head = %d.\n", - FUNC, cache_ptr->mdjsc_cb_tbl_fl_head); - HDfprintf(stdout, "%s: cache_ptr->num_mdjsc_cbs = %d.\n", - FUNC, cache_ptr->num_mdjsc_cbs); - HDfprintf(stdout, "%s: cache_ptr->mdjsc_cb_tbl_len = %d.\n", - FUNC, cache_ptr->mdjsc_cb_tbl_len); -#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "mdjsc_cb_tbl corrupt(1)?!?!"); } @@ -2168,10 +1981,6 @@ H5C2_register_mdjsc_callback(H5C2_t * cache_ptr, ) ) { -#if 0 /* JRM */ - HDfprintf(stdout, "%s: mdjsc_cb_tbl corrupt(2)?!?!.", - FUNC); -#endif /* JRM */ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "mdjsc_cb_tbl corrupt(2)?!?!"); } @@ -2258,9 +2067,6 @@ H5C2_shrink_mdjsc_callback_table(H5C2_t * cache_ptr) old_mdjsc_cb_tbl_len = cache_ptr->mdjsc_cb_tbl_len; new_mdjsc_cb_tbl_len = old_mdjsc_cb_tbl_len / 2; -#if 0 /* JRM */ - HDfprintf(stdout, "new_mdjsc_cb_tbl_len = %d.\n", new_mdjsc_cb_tbl_len); -#endif /* JRM */ while ( ( (new_mdjsc_cb_tbl_len / 2) >= H5C2__MIN_MDJSC_CB_TBL_LEN ) && ( (((double)(cache_ptr->num_mdjsc_cbs)) / @@ -2270,9 +2076,6 @@ H5C2_shrink_mdjsc_callback_table(H5C2_t * cache_ptr) cache_ptr->mdjsc_cb_tbl_max_idx_in_use ) ) { new_mdjsc_cb_tbl_len /= 2; -#if 0 /* JRM */ - HDfprintf(stdout, "new_mdjsc_cb_tbl_len = %d.\n", new_mdjsc_cb_tbl_len); -#endif /* JRM */ } if ( ( new_mdjsc_cb_tbl_len < H5C2__MIN_MDJSC_CB_TBL_LEN ) || @@ -2346,156 +2149,173 @@ done: /********************** journal file management code **********************/ /**************************************************************************/ -/****************************************************************************** - * - * Function: H5C2_jb__bin2hex - * - * Programmer: Mike McGreevy - * Tuesday, March 4, 2008 - * - * Purpose: Convert binary data into hexadecimal. - * - * Returns: SUCCEED on success. - * - ******************************************************************************/ - -herr_t -H5C2_jb__bin2hex(const uint8_t * buf, - char * hexdata, - size_t * hexlength, - size_t buf_size) - -{ - size_t v; /* Local index variable */ - uint8_t c; - char * t; - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5C2_jb__bin2hex) - - t = hexdata; - t[0] = ' '; - for (v = 0; v < buf_size; v++) { - - t = &hexdata[v * 3 + 1]; - c = buf[v]; - HDsnprintf(t, (size_t)3, "%02x ", c); - t[2] = ' '; - - } /* end for */ - t[3] = '\n'; - t[4] = 0; - - * hexlength = v * 3 + 2; - - FUNC_LEAVE_NOAPI(SUCCEED) +/* The following macros are wrappers for the low level binary journal file + * functions. They exist, as it is likely that these function will be + * converted into macros once we have asynchronous journal file writes + * running, and by setting up these wrappers now, we will make this + * conversion easier. + */ -} /* end H5C2_jb__bin2hex*/ +#define H5C2_JB_BJF__WRITE_BUFFER(struct_ptr, \ + buf_size, \ + buf_ptr, \ + is_end_trans, \ + trans_num, \ + fail_return) \ +if ( H5C2_jb_bjf__write_buffer((struct_ptr), (buf_size), (buf_ptr), \ + (is_end_trans), (trans_num)) != SUCCEED ) { \ + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (fail_return), \ + "H5C2_jb_bjf__write_buffer() failed."); \ +} + +#define H5C2_jb_BJF__WRITE_CHKSUM(struct_ptr, \ + is_end_trans, \ + trans_num, \ + fail_return) \ +if ( H5C2_jb_bjf__write_chksum((struct_ptr), (is_end_trans), (trans_num)) \ + != SUCCEED ) { \ + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (fail_return), \ + "H5C2_jb_bjf__write_chksum() failed."); \ +} + +#define H5C2_JB_BJF__WRITE_LENGTH(struct_ptr, \ + length, \ + is_end_trans, \ + trans_num, \ + fail_return) \ +if ( H5C2_jb_bjf__write_length((struct_ptr), (length), (is_end_trans), \ + (trans_num)) != SUCCEED ) { \ + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (fail_return), \ + "H5C2_jb_bjf__write_length() failed."); \ +} + +#define H5C2_JB_BJF__WRITE_OFFSET(struct_ptr, \ + offset, \ + is_end_trans, \ + trans_num, \ + fail_return) \ +if ( H5C2_jb_bjf__write_offset((struct_ptr), (offset), (is_end_trans), \ + (trans_num)) != SUCCEED ) { \ + HDfprintf(stdout, "%s: H5C2_jb_bjf__write_offset() failed.\n", FUNC); \ + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (fail_return), \ + "H5C2_jb_bjf__write_offset() failed."); \ +} + +#define H5C2_JB_BJF__WRITE_SIG_AND_VER(struct_ptr, \ + sig_size, \ + sig_ptr, \ + version, \ + keep_chksum, \ + is_end_trans, \ + trans_num, \ + fail_return) \ +if ( H5C2_jb_bjf__write_sig_and_ver((struct_ptr), (sig_size), (sig_ptr), \ + (version), (keep_chksum), \ + (is_end_trans), (trans_num)) \ + != SUCCEED ) { \ + HDfprintf(stdout, "%s: H5C2_jb_bjf__write_sig_and_ver() failed.\n", \ + FUNC); \ + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (fail_return), \ + "H5C2_jb_bjf__write_sig_and_ver() failed."); \ +} + +#define H5C2_JB_BJF__WRITE_TRANS_NUM(struct_ptr, \ + is_end_trans, \ + trans_num, \ + fail_return) \ +if ( H5C2_jb_bjf__write_trans_num((struct_ptr), (is_end_trans), \ + (trans_num)) != SUCCEED ) { \ + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (fail_return), \ + "H5C2_jb_bjf__write_trans_num() failed."); \ +} /****************************************************************************** * - * Function: H5C2_jb__comment + * Function: H5C2_jb_bjf__comment * - * Programmer: Mike McGreevy - * Wednesday, February 6, 2008 + * Programmer: John Mainzer * - * Purpose: Insert the supplied comment in the journal file. This - * call may be ignored if the journal file is machine - * readable. + * Purpose: In the binary journal file format, a comment is + * a no-op. Thus in this function, we simply verify + * that we are in fact writing a binary journal file, + * and then return. * * Returns: SUCCEED on success. * ******************************************************************************/ -herr_t -H5C2_jb__comment(H5C2_jbrb_t * struct_ptr, - const char * comment_ptr) +static herr_t +H5C2_jb_bjf__comment(H5C2_jbrb_t * struct_ptr, + const char * comment_ptr) { - char * temp = NULL; - size_t temp_len; herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI(H5C2_jb__comment, FAIL) + FUNC_ENTER_NOAPI(H5C2_jb_bjf__comment, FAIL) /* Check Arguments */ - HDassert(struct_ptr); - HDassert(comment_ptr); - HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC); - HDassert(struct_ptr->hdf5_file_name); + HDassert( struct_ptr != NULL ); + HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC ); + HDassert( comment_ptr != NULL ); - /* Verify that header message is present in journal file or ring buffer. - * If not, write it. + /* the following really should be an assert, but the FUNC ENTER/LEAVE + * macros are happier if we have at least one call to HGOTO_ERROR(). */ - if ( struct_ptr->header_present == FALSE ) { - - if ( H5C2_jb__write_header_entry(struct_ptr) != SUCCEED ) { - - HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ - "H5C2_jb__write_header_entry() failed.\n") - } - - } /* end if */ - temp_len = HDstrlen(comment_ptr) + 11; - if(NULL == (temp = H5MM_malloc(temp_len + 1))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "allocation of temp buffer failed.") - - /* Write comment message */ - HDsnprintf(temp, (temp_len + 1), "C comment %s\n", comment_ptr); - HDassert(temp_len == HDstrlen(temp)); + if ( struct_ptr->human_readable ) { - if(H5C2_jb__write_to_buffer(struct_ptr, temp_len, temp, FALSE, struct_ptr->cur_trans) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, "H5C2_jb__write_to_buffer() failed.\n") + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "human_readable is TRUE?!?!\n") + } done: - if(NULL != temp) { - temp = H5MM_xfree(temp); - if(NULL != temp) - HDONE_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "free of assembly buffer failed.") - } /* end if */ FUNC_LEAVE_NOAPI(ret_value) -} /* end H5C2_jb__comment */ + +} /* H5C2_jb_bjf__comment() */ /***************************************************************************** * - * Function: H5C2_jb__end_transaction + * Function: H5C2_jb_bjf__end_transaction * - * Programmer: Mike McGreevy - * Wednesday, February 6, 2008 + * Programmer: John Mainzer * * Purpose: Verify that the supplied transaction is in progress, * and that at least one journal entry has been written - * under it. Then construct an end transaction message, - * and write it to the current journal buffer. Make note - * that the supplied transaction is closed, and that no - * transaction is in progress. + * under it. + * + * Then write an end transaction message to the ring + * buffer. + * + * Make note that the supplied transaction is closed, + * and that no transaction is in progress. * * Returns: SUCCEED on success. * + * Changes: None. + * *****************************************************************************/ -herr_t -H5C2_jb__end_transaction(H5C2_jbrb_t * struct_ptr, - uint64_t trans_num) + +static herr_t +H5C2_jb_bjf__end_transaction(H5C2_jbrb_t * struct_ptr, + uint64_t trans_num) { - char temp[25]; 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 */ + FUNC_ENTER_NOAPI(H5C2_jb_bjf__end_transaction, FAIL) + /* Check Arguments */ - HDassert(struct_ptr); - HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC); + HDassert( struct_ptr != NULL ); + HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC ); + HDassert( struct_ptr->human_readable == FALSE ); /* Verify that the supplied transaction is in progress */ if ( ( struct_ptr->trans_in_prog != TRUE ) || ( struct_ptr->cur_trans != trans_num ) ) { HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "Transaction not in progress or bad transaction number.") + "Transaction not in progress or bad transaction number.") } /* end if */ /* Verify that at least one journal entry has been written under @@ -2507,19 +2327,22 @@ H5C2_jb__end_transaction(H5C2_jbrb_t * struct_ptr, "Empty transaction -- at least one journal entry required.") } /* end if */ - - /* Prepare end transaction message */ - HDsnprintf(temp, (size_t)25, "3 end_trans %llu\n", trans_num); - /* Write end transaction message */ - if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(temp), temp, - TRUE, trans_num ) < 0 ) { - - HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ - "H5C2_jb__write_to_buffer() failed.\n") - } /* end if */ - - /* reset boolean flag indicating if at least one journal entry has + H5C2_JB_BJF__WRITE_SIG_AND_VER(struct_ptr, \ + H5C2_BJNL__SIG_LEN, \ + H5C2_BJNL__END_TRANS_SIG, \ + H5C2_BJNL__END_TRANS_VER, \ + /* keep_chksum */ FALSE, \ + /* is_end_trans */ FALSE, \ + trans_num, \ + /* fail_return */ FAIL) + + H5C2_JB_BJF__WRITE_TRANS_NUM(struct_ptr, \ + /* is_end_trans */ TRUE, \ + trans_num, \ + /* fail_return */ FAIL) + + /* reset boolean flag indicating that at least one journal entry has * been written under transaction */ struct_ptr->jentry_written = FALSE; @@ -2531,346 +2354,2166 @@ done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5C2_jb__end_transaction */ +} /* end H5C2_jb_bjf__end_transaction */ /****************************************************************************** * - * Function: H5C2_jb__eoa + * Function: H5C2_jb_bjf__eoa * - * Programmer: Mike McGreevy - * July 29, 2008 + * Programmer: John Mainzer * - * Purpose: Insert the supplied EOA into the journal file. + * Purpose: Write an end of address space message with the + * supplied EOA in binary format to the journal file. + * + * Note that EOA messages are not generated by the + * metadata cache, and thus are not associated with + * transactions. Since H5C2_jb__write_to_buffer() + * expects a transaction number, we use + * struct_ptr->cur_trans and pass is_end_trans + * as FALSE. However, this is just a cluge to + * keep pre-existing code happy. * * Returns: SUCCEED on success. * + * Changes: None. + * ******************************************************************************/ -herr_t -H5C2_jb__eoa(H5C2_jbrb_t * struct_ptr, +static herr_t +H5C2_jb_bjf__eoa(H5C2_jbrb_t * struct_ptr, haddr_t eoa) { - char temp[41]; - size_t temp_len = 41; herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI(H5C2_jb__eoa, FAIL) + FUNC_ENTER_NOAPI(H5C2_jb_bjf__eoa, FAIL) /* Check Arguments */ - HDassert(struct_ptr); - HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC); - HDassert(struct_ptr->hdf5_file_name); + HDassert( struct_ptr != NULL ); + HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC ); + HDassert( struct_ptr->human_readable == FALSE ); + HDassert( struct_ptr->hdf5_file_name != NULL ); /* Verify that header message is present in journal file or ring buffer. * If not, write it. */ - if(struct_ptr->header_present == FALSE ) { - if(H5C2_jb__write_header_entry(struct_ptr) != SUCCEED) - HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, "H5C2_jb__write_header_entry() failed.\n") + if ( struct_ptr->header_present == FALSE ) { + + if ( H5C2_jb__write_header_entry(struct_ptr) != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__write_header_entry() failed.\n") + } } /* end if */ - /* Write EOA message */ - HDsnprintf(temp, temp_len, "E eoa_value 0x%llx\n", eoa); - HDassert(HDstrlen(temp) < temp_len); + /* Note that EOA messages are not generated by the metadata cache, and + * thus are not associated with transactions. Since + * H5C2_jb__write_to_buffer() expects a transaction number, we use + * struct_ptr->cur_trans and pass is_end_trans as FALSE. However, + * this is just a cluge to keep pre-existing code happy. + */ - if(H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(temp), temp, FALSE, struct_ptr->cur_trans) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, "H5C2_jb__write_to_buffer() failed.\n") + /* Write EOA message */ + H5C2_JB_BJF__WRITE_SIG_AND_VER(struct_ptr, \ + H5C2_BJNL__SIG_LEN, \ + H5C2_BJNL__END_ADDR_SPACE_SIG, \ + H5C2_BJNL__END_ADDR_SPACE_VER, \ + /* keep_chksum */ FALSE, \ + /* is_end_trans */ FALSE, \ + struct_ptr->cur_trans, \ + /* fail_return */ FAIL) + + H5C2_JB_BJF__WRITE_OFFSET(struct_ptr, \ + eoa, \ + /* is_end_trans */ FALSE, \ + struct_ptr->cur_trans, \ + /* fail_return */ FAIL) done: + FUNC_LEAVE_NOAPI(ret_value) -} /* end H5C2_jb__eoa */ + +} /* end H5C2_jb_bjf__eoa */ /****************************************************************************** * - * Function: H5C2_jb__flush + * Function: H5C2_jb_bjf__journal_entry * - * Programmer: Mike McGreevy - * Wednesday, February 6, 2008 + * Programmer: John Mainzer * - * Purpose: Verify that there is no transaction in progress. Then - * flush all journal entries in the journal buffers to the - * journal file. Do not return until all entries are on - * disk. + * Purpose: Verify that the specified transaction is open. Then + * write a binary journal file message to the ring buffer. * * Returns: SUCCEED on success. * ******************************************************************************/ -herr_t -H5C2_jb__flush(H5C2_jbrb_t * struct_ptr) +static herr_t +H5C2_jb_bjf__journal_entry(H5C2_jbrb_t * struct_ptr, + uint64_t trans_num, + haddr_t base_addr, + size_t length, + const uint8_t * body) { - int result; - int i; herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI(H5C2_jb__flush, FAIL) + FUNC_ENTER_NOAPI(H5C2_jb_bjf__journal_entry, FAIL) /* Check Arguments */ HDassert(struct_ptr); HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC); - - /* Check if transaction is in progress */ + HDassert(struct_ptr->human_readable == FALSE ); - if (struct_ptr->trans_in_prog != FALSE) { + /* Verify that the supplied transaction is in progress */ + if ( ( struct_ptr->trans_in_prog != TRUE ) || + ( struct_ptr->cur_trans != trans_num ) ) { HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "Attempt to flush buffers with transaction in progress.") + "Transaction not in progress or bad transaction number.") } /* end if */ - if (struct_ptr->get > struct_ptr->put) { - - /* write from get through end of buffer */ - result = HDwrite(struct_ptr->journal_file_fd, - (*struct_ptr->buf)[struct_ptr->get], - (struct_ptr->num_bufs - struct_ptr->get) * struct_ptr->buf_size); - - if ( result == -1 ) { + H5C2_JB_BJF__WRITE_SIG_AND_VER(struct_ptr, \ + H5C2_BJNL__SIG_LEN, \ + H5C2_BJNL__JOURNAL_ENTRY_SIG, \ + H5C2_BJNL__JOURNAL_ENTRY_VER, \ + /* keep_chksum */ TRUE, \ + /* is_end_trans */ FALSE, \ + trans_num, \ + /* fail_return */ FAIL) + + H5C2_JB_BJF__WRITE_TRANS_NUM(struct_ptr, \ + /* is_end_trans */ FALSE, \ + trans_num, \ + /* fail_return */ FAIL) + + H5C2_JB_BJF__WRITE_OFFSET(struct_ptr, \ + base_addr, \ + /* is_end_trans */ FALSE, \ + trans_num, \ + /* fail_return */ FAIL) + + H5C2_JB_BJF__WRITE_LENGTH(struct_ptr, \ + length, \ + /* is_end_trans */ FALSE, \ + trans_num, \ + /* fail_return */ FAIL) + + H5C2_JB_BJF__WRITE_BUFFER(struct_ptr, \ + /* buf_size */ length, \ + /* buf_ptr */ (const char *)body, \ + /* is_end_trans */ FALSE, \ + trans_num, \ + /* fail_return */ FAIL) + + H5C2_jb_BJF__WRITE_CHKSUM(struct_ptr, \ + /* is_end_trans */ FALSE, \ + trans_num, \ + /* fail_return */ FAIL) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \ - "Journal file write failed(1).") - } - - struct_ptr->bufs_in_use -= (struct_ptr->num_bufs - struct_ptr->get); - struct_ptr->rb_free_space += (struct_ptr->num_bufs - struct_ptr->get) * struct_ptr->buf_size; - struct_ptr->get = 0; - - } /* end if */ + /* Indicate that at least one journal entry has been written under + * this transaction + */ + struct_ptr->jentry_written = TRUE; - if (struct_ptr->get < struct_ptr->put) { - /* write from get up to, but not including, put */ - result = HDwrite(struct_ptr->journal_file_fd, - (*struct_ptr->buf)[struct_ptr->get], - (struct_ptr->put - struct_ptr->get) * struct_ptr->buf_size); +done: - if ( result == -1 ) { + FUNC_LEAVE_NOAPI(ret_value) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \ - "Journal file write failed (2).") - } +} /* H5C2_jb_bjf__journal_entry() */ - struct_ptr->bufs_in_use -= (struct_ptr->put - struct_ptr->get); - struct_ptr->rb_free_space += (struct_ptr->put - struct_ptr->get) * struct_ptr->buf_size; - struct_ptr->get = struct_ptr->put; + +/****************************************************************************** + * + * Function: H5C2_jb_bjf__start_transaction + * + * Programmer: John Mainzer + * + * Purpose: Verify that there is no transaction in progress, and + * that the supplied transaction number greater than + * the last. Then write a binary start transaction + * message to the ring buffer. Make note of the fact + * that the supplied transaction is in progress. + * + * Returns: SUCCEED on success. + * + * Changes: None + * + ******************************************************************************/ - } /* end if */ +static herr_t +H5C2_jb_bjf__start_transaction(H5C2_jbrb_t * struct_ptr, + uint64_t trans_num) - if ( struct_ptr->cur_buf_free_space != struct_ptr->buf_size ) { +{ + herr_t ret_value = SUCCEED; - /* flush partially filled portion of current journal buffer to disk */ - result = HDwrite(struct_ptr->journal_file_fd, - (*struct_ptr->buf)[struct_ptr->put], - struct_ptr->buf_size - struct_ptr->cur_buf_free_space); + FUNC_ENTER_NOAPI(H5C2_jb_bjf__start_transaction, FAIL) - if ( result == -1 ) { + /* Check Arguments */ + HDassert(struct_ptr); + HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC); + HDassert(struct_ptr->human_readable == FALSE ); + + /* Verify that there is no transaction in progress */ + if ( struct_ptr->trans_in_prog != FALSE ) { - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \ - "Journal file write failed (3).") - } + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "Transaction already in progress.") + } /* end if */ - struct_ptr->bufs_in_use--; - struct_ptr->rb_free_space += (struct_ptr->buf_size - struct_ptr->cur_buf_free_space); + /* Verify that the supplied transaction number greater than the last */ + if ( (struct_ptr->cur_trans) >= trans_num ) { + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "New transaction out of sequence.") } /* end if */ - HDassert(struct_ptr->bufs_in_use == 0); - HDassert(struct_ptr->rb_free_space == struct_ptr->num_bufs * struct_ptr->buf_size); + /* Verify that header message is present in journal file or ring buffer. + * If not, write it. + */ + if ( struct_ptr->header_present == FALSE ) { - /* perform sync to ensure everything gets to disk before returning */ - /* Note: there is no HDfsync function, so for now, the standard - fsync is being used. */ - if(fsync(struct_ptr->journal_file_fd) < 0) - HGOTO_ERROR(H5E_IO, H5E_SYNCFAIL, FAIL, "Journal file sync failed.") + if ( H5C2_jb__write_header_entry(struct_ptr) != SUCCEED ) { - /* record last transaction number that made it to disk */ - struct_ptr->last_trans_on_disk = - (*struct_ptr->trans_tracking)[struct_ptr->put]; + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__write_header_entry() failed.\n") + } - /* MIKE: optimization note: don't reset to top of ring buffer. - * instead, keep filling out current buffer so we can keep writes - * on block boundaries. - */ - struct_ptr->cur_buf_free_space = struct_ptr->buf_size; - struct_ptr->rb_space_to_rollover = struct_ptr->num_bufs * struct_ptr->buf_size; - struct_ptr->head = (*struct_ptr->buf)[0]; - struct_ptr->put = 0; + } /* end if */ - /* Propogate the last transaction on in the buffers throughout the - * transaction tracking array. */ - for(i = 0; i < struct_ptr->num_bufs; i++) - (*struct_ptr->trans_tracking)[i] = struct_ptr->last_trans_on_disk; - /* update get index */ - struct_ptr->get = struct_ptr->put; + /* Write start transaction message */ + H5C2_JB_BJF__WRITE_SIG_AND_VER(struct_ptr, \ + H5C2_BJNL__SIG_LEN, \ + H5C2_BJNL__BEGIN_TRANS_SIG, \ + H5C2_BJNL__BEGIN_TRANS_VER, \ + /* keep_chksum */ FALSE, \ + /* is_end_trans */ FALSE, \ + trans_num, \ + /* fail_return */ FAIL) + + H5C2_JB_BJF__WRITE_TRANS_NUM(struct_ptr, \ + /* is_end_trans */ FALSE, \ + trans_num, \ + /* fail_return */ FAIL) + + /* Make note of the fact that supplied transaction is in progress */ + struct_ptr->trans_in_prog = TRUE; + struct_ptr->cur_trans = trans_num; done: + FUNC_LEAVE_NOAPI(ret_value) -} /* end H5C2_jb__flush */ + +} /* end H5C2_jb_bjf__start_transaction */ /****************************************************************************** * - * Function: H5C2_jb__flush_full_buffers + * Function: H5C2_jb_bjf__write_buf * - * Programmer: Mike McGreevy - * Wednesday, February 6, 2008 + * Programmer: John Mainzer + * 4/24/09 * - * Purpose: Flush all the dirtied buffers in the ring buffer - * starting with the buffer referenced by struct_ptr->get - * and ending with the buffer right before the one - * referenced by struct_ptr->put. + * Purpose: Copy the supplied buffer to the ring buffer as + * efficiently as possible. + * + * If there is space available in the current buffer in + * the ring buffer is big enough, just memcpy the + * supplied buffer directly into the ring buffer buffer + * and update its fields accordingly. + * + * If the supplied buffer will cross ring buffer buffer + * boundaries, for now just call + * H5C2_jb__write_to_buffer(). + * + * In either case, if struct_ptr->chksum_cur_msg is TRUE, + * update struct_ptr->msg_chksum. + * + * Note that this function will probably prove to be + * a hot spot in profiling, so we should more or less + * plan on converting it into a macro at some point. * * Returns: SUCCEED on success. + * FAIL on failure. + * + * Changes: None. * ******************************************************************************/ -herr_t -H5C2_jb__flush_full_buffers(H5C2_jbrb_t * struct_ptr) +static herr_t +H5C2_jb_bjf__write_buffer(H5C2_jbrb_t * struct_ptr, + size_t buf_size, + const char * buf_ptr, + hbool_t is_end_trans, + uint64_t trans_num) { - int result; - herr_t ret_value = SUCCEED; + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5C2_jb__flush_full_buffers, FAIL) + FUNC_ENTER_NOAPI(H5C2_jb_bjf__write_buffer, FAIL) - /* this asserts that at least one buffer is in use */ - HDassert(struct_ptr->bufs_in_use > 0); - /* write an assert to verify that at least one buffer is full */ - HDassert( (struct_ptr->put != struct_ptr->get) || - (struct_ptr->rb_free_space == 0) ); + HDassert( struct_ptr != NULL ); + HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC ); + HDassert( buf_size > 0 ); + HDassert( buf_ptr != NULL ); + HDassert( trans_num > 0 ); - /* flush all full, dirtied journal buffers to disk */ - if (struct_ptr->get < struct_ptr->put) { + /* is_end_trans must be FALSE if struct_ptr->chksum_cur_msg is TRUE. + * Throw an error if this invarient doesn't hold. + */ - /* can write solid chunk from get up to, but not - * including, put - */ - result = HDwrite(struct_ptr->journal_file_fd, - (*struct_ptr->buf)[struct_ptr->get], - (struct_ptr->put - struct_ptr->get) * - struct_ptr->buf_size); + if ( ( is_end_trans ) && ( struct_ptr->chksum_cur_msg ) ) { - if ( result == -1 ) { + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "is_end_trans and struct_ptr->chksum_cur_msg both true.") + } - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \ - "Journal file write failed (1).") - } + /* Update the check sum if required */ + if ( struct_ptr->chksum_cur_msg ) { - struct_ptr->bufs_in_use -= (struct_ptr->put - struct_ptr->get); - struct_ptr->rb_free_space += (struct_ptr->put - struct_ptr->get) * struct_ptr->buf_size; + struct_ptr->msg_chksum = H5_checksum_metadata((const void *)(buf_ptr), + buf_size, + struct_ptr->msg_chksum); + } - } /* end if */ + if ( buf_size < struct_ptr->cur_buf_free_space ) { - else { + /* If the buffer will fit in the current ring buffer buffer with space + * left over, just memcpy() it in and touch up the ring buffer + * fields accordingly. + * + * This is the common case, so when we convert this function into + * a macro, this will allow us to avoid a function call in the vast + * majority of cases. + */ - /* write from get through end of buffer */ - result = HDwrite(struct_ptr->journal_file_fd, - (*struct_ptr->buf)[struct_ptr->get], - (struct_ptr->num_bufs - struct_ptr->get) * struct_ptr->buf_size); + /* write data into journal buffer */ + HDmemcpy(struct_ptr->head, (const void *)buf_ptr, buf_size); - if ( result == -1 ) { + /* increment bufs_in_use as necessary */ + if ( ( struct_ptr->bufs_in_use == 0 ) ) { - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \ - "Journal file write failed (2).") + struct_ptr->bufs_in_use++; } - struct_ptr->bufs_in_use -= (struct_ptr->num_bufs - struct_ptr->get); - struct_ptr->rb_free_space += (struct_ptr->num_bufs - struct_ptr->get) * - struct_ptr->buf_size; + /* update head pointer */ + struct_ptr->head = &(struct_ptr->head[buf_size]); - /* if put = 0, then everything that needs to be flushed will have been - * flushed, so we can stop here. Otherwise, need to flush all buffers - * from the start of the ring buffer's allocated space up to, but not - * including, the buffer indexed by put. + /* update rb_free_space */ + struct_ptr->rb_free_space -= buf_size; + + /* update current buffer usage */ + struct_ptr->cur_buf_free_space -= buf_size; + + /* update end of buffer space */ + struct_ptr->rb_space_to_rollover -= buf_size; + + if ( is_end_trans == TRUE ) { + + (*struct_ptr->trans_tracking)[struct_ptr->put] = trans_num; + } + + HDassert( struct_ptr->cur_buf_free_space > 0 ); + + } else { + + /* Here, handle the case where the write will reach the edge + * of a ring buffer buffer. This gets a bit more complex, so + * for now at least, we will call H5C2_jb__write_to_buffer(). + * If this proves too costly, further optimizations will be necessary. */ - if (struct_ptr->put != 0) { - result = HDwrite(struct_ptr->journal_file_fd, - (*struct_ptr->buf)[0], - (struct_ptr->put) * struct_ptr->buf_size); + if ( H5C2_jb__write_to_buffer(struct_ptr, buf_size, buf_ptr, + is_end_trans, trans_num) != SUCCEED ) { - if ( result == -1 ) { + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__write_to_buffer() failed.") + } + } - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \ - "Journal file write failed(3).") - } /* end if */ +done: - struct_ptr->rb_free_space += (struct_ptr->put * struct_ptr->buf_size); + FUNC_LEAVE_NOAPI(ret_value) - } /* end if */ +} /* H5C2_jb_bjf__write_buffer() */ + + +/****************************************************************************** + * + * Function: H5C2_jb_bjf__write_chksum + * + * Programmer: John Mainzer + * 4/24/09 + * + * Purpose: Write the checksum of a binary journal file message + * to the ring buffer as eficiently as possible. Note + * that this checksum is computed only on the body of + * the message -- not the signature and version. + * + * If there is space available in the current buffer in + * the ring buffer is big enough, just write the chksum + * directly into the ring buffer buffer and update its + * fields accordingly. + * + * If the chksum will cross ring buffer buffer boundaries, + * for now just call H5C2_jb__write_to_buffer(). + * + * Note that this function will probably prove to be + * a hot spot in profiling, so we should more or less + * plan on converting it into a macro at some point. + * + * Returns: SUCCEED on success. + * FAIL on failure. + * + * Changes: None. + * + ******************************************************************************/ - struct_ptr->bufs_in_use -= struct_ptr->put; +static herr_t +H5C2_jb_bjf__write_chksum(H5C2_jbrb_t * struct_ptr, + hbool_t is_end_trans, + uint64_t trans_num) +{ + herr_t ret_value = SUCCEED; /* Return value */ + uint8_t * p; + const size_t chksum_size = 4; - } /* end else */ - - HDassert(struct_ptr->bufs_in_use <= 1); + FUNC_ENTER_NOAPI(H5C2_jb_bjf__write_chksum, FAIL) - /* update get index */ - struct_ptr->get = struct_ptr->put; - - /* record last transaction number that made it to disk */ - if (struct_ptr->put == 0) { + HDassert( struct_ptr != NULL ); + HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC ); + HDassert( trans_num > 0 ); - struct_ptr->last_trans_on_disk = - (*struct_ptr->trans_tracking)[struct_ptr->num_bufs - 1]; + if ( ! (struct_ptr->chksum_cur_msg) ) { - } else { + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "struct_ptr->chksum_cur_msg is false?!?!.") + } + + if ( chksum_size < struct_ptr->cur_buf_free_space ) { + + /* If the checksum will fit in the current buffer with space + * left over, just write it directly into the buffer, and + * touch up the ring buffer fields accordingly. + * + * This is the common case, so when we convert this function into + * a macro, this will allow us to avoid a function call in the vast + * majority of cases. + */ + + /* write data into journal buffer */ + + p = (uint8_t *)(struct_ptr->head); + + UINT32ENCODE(p, struct_ptr->msg_chksum); + + HDassert( p == ((uint8_t *)(struct_ptr->head + chksum_size)) ); + + /* increment bufs_in_use as necessary */ + if ( ( struct_ptr->bufs_in_use == 0 ) ) { + + struct_ptr->bufs_in_use++; + } + + /* update head pointer */ + struct_ptr->head = &(struct_ptr->head[chksum_size]); + + /* update rb_free_space */ + struct_ptr->rb_free_space -= chksum_size; + + /* update current buffer usage */ + struct_ptr->cur_buf_free_space -= chksum_size; + + /* update end of buffer space */ + struct_ptr->rb_space_to_rollover -= chksum_size; + + if ( is_end_trans == TRUE ) { + + (*struct_ptr->trans_tracking)[struct_ptr->put] = trans_num; + } + + HDassert( struct_ptr->cur_buf_free_space > 0 ); + + } else { + + /* Here, handle the case where the write will reach the edge + * of a buffer. This gets a bit more complex, so for now at + * least, we will construct a buffer containing a binary + * representation of the checksum, and then call + * H5C2_jb__write_to_buffer(). If this proves too costly, + * further optimizations will be necessary. + */ + + uint8_t buf[chksum_size + 1]; + + p = buf; + + UINT32ENCODE(p, struct_ptr->msg_chksum); + + HDassert( p == &(buf[chksum_size]) ); + + if ( H5C2_jb__write_to_buffer(struct_ptr, chksum_size, + (const char *)buf, + is_end_trans, trans_num) != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__write_to_buffer() failed.") + } + } + + /* re-set the checksum computation fields */ + struct_ptr->chksum_cur_msg = FALSE; + struct_ptr->msg_chksum = 0; + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5C2_jb_bjf__write_chksum() */ + + +/****************************************************************************** + * + * Function: H5C2_jb_bjf__write_length + * + * Programmer: John Mainzer + * 4/24/09 + * + * Purpose: Write a HDF5 file length to the ring buffer as + * efficiently as possible. + * + * If the space available in the current buffer in + * the ring buffer is big enough, just encode the + * lenght directly into the buffer and update its + * fields accordingly. + * + * If the binary representation of the length will + * touch buffer boundaries, create a buffer containing + * the binary representation of the length, and then + * call H5C2_jb__write_to_buffer() to handle the write. + * + * In either case, if struct_ptr->chksum_cur_msg is TRUE, + * update struct_ptr->msg_chksum. + * + * Note that this function will probably prove to be + * a hot spot in profiling, so we should more or less + * plan on converting it into a macro at some point. + * + * Returns: SUCCEED on success. + * FAIL on failure. + * + * Changes: None. + * + ******************************************************************************/ + +static herr_t +H5C2_jb_bjf__write_length(H5C2_jbrb_t * struct_ptr, + size_t length, + hbool_t is_end_trans, + uint64_t trans_num) +{ + herr_t ret_value = SUCCEED; /* Return value */ + uint8_t * p; + size_t length_width; + + FUNC_ENTER_NOAPI(H5C2_jb_bjf__write_length, FAIL) + + HDassert( struct_ptr != NULL ); + HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC ); + HDassert( trans_num > 0 ); + + /* is_end_trans must be FALSE if struct_ptr->chksum_cur_msg is TRUE. + * Throw an error if this invarient doesn't hold. + */ + + if ( ( is_end_trans ) && ( struct_ptr->chksum_cur_msg ) ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "is_end_trans and struct_ptr->chksum_cur_msg both true.") + } + + length_width = struct_ptr->length_width; + + HDassert( ( length_width == 2 ) || + ( length_width == 4 ) || + ( length_width == 8 ) ); + + if ( length_width < struct_ptr->cur_buf_free_space ) { + + /* If the offset will fit in the current buffer with space + * left over, just write it directly into the buffer, and + * touch up the ring buffer fields accordingly. + * + * This is the common case, so when we convert this function into + * a macro, this will allow us to avoid a function call in the vast + * majority of cases. + */ + + /* write data into journal buffer */ + + p = (uint8_t *)(struct_ptr->head); + + switch ( length_width ) + { + case 2: + UINT16ENCODE(p, length); + break; + + case 4: + UINT32ENCODE(p, length); + break; + + case 8: + UINT64ENCODE(p, length); + break; + + default: + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "length_width out of range (1).") + break; + } + + HDassert( p == ((uint8_t *)(struct_ptr->head + length_width)) ); + + /* increment bufs_in_use as necessary */ + if ( ( struct_ptr->bufs_in_use == 0 ) ) { + + struct_ptr->bufs_in_use++; + } + + /* Update the check sum if required */ + if ( struct_ptr->chksum_cur_msg ) { + + struct_ptr->msg_chksum = + H5_checksum_metadata((const void *)(struct_ptr->head), + length_width, + struct_ptr->msg_chksum); + } + + /* update head pointer */ + struct_ptr->head = &(struct_ptr->head[length_width]); + + /* update rb_free_space */ + struct_ptr->rb_free_space -= length_width; + + /* update current buffer usage */ + struct_ptr->cur_buf_free_space -= length_width; + + /* update end of buffer space */ + struct_ptr->rb_space_to_rollover -= length_width; + + if ( is_end_trans == TRUE ) { + + (*struct_ptr->trans_tracking)[struct_ptr->put] = trans_num; + } + + HDassert( struct_ptr->cur_buf_free_space > 0 ); + + } else { + + /* Here, handle the case where the write will reach the edge + * of a buffer. This gets a bit more complex, so for now at + * least, we will construct a buffer containing a binary + * representation of the offset, and then call + * H5C2_jb__write_to_buffer(). If this proves too costly, + * further optimizations will be necessary. + */ + + uint8_t buf[17]; // should be big enough for a long time. + + HDassert( length_width < 17 ) ; + + p = buf; + + switch ( length_width ) + { + case 2: + UINT16ENCODE(p, length); + break; + + case 4: + UINT32ENCODE(p, length); + break; + + case 8: + UINT64ENCODE(p, length); + break; + + default: + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "length_width out of range (2).") + break; + } + + HDassert( p == &(buf[length_width]) ); + + if ( H5C2_jb__write_to_buffer(struct_ptr, length_width, + (const char *)buf, + is_end_trans, trans_num) != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__write_to_buffer() failed.") + } + + /* Update the check sum if required */ + if ( struct_ptr->chksum_cur_msg ) { + + struct_ptr->msg_chksum = H5_checksum_metadata((const void *)(buf), + length_width, + struct_ptr->msg_chksum); + } + } + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5C2_jb_bjf__write_length() */ + + +/****************************************************************************** + * + * Function: H5C2_jb_bjf__write_offset + * + * Programmer: John Mainzer + * 4/24/09 + * + * Purpose: Write a HDF5 file offset to the ring buffer as + * efficiently as possible. + * + * If the space available in the current buffer in + * the ring buffer is big enough, just encode the + * offset directly into the buffer and update its + * fields accordingly. + * + * If the binary representation of the offset will + * touch buffer boundaries, create a buffer containing + * the binary representation of the offset, and then + * call H5C2_jb__write_to_buffer() to handle the write. + * + * In either case, if struct_ptr->chksum_cur_msg is TRUE, + * update struct_ptr->msg_chksum. + * + * Note that this function will probably prove to be + * a hot spot in profiling, so we should more or less + * plan on converting it into a macro at some point. + * + * Returns: SUCCEED on success. + * FAIL on failure. + * + * Changes: None. + * + ******************************************************************************/ + +static herr_t +H5C2_jb_bjf__write_offset(H5C2_jbrb_t * struct_ptr, + haddr_t offset, + hbool_t is_end_trans, + uint64_t trans_num) +{ + herr_t ret_value = SUCCEED; /* Return value */ + uint8_t * p; + size_t offset_width; + + FUNC_ENTER_NOAPI(H5C2_jb_bjf__write_offset, FAIL) + + HDassert( struct_ptr != NULL ); + HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC ); + /* eoa messages can be written outside transactions -- so it is + * possible that the trans_num will be 0. Since the trans_num is + * not used unless is_end_trans is TRUE, we make an exception for + * the eoa message. + */ + HDassert( ( ! is_end_trans ) || ( trans_num > 0 ) ); + + /* is_end_trans must be FALSE if struct_ptr->chksum_cur_msg is TRUE. + * Throw an error if this invarient doesn't hold. + */ + + if ( ( is_end_trans ) && ( struct_ptr->chksum_cur_msg ) ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "is_end_trans and struct_ptr->chksum_cur_msg both true.") + } + + offset_width = struct_ptr->offset_width; + + HDassert( ( offset_width == 2 ) || + ( offset_width == 4 ) || + ( offset_width == 8 ) ); + + if ( offset_width < struct_ptr->cur_buf_free_space ) { + + /* If the offset will fit in the current buffer with space + * left over, just write it directly into the buffer, and + * touch up the ring buffer fields accordingly. + * + * This is the common case, so when we convert this function into + * a macro, this will allow us to avoid a function call in the vast + * majority of cases. + */ + + /* write data into journal buffer */ + + p = (uint8_t *)(struct_ptr->head); + + switch ( offset_width ) + { + case 2: + UINT16ENCODE(p, offset); + break; + + case 4: + UINT32ENCODE(p, offset); + break; + + case 8: + UINT64ENCODE(p, offset); + break; + + default: + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "offset_width out of range (1).") + break; + } + + HDassert( p == ((uint8_t *)(struct_ptr->head + offset_width)) ); + + /* increment bufs_in_use as necessary */ + if ( ( struct_ptr->bufs_in_use == 0 ) ) { + + struct_ptr->bufs_in_use++; + } + + /* Update the check sum if required */ + if ( struct_ptr->chksum_cur_msg ) { + + struct_ptr->msg_chksum = + H5_checksum_metadata((const void *)(struct_ptr->head), + offset_width, + struct_ptr->msg_chksum); + } + + /* update head pointer */ + struct_ptr->head = &(struct_ptr->head[offset_width]); + + /* update rb_free_space */ + struct_ptr->rb_free_space -= offset_width; + + /* update current buffer usage */ + struct_ptr->cur_buf_free_space -= offset_width; + + /* update end of buffer space */ + struct_ptr->rb_space_to_rollover -= offset_width; + + if ( is_end_trans == TRUE ) { + + (*struct_ptr->trans_tracking)[struct_ptr->put] = trans_num; + } + + HDassert( struct_ptr->cur_buf_free_space > 0 ); + + } else { + + /* Here, handle the case where the write will reach the edge + * of a buffer. This gets a bit more complex, so for now at + * least, we will construct a buffer containing a binary + * representation of the offset, and then call + * H5C2_jb__write_to_buffer(). If this proves too costly, + * further optimizations will be necessary. + */ + + uint8_t buf[17]; // should be big enough for a long time. + + HDassert( offset_width < 17 ) ; + + p = buf; + + switch ( offset_width ) + { + case 2: + UINT16ENCODE(p, offset); + break; + + case 4: + UINT32ENCODE(p, offset); + break; + + case 8: + UINT64ENCODE(p, offset); + break; + + default: + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "offset_width out of range (2).") + break; + } + + HDassert( p == &(buf[offset_width]) ); + + if ( H5C2_jb__write_to_buffer(struct_ptr, offset_width, + (const char *)buf, + is_end_trans, trans_num) != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__write_to_buffer() failed.") + } + + /* Update the check sum if required */ + if ( struct_ptr->chksum_cur_msg ) { + + struct_ptr->msg_chksum = H5_checksum_metadata((const void *)(buf), + offset_width, + struct_ptr->msg_chksum); + } + + } + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5C2_jb_bjf__write_offset() */ + + +/****************************************************************************** + * + * Function: H5C2_jb_bjf__write_sig_and_ver + * + * Programmer: John Mainzer + * 4/24/09 + * + * Purpose: Write the signature and version of a binary journal + * file message to the ring buffer as efficiently as + * possible. + * + * If there is space available in the current buffer in + * the ring buffer is big enough, just memcpy the + * signature and write the version directly into the + * buffer and update its fields accordingly. + * + * If the signature and version will cross buffer + * boundaries, for now just call + * H5C2_jb__write_to_buffer(). + * + * In either case, if keep_chksum is TRUE, initialize + * struct_ptr->msg_chksum to 0, and set struct_ptr-> + * chksum_cur_msg to TRUE. + * + * Observe that the checksum does not include the + * signature and version. + * + * Note that this function will probably prove to be + * a hot spot in profiling, so we should more or less + * plan on converting it into a macro at some point. + * + * Returns: SUCCEED on success. + * FAIL on failure. + * + * Changes: None. + * + ******************************************************************************/ + +static herr_t +H5C2_jb_bjf__write_sig_and_ver(H5C2_jbrb_t * struct_ptr, + size_t sig_size, + const char * sig_ptr, + const uint8_t version, + hbool_t keep_chksum, + hbool_t is_end_trans, + uint64_t trans_num) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5C2_jb_bjf__write_sig_and_ver, FAIL) + + HDassert( struct_ptr != NULL ); + HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC ); + HDassert( sig_size > 0 ); + HDassert( sig_ptr != NULL ); + HDassert( sig_size == HDstrlen(sig_ptr) ); + HDassert( ! is_end_trans ); + /* eoa messages can occur outside of transactions -- and thus it is + * possible that we will have to process one before any transaction + * has started -- in which case trans_num will be 0. Since the trans_num + * isn't used unless is_end_trans is TRUE, we carve a small exception + * for the eoa message. + */ + HDassert( ( ! is_end_trans ) || ( trans_num > 0 ) ); + + if ( sig_size + 1 < struct_ptr->cur_buf_free_space ) { + + /* If the signature and version will fit in the current buffer + * with space left over, just memcpy()/write it in and touch up + * the ring bufferfields accordingly. + * + * This is the common case, so when we convert this function into + * a macro, this will allow us to avoid a function call in the vast + * majority of cases. + */ + + /* write the signature into journal buffer */ + HDmemcpy(struct_ptr->head, (const void *)sig_ptr, sig_size); + + struct_ptr->head[sig_size] = (char)version; + + /* update head pointer */ + struct_ptr->head = &(struct_ptr->head[sig_size + 1]); + + /* increment bufs_in_use as necessary */ + if ( ( struct_ptr->bufs_in_use == 0 ) ) { + + struct_ptr->bufs_in_use++; + } + + /* update rb_free_space */ + struct_ptr->rb_free_space -= sig_size + 1; + + /* update current buffer usage */ + struct_ptr->cur_buf_free_space -= sig_size + 1; + + /* update end of buffer space */ + struct_ptr->rb_space_to_rollover -= sig_size + 1; + + /* is_end_trans must be false in this call, so just throw an + * error if it is TRUE. + */ + + if ( is_end_trans ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "is_end_trans TRUE when writing signiture.") + } + + HDassert( struct_ptr->cur_buf_free_space > 0 ); + + } else { + + /* Here, handle the case where the write will reach the edge + * of a buffer. This gets a bit more complex, so for now at + * least, we will call H5C2_jb__write_to_buffer(). If this + * proves too costly, further optimizations will be necessary. + */ + + uint8_t buf[sig_size + 2]; + + HDmemcpy(buf, (const void *)sig_ptr, sig_size); + buf[sig_size] = version; + + if ( H5C2_jb__write_to_buffer(struct_ptr, sig_size + 1, + (const char *)buf, + is_end_trans, trans_num) != SUCCEED ) { + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__write_to_buffer() failed.") + } + } + + if ( struct_ptr->chksum_cur_msg ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "struct_ptr->chksum_cur_msg is already TRUE") + } + + if ( keep_chksum ) { + + struct_ptr->chksum_cur_msg = TRUE; + struct_ptr->msg_chksum = 0; + } + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5C2_jb_bjf__write_sig_and_ver() */ + + +/****************************************************************************** + * + * Function: H5C2_jb_bjf__write_trans_num() + * + * Programmer: John Mainzer + * 4/24/09 + * + * Purpose: Write the transaction number in a binary journal file + * message to the ring buffer as efficiently as possible. + * + * If the space available in the current buffer in + * the ring buffer is big enough, just write the + * transaction number directly into the buffer and + * update its fields accordingly. + * + * If the transaction will cross or touch buffer + * boundaries, construct binary representation of the + * transaction number in a buffer, and pass it to + * H5C2_jb__write_to_buffer(). + * + * In either case, if struct_ptr->chksum_cur_msg is TRUE, + * update struct_ptr->msg_chksum. + * + * Note that this function will probably prove to be + * a hot spot in profiling, so we should more or less + * plan on converting it into a macro at some point. + * + * Returns: SUCCEED on success. + * FAIL on failure. + * + * Changes: None. + * + ******************************************************************************/ + +static herr_t +H5C2_jb_bjf__write_trans_num(H5C2_jbrb_t * struct_ptr, + hbool_t is_end_trans, + uint64_t trans_num) +{ + const size_t trans_num_size = 8; + herr_t ret_value = SUCCEED; /* Return value */ + uint8_t * p; + + FUNC_ENTER_NOAPI(H5C2_jb_bjf__write_trans_num, FAIL) + + HDassert( struct_ptr != NULL ); + HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC ); + HDassert( trans_num > 0 ); + + /* is_end_trans must be FALSE if struct_ptr->chksum_cur_msg is TRUE. + * Throw an error if this invarient doesn't hold. + */ + + if ( ( is_end_trans ) && ( struct_ptr->chksum_cur_msg ) ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "is_end_trans and struct_ptr->chksum_cur_msg both true.") + } + + if ( trans_num_size < struct_ptr->cur_buf_free_space ) { + + /* If the transaction number will fit in the current buffer with space + * left over, just write it directly into the buffer, and touch up the + * ring buffer fields accordingly. + * + * This is the common case, so when we convert this function into + * a macro, this will allow us to avoid a function call in the vast + * majority of cases. + */ + + /* write data into journal buffer */ + p = (uint8_t *)(struct_ptr->head); + UINT64ENCODE(p, trans_num); + + HDassert( p == ((uint8_t *)(struct_ptr->head + trans_num_size)) ); + + /* increment bufs_in_use as necessary */ + if ( ( struct_ptr->bufs_in_use == 0 ) ) { + + struct_ptr->bufs_in_use++; + } + + /* Update the check sum if required */ + if ( struct_ptr->chksum_cur_msg ) { + + struct_ptr->msg_chksum = + H5_checksum_metadata((const void *)(struct_ptr->head), + trans_num_size, + struct_ptr->msg_chksum); + } + + /* update head pointer */ + struct_ptr->head = &(struct_ptr->head[trans_num_size]); + + /* update rb_free_space */ + struct_ptr->rb_free_space -= trans_num_size; + + /* update current buffer usage */ + struct_ptr->cur_buf_free_space -= trans_num_size; + + /* update end of buffer space */ + struct_ptr->rb_space_to_rollover -= trans_num_size; + + if ( is_end_trans == TRUE ) { + + (*struct_ptr->trans_tracking)[struct_ptr->put] = trans_num; + } + + HDassert( struct_ptr->cur_buf_free_space > 0 ); + + } else { + + /* Here, handle the case where the write will reach the edge + * of a buffer. This gets a bit more complex, so for now at + * least, we will construct a buffer containing a binary representation + * of the transaction number, and then call H5C2_jb__write_to_buffer(). + * If this proves too costly, further optimizations will be necessary. + */ + + uint8_t buf[trans_num_size + 1]; + + p = buf; + + UINT64ENCODE(p, trans_num); + + HDassert( p == &(buf[trans_num_size]) ); + + if ( H5C2_jb__write_to_buffer(struct_ptr, trans_num_size, + (const char *)buf, + is_end_trans, trans_num) != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__write_to_buffer() failed.") + } + + /* Update the check sum if required */ + if ( struct_ptr->chksum_cur_msg ) { + + struct_ptr->msg_chksum = H5_checksum_metadata((const void *)(buf), + trans_num_size, + struct_ptr->msg_chksum); + } + + } + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5C2_jb_bjf__write_trans_num() */ + + +/****************************************************************************** + * + * Function: H5C2_jb__bin2hex + * + * Programmer: Mike McGreevy + * Tuesday, March 4, 2008 + * + * Purpose: Convert binary data into hexadecimal. + * + * Returns: SUCCEED on success. + * + ******************************************************************************/ + +herr_t +H5C2_jb__bin2hex(const uint8_t * buf, + char * hexdata, + size_t * hexlength, + size_t buf_size) + +{ + size_t v; /* Local index variable */ + uint8_t c; + char * t; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5C2_jb__bin2hex) + + t = hexdata; + t[0] = ' '; + for (v = 0; v < buf_size; v++) { + + t = &hexdata[v * 3 + 1]; + c = buf[v]; + HDsnprintf(t, (size_t)3, "%02x ", c); + t[2] = ' '; + + } /* end for */ + t[3] = '\n'; + t[4] = 0; + + * hexlength = v * 3 + 2; + + FUNC_LEAVE_NOAPI(SUCCEED) + +} /* end H5C2_jb__bin2hex*/ + + +/****************************************************************************** + * + * Function: H5C2_jb__comment + * + * Programmer: Mike McGreevy + * Wednesday, February 6, 2008 + * + * Purpose: Insert the supplied comment in the journal file. This + * call may be ignored if the journal file is machine + * readable. + * + * Returns: SUCCEED on success. + * + * Changes: Turned this function into a switch board function, + * calling either the human readable or the binary + * journal file version of the function as indicated + * by struct_ptr->human_readable. + * + * The original version of this file has been renamed + * to H5C2_jb_hrjf__comment(). + * + * JRM -- 4/2/09 + * + ******************************************************************************/ + +herr_t +H5C2_jb__comment(H5C2_jbrb_t * struct_ptr, + const char * comment_ptr) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5C2_jb__comment, FAIL) + + /* Check Arguments */ + HDassert( struct_ptr != NULL ); + HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC ); + HDassert( comment_ptr != NULL ); + + if ( struct_ptr->human_readable ) { + + if ( H5C2_jb_hrjf__comment(struct_ptr, comment_ptr) != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb_hrjf__comment() failed.") + } + } else { + + if ( H5C2_jb_bjf__comment(struct_ptr, comment_ptr) != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb_bjf__comment() failed.") + } + } + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* end H5C2_jb__comment */ + + +/***************************************************************************** + * + * Function: H5C2_jb__end_transaction + * + * Programmer: Mike McGreevy + * Wednesday, February 6, 2008 + * + * Purpose: Verify that the supplied transaction is in progress, + * and that at least one journal entry has been written + * under it. Then construct an end transaction message, + * and write it to the current journal buffer. Make note + * that the supplied transaction is closed, and that no + * transaction is in progress. + * + * Returns: SUCCEED on success. + * + * Changes: Turned this function into a switch board function, + * calling either the human readable or the binary + * journal file version of the function as indicated + * by struct_ptr->human_readable. + * + * The original version of this file has been renamed + * to H5C2_jb_hrjf__end_transaction(). + * + * JRM -- 4/2/09 + * + *****************************************************************************/ + +herr_t +H5C2_jb__end_transaction(H5C2_jbrb_t * struct_ptr, + uint64_t trans_num) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5C2_jb__end_transaction, FAIL) + + /* Check Arguments */ + HDassert( struct_ptr ); + HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC ); + + if ( struct_ptr->human_readable ) { + + if ( H5C2_jb_hrjf__end_transaction(struct_ptr, trans_num) != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb_hrjf__end_transaction() failed.") + } + } else { + + if ( H5C2_jb_bjf__end_transaction(struct_ptr, trans_num) != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb_bjf__end_transaction() failed.") + } + } + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* end H5C2_jb__end_transaction */ + + +/****************************************************************************** + * + * Function: H5C2_jb__eoa + * + * Programmer: Mike McGreevy + * July 29, 2008 + * + * Purpose: Insert the supplied EOA into the journal file. + * + * Returns: SUCCEED on success. + * + * Changes: Turned this function into a switch board function, + * calling either the human readable or the binary + * journal file version of the function as indicated + * by struct_ptr->human_readable. + * + * The original version of this file has been renamed + * to H5C2_jb_hrjf__eoa(). + * + * JRM -- 4/2/09 + * + ******************************************************************************/ + +herr_t +H5C2_jb__eoa(H5C2_jbrb_t * struct_ptr, + haddr_t eoa) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5C2_jb__eoa, FAIL) + + /* Check Arguments */ + HDassert( struct_ptr ); + HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC ); + HDassert( struct_ptr->hdf5_file_name ); + + if ( struct_ptr->human_readable ) { + + if ( H5C2_jb_hrjf__eoa(struct_ptr, eoa) != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb_hrjf__eoa() failed.") + } + } else { + + if ( H5C2_jb_bjf__eoa(struct_ptr, eoa) != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb_bjf__eoa() failed.") + } + } + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5C2_jb__eoa() */ + + +/****************************************************************************** + * + * Function: H5C2_jb__flush + * + * Programmer: Mike McGreevy + * Wednesday, February 6, 2008 + * + * Purpose: Verify that there is no transaction in progress. Then + * flush all journal entries in the journal buffers to the + * journal file. Do not return until all entries are on + * disk. + * + * Returns: SUCCEED on success. + * + ******************************************************************************/ + +herr_t +H5C2_jb__flush(H5C2_jbrb_t * struct_ptr) +{ + int result; + int i; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5C2_jb__flush, FAIL) + + /* Check Arguments */ + HDassert(struct_ptr); + HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC); + + /* Check if transaction is in progress */ + + if (struct_ptr->trans_in_prog != FALSE) { + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "Attempt to flush buffers with transaction in progress.") + } /* end if */ + + if (struct_ptr->get > struct_ptr->put) { + + /* write from get through end of buffer */ + result = HDwrite(struct_ptr->journal_file_fd, + (*struct_ptr->buf)[struct_ptr->get], + (struct_ptr->num_bufs - struct_ptr->get) * struct_ptr->buf_size); + + if ( result == -1 ) { + + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \ + "Journal file write failed(1).") + } + + struct_ptr->bufs_in_use -= (struct_ptr->num_bufs - struct_ptr->get); + struct_ptr->rb_free_space += (struct_ptr->num_bufs - struct_ptr->get) * struct_ptr->buf_size; + struct_ptr->get = 0; + + } /* end if */ + + if (struct_ptr->get < struct_ptr->put) { + + /* write from get up to, but not including, put */ + result = HDwrite(struct_ptr->journal_file_fd, + (*struct_ptr->buf)[struct_ptr->get], + (struct_ptr->put - struct_ptr->get) * struct_ptr->buf_size); + + if ( result == -1 ) { + + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \ + "Journal file write failed (2).") + } + + struct_ptr->bufs_in_use -= (struct_ptr->put - struct_ptr->get); + struct_ptr->rb_free_space += (struct_ptr->put - struct_ptr->get) * struct_ptr->buf_size; + struct_ptr->get = struct_ptr->put; + + } /* end if */ + + if ( struct_ptr->cur_buf_free_space != struct_ptr->buf_size ) { + + /* flush partially filled portion of current journal buffer to disk */ + result = HDwrite(struct_ptr->journal_file_fd, + (*struct_ptr->buf)[struct_ptr->put], + struct_ptr->buf_size - struct_ptr->cur_buf_free_space); + + if ( result == -1 ) { + + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \ + "Journal file write failed (3).") + } + + struct_ptr->bufs_in_use--; + struct_ptr->rb_free_space += (struct_ptr->buf_size - struct_ptr->cur_buf_free_space); + + } /* end if */ + + HDassert(struct_ptr->bufs_in_use == 0); + HDassert(struct_ptr->rb_free_space == struct_ptr->num_bufs * struct_ptr->buf_size); + + /* perform sync to ensure everything gets to disk before returning */ + /* Note: there is no HDfsync function, so for now, the standard + fsync is being used. */ + if(fsync(struct_ptr->journal_file_fd) < 0) + HGOTO_ERROR(H5E_IO, H5E_SYNCFAIL, FAIL, "Journal file sync failed.") + + /* record last transaction number that made it to disk */ + struct_ptr->last_trans_on_disk = + (*struct_ptr->trans_tracking)[struct_ptr->put]; + + /* MIKE: optimization note: don't reset to top of ring buffer. + * instead, keep filling out current buffer so we can keep writes + * on block boundaries. + */ + struct_ptr->cur_buf_free_space = struct_ptr->buf_size; + struct_ptr->rb_space_to_rollover = struct_ptr->num_bufs * struct_ptr->buf_size; + struct_ptr->head = (*struct_ptr->buf)[0]; + struct_ptr->put = 0; + + /* Propogate the last transaction on in the buffers throughout the + * transaction tracking array. */ + for(i = 0; i < struct_ptr->num_bufs; i++) + (*struct_ptr->trans_tracking)[i] = struct_ptr->last_trans_on_disk; + + /* update get index */ + struct_ptr->get = struct_ptr->put; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5C2_jb__flush */ + + +/****************************************************************************** + * + * Function: H5C2_jb__flush_full_buffers + * + * Programmer: Mike McGreevy + * Wednesday, February 6, 2008 + * + * Purpose: Flush all the dirtied buffers in the ring buffer + * starting with the buffer referenced by struct_ptr->get + * and ending with the buffer right before the one + * referenced by struct_ptr->put. + * + * Returns: SUCCEED on success. + * + ******************************************************************************/ + +herr_t +H5C2_jb__flush_full_buffers(H5C2_jbrb_t * struct_ptr) +{ + int result; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5C2_jb__flush_full_buffers, FAIL) + + /* this asserts that at least one buffer is in use */ + HDassert(struct_ptr->bufs_in_use > 0); + /* write an assert to verify that at least one buffer is full */ + HDassert( (struct_ptr->put != struct_ptr->get) || + (struct_ptr->rb_free_space == 0) ); + + /* flush all full, dirtied journal buffers to disk */ + if (struct_ptr->get < struct_ptr->put) { + + /* can write solid chunk from get up to, but not + * including, put + */ + result = HDwrite(struct_ptr->journal_file_fd, + (*struct_ptr->buf)[struct_ptr->get], + (struct_ptr->put - struct_ptr->get) * + struct_ptr->buf_size); + + if ( result == -1 ) { + + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \ + "Journal file write failed (1).") + } + + struct_ptr->bufs_in_use -= (struct_ptr->put - struct_ptr->get); + struct_ptr->rb_free_space += (struct_ptr->put - struct_ptr->get) * struct_ptr->buf_size; + + } /* end if */ + + else { + + /* write from get through end of buffer */ + result = HDwrite(struct_ptr->journal_file_fd, + (*struct_ptr->buf)[struct_ptr->get], + (struct_ptr->num_bufs - struct_ptr->get) * struct_ptr->buf_size); + + if ( result == -1 ) { + + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \ + "Journal file write failed (2).") + } + + struct_ptr->bufs_in_use -= (struct_ptr->num_bufs - struct_ptr->get); + struct_ptr->rb_free_space += (struct_ptr->num_bufs - struct_ptr->get) * + struct_ptr->buf_size; + + /* if put = 0, then everything that needs to be flushed will have been + * flushed, so we can stop here. Otherwise, need to flush all buffers + * from the start of the ring buffer's allocated space up to, but not + * including, the buffer indexed by put. + */ + if (struct_ptr->put != 0) { + + result = HDwrite(struct_ptr->journal_file_fd, + (*struct_ptr->buf)[0], + (struct_ptr->put) * struct_ptr->buf_size); + + if ( result == -1 ) { + + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \ + "Journal file write failed(3).") + } /* end if */ + + struct_ptr->rb_free_space += (struct_ptr->put * struct_ptr->buf_size); + + } /* end if */ + + struct_ptr->bufs_in_use -= struct_ptr->put; + + } /* end else */ + + HDassert(struct_ptr->bufs_in_use <= 1); + + /* update get index */ + struct_ptr->get = struct_ptr->put; + + /* record last transaction number that made it to disk */ + if (struct_ptr->put == 0) { + + struct_ptr->last_trans_on_disk = + (*struct_ptr->trans_tracking)[struct_ptr->num_bufs - 1]; + + } else { + + struct_ptr->last_trans_on_disk = + (*struct_ptr->trans_tracking)[struct_ptr->put - 1]; + } + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* end H5C2_jb__flush_full_buffers */ + + +/****************************************************************************** + * + * Function: H5C2_jb__get_last_transaction_on_disk + * + * Programmer: Mike McGreevy + * Wednesday, February 6, 2008 + * + * Purpose: Lookup the number of the last transaction to have been + * fully written to disk, and place its transaction + * number in *trans_num_ptr. If no transaction has made + * it to disk, load zero into *trans_num_ptr. + * + * Returns: SUCCEED on success. + * + ******************************************************************************/ + +herr_t +H5C2_jb__get_last_transaction_on_disk(H5C2_jbrb_t * struct_ptr, + uint64_t * trans_num_ptr) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5C2_jb__get_last_transaction_on_disk, FAIL) + + /* Check Arguments */ + HDassert( struct_ptr != NULL ); + HDassert( trans_num_ptr != NULL ); + HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC ); + + /* JRM: In machine readable version, lets check to see if a sync is + * necessary, and call it only if it is. + */ + /* perform a sync to ensure everything gets to disk before continuing */ + /* Note: there is no HDfsync function, so for now, the standard + fsync is being used. */ + if(fsync(struct_ptr->journal_file_fd) < 0 ) + HGOTO_ERROR(H5E_IO, H5E_SYNCFAIL, FAIL, "Jounal file sync failed.") + + * trans_num_ptr = struct_ptr->last_trans_on_disk; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5C2_jb__get_last_transaction_on_disk */ + + +/****************************************************************************** + * + * Function: H5C2_jb_hrjf__comment + * + * Programmer: Mike McGreevy + * Wednesday, February 6, 2008 + * + * Purpose: Insert the supplied comment in the journal file. This + * call may be ignored if the journal file is machine + * readable. + * + * Returns: SUCCEED on success. + * + * Changes: Renamed H5C2_jb__comment() to H5C2_jb_hrjf__comment(). + * + * JRM -- 5/2/09 + * + ******************************************************************************/ + +static herr_t +H5C2_jb_hrjf__comment(H5C2_jbrb_t * struct_ptr, + const char * comment_ptr) +{ + char * temp = NULL; + size_t temp_len; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5C2_jb_hrjf__comment, FAIL) + + /* Check Arguments */ + HDassert(struct_ptr); + HDassert(comment_ptr); + HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC); + HDassert(struct_ptr->hdf5_file_name); + + /* Verify that header message is present in journal file or ring buffer. + * If not, write it. + */ + if ( struct_ptr->header_present == FALSE ) { + + if ( H5C2_jb__write_header_entry(struct_ptr) != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__write_header_entry() failed.\n") + } + + } /* end if */ + + temp_len = HDstrlen(comment_ptr) + 11; + if(NULL == (temp = H5MM_malloc(temp_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "allocation of temp buffer failed.") + + /* Write comment message */ + HDsnprintf(temp, (temp_len + 1), "C comment %s\n", comment_ptr); + HDassert(temp_len == HDstrlen(temp)); + + if(H5C2_jb__write_to_buffer(struct_ptr, temp_len, temp, FALSE, struct_ptr->cur_trans) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, "H5C2_jb__write_to_buffer() failed.\n") + +done: + if(NULL != temp) { + temp = H5MM_xfree(temp); + if(NULL != temp) + HDONE_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "free of assembly buffer failed.") + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5C2_jb hrjf__comment() */ + + +/***************************************************************************** + * + * Function: H5C2_jb_hrjf__end_transaction + * + * Programmer: Mike McGreevy + * Wednesday, February 6, 2008 + * + * Purpose: Verify that the supplied transaction is in progress, + * and that at least one journal entry has been written + * under it. Then construct an end transaction message, + * and write it to the current journal buffer. Make note + * that the supplied transaction is closed, and that no + * transaction is in progress. + * + * Returns: SUCCEED on success. + * + * Changes: Renamed H5C2_jb__end_transaction() to + * H5C2_jb_hrjf__end_transaction(). + * JRM -- 5/2/09 + * + *****************************************************************************/ + +static herr_t +H5C2_jb_hrjf__end_transaction(H5C2_jbrb_t * struct_ptr, + uint64_t trans_num) +{ + char temp[25]; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5C2_jb_hrjf__end_transaction, FAIL) + + /* Check Arguments */ + HDassert(struct_ptr); + HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC); + + /* Verify that the supplied transaction is in progress */ + if ( ( struct_ptr->trans_in_prog != TRUE ) || + ( struct_ptr->cur_trans != trans_num ) ) { + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "Transaction not in progress or bad transaction number.") + } /* end if */ + + /* Verify that at least one journal entry has been written under + * the current transaction + */ + if ( struct_ptr->jentry_written != TRUE ) { + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "Empty transaction -- at least one journal entry required.") + } /* end if */ + + + /* Prepare end transaction message */ + HDsnprintf(temp, (size_t)25, "3 end_trans %llu\n", trans_num); + + /* Write end transaction message */ + if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(temp), temp, + TRUE, trans_num ) < 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__write_to_buffer() failed.\n") + } /* end if */ + + /* reset boolean flag indicating if at least one journal entry has + * been written under transaction + */ + struct_ptr->jentry_written = FALSE; + + /* Close current transaction */ + struct_ptr->trans_in_prog = FALSE; + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* end H5C2_jb_hrjf__end_transaction */ + + +/****************************************************************************** + * + * Function: H5C2_jb_hrjf__eoa + * + * Programmer: Mike McGreevy + * July 29, 2008 + * + * Purpose: Insert the supplied EOA into the journal file. + * + * Returns: SUCCEED on success. + * + * Changes: Renamed H5C2_jb__eoa() to H5C2_jb_hrjf__eoa(). + * JRM -- 5/2/09 + * + ******************************************************************************/ + +static herr_t +H5C2_jb_hrjf__eoa(H5C2_jbrb_t * struct_ptr, + haddr_t eoa) +{ + char temp[41]; + size_t temp_len = 41; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5C2_jb_hrjf__eoa, FAIL) + + /* Check Arguments */ + HDassert(struct_ptr); + HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC); + HDassert(struct_ptr->hdf5_file_name); + + /* Verify that header message is present in journal file or ring buffer. + * If not, write it. + */ + if(struct_ptr->header_present == FALSE ) { + if(H5C2_jb__write_header_entry(struct_ptr) != SUCCEED) + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, "H5C2_jb__write_header_entry() failed.\n") + } /* end if */ + + /* Write EOA message */ + HDsnprintf(temp, temp_len, "E eoa_value 0x%llx\n", eoa); + HDassert(HDstrlen(temp) < temp_len); + + if(H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(temp), temp, FALSE, struct_ptr->cur_trans) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, "H5C2_jb__write_to_buffer() failed.\n") + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5C2_jb_hrjf__eoa() */ + + +/****************************************************************************** + * + * Function: H5C2_jb_hrjf__journal_entry + * + * Programmer: Mike McGreevy + * Wednesday, February 6, 2008 + * + * Purpose: Verify that the specified transaction is open. Then + * construct a journal entry recording the supplied base + * address, length, and body, and write it to the current + * journal buffer. + * + * Returns: SUCCEED on success. + * + * Changes: Renamed H5C2_jb__journal_entry() to + * H5C2_jb_hrjf__journal_entry(). + * JRM -- 5/2/09 + * + ******************************************************************************/ + +static herr_t +H5C2_jb_hrjf__journal_entry(H5C2_jbrb_t * struct_ptr, + uint64_t trans_num, + haddr_t base_addr, + size_t length, + const uint8_t * body) +{ + + char * temp = NULL; + char * hexdata = NULL; + size_t hexlength; + herr_t ret_value = SUCCEED; + uint8_t * bodydata; + + FUNC_ENTER_NOAPI(H5C2_jb_hrjf__journal_entry, FAIL) + + /* Check Arguments */ + HDassert(struct_ptr); + HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC); + + /* Make a copy of body data */ + if ( (bodydata = H5MM_malloc(length)) == NULL ) { + + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ + "allocation of assembly buffer failed."); + } + + HDmemcpy(bodydata, body, length); + + /* Verify that the supplied transaction is in progress */ + if ( ( struct_ptr->trans_in_prog != TRUE ) || + ( struct_ptr->cur_trans != trans_num ) ) { + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "Transaction not in progress or bad transaction number.") + } /* end if */ + + if ( (temp = H5MM_malloc(length + 100)) == NULL ) { + + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ + "allocation of assembly buffer failed."); + } + + if ( (hexdata = H5MM_malloc(length * 40)) == NULL ) { + + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ + "allocation of assembly buffer failed."); + } + + /* Write journal entry */ + HDsnprintf(temp, + (size_t)(length + 100), + "2 trans_num %llu length %zu base_addr 0x%lx body ", + trans_num, + length, + (unsigned long)base_addr); + + if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(temp), temp, FALSE, trans_num) < 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__write_to_buffer() failed.\n") + } /* end if */ + + /* Convert data from binary to hex */ + H5C2_jb__bin2hex(bodydata, hexdata, &hexlength, length); + + if ( H5C2_jb__write_to_buffer(struct_ptr, hexlength, hexdata, FALSE, trans_num) < 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__write_to_buffer() failed.\n") + } /* end if */ + + /* Indicate that at least one journal entry has been written under + * this transaction + */ + if ( struct_ptr->jentry_written == FALSE ) { - struct_ptr->last_trans_on_disk = - (*struct_ptr->trans_tracking)[struct_ptr->put - 1]; + struct_ptr->jentry_written = TRUE; } done: + if(bodydata != NULL) { + bodydata = H5MM_xfree(bodydata); + if(bodydata != NULL) + HDONE_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "free of assembly buffer failed.") + } /* end if */ + + if(temp != NULL) { + temp = H5MM_xfree(temp); + if(temp != NULL) + HDONE_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "free of assembly buffer failed.") + } /* end if */ + + if(hexdata != NULL) { + hexdata = H5MM_xfree(hexdata); + if(hexdata != NULL) + HDONE_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "free of assembly buffer failed.") + } /* end if */ FUNC_LEAVE_NOAPI(ret_value) -} /* end H5C2_jb__flush_full_buffers */ +} /* H5C2_jb_hrjf__journal_entry() */ /****************************************************************************** * - * Function: H5C2_jb__get_last_transaction_on_disk + * Function: H5C2_jb_hrjf__start_transaction * * Programmer: Mike McGreevy * Wednesday, February 6, 2008 * - * Purpose: Lookup the number of the last transaction to have been - * fully written to disk, and place its transaction - * number in *trans_num_ptr. If no transaction has made - * it to disk, load zero into *trans_num_ptr. + * Purpose: Verify that there is no transaction in progress, and + * that the supplied transaction number greater than + * the last. Then construct a start transaction message, + * and write it to the current journal buffer. Make note + * of the fact that the supplied transaction is in + * progress. * * Returns: SUCCEED on success. * + * Changes: Renamed H5C2_jb__start_transaction() to + * H5C2_jb_hrjf__start_transaction(). + * JRM -- 5/2/09 + * ******************************************************************************/ -herr_t -H5C2_jb__get_last_transaction_on_disk(H5C2_jbrb_t * struct_ptr, - uint64_t * trans_num_ptr) +static herr_t +H5C2_jb_hrjf__start_transaction(H5C2_jbrb_t * struct_ptr, + uint64_t trans_num) + { + char temp[150]; herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI(H5C2_jb__get_last_transaction_on_disk, FAIL) - + FUNC_ENTER_NOAPI(H5C2_jb_hrjf__start_transaction, FAIL) + /* Check Arguments */ - HDassert( struct_ptr != NULL ); - HDassert( trans_num_ptr != NULL ); - HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC ); + HDassert(struct_ptr); + HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC); + + /* Verify that there is no transaction in progress */ + if ( struct_ptr->trans_in_prog != FALSE ) { - /* JRM: In machine readable version, lets check to see if a sync is - * necessary, and call it only if it is. + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "Transaction already in progress.") + } /* end if */ + + /* JRM: Heads up: we may relax this constraint to rquire that the + * new transaction number is greater than the old, but possibly + * not the next integer in sequence. Will this cause problems + * with testing? */ - /* perform a sync to ensure everything gets to disk before continuing */ - /* Note: there is no HDfsync function, so for now, the standard - fsync is being used. */ - if(fsync(struct_ptr->journal_file_fd) < 0 ) - HGOTO_ERROR(H5E_IO, H5E_SYNCFAIL, FAIL, "Jounal file sync failed.") - * trans_num_ptr = struct_ptr->last_trans_on_disk; + /* Verify that the supplied transaction number greater than the last */ + if ( (struct_ptr->cur_trans) >= trans_num ) { + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "New transaction out of sequence.") + } /* end if */ + + /* Verify that header message is present in journal file or ring buffer. + * If not, write it. + */ + if ( struct_ptr->header_present == FALSE ) { + + if ( H5C2_jb__write_header_entry(struct_ptr) != SUCCEED ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__write_header_entry() failed.\n") + } + + } /* end if */ + + /* Write start transaction message */ + HDsnprintf(temp, (size_t)150, "1 bgn_trans %llu\n", trans_num); + if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(temp), temp, + FALSE, trans_num) < 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__write_to_buffer() failed.\n") + } /* end if */ + + /* Make note of the fact that supplied transaction is in progress */ + struct_ptr->trans_in_prog = TRUE; + struct_ptr->cur_trans = trans_num; done: + FUNC_LEAVE_NOAPI(ret_value) -} /* end H5C2_jb__get_last_transaction_on_disk */ + +} /* H5C2_jb_hrjf__start_transaction() */ /****************************************************************************** @@ -2896,6 +4539,12 @@ done: * the HDF5 file isn't available at this time, wait * until our first real entry to write the header. * + * JRM -- 4/16/09 + * Added the sizeof_addr and sizeof_size parameters, and + * associated code. These parameters must contain the + * values of the same name in the instance of H5F_file_t + * associated with the target file. + * ******************************************************************************/ herr_t @@ -2906,7 +4555,9 @@ H5C2_jb__init(H5C2_jbrb_t * struct_ptr, size_t buf_size, int num_bufs, hbool_t use_aio, - hbool_t human_readable) + hbool_t human_readable, + size_t sizeof_addr, + size_t sizeof_size) { int i; herr_t ret_value = SUCCEED; @@ -2935,6 +4586,10 @@ H5C2_jb__init(H5C2_jbrb_t * struct_ptr, struct_ptr->jentry_written = FALSE; struct_ptr->use_aio = use_aio; struct_ptr->human_readable = human_readable; + struct_ptr->offset_width = (int)sizeof_addr; + struct_ptr->length_width = (int)sizeof_size; + struct_ptr->chksum_cur_msg = FALSE; + struct_ptr->msg_chksum = 0; struct_ptr->journal_is_empty = TRUE; struct_ptr->cur_trans = 0; struct_ptr->last_trans_on_disk = 0; @@ -3023,13 +4678,7 @@ H5C2_jb__init(H5C2_jbrb_t * struct_ptr, /* Define head pointer to point at where we are writing to in the buffer */ struct_ptr->head = (*struct_ptr->buf)[struct_ptr->put]; -#if 0 /* JRM */ - if ( H5C2_jb__write_header_entry(struct_ptr) != SUCCEED ) { - HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ - "H5C2_jb__write_header_entry() failed.\n") - } -#endif /* JRM */ done: FUNC_LEAVE_NOAPI(ret_value) @@ -3051,6 +4700,16 @@ done: * * Returns: SUCCEED on success. * + * Changes: Turned this function into a switch board function, + * calling either the human readable or the binary + * journal file version of the function as indicated + * by struct_ptr->human_readable. + * + * The original version of this file has been renamed + * to H5C2_jb_hrjf__journal_entry(). + * + * JRM -- 4/2/09 + * ******************************************************************************/ herr_t @@ -3068,95 +4727,34 @@ H5C2_jb__journal_entry(H5C2_jbrb_t * struct_ptr, uint8_t * bodydata; 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(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC); - - /* Make a copy of body data */ - if ( (bodydata = H5MM_malloc(length)) == NULL ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ - "allocation of assembly buffer failed."); - } - - HDmemcpy(bodydata, body, length); - - /* Verify that the supplied transaction is in progress */ - if ( ( struct_ptr->trans_in_prog != TRUE ) || - ( struct_ptr->cur_trans != trans_num ) ) { - - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "Transaction not in progress or bad transaction number.") - } /* end if */ - - if ( (temp = H5MM_malloc(length + 100)) == NULL ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ - "allocation of assembly buffer failed."); - } - - if ( (hexdata = H5MM_malloc(length * 40)) == NULL ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ - "allocation of assembly buffer failed."); - } - - /* Write journal entry */ - HDsnprintf(temp, - (size_t)(length + 100), - "2 trans_num %llu length %zu base_addr 0x%lx body ", - trans_num, - length, - (unsigned long)base_addr); - - if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(temp), temp, FALSE, trans_num) < 0 ) { - HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ - "H5C2_jb__write_to_buffer() failed.\n") - } /* end if */ + /* Check Arguments */ + HDassert( struct_ptr != NULL ); + HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC ); - /* Convert data from binary to hex */ - H5C2_jb__bin2hex(bodydata, hexdata, &hexlength, length); + if ( struct_ptr->human_readable ) { - if ( H5C2_jb__write_to_buffer(struct_ptr, hexlength, hexdata, FALSE, trans_num) < 0 ) { + if ( H5C2_jb_hrjf__journal_entry(struct_ptr, trans_num, base_addr, + length, body) != SUCCEED ) { - HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ - "H5C2_jb__write_to_buffer() failed.\n") - } /* end if */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb_hrjf__journal_entry() failed.") + } + } else { - /* Indicate that at least one journal entry has been written under - * this transaction - */ - if ( struct_ptr->jentry_written == FALSE ) { + if ( H5C2_jb_bjf__journal_entry(struct_ptr, trans_num, base_addr, + length, body) != SUCCEED ) { - struct_ptr->jentry_written = TRUE; + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb_bjf__journal_entry() failed.") + } } done: - if(bodydata != NULL) { - bodydata = H5MM_xfree(bodydata); - if(bodydata != NULL) - HDONE_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "free of assembly buffer failed.") - } /* end if */ - - if(temp != NULL) { - temp = H5MM_xfree(temp); - if(temp != NULL) - HDONE_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "free of assembly buffer failed.") - } /* end if */ - - if(hexdata != NULL) { - hexdata = H5MM_xfree(hexdata); - if(hexdata != NULL) - HDONE_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "free of assembly buffer failed.") - } /* end if */ FUNC_LEAVE_NOAPI(ret_value) -} /* end H5C2_jb__journal_entry */ + +} /* H5C2_jb__journal_entry() */ /****************************************************************************** @@ -3175,6 +4773,16 @@ done: * * Returns: SUCCEED on success. * + * Changes: Turned this function into a switch board function, + * calling either the human readable or the binary + * journal file version of the function as indicated + * by struct_ptr->human_readable. + * + * The original version of this file has been renamed + * to H5C2_jb_hrjf__start_transaction(). + * + * JRM -- 4/2/09 + * ******************************************************************************/ herr_t @@ -3182,68 +4790,37 @@ H5C2_jb__start_transaction(H5C2_jbrb_t * struct_ptr, uint64_t trans_num) { - char temp[150]; 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); - - /* Verify that there is no transaction in progress */ - if ( struct_ptr->trans_in_prog != FALSE ) { - - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "Transaction already in progress.") - } /* end if */ - - /* JRM: Heads up: we may relax this constraint to rquire that the - * new transaction number is greater than the old, but possibly - * not the next integer in sequence. Will this cause problems - * with testing? - */ - /* Verify that the supplied transaction number greater than the last */ - if ( (struct_ptr->cur_trans) >= trans_num ) { - - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "New transaction out of sequence.") - } /* end if */ + /* Check Arguments */ + HDassert( struct_ptr != NULL ); + HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC ); - /* Verify that header message is present in journal file or ring buffer. - * If not, write it. - */ - if ( struct_ptr->header_present == FALSE ) { + if ( struct_ptr->human_readable ) { - if ( H5C2_jb__write_header_entry(struct_ptr) != SUCCEED ) { + if ( H5C2_jb_hrjf__start_transaction(struct_ptr, trans_num) + != SUCCEED ) { HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ - "H5C2_jb__write_header_entry() failed.\n") + "H5C2_jb_hrjf__start_transaction() failed.") } + } else { - } /* end if */ - - /* Write start transaction message */ - HDsnprintf(temp, (size_t)150, "1 bgn_trans %llu\n", trans_num); - if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(temp), temp, - FALSE, trans_num) < 0 ) { - - HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ - "H5C2_jb__write_to_buffer() failed.\n") - } /* end if */ - - /* Make note of the fact that supplied transaction is in progress */ - struct_ptr->trans_in_prog = TRUE; - struct_ptr->cur_trans = trans_num; + if ( H5C2_jb_bjf__start_transaction(struct_ptr, trans_num) + != SUCCEED ) { + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb_bjf__start_transaction() failed.") + } + } + done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5C2_jb__start_transaction */ +} /* H5C2_jb__start_transaction() */ /****************************************************************************** @@ -3462,6 +5039,10 @@ done: * Replaced all white space in the creation date * string with underscores. * + * JRM -- 4/16/09 + * Updated function to include the offset and length + * sizes in the header if human_readable is FALSE. + * ******************************************************************************/ herr_t @@ -3544,20 +5125,55 @@ H5C2_jb__write_header_entry(H5C2_jbrb_t * struct_ptr) /* Format the header message in the temporary buffer */ - chars_written = - HDsnprintf(buf, - buf_len - 1, - "0 %s %ld %s %s %s %d %s %10.10s %s %d\n", - H5C2_JNL__VER_NUM_TAG, - struct_ptr->jvers, - H5C2_JNL__TGT_FILE_NAME_TAG, - struct_ptr->hdf5_file_name, - H5C2_JNL__JNL_MAGIC_TAG, - (int)(struct_ptr->journal_magic), - H5C2_JNL__CREATION_DATE_TAG, - time_buf, - H5C2_JNL__HUMAN_READABLE_TAG, - struct_ptr->human_readable); + if ( struct_ptr->human_readable ) { + + chars_written = + HDsnprintf(buf, + buf_len - 1, + "0 %s %ld %s %s %s %d %s %10.10s %s %d\n", + H5C2_JNL__VER_NUM_TAG, + struct_ptr->jvers, + H5C2_JNL__TGT_FILE_NAME_TAG, + struct_ptr->hdf5_file_name, + H5C2_JNL__JNL_MAGIC_TAG, + (int)(struct_ptr->journal_magic), + H5C2_JNL__CREATION_DATE_TAG, + time_buf, + H5C2_JNL__HUMAN_READABLE_TAG, + struct_ptr->human_readable); + + } else { + + /* Only include the offset and length widths in header for a binary + * journal file. Leave this data out of the human readable journal + * file header because: + * + * 1) Everything is in ASCII so it isn't needed, and + * + * 2) If we included it anyway, we would have to update the + * tests for the human readable journal file code. + */ + + chars_written = + HDsnprintf(buf, + buf_len - 1, + "0 %s %ld %s %s %s %d %s %10.10s %s %d %s %d %s %d\n", + H5C2_JNL__VER_NUM_TAG, + struct_ptr->jvers, + H5C2_JNL__TGT_FILE_NAME_TAG, + struct_ptr->hdf5_file_name, + H5C2_JNL__JNL_MAGIC_TAG, + (int)(struct_ptr->journal_magic), + H5C2_JNL__CREATION_DATE_TAG, + time_buf, + H5C2_JNL__HUMAN_READABLE_TAG, + struct_ptr->human_readable, + H5C2_JNL__OFFSET_WIDTH_TAG, + struct_ptr->offset_width, + H5C2_JNL__LENGTH_WIDTH_TAG, + struct_ptr->length_width); + + } if ( chars_written >= buf_len - 1 ) { @@ -3634,7 +5250,8 @@ H5C2_jb__write_to_buffer(H5C2_jbrb_t * struct_ptr, HDassert(struct_ptr); HDassert(data); HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC); - HDassert(HDstrlen(data) == size); + HDassert( ( struct_ptr->human_readable == FALSE ) || + ( HDstrlen(data) == size ) ); HDassert(struct_ptr->rb_space_to_rollover <= struct_ptr->num_bufs * struct_ptr->buf_size); HDassert(struct_ptr->rb_space_to_rollover > 0); @@ -3648,7 +5265,8 @@ H5C2_jb__write_to_buffer(H5C2_jbrb_t * struct_ptr, /* Assertions */ HDassert(size != 0); - HDassert(HDstrlen(data) >= struct_ptr->rb_space_to_rollover); + HDassert( ( struct_ptr->human_readable == FALSE ) || + ( HDstrlen(data) >= struct_ptr->rb_space_to_rollover ) ); /* fill up remaining space in the ring buffer */ HDmemcpy(struct_ptr->head, data, struct_ptr->rb_space_to_rollover); diff --git a/src/H5C2pkg.h b/src/H5C2pkg.h index af3ac81..2c49200 100644 --- a/src/H5C2pkg.h +++ b/src/H5C2pkg.h @@ -110,6 +110,33 @@ * * human_readable: Boolean flag that indicates whether the journal file * is to be human readable or machine readable. + * + * offset_width: If human_readable is FALSE, this field contains the + * width of offsets in the HDF5 file in bytes (as + * specified in the superblock -- sizeof_addr in + * H5F_file_t). + * + * If human_readable is TRUE, this field is undefined. + * + * length_width: If human_readable is FALSE, this field contains the + * width of lengths in the HDF5 file in bytes (as + * specified in the super block -- sizeof_size in + * H5F_file_t). + * + * chksum_cur_msg: Boolean flag that is only defined if human_readable + * is false. It is used to indicate whether the current + * journal message must be checksumed. If true, the + * message checksum to date is stored in the msg_chksum + * (discussed below). + * + * If the journal message is being checksumed, this + * field will be set back to FALSE when the checksum + * of the messages is written to buffer. + * + * msg_chksum: uint32_t used to compile the checksum of a binary + * journal file message. Note that not all messages + * are checksumed -- this field is only defined when + * chksum_cur_msg is TRUE. * * journal_is_empty: Boolean flag that indicates if the journal file * associated with the ring buffer is currently @@ -171,6 +198,22 @@ #define H5C2_JNL__JNL_MAGIC_TAG "journal_magic" #define H5C2_JNL__CREATION_DATE_TAG "creation_date" #define H5C2_JNL__HUMAN_READABLE_TAG "human_readable" +#define H5C2_JNL__OFFSET_WIDTH_TAG "offset_width" +#define H5C2_JNL__LENGTH_WIDTH_TAG "length_width" + +/* signatures and versions used to mark the beginnings of journal file + * messages in binary journal files. + */ + +#define H5C2_BJNL__SIG_LEN ((size_t)(4)) +#define H5C2_BJNL__BEGIN_TRANS_SIG "btrn" +#define H5C2_BJNL__BEGIN_TRANS_VER ((uint8_t)(0)) +#define H5C2_BJNL__JOURNAL_ENTRY_SIG "jent" +#define H5C2_BJNL__JOURNAL_ENTRY_VER ((uint8_t)(0)) +#define H5C2_BJNL__END_TRANS_SIG "etrn" +#define H5C2_BJNL__END_TRANS_VER ((uint8_t)(0)) +#define H5C2_BJNL__END_ADDR_SPACE_SIG "eoas" +#define H5C2_BJNL__END_ADDR_SPACE_VER ((uint8_t)(0)) struct H5C2_jbrb_t { @@ -186,6 +229,10 @@ struct H5C2_jbrb_t hbool_t jentry_written; hbool_t use_aio; hbool_t human_readable; + int offset_width; + int length_width; + hbool_t chksum_cur_msg; + uint32_t msg_chksum; hbool_t journal_is_empty; uint64_t cur_trans; uint64_t last_trans_on_disk; diff --git a/src/H5C2private.h b/src/H5C2private.h index 744f6e9..5ed4254 100644 --- a/src/H5C2private.h +++ b/src/H5C2private.h @@ -1625,7 +1625,9 @@ H5_DLL herr_t H5C2_jb__init(H5C2_jbrb_t * struct_ptr, size_t buf_size, int num_bufs, hbool_t use_aio, - hbool_t human_readable); + hbool_t human_readable, + size_t sizeof_addr, + size_t sizeof_size); H5_DLL herr_t H5C2_jb__start_transaction(H5C2_jbrb_t * struct_ptr, uint64_t trans_num); diff --git a/test/cache2.c b/test/cache2.c index 6f817f6..840865e 100644 --- a/test/cache2.c +++ b/test/cache2.c @@ -9674,11 +9674,7 @@ check_flush_cache__flush_op_test(H5F_t * file_ptr, } else if ( ( cache_ptr->index_len != 0 ) || ( cache_ptr->index_size != 0 ) ) { -#if 0 /* JRM */ - HDfprintf(stdout, "%s:(1) index_len = %ld, index_size = %ld.\n", - fcn_name, (long)(cache_ptr->index_len), - (long)(cache_ptr->index_size)); -#endif /* JRM */ + pass2 = FALSE; HDsnprintf(msg, (size_t)128, diff --git a/test/cache2_api.c b/test/cache2_api.c index dcb1ae2..dc31619 100644 --- a/test/cache2_api.c +++ b/test/cache2_api.c @@ -276,24 +276,6 @@ check_fapl_mdc_api_calls(void) if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); -#if 0 /* JRM */ - /* since this is the test cache, must build the cache explicitly */ - /* remove this when we start using the new cache */ - if ( pass2 ) - { - if ( H5AC2_create(file_ptr, &default_config) != SUCCEED ) { - - pass2 = FALSE; - failure_mssg2 = "Can't construct test cache.\n"; - - } else { - - cache_ptr = file_ptr->shared->cache2; - } - } - - if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); -#endif /* JRM */ /* verify that we can access the internal version of the cache config */ if ( pass2 ) { @@ -463,24 +445,6 @@ check_fapl_mdc_api_calls(void) if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); -#if 0 /* JRM */ - /* since this is the test cache, must build the cache explicitly */ - /* remove this when we start using the new cache */ - if ( pass2 ) - { - if ( H5AC2_create(file_ptr, &default_config) != SUCCEED ) { - - pass2 = FALSE; - failure_mssg2 = "Can't construct test cache.\n"; - - } else { - - cache_ptr = file_ptr->shared->cache2; - } - } - - if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); -#endif /* JRM */ /* verify that we can access the internal version of the cache config */ if ( pass2 ) { @@ -3309,9 +3273,7 @@ check_file_mdc_api_errs(void) size_t cur_size; int cur_num_entries; double hit_rate; -#if 0 /* JRM */ - H5F_t * file_ptr = NULL; -#endif /* JRM */ + H5AC2_cache_config_t default_config = H5AC2__DEFAULT_CACHE_CONFIG; H5AC2_cache_config_t scratch; @@ -3354,32 +3316,7 @@ check_file_mdc_api_errs(void) failure_mssg2 = "H5Fcreate() failed.\n"; } } -#if 0 /* JRM */ - /* get a pointer to the files internal data structure */ - if ( pass2 ) { - - file_ptr = (H5F_t *)H5I_object_verify(file_id, H5I_FILE); - - if ( file_ptr == NULL ) { - - pass2 = FALSE; - failure_mssg2 = "Can't get file_ptr.\n"; - - } - } - - /* since this is the test cache, must build the cache explicitly */ - /* remove this when we start using the new cache */ - if ( pass2 ) - { - if ( H5AC2_create(file_ptr, &default_config) != SUCCEED ) { - - pass2 = FALSE; - failure_mssg2 = "Can't construct test cache.\n"; - } - } -#endif /* JRM */ validate_mdc_config(file_id, &default_config, TRUE, 1); diff --git a/test/cache2_common.c b/test/cache2_common.c index 691792d..c9c49f9 100644 --- a/test/cache2_common.c +++ b/test/cache2_common.c @@ -3212,8 +3212,8 @@ flush_cache2(H5F_t * file_ptr, verify_unprotected2(); if ( show_progress ) { - HDfprintf(stdout, "%s: mile_post = %d.\n", - fcn_name, mile_post++); /* 1 */ + HDfprintf(stdout, "%s: mile_post = %d - %d.\n", + fcn_name, mile_post++, (int)pass2); /* 1 */ } if ( pass2 ) { @@ -3235,8 +3235,8 @@ flush_cache2(H5F_t * file_ptr, } if ( show_progress ) { - HDfprintf(stdout, "%s: mile_post = %d.\n", - fcn_name, mile_post++); /* 2 */ + HDfprintf(stdout, "%s: mile_post = %d - %d.\n", + fcn_name, mile_post++, (int)pass2); /* 2 */ } if ( dump_stats ) { @@ -3245,8 +3245,8 @@ flush_cache2(H5F_t * file_ptr, } if ( show_progress ) { - HDfprintf(stdout, "%s: mile_post = %d.\n", - fcn_name, mile_post++); /* 3 */ + HDfprintf(stdout, "%s: *mile_post = %d - %d.\n", + fcn_name, mile_post++, (int)pass2); /* 3 */ } if ( result < 0 ) { @@ -3256,8 +3256,8 @@ flush_cache2(H5F_t * file_ptr, } if ( show_progress ) { - HDfprintf(stdout, "%s: mile_post = %d.\n", - fcn_name, mile_post++); /* 4 */ + HDfprintf(stdout, "%s: mile_post = %d - %d.\n", + fcn_name, mile_post++, (int)pass2); /* 4 */ } return; @@ -3678,18 +3678,6 @@ rename_entry2(H5C2_t * cache_ptr, ( ( ! ( entry_ptr->header.destroy_in_progress ) ) && ( entry_ptr->header.addr != new_addr ) ) ) { -#if 0 /* 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()."; @@ -4272,17 +4260,6 @@ unprotect_entry2(H5F_t * file_ptr, HDassert( entry_ptr->is_dirty ); } -#if 0 /* JRM */ - if ( entry_ptr->header.is_protected != entry_ptr->is_protected ) { - - HDfprintf(stdout, - "(%d, %d, %d): header.is_protected = %d != is_protected = %d.\n", - type, idx, entry_ptr->ro_ref_count, - (int)(entry_ptr->header.is_protected), - (int)(entry_ptr->is_protected)); - } -#endif /* JRM */ - HDassert( entry_ptr->header.is_protected == entry_ptr->is_protected ); HDassert( entry_ptr->header.is_read_only == entry_ptr->is_read_only ); HDassert( entry_ptr->header.ro_ref_count == entry_ptr->ro_ref_count ); @@ -5985,11 +5962,7 @@ check_and_validate_cache_hit_rate(hid_t file_id, pass2 = FALSE; failure_mssg2 = "unexpected hit rate (1)."; -#if 1 /* JRM */ - HDfprintf(stdout, "actual/expected hit rate = %f/%f.\n", - hit_rate, expected_hit_rate); - HDassert(0); -#endif /* JRM */ + } } diff --git a/test/cache2_jnl_file_marking.c b/test/cache2_jnl_file_marking.c index 89f1e92..3c1b86b 100644 --- a/test/cache2_jnl_file_marking.c +++ b/test/cache2_jnl_file_marking.c @@ -1791,9 +1791,7 @@ setup_mdj_file_marking_on_open_test(hbool_t verbose) /* close the data set, the data space, and the file */ if ( ( H5Dclose(dataset_id) < 0 ) || ( H5Sclose(dataspace_id) < 0 ) || -#if 1 /* JRM */ ( H5Pclose(fapl_id) < 0 ) || -#endif /* JRM */ ( H5Fclose(file_id) < 0 ) ) { pass2 = FALSE; diff --git a/test/cache2_journal.c b/test/cache2_journal.c index 0819cf3..bd1f862 100644 --- a/test/cache2_journal.c +++ b/test/cache2_journal.c @@ -128,7 +128,8 @@ static void open_existing_file_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); + H5C2_t ** cache_ptr_ptr, + hbool_t human_readable); static void open_existing_file_without_journaling(const char * hdf_file_name, hid_t * file_id_ptr, @@ -140,6 +141,7 @@ static void setup_cache_for_journaling(const char * hdf_file_name, hid_t * file_id_ptr, H5F_t ** file_ptr_ptr, H5C2_t ** cache_ptr_ptr, + hbool_t human_readable, hbool_t use_core_driver_if_avail); static void takedown_cache_after_journaling(hid_t file_id, @@ -148,7 +150,8 @@ static void takedown_cache_after_journaling(hid_t file_id, hbool_t use_core_driver_if_avail); static void verify_journal_contents(const char * journal_file_path_ptr, - const char * expected_file_path_ptr); + const char * expected_file_path_ptr, + hbool_t human_readable); static void verify_journal_deleted(const char * journal_file_path_ptr); @@ -207,19 +210,30 @@ static void verify_mdjsc_callback_execution(void); static void verify_mdjsc_callback_registration_deregistration(void); +static void check_binary_message_format(void); + +static void verify_journal_msg(int fd, + uint8_t expected_msg[], + int expected_msg_len, + hbool_t last_msg, + const char * mismatch_failure_msg, + const char * read_failure_msg, + const char * eof_failure_msg, + const char * not_last_msg_msg); + static void check_message_format(void); static void check_legal_calls(void); static void check_transaction_tracking(void); -static void mdj_api_example_test(void); +static void mdj_api_example_test(hbool_t human_readable); -static void mdj_smoke_check_00(void); +static void mdj_smoke_check_00(hbool_t human_readable); -static void mdj_smoke_check_01(void); +static void mdj_smoke_check_01(hbool_t human_readable); -static void mdj_smoke_check_02(void); +static void mdj_smoke_check_02(hbool_t human_readable); static void write_verify_trans_num(H5C2_jbrb_t * struct_ptr, uint64_t trans_num, @@ -1921,6 +1935,9 @@ jrnl_row_major_scan_forward2(H5F_t * file_ptr, * * Modifications: * + * JRM -- 6/10/09 + * Added human readable parameter. + * *------------------------------------------------------------------------- */ @@ -1929,7 +1946,8 @@ open_existing_file_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) + H5C2_t ** cache_ptr_ptr, + hbool_t human_readable) { const char * fcn_name = "open_existing_file_for_journaling()"; hbool_t show_progress = FALSE; @@ -2018,7 +2036,7 @@ open_existing_file_for_journaling(const char * hdf_file_name, jnl_config.jbrb_buf_size = (8 * 1024); jnl_config.jbrb_num_bufs = 2; jnl_config.jbrb_use_aio = FALSE; - jnl_config.jbrb_human_readable = TRUE; + jnl_config.jbrb_human_readable = human_readable; } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); @@ -2291,6 +2309,11 @@ open_existing_file_without_journaling(const char * hdf_file_name, * * Modifications: * + * Added the human_readable parameter and associated + * code to allow selection of either binary or human + * readable journal file. + * JRM -- 5/8/09 + * *------------------------------------------------------------------------- */ @@ -2300,6 +2323,7 @@ setup_cache_for_journaling(const char * hdf_file_name, hid_t * file_id_ptr, H5F_t ** file_ptr_ptr, H5C2_t ** cache_ptr_ptr, + hbool_t human_readable, #if USE_CORE_DRIVER hbool_t use_core_driver_if_avail) #else /* USE_CORE_DRIVER */ @@ -2436,6 +2460,8 @@ setup_cache_for_journaling(const char * hdf_file_name, if ( pass2 ) { + jnl_config.jbrb_human_readable = human_readable; + result = H5Pset_jnl_config(fapl_id, &jnl_config); if ( result < 0 ) { @@ -2651,12 +2677,17 @@ takedown_cache_after_journaling(hid_t file_id, * * Modifications: * + * JRM -- 6/10/09 + * Updated function to deal with binary as well as human + * readable journal files. + * *------------------------------------------------------------------------- */ static void verify_journal_contents(const char * journal_file_path_ptr, - const char * expected_file_path_ptr) + const char * expected_file_path_ptr, + hbool_t human_readable) { const char * fcn_name = "verify_journal_contents()"; char ch; @@ -2690,6 +2721,14 @@ verify_journal_contents(const char * journal_file_path_ptr, } } + if ( ( pass2 ) && ( verbose ) ) { + + HDfprintf(stdout, "%s: *journal_file_path_ptr = \"%s\"\n", + fcn_name, journal_file_path_ptr); + HDfprintf(stdout, "%s: *expected_file_path_ptr = \"%s\"\n", + fcn_name, expected_file_path_ptr); + } + /* get the actual length of the journal file */ if ( pass2 ) { @@ -2923,16 +2962,29 @@ verify_journal_contents(const char * journal_file_path_ptr, if ( pass2 ) { - if ( HDstrcmp(journal_buf, expected_buf) != 0 ) { + if ( human_readable ) { - if ( verbose ) { + if ( HDstrcmp(journal_buf, expected_buf) != 0 ) { + + if ( verbose ) { + + HDfprintf(stdout, + "expected_buf = \"%s\"\n", expected_buf); + HDfprintf(stdout, + "journal_buf = \"%s\"\n", journal_buf); + } - HDfprintf(stdout, "expected_buf = \"%s\"\n", expected_buf); - HDfprintf(stdout, "journal_buf = \"%s\"\n", journal_buf); + failure_mssg2 = "Unexpected journal file contents(2)."; + pass2 = FALSE; } + } else { /* binary journal file -- can't use strcmp() */ - failure_mssg2 = "Unexpected journal file contents(2)."; - pass2 = FALSE; + if ( HDmemcmp(journal_buf, expected_buf, (size_t)cur_buf_len) + != 0 ) { + + failure_mssg2 = "Unexpected journal file contents(2b)."; + pass2 = FALSE; + } } } } @@ -3154,16 +3206,18 @@ verify_journal_empty(const char * journal_file_path_ptr) * Programmer: John Mainzer * 3/11/08 * - * Changes: None. + * Changes: Modified function to run using either a human readable + * or binary journal file. + * JRM -- 5/8/9 * *------------------------------------------------------------------------- */ static void -mdj_smoke_check_00(void) +mdj_smoke_check_00(hbool_t human_readable) { const char * fcn_name = "mdj_smoke_check_00()"; - const char * testfiles[] = + const char * human_readable_testfiles[] = { "testfiles/cache2_journal_sc00_000.jnl", "testfiles/cache2_journal_sc00_001.jnl", @@ -3186,12 +3240,36 @@ mdj_smoke_check_00(void) "testfiles/cache2_journal_sc00_018.jnl", NULL }; + const char * binary_testfiles[] = + { + "testfiles/cache2_journal_bsc00_000.jnl", + "testfiles/cache2_journal_bsc00_001.jnl", + "testfiles/cache2_journal_bsc00_002.jnl", + "testfiles/cache2_journal_bsc00_003.jnl", + "testfiles/cache2_journal_bsc00_004.jnl", + "testfiles/cache2_journal_bsc00_005.jnl", + "testfiles/cache2_journal_bsc00_006.jnl", + "testfiles/cache2_journal_bsc00_007.jnl", + "testfiles/cache2_journal_bsc00_008.jnl", + "testfiles/cache2_journal_bsc00_009.jnl", + "testfiles/cache2_journal_bsc00_010.jnl", + "testfiles/cache2_journal_bsc00_011.jnl", + "testfiles/cache2_journal_bsc00_012.jnl", + "testfiles/cache2_journal_bsc00_013.jnl", + "testfiles/cache2_journal_bsc00_014.jnl", + "testfiles/cache2_journal_bsc00_015.jnl", + "testfiles/cache2_journal_bsc00_016.jnl", + "testfiles/cache2_journal_bsc00_017.jnl", + "testfiles/cache2_journal_bsc00_018.jnl", + NULL + }; + char * ((* testfiles)[]); char filename[512]; char journal_filename[H5AC2__MAX_JOURNAL_FILE_NAME_LEN + 1]; hbool_t testfile_missing = FALSE; hbool_t show_progress = FALSE; hbool_t verbose = FALSE; - hbool_t update_architypes = FALSE; + hbool_t update_architypes; herr_t result; int cp = 0; hid_t file_id = -1; @@ -3199,7 +3277,20 @@ mdj_smoke_check_00(void) H5C2_t * cache_ptr = NULL; H5AC2_jnl_config_t jnl_config; - TESTING("mdj smoke check 00 -- general coverage"); + if ( human_readable ) { + + testfiles = &human_readable_testfiles; + /* set update_architypes to TRUE to generate new architype files */ + update_architypes = FALSE; + TESTING("human readable mdj smoke check 00 -- general coverage"); + + } else { + + testfiles = &binary_testfiles; + /* set update_architypes to TRUE to generate new architype files */ + update_architypes = TRUE; + TESTING("binary mdj smoke check 00 -- general coverage"); + } pass2 = TRUE; @@ -3253,10 +3344,10 @@ mdj_smoke_check_00(void) /* clean out any existing journal file */ HDremove(journal_filename); setup_cache_for_journaling(filename, journal_filename, &file_id, - &file_ptr, &cache_ptr, FALSE); + &file_ptr, &cache_ptr, human_readable, FALSE); if ( show_progress ) - HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); + HDfprintf(stdout, "%s:%d *cp = %d.\n", fcn_name, pass2, cp++); /********************************************************************/ @@ -3271,7 +3362,9 @@ mdj_smoke_check_00(void) 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"); @@ -3280,12 +3373,13 @@ mdj_smoke_check_00(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[0]); + copy_file(journal_filename, (*testfiles)[0]); } - - if ( file_exists(testfiles[0]) ) { - verify_journal_contents(journal_filename, testfiles[0]); + if ( file_exists((*testfiles)[0]) ) { + + verify_journal_contents(journal_filename, (*testfiles)[0], + human_readable); } else { @@ -3360,12 +3454,13 @@ mdj_smoke_check_00(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[1]); + copy_file(journal_filename, (*testfiles)[1]); } - if ( file_exists(testfiles[1]) ) { + if ( file_exists((*testfiles)[1]) ) { - verify_journal_contents(journal_filename, testfiles[1]); + verify_journal_contents(journal_filename, (*testfiles)[1], + human_readable); } else { @@ -3408,12 +3503,13 @@ mdj_smoke_check_00(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[2]); + copy_file(journal_filename, (*testfiles)[2]); } - if ( file_exists(testfiles[2]) ) { + if ( file_exists((*testfiles)[2]) ) { - verify_journal_contents(journal_filename, testfiles[2]); + verify_journal_contents(journal_filename, (*testfiles)[2], + human_readable); } else { @@ -3446,12 +3542,13 @@ mdj_smoke_check_00(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[3]); + copy_file(journal_filename, (*testfiles)[3]); } - if ( file_exists(testfiles[3]) ) { + if ( file_exists((*testfiles)[3]) ) { - verify_journal_contents(journal_filename, testfiles[3]); + verify_journal_contents(journal_filename, (*testfiles)[3], + human_readable); } else { @@ -3494,12 +3591,13 @@ mdj_smoke_check_00(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[4]); + copy_file(journal_filename, (*testfiles)[4]); } - if ( file_exists(testfiles[4]) ) { + if ( file_exists((*testfiles)[4]) ) { - verify_journal_contents(journal_filename, testfiles[4]); + verify_journal_contents(journal_filename, (*testfiles)[4], + human_readable); } else { @@ -3547,12 +3645,13 @@ mdj_smoke_check_00(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[5]); + copy_file(journal_filename, (*testfiles)[5]); } - if ( file_exists(testfiles[5]) ) { + if ( file_exists((*testfiles)[5]) ) { - verify_journal_contents(journal_filename, testfiles[5]); + verify_journal_contents(journal_filename, (*testfiles)[5], + human_readable); } else { @@ -3586,12 +3685,13 @@ mdj_smoke_check_00(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[6]); + copy_file(journal_filename, (*testfiles)[6]); } - if ( file_exists(testfiles[6]) ) { + if ( file_exists((*testfiles)[6]) ) { - verify_journal_contents(journal_filename, testfiles[6]); + verify_journal_contents(journal_filename, (*testfiles)[6], + human_readable); } else { @@ -3637,12 +3737,13 @@ mdj_smoke_check_00(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[7]); + copy_file(journal_filename, (*testfiles)[7]); } - if ( file_exists(testfiles[7]) ) { + if ( file_exists((*testfiles)[7]) ) { - verify_journal_contents(journal_filename, testfiles[7]); + verify_journal_contents(journal_filename, (*testfiles)[7], + human_readable); } else { @@ -3700,12 +3801,13 @@ mdj_smoke_check_00(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[8]); + copy_file(journal_filename, (*testfiles)[8]); } - if ( file_exists(testfiles[8]) ) { + if ( file_exists((*testfiles)[8]) ) { - verify_journal_contents(journal_filename, testfiles[8]); + verify_journal_contents(journal_filename, (*testfiles)[8], + human_readable); } else { @@ -3766,12 +3868,13 @@ mdj_smoke_check_00(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[9]); + copy_file(journal_filename, (*testfiles)[9]); } - if ( file_exists(testfiles[9]) ) { + if ( file_exists((*testfiles)[9]) ) { - verify_journal_contents(journal_filename, testfiles[9]); + verify_journal_contents(journal_filename, (*testfiles)[9], + human_readable); } else { @@ -3836,12 +3939,13 @@ mdj_smoke_check_00(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[10]); + copy_file(journal_filename, (*testfiles)[10]); } - if ( file_exists(testfiles[10]) ) { + if ( file_exists((*testfiles)[10]) ) { - verify_journal_contents(journal_filename, testfiles[10]); + verify_journal_contents(journal_filename, (*testfiles)[10], + human_readable); } else { @@ -3891,12 +3995,13 @@ mdj_smoke_check_00(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[11]); + copy_file(journal_filename, (*testfiles)[11]); } - if ( file_exists(testfiles[11]) ) { + if ( file_exists((*testfiles)[11]) ) { - verify_journal_contents(journal_filename, testfiles[11]); + verify_journal_contents(journal_filename, (*testfiles)[11], + human_readable); } else { @@ -3992,12 +4097,13 @@ mdj_smoke_check_00(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[12]); + copy_file(journal_filename, (*testfiles)[12]); } - if ( file_exists(testfiles[12]) ) { + if ( file_exists((*testfiles)[12]) ) { - verify_journal_contents(journal_filename, testfiles[12]); + verify_journal_contents(journal_filename, (*testfiles)[12], + human_readable); } else { @@ -4021,12 +4127,13 @@ mdj_smoke_check_00(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[13]); + copy_file(journal_filename, (*testfiles)[13]); } - if ( file_exists(testfiles[13]) ) { + if ( file_exists((*testfiles)[13]) ) { - verify_journal_contents(journal_filename, testfiles[13]); + verify_journal_contents(journal_filename, (*testfiles)[13], + human_readable); } else { @@ -4052,12 +4159,13 @@ mdj_smoke_check_00(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[14]); + copy_file(journal_filename, (*testfiles)[14]); } - if ( file_exists(testfiles[14]) ) { + if ( file_exists((*testfiles)[14]) ) { - verify_journal_contents(journal_filename, testfiles[14]); + verify_journal_contents(journal_filename, (*testfiles)[14], + human_readable); } else { @@ -4106,12 +4214,13 @@ mdj_smoke_check_00(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[15]); + copy_file(journal_filename, (*testfiles)[15]); } - if ( file_exists(testfiles[15]) ) { + if ( file_exists((*testfiles)[15]) ) { - verify_journal_contents(journal_filename, testfiles[15]); + verify_journal_contents(journal_filename, (*testfiles)[15], + human_readable); } else { @@ -4137,12 +4246,13 @@ mdj_smoke_check_00(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[16]); + copy_file(journal_filename, (*testfiles)[16]); } - if ( file_exists(testfiles[16]) ) { + if ( file_exists((*testfiles)[16]) ) { - verify_journal_contents(journal_filename, testfiles[16]); + verify_journal_contents(journal_filename, (*testfiles)[16], + human_readable); } else { @@ -4188,7 +4298,7 @@ mdj_smoke_check_00(void) /* c) Re-open the hdf5 file. */ open_existing_file_for_journaling(filename, journal_filename, &file_id, - &file_ptr, &cache_ptr); + &file_ptr, &cache_ptr, human_readable); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); @@ -4208,12 +4318,13 @@ mdj_smoke_check_00(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[17]); + copy_file(journal_filename, (*testfiles)[17]); } - if ( file_exists(testfiles[17]) ) { + if ( file_exists((*testfiles)[17]) ) { - verify_journal_contents(journal_filename, testfiles[17]); + verify_journal_contents(journal_filename, (*testfiles)[17], + human_readable); } else { @@ -4369,12 +4480,13 @@ mdj_smoke_check_00(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[18]); + copy_file(journal_filename, (*testfiles)[18]); } - if ( file_exists(testfiles[18]) ) { + if ( file_exists((*testfiles)[18]) ) { - verify_journal_contents(journal_filename, testfiles[18]); + verify_journal_contents(journal_filename, (*testfiles)[18], + human_readable); } else { @@ -4474,16 +4586,18 @@ mdj_smoke_check_00(void) * Programmer: John Mainzer * 5/19/08 * - * Changes: None. + * Changes: Modified function to run using either a human readable + * or binary journal file. + * JRM -- 5/13/09 * *------------------------------------------------------------------------- */ static void -mdj_smoke_check_01(void) +mdj_smoke_check_01(hbool_t human_readable) { const char * fcn_name = "mdj_smoke_check_01()"; - const char * testfiles[] = + const char * human_readable_testfiles[] = { "testfiles/cache2_journal_sc01_000.jnl", "testfiles/cache2_journal_sc01_001.jnl", @@ -4492,13 +4606,23 @@ mdj_smoke_check_01(void) "testfiles/cache2_journal_sc01_004.jnl", NULL }; + const char * binary_testfiles[] = + { + "testfiles/cache2_journal_bsc01_000.jnl", + "testfiles/cache2_journal_bsc01_001.jnl", + "testfiles/cache2_journal_bsc01_002.jnl", + "testfiles/cache2_journal_bsc01_003.jnl", + "testfiles/cache2_journal_bsc01_004.jnl", + NULL + }; + char * ((* testfiles)[]); char filename[512]; char journal_filename[H5AC2__MAX_JOURNAL_FILE_NAME_LEN + 1]; hbool_t testfile_missing = FALSE; hbool_t show_progress = FALSE; hbool_t dirty_inserts = FALSE; hbool_t verbose = FALSE; - hbool_t update_architypes = FALSE; + hbool_t update_architypes; int dirty_unprotects = FALSE; int dirty_destroys = FALSE; hbool_t display_stats = FALSE; @@ -4509,8 +4633,21 @@ mdj_smoke_check_01(void) hid_t file_id = -1; H5F_t * file_ptr = NULL; H5C2_t * cache_ptr = NULL; - - TESTING("mdj smoke check 01 -- jrnl clean ins, prot, unprot, del, ren"); + + if ( human_readable ) { + + testfiles = &human_readable_testfiles; + /* set update_architypes to TRUE to generate new architype files */ + update_architypes = FALSE; + TESTING("hr mdj smoke check 01 -- jnl clean ins, prot, unprot, del, ren"); + + } else { + + testfiles = &binary_testfiles; + /* set update_architypes to TRUE to generate new architype files */ + update_architypes = FALSE; + TESTING("b mdj smoke check 01 -- jnl clean ins, prot, unprot, del, ren"); + } pass2 = TRUE; @@ -4571,12 +4708,12 @@ mdj_smoke_check_01(void) * * Thus, if we want to use the core file driver when available, we * will either have to remove the end of address space from the - * journal entries, get the different file drivers to aggree on + * journal entries, get the different file drivers to agree on * end of address space, or maintain different sets of architype * files for the different file drivers. */ setup_cache_for_journaling(filename, journal_filename, &file_id, - &file_ptr, &cache_ptr, FALSE); + &file_ptr, &cache_ptr, human_readable, FALSE); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); @@ -4612,12 +4749,13 @@ mdj_smoke_check_01(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[0]); + copy_file(journal_filename, (*testfiles)[0]); } - if ( file_exists(testfiles[0]) ) { + if ( file_exists((*testfiles)[0]) ) { - verify_journal_contents(journal_filename, testfiles[0]); + verify_journal_contents(journal_filename, (*testfiles)[0], + human_readable); } else { @@ -4657,12 +4795,13 @@ mdj_smoke_check_01(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[1]); + copy_file(journal_filename, (*testfiles)[1]); } - if ( file_exists(testfiles[1]) ) { + if ( file_exists((*testfiles)[1]) ) { - verify_journal_contents(journal_filename, testfiles[1]); + verify_journal_contents(journal_filename, (*testfiles)[1], + human_readable); } else { @@ -4702,12 +4841,13 @@ mdj_smoke_check_01(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[2]); + copy_file(journal_filename, (*testfiles)[2]); } - if ( file_exists(testfiles[2]) ) { + if ( file_exists((*testfiles)[2]) ) { - verify_journal_contents(journal_filename, testfiles[2]); + verify_journal_contents(journal_filename, (*testfiles)[2], + human_readable); } else { @@ -4742,12 +4882,13 @@ mdj_smoke_check_01(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[3]); + copy_file(journal_filename, (*testfiles)[3]); } - if ( file_exists(testfiles[3]) ) { + if ( file_exists((*testfiles)[3]) ) { - verify_journal_contents(journal_filename, testfiles[3]); + verify_journal_contents(journal_filename, (*testfiles)[3], + human_readable); } else { @@ -4782,12 +4923,13 @@ mdj_smoke_check_01(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[4]); + copy_file(journal_filename, (*testfiles)[4]); } - if ( file_exists(testfiles[4]) ) { + if ( file_exists((*testfiles)[4]) ) { - verify_journal_contents(journal_filename, testfiles[4]); + verify_journal_contents(journal_filename, (*testfiles)[4], + human_readable); } else { @@ -4852,16 +4994,18 @@ mdj_smoke_check_01(void) * Programmer: John Mainzer * 5/19/08 * - * Changes: None. + * Changes: Modified function to run using either a human readable + * or binary journal file. + * JRM -- 5/13/09 * *------------------------------------------------------------------------- */ static void -mdj_smoke_check_02(void) +mdj_smoke_check_02(hbool_t human_readable) { const char * fcn_name = "mdj_smoke_check_02()"; - const char * testfiles[] = + const char * human_readable_testfiles[] = { "testfiles/cache2_journal_sc02_000.jnl", "testfiles/cache2_journal_sc02_001.jnl", @@ -4870,6 +5014,16 @@ mdj_smoke_check_02(void) "testfiles/cache2_journal_sc02_004.jnl", NULL }; + const char * binary_testfiles[] = + { + "testfiles/cache2_journal_bsc02_000.jnl", + "testfiles/cache2_journal_bsc02_001.jnl", + "testfiles/cache2_journal_bsc02_002.jnl", + "testfiles/cache2_journal_bsc02_003.jnl", + "testfiles/cache2_journal_bsc02_004.jnl", + NULL + }; + char * ((* testfiles)[]); char filename[512]; char journal_filename[H5AC2__MAX_JOURNAL_FILE_NAME_LEN + 1]; hbool_t testfile_missing = FALSE; @@ -4887,8 +5041,21 @@ mdj_smoke_check_02(void) hid_t file_id = -1; H5F_t * file_ptr = NULL; H5C2_t * cache_ptr = NULL; - - TESTING("mdj smoke check 02 -- jrnl dirty ins, prot, unprot, del, ren"); + + if ( human_readable ) { + + testfiles = &human_readable_testfiles; + /* set update_architypes to TRUE to generate new architype files */ + update_architypes = FALSE; + TESTING("hr mdj smoke check 02 -- jnl dirty ins, prot, unprot, del, ren"); + + } else { + + testfiles = &binary_testfiles; + /* set update_architypes to TRUE to generate new architype files */ + update_architypes = FALSE; + TESTING("b mdj smoke check 02 -- jnl dirty ins, prot, unprot, del, ren"); + } pass2 = TRUE; @@ -4954,7 +5121,7 @@ mdj_smoke_check_02(void) * files for the different file drivers. */ setup_cache_for_journaling(filename, journal_filename, &file_id, - &file_ptr, &cache_ptr, FALSE); + &file_ptr, &cache_ptr, human_readable, FALSE); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); @@ -4990,12 +5157,13 @@ mdj_smoke_check_02(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[0]); + copy_file(journal_filename, (*testfiles)[0]); } - if ( file_exists(testfiles[0]) ) { + if ( file_exists((*testfiles)[0]) ) { - verify_journal_contents(journal_filename, testfiles[0]); + verify_journal_contents(journal_filename, (*testfiles)[0], + human_readable); } else { @@ -5035,12 +5203,13 @@ mdj_smoke_check_02(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[1]); + copy_file(journal_filename, (*testfiles)[1]); } - if ( file_exists(testfiles[1]) ) { + if ( file_exists((*testfiles)[1]) ) { - verify_journal_contents(journal_filename, testfiles[1]); + verify_journal_contents(journal_filename, (*testfiles)[1], + human_readable); } else { @@ -5080,12 +5249,13 @@ mdj_smoke_check_02(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[2]); + copy_file(journal_filename, (*testfiles)[2]); } - if ( file_exists(testfiles[2]) ) { + if ( file_exists((*testfiles)[2]) ) { - verify_journal_contents(journal_filename, testfiles[2]); + verify_journal_contents(journal_filename, (*testfiles)[2], + human_readable); } else { @@ -5120,12 +5290,13 @@ mdj_smoke_check_02(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[3]); + copy_file(journal_filename, (*testfiles)[3]); } - if ( file_exists(testfiles[3]) ) { + if ( file_exists((*testfiles)[3]) ) { - verify_journal_contents(journal_filename, testfiles[3]); + verify_journal_contents(journal_filename, (*testfiles)[3], + human_readable); } else { @@ -5160,12 +5331,13 @@ mdj_smoke_check_02(void) if ( update_architypes ) { - copy_file(journal_filename, testfiles[4]); + copy_file(journal_filename, (*testfiles)[4]); } - if ( file_exists(testfiles[4]) ) { + if ( file_exists((*testfiles)[4]) ) { - verify_journal_contents(journal_filename, testfiles[4]); + verify_journal_contents(journal_filename, (*testfiles)[4], + human_readable); } else { @@ -5312,7 +5484,10 @@ mdj_smoke_check_02(void) * * Modifications: * - * None. + * Modified the function to used either the human readable + * or the binary journal file format as directed via the + * new human_readable parameter. + * JRM -- 5/13/09 * *------------------------------------------------------------------------- */ @@ -5323,7 +5498,7 @@ mdj_smoke_check_02(void) #define NUM_RANDOM_ACCESSES 200000 static void -mdj_api_example_test(void) +mdj_api_example_test(hbool_t human_readable) { const char * fcn_name = "mdj_api_example_test()"; char filename[512]; @@ -5350,7 +5525,15 @@ mdj_api_example_test(void) H5AC2_jnl_config_t jnl_config_1; - TESTING("mdj example code"); + if ( human_readable ) { + + TESTING("mdj example code -- human readable journal file"); + + } else { + + TESTING("mdj example code -- binary journal file"); + + } if ( skip_long_tests2 > 0 ) { @@ -5510,7 +5693,7 @@ mdj_api_example_test(void) /* the journal buffer size should be some multiple of the block * size of the underlying file system. */ - jnl_config_0.jbrb_buf_size = (8 * 1024); + jnl_config_0.jbrb_buf_size = (16 * 1024); /* the number of journal buffers should be either 1 or 2 when * synchronous I/O is used for journal writes. If AIO is used, @@ -5525,11 +5708,14 @@ mdj_api_example_test(void) */ jnl_config_0.jbrb_use_aio = FALSE; - /* At present only human readable journal file are supported - * so this field will be TRUE for now. Once it becomes available, - * machine readable journal files should be smaller and faster. - */ - jnl_config_0.jbrb_human_readable = TRUE; + /* set human readable as specified in the human_readable parameter + * to this function. If human_readable is FALSE, we will use + * the binary journal file format which should reduce the size + * of the journal file by about two thirds, and also reduce the + * overhead involved in formating journal entries for writing + * to the journal file. + */ + jnl_config_0.jbrb_human_readable = human_readable; status = H5Pset_jnl_config(fapl_id, &jnl_config_0); @@ -5832,7 +6018,7 @@ mdj_api_example_test(void) * On the other hand, it will impose a significant file I/O * overhead, and slow us down. (try it both ways). */ -#if 1 /* JRM */ +#if 1 status = H5Fflush(file_id, H5F_SCOPE_GLOBAL); if ( status < 0 ) { @@ -5840,7 +6026,7 @@ mdj_api_example_test(void) pass2 = FALSE; failure_mssg2 = "H5Fflush() failed."; } -#endif /* JRM */ +#endif } if ( ( pass2 ) && ( report_progress ) ) { @@ -7139,10 +7325,6 @@ verify_mdjsc_table_config(H5C2_t * cache_ptr, { pass2 = FALSE; failure_mssg2 = "mdjsc callback table len mismatch"; -#if 1 /* JRM */ - HDfprintf(stdout, "cache_ptr->mdjsc_cb_tbl_len = %d(%d).\n", - cache_ptr->mdjsc_cb_tbl_len, table_len); -#endif /* JRM */ } else if ( cache_ptr->num_mdjsc_cbs != num_entries ) { @@ -7151,11 +7333,6 @@ verify_mdjsc_table_config(H5C2_t * cache_ptr, } else if ( cache_ptr->mdjsc_cb_tbl_max_idx_in_use != max_idx_in_use ) { -#if 1 /* JRM */ - HDfprintf(stdout, - "cache_ptr->mdjsc_cb_tbl_max_idx_in_use = %d(%d)\n", - cache_ptr->mdjsc_cb_tbl_max_idx_in_use, max_idx_in_use); -#endif /* JRM */ pass2 = FALSE; failure_mssg2 = "mdjsc callback table max idx in use mismatch"; } @@ -7234,12 +7411,6 @@ verify_mdjsc_table_config(H5C2_t * cache_ptr, pass2 = FALSE; failure_mssg2 = "mdjsc callback table free list shorter than expected."; -#if 1 /* JRM */ - HDfprintf(stdout, "i = %d (%d - %d = %d)\n", i, - table_len, num_entries, (table_len - num_entries)); - HDfprintf(stdout, "cache_ptr->mdjsc_cb_tbl_fl_head = %d.\n", - cache_ptr->mdjsc_cb_tbl_fl_head); -#endif /* JRM */ } else if ( ( record_ptr != NULL ) && ( record_ptr->fl_next != -1 ) ) { @@ -7540,7 +7711,7 @@ verify_mdjsc_callback_error_rejection(void) /* clean out any existing journal file */ HDremove(journal_filename); setup_cache_for_journaling(filename, journal_filename, &file_id, - &file_ptr, &cache_ptr, FALSE); + &file_ptr, &cache_ptr, TRUE, FALSE); if ( show_progress ) { @@ -7934,7 +8105,7 @@ verify_mdjsc_callback_execution(void) /* clean out any existing journal file */ HDremove(journal_filename); setup_cache_for_journaling(filename, journal_filename, &file_id, - &file_ptr, &cache_ptr, FALSE); + &file_ptr, &cache_ptr, TRUE, FALSE); if ( show_progress ) { @@ -9252,7 +9423,7 @@ verify_mdjsc_callback_registration_deregistration(void) /* clean out any existing journal file */ HDremove(journal_filename); setup_cache_for_journaling(filename, journal_filename, &file_id, - &file_ptr, &cache_ptr, FALSE); + &file_ptr, &cache_ptr, TRUE, FALSE); /* 2) Register a callback. Verify that is is added correctly to @@ -10290,6 +10461,10 @@ verify_mdjsc_callback_registration_deregistration(void) * * Programmer: Mike McGreevy * Thursday, February 21, 2008 + * + * Changes: John Mainzer -- 4/16/09 + * Updated for the addition of new parameters to + * H5C2_jb__init(). * **************************************************************************/ @@ -10369,6 +10544,10 @@ check_buffer_writes(void) /* Initialize H5C2_jbrb_t structure. */ if ( pass2 ) { + /* Note that the sizeof_addr & sizeof_size parameters are + * ignored when human_readable is TRUE. + */ + result = H5C2_jb__init(/* H5C2_jbrb_t */ &jbrb_struct, /* journal_magic */ 123, /* HDF5 file name */ HDF5_FILE_NAME, @@ -10376,7 +10555,9 @@ check_buffer_writes(void) /* Buffer size */ 16, /* Number of Buffers */ 3, /* Use Synchronois I/O */ FALSE, - /* human readable journal */ TRUE); + /* human readable journal */ TRUE, + /* sizeof_addr */ 8, + /* sizeof_size */ 8); if ( result != 0) { @@ -10685,6 +10866,10 @@ write_noflush_verify(H5C2_jbrb_t * struct_ptr, * Changes: JRM -- 3/21/09 * Updated test to handle the new journal creation time strings * in which all white space is replaced with underscores. + * + * JRM -- 4/16/09 + * Updated for the addition of new parameters to + * H5C2_jb__init(). * **************************************************************************/ static void @@ -10727,6 +10912,10 @@ check_message_format(void) /* Initialize H5C2_jbrb_t structure. */ if ( pass2 ) { + /* Note that the sizeof_addr & sizeof_size parameters are + * ignored when human_readable is TRUE. + */ + result = H5C2_jb__init(/* H5C2_jbrb_t */ &jbrb_struct, /* journal_magic */ 123, /* HDF5 file name */ HDF5_FILE_NAME, @@ -10734,7 +10923,9 @@ check_message_format(void) /* Buffer size */ 16, /* Number of Buffers */ 3, /* Use Synchronois I/O */ FALSE, - /* human readable journal */ TRUE); + /* human readable journal */ TRUE, + /* sizeof_addr */ 8, + /* sizeof_size */ 8); if ( result != 0) { @@ -11254,36 +11445,48 @@ check_message_format(void) } /* end check_message_format */ - /*************************************************************************** - * Function: check_legal_calls + * Function: check_binary_message_format * - * Purpose: Verify that all H5C_jb functions prevent use when appropriate. + * Purpose: Verify that the functions that write binary messages into + * the journal buffers actually write the correct messages. + * + * Note that this test was hacked from Mike's similar test + * for the human readable journal messages. Unlike Mike's + * code, it also tests the eoa message. * * Return: void * - * Programmer: Mike McGreevy - * Tuesday, February 26, 2008 + * Programmer: John Mainzer + * 5/2/09 + * + * Changes: None. * **************************************************************************/ + static void -check_legal_calls(void) +check_binary_message_format(void) { - const char * fcn_name = "check_legal_calls(): "; + const char * fcn_name = "check_binary_message_format()"; char filename[512]; - herr_t result; - H5C2_jbrb_t jbrb_struct; + char time_buf[32]; + char verify[9][500]; + char from_journal[9][500]; + char * p; hbool_t show_progress = FALSE; int32_t checkpoint = 1; + int i; + int fd; + herr_t result; + FILE * readback; + H5C2_jbrb_t jbrb_struct; + time_t current_date; - TESTING("journaling routine compatibility"); + TESTING("binary journal file message format"); pass2 = TRUE; - /* Give structure its magic number */ - jbrb_struct.magic = H5C2__H5C2_JBRB_T_MAGIC; - /* setup the file name */ if ( pass2 ) { @@ -11297,137 +11500,1182 @@ check_legal_calls(void) } /* end if */ - if ( show_progress ) /* 1 */ - HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, - checkpoint++, (int)pass2); + /* Give structure its magic number */ + jbrb_struct.magic = H5C2__H5C2_JBRB_T_MAGIC; - /* Initialize H5C2_jbrb_t structure. This call should SUCCEED. */ + /* Initialize H5C2_jbrb_t structure. */ if ( pass2 ) { + /* Note that the sizeof_addr & sizeof_size parameters are + * ignored when human_readable is TRUE. + */ + result = H5C2_jb__init(/* H5C2_jbrb_t */ &jbrb_struct, - /* journal magic */ 123, + /* journal_magic */ 123, /* HDF5 file name */ HDF5_FILE_NAME, /* journal file name */ filename, - /* Buffer size */ 4000, + /* Buffer size */ 16, /* Number of Buffers */ 3, /* Use Synchronois I/O */ FALSE, - /* human readable journal */ TRUE); + /* human readable journal */ FALSE, + /* sizeof_addr */ 8, + /* sizeof_size */ 8); - if ( result != SUCCEED) { + if ( result != 0) { pass2 = FALSE; - failure_mssg2 = "H5C2_jb_init failed, check 3"; + failure_mssg2 = "H5C2_jb_init failed, check 2"; } /* end if */ } /* end if */ - if ( show_progress ) /* 2 */ - HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, - checkpoint++, (int)pass2); -#if 0 - /* Start transaction 2. This should FAIL because transaction 1 has - not occurred yet. Ensure that it fails, and flag an error if it - does not. */ - /* transaction numbers need not be sequential, only monitonically - * increasing -- thus this is not an error any more. - * -- JRM - */ + if ( show_progress ) /* 1 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* Start a transaction */ if ( pass2 ) { - if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, - /* Transaction # */ (uint64_t)2) - == SUCCEED ) { - + if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, + /* trans number */ (uint64_t)1) + != SUCCEED ) { + pass2 = FALSE; - failure_mssg2 = "H5C2_jb__start_transaction should have failed"; + failure_mssg2 = "H5C2_jb__start_transaction failed"; - } /* end if */ + } /* end if */ - } /* end if */ -#endif - if ( show_progress ) /* 3 */ - HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, - checkpoint++, (int)pass2); + } /* end if */ - /* End transaction 1. This should FAIL because transaction 1 has - not started yet. Ensure that it fails, and flag an error if it - does not. */ + if ( show_progress ) /* 2 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* Write a journal entry */ if ( pass2 ) { - if ( H5C2_jb__end_transaction(/* H5C2_jbrb_t */ &jbrb_struct, - /* Transaction # */ (uint64_t)1) - == SUCCEED ) { - + if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, + /* trans number */ (uint64_t)1, + /* base address */ (haddr_t)0, + /* data length */ 1, + /* data */ (const uint8_t *)"A") + != SUCCEED ) { + pass2 = FALSE; - failure_mssg2 = "H5C2_jb__end_transaction should have failed"; - - } /* end if */ + failure_mssg2 = "H5C2_jb__journal_entry failed"; + + } /* end if */ } /* end if */ - if ( show_progress ) /* 4 */ - HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, - checkpoint++, (int)pass2); + if ( show_progress ) /* 3 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); - /* Attempt to write a journal entry before transaction has started.. - This should FAIL because transaction 1 has not started yet. Ensure - that it fails, and flag an error if it does not. */ + /* Write an eoa message */ if ( pass2 ) { - if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, - /* Transaction # */ (uint64_t)1, - /* Base Address */ (haddr_t)123456789, - /* Length */ 16, - /* Body */ (const uint8_t *)"This should fail") - == SUCCEED ) { - + if ( H5C2_jb__eoa(/* H5C2_jbrb_t */ &jbrb_struct, + /* eoa */ (haddr_t)0x01020304) + != SUCCEED ) { + pass2 = FALSE; - failure_mssg2 = "H5C2_jb__journal_entry should have failed"; + failure_mssg2 = "H5C2_jb__eoa failed(1)"; - } /* end if */ + } /* end if */ } /* end if */ - if ( show_progress ) /* 5 */ - HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, - checkpoint++, (int)pass2); - - /* Start transaction 1. This should SUCCEED. */ + if ( show_progress ) /* 4 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* Write a journal entry */ if ( pass2 ) { - if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, - /* Transaction # */ (uint64_t)1) + if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, + /* trans number */ (uint64_t)1, + /* base address */ (haddr_t)1, + /* data length */ 2, + /* data */ (const uint8_t *)"AB") != SUCCEED ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__journal_entry failed"; - pass2 = FALSE; - failure_mssg2 = "H5C2_jb__start_transaction failed"; - - } /* end if */ + } /* end if */ } /* end if */ - if ( show_progress ) /* 6 */ - HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, - checkpoint++, (int)pass2); - - /* Attempt to start transaction 1 again. This should FAIL because - transaction 1 is already open. Ensure that it fails, and flag an - error if it does not. */ + if ( show_progress ) /* 5 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* Write a journal entry */ if ( pass2 ) { - if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, - /* Transaction # */ (uint64_t)1) - == SUCCEED ) { - - pass2 = FALSE; - failure_mssg2 = "H5C2_jb__start_transaction should have failed"; + if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, + /* trans number */ (uint64_t)1, + /* base address */ (haddr_t)3, + /* data length */ 4, + /* data */ (const uint8_t *)"CDEF") + != SUCCEED ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__journal_entry failed"; - } /* end if */ + } /* end if */ } /* end if */ - if ( show_progress ) /* 7 */ + if ( show_progress ) /* 6 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* End transaction */ + if ( pass2 ) { + if ( H5C2_jb__end_transaction(/* H5C2_jbrb_t */ &jbrb_struct, + /* trans number */ (uint64_t)1) + != SUCCEED ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__end_transaction failed (1)"; + + } /* end if */ + + } /* end if */ + + if ( show_progress ) /* 7 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* Write an eoa message */ + if ( pass2 ) { + + if ( H5C2_jb__eoa(/* H5C2_jbrb_t */ &jbrb_struct, + /* eoa */ (haddr_t)0x0102030405) + != SUCCEED ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__eoa failed(2)"; + + } /* end if */ + + } /* end if */ + + if ( show_progress ) /* 8 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* Start a transaction */ + if ( pass2 ) { + + if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, + /* trans number */ (uint64_t)2) + != SUCCEED ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__start_transaction failed"; + + } /* end if */ + + } /* end if */ + + if ( show_progress ) /* 9 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* Write a journal entry */ + if ( pass2 ) { + + if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, + /* trans number */ (uint64_t)2, + /* base address */ (haddr_t)285, + /* data length */ 11, + /* data */ (const uint8_t *)"Test Data?!") + != SUCCEED ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__journal_entry failed"; + + } /* end if */ + + } /* end if */ + + if ( show_progress ) /* 10 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* End transaction */ + if ( pass2 ) { + if ( H5C2_jb__end_transaction(/* H5C2_jbrb_t */ &jbrb_struct, + /* trans number */ (uint64_t)2) + != SUCCEED ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__end_transaction failed (2)"; + + } /* end if */ + + } /* end if */ + + if ( show_progress ) /* 11 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* Flush the journal buffers. */ + if ( pass2 ) { + + if ( H5C2_jb__flush(/* H5C2_jbrb_t */ &jbrb_struct) + != SUCCEED ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__flush failed"; + + } /* end if */ + + } /* end if */ + + if ( pass2 ) { + + current_date = time(NULL); + + /* load ascii representation of current_date into time_buf[], + * replacing white space with underscores. + */ + time_buf[31] = '\0'; /* just to be safe */ + + if ( (p = HDctime(¤t_date)) == NULL ) { + + pass2 = FALSE; + failure_mssg2 = "HDctime() failed"; + + } else { + + /* copy the string into time_buf, replacing white space with + * underscores. + * + * Do this to make parsing the header easier. + */ + i = 0; + + while ( ( i < 31 ) && ( *p != '\0' ) ) { + + if ( isspace(*p) ) { + + time_buf[i] = '_'; + + } else { + + time_buf[i] = *p; + } + + i++; + p++; + } + + time_buf[i] = '\0'; + } + } + + if ( show_progress ) /* 12 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + if ( pass2 ) { + + char expected_header[256]; + int expected_header_len; + + uint8_t expected_msg_1[] = + { + /* mssg 1: begin transaction 1 */ + /* header: */ 'b', 't', 'r', 'n', + /* version: */ 0x00, + /* trans num: */ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + int expected_msg_1_len = 13; + + uint8_t expected_msg_2[] = + { + /* mssg 2: journal entry */ + /* header: */ 'j', 'e', 'n', 't', + /* version: */ 0x00, + /* trans num: */ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* base addr: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* length: */ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* body: */ 'A', + /* chksum: */ 0x7c, 0x5f, 0xad, 0xda + }; + int expected_msg_2_len = 34; + + uint8_t expected_msg_3[] = + { + /* mssg 3: eoas */ + /* header: */ 'e', 'o', 'a', 's', + /* version: */ 0x00, + /* trans num: */ 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00 + }; + int expected_msg_3_len = 13; + + uint8_t expected_msg_4[] = + { + /* mssg 4: journal entry */ + /* header: */ 'j', 'e', 'n', 't', + /* version: */ 0x00, + /* trans num: */ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* base addr: */ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* length: */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* body: */ 'A', 'B', + /* chksum: */ 0x33, 0x93, 0x98, 0x21 + }; + int expected_msg_4_len = 35; + + uint8_t expected_msg_5[] = + { + /* mssg 5: journal entry */ + /* header: */ 'j', 'e', 'n', 't', + /* version: */ 0x00, + /* trans num: */ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* base addr: */ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* length: */ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* body: */ 'C', 'D', 'E', 'F', + /* chksum: */ 0x6e, 0x7d, 0xaf, 0x57 + }; + int expected_msg_5_len = 37; + + uint8_t expected_msg_6[] = + { + /* mssg 6: end transaction 1 */ + /* header: */ 'e', 't', 'r', 'n', + /* version: */ 0x00, + /* trans num: */ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + int expected_msg_6_len = 13; + + uint8_t expected_msg_7[] = + { + /* mssg 7: eoas */ + /* header: */ 'e', 'o', 'a', 's', + /* version: */ 0x00, + /* trans num: */ 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00 + }; + int expected_msg_7_len = 13; + + uint8_t expected_msg_8[] = + { + /* mssg 8: begin transaction 2 */ + /* header: */ 'b', 't', 'r', 'n', + /* version: */ 0x00, + /* trans num: */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + int expected_msg_8_len = 13; + + uint8_t expected_msg_9[] = + { + /* mssg 9: journal entry */ + /* h9ader: */ 'j', 'e', 'n', 't', + /* version: */ 0x00, + /* trans num: */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* base addr: */ 0x1d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* length: */ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* body: */ 'T', 'e', 's', 't', ' ', 'D', 'a', 't', + 'a', '?', '!', + /* chksum: */ 0x01, 0x7f, 0xf3, 0x43 + }; + int expected_msg_9_len = 44; + + uint8_t expected_msg_10[] = + { + /* mssg 10: end transaction 2 */ + /* header: */ 'e', 't', 'r', 'n', + /* version: */ 0x00, + /* trans num: */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + int expected_msg_10_len = 13; + + + sprintf(expected_header, "0 ver_num 1 target_file_name HDF5.file journal_magic 123 creation_date %10.10s human_readable 0 offset_width 8 length_width 8\n", time_buf); + expected_header_len = HDstrlen(expected_header); + + if ( (fd = HDopen(filename, O_RDONLY, 0777)) == -1 ) { + + pass2 = FALSE; + failure_mssg2 = "Can't open journal file for test (1)."; + + } + + if ( pass2 ) { + + verify_journal_msg( + /* fd */ fd, + /* expected_msg */ expected_header, + /* expected msg len */ expected_header_len, + /* last_msg */ FALSE, + /* mismatch failuer msg */ "expected and actual headers differ.", + /* read failure msg */ "error reading header.", + /* eof failure msg */ "encountered eof in header msg.", + /* not last msg failure */ NULL); + + verify_journal_msg( + /* fd */ fd, + /* expected_msg */ expected_msg_1, + /* expected msg len */ expected_msg_1_len, + /* last_msg */ FALSE, + /* mismatch failuer msg */ "expected and actual msg 1 differ.", + /* read failure msg */ "error reading msg 1.", + /* eof failure msg */ "encountered eof in msg 1.", + /* not last msg failure */ NULL); + + verify_journal_msg( + /* fd */ fd, + /* expected_msg */ expected_msg_2, + /* expected msg len */ expected_msg_2_len, + /* last_msg */ FALSE, + /* mismatch failuer msg */ "expected and actual msg 2 differ.", + /* read failure msg */ "error reading msg 2.", + /* eof failure msg */ "encountered eof in msg 2", + /* not last msg failure */ NULL); + + verify_journal_msg( + /* fd */ fd, + /* expected_msg */ expected_msg_3, + /* expected msg len */ expected_msg_3_len, + /* last_msg */ FALSE, + /* mismatch failuer msg */ "expected and actual msg 3 differ.", + /* read failure msg */ "error reading msg 3.", + /* eof failure msg */ "encountered eof in msg 3", + /* not last msg failure */ NULL); + + verify_journal_msg( + /* fd */ fd, + /* expected_msg */ expected_msg_4, + /* expected msg len */ expected_msg_4_len, + /* last_msg */ FALSE, + /* mismatch failuer msg */ "expected and actual msg 4 differ.", + /* read failure msg */ "error reading msg 4.", + /* eof failure msg */ "encountered eof in msg 4", + /* not last msg failure */ NULL); + + verify_journal_msg( + /* fd */ fd, + /* expected_msg */ expected_msg_5, + /* expected msg len */ expected_msg_5_len, + /* last_msg */ FALSE, + /* mismatch failuer msg */ "expected and actual msg 5 differ.", + /* read failure msg */ "error reading msg 5.", + /* eof failure msg */ "encountered eof in msg 5", + /* not last msg failure */ NULL); + + verify_journal_msg( + /* fd */ fd, + /* expected_msg */ expected_msg_6, + /* expected msg len */ expected_msg_6_len, + /* last_msg */ FALSE, + /* mismatch failuer msg */ "expected and actual msg 6 differ.", + /* read failure msg */ "error reading msg 6.", + /* eof failure msg */ "encountered eof in msg 6", + /* not last msg failure */ NULL); + + verify_journal_msg( + /* fd */ fd, + /* expected_msg */ expected_msg_7, + /* expected msg len */ expected_msg_7_len, + /* last_msg */ FALSE, + /* mismatch failuer msg */ "expected and actual msg7 differ.", + /* read failure msg */ "error reading msg 7.", + /* eof failure msg */ "encountered eof in msg 7", + /* not last msg failure */ NULL); + + verify_journal_msg( + /* fd */ fd, + /* expected_msg */ expected_msg_8, + /* expected msg len */ expected_msg_8_len, + /* last_msg */ FALSE, + /* mismatch failuer msg */ "expected and actual msg 8 differ.", + /* read failure msg */ "error reading msg 8.", + /* eof failure msg */ "encountered eof in msg 8", + /* not last msg failure */ NULL); + + verify_journal_msg( + /* fd */ fd, + /* expected_msg */ expected_msg_9, + /* expected msg len */ expected_msg_9_len, + /* last_msg */ FALSE, + /* mismatch failuer msg */ "expected and actual msg 9 differ.", + /* read failure msg */ "error reading msg 9.", + /* eof failure msg */ "encountered eof in msg 9", + /* not last msg failure */ NULL); + + verify_journal_msg( + /* fd */ fd, + /* expected_msg */ expected_msg_10, + /* expected msg len */ expected_msg_10_len, + /* last_msg */ TRUE, + /* mismatch failuer msg */ "expected and actual msg 10 differ.", + /* read failure msg */ "error reading msg 10.", + /* eof failure msg */ "encountered eof in msg 10", + /* not last msg failure */ "msg 10 does not end file"); + + if ( HDclose(fd) != 0 ) { + + pass2 = FALSE; + failure_mssg2 = "Unable to close journal file (1)."; + } + } + } + + /* Truncate the journal file */ + if ( pass2 ) { + + if ( H5C2_jb__trunc(&jbrb_struct) != SUCCEED ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__trunc failed"; + + } /* end if */ + + } /* end if */ + + if ( show_progress ) /* 13 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* Write an eoa message */ + if ( pass2 ) { + + if ( H5C2_jb__eoa(/* H5C2_jbrb_t */ &jbrb_struct, + /* eoa */ (haddr_t)0x010203040506) + != SUCCEED ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__eoa failed(3)"; + + } /* end if */ + + } /* end if */ + + if ( show_progress ) /* 14 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* Start a transaction */ + if ( pass2 ) { + + if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, + /* trans number */ (uint64_t)3) + != SUCCEED ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__start_transaction failed"; + + } /* end if */ + + } /* end if */ + + if ( show_progress ) /* 15 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* Write a journal entry */ + if ( pass2 ) { + + if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, + /* trans number */ (uint64_t)3, + /* base address */ (haddr_t)28591, + /* data length */ 6, + /* data */ (const uint8_t *)"#1nN`}" ) + != SUCCEED ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__journal_entry failed"; + + } /* end if */ + + } /* end if */ + + if ( show_progress ) /* 16 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* End transaction */ + if ( pass2 ) { + if ( H5C2_jb__end_transaction(/* H5C2_jbrb_t */ &jbrb_struct, + /* trans number */ (uint64_t)3) + != SUCCEED ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__end_transaction failed (3)"; + + } /* end if */ + + } /* end if */ + + if ( show_progress ) /* 17 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* Add a comment */ + if ( pass2 ) { + if ( H5C2_jb__comment(/* H5C2_jbrb_t */ &jbrb_struct, + /* comment message */ "This is a comment!") + != SUCCEED ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__comment failed"; + + } /* end if */ + + } /* end if */ + + if ( show_progress ) /* 18 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* Add a comment */ + if ( pass2 ) { + if ( H5C2_jb__comment(/* H5C2_jbrb_t */ &jbrb_struct, + /* comment message */ "This is another comment!") + != SUCCEED ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__comment failed"; + + } /* end if */ + + } /* end if */ + + if ( show_progress ) /* 19 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* Flush the journal buffers. */ + if ( pass2 ) { + + if ( H5C2_jb__flush(/* H5C2_jbrb_t */ &jbrb_struct) + != SUCCEED ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__flush failed"; + + } /* end if */ + + } /* end if */ + + if ( pass2 ) { + + current_date = time(NULL); + + /* load ascii representation of current_date into time_buf[], + * replacing white space with underscores. + */ + + time_buf[31] = '\0'; /* just to be safe */ + + if ( (p = HDctime(¤t_date)) == NULL ) { + + pass2 = FALSE; + failure_mssg2 = "HDctime() failed"; + + } else { + + /* copy the string into time_buf, replacing white space with + * underscores. + * + * Do this to make parsing the header easier. + */ + i = 0; + + while ( ( i < 31 ) && ( *p != '\0' ) ) { + + if ( isspace(*p) ) { + + time_buf[i] = '_'; + + } else { + + time_buf[i] = *p; + } + + i++; + p++; + } + + time_buf[i] = '\0'; + } + } + + if ( show_progress ) /* 20 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + if ( pass2 ) { + + char expected_header[256]; + int expected_header_len; + + uint8_t expected_msg_11[] = + { + /* mssg 11: eoas */ + /* header: */ 'e', 'o', 'a', 's', + /* version: */ 0x00, + /* trans num: */ 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00 + }; + int expected_msg_11_len = 13; + + + uint8_t expected_msg_12[] = + { + /* mssg 12: begin transaction 3 */ + /* header: */ 'b', 't', 'r', 'n', + /* version: */ 0x00, + /* trans num: */ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + int expected_msg_12_len = 13; + + uint8_t expected_msg_13[] = + { + /* mssg 13: journal entry */ + /* header: */ 'j', 'e', 'n', 't', + /* version: */ 0x00, + /* trans num: */ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* base addr: */ 0xaf, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* length: */ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* body: */ '#', '1', 'n', 'N', '`', '}', + /* chksum: */ 0x6b, 0x60, 0x0d, 0x6d + }; + int expected_msg_13_len = 39; + + uint8_t expected_msg_14[] = + { + /* mssg 14: end transaction 1 */ + /* header: */ 'e', 't', 'r', 'n', + /* version: */ 0x00, + /* trans num: */ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + int expected_msg_14_len = 13; + + sprintf(expected_header, "0 ver_num 1 target_file_name HDF5.file journal_magic 123 creation_date %10.10s human_readable 0 offset_width 8 length_width 8\n", time_buf); + expected_header_len = HDstrlen(expected_header); + + if ( (fd = HDopen(filename, O_RDONLY, 0777)) == -1 ) { + + pass2 = FALSE; + failure_mssg2 = "Can't open journal file for test (2)."; + + } + + if ( pass2 ) { + + verify_journal_msg( + /* fd */ fd, + /* expected_msg */ expected_header, + /* expected msg len */ expected_header_len, + /* last_msg */ FALSE, + /* mismatch failuer msg */ "expected and actual headers differ.", + /* read failure msg */ "error reading header.", + /* eof failure msg */ "encountered eof in header msg.", + /* not last msg failure */ NULL); + + verify_journal_msg( + /* fd */ fd, + /* expected_msg */ expected_msg_11, + /* expected msg len */ expected_msg_11_len, + /* last_msg */ FALSE, + /* mismatch failuer msg */ "expected and actual msg 11 differ.", + /* read failure msg */ "error reading msg 11.", + /* eof failure msg */ "encountered eof in msg 11.", + /* not last msg failure */ NULL); + + verify_journal_msg( + /* fd */ fd, + /* expected_msg */ expected_msg_12, + /* expected msg len */ expected_msg_12_len, + /* last_msg */ FALSE, + /* mismatch failuer msg */ "expected and actual msg 12 differ.", + /* read failure msg */ "error reading msg 12.", + /* eof failure msg */ "encountered eof in msg 12", + /* not last msg failure */ NULL); + + verify_journal_msg( + /* fd */ fd, + /* expected_msg */ expected_msg_13, + /* expected msg len */ expected_msg_13_len, + /* last_msg */ FALSE, + /* mismatch failuer msg */ "expected and actual msg 13 differ.", + /* read failure msg */ "error reading msg 13.", + /* eof failure msg */ "encountered eof in msg 13", + /* not last msg failure */ NULL); + + verify_journal_msg( + /* fd */ fd, + /* expected_msg */ expected_msg_14, + /* expected msg len */ expected_msg_14_len, + /* last_msg */ TRUE, + /* mismatch failuer msg */ "expected and actual msg 14 differ.", + /* read failure msg */ "error reading msg 14.", + /* eof failure msg */ "encountered eof in msg 14", + /* not last msg failure */ "msg 14 does not end file"); + + + if ( HDclose(fd) != 0 ) { + + pass2 = FALSE; + failure_mssg2 = "Unable to close journal file (1)."; + } + } + } + + /* Truncate the journal file */ + if ( pass2 ) { + + if ( H5C2_jb__trunc(&jbrb_struct) != SUCCEED ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__trunc failed"; + + } /* end if */ + + } /* end if */ + + /* take down the journal file */ + if ( pass2 ) { + + if (H5C2_jb__takedown(&jbrb_struct) != SUCCEED) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__takedown failed"; + + } /* end if */ + + } /* end if */ + + if ( show_progress ) /* 20 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* report pass / failure information */ + if ( pass2 ) { PASSED(); } else { H5_FAILED(); } + + if ( ! pass2 ) { + + failures2++; + HDfprintf(stdout, "%s: failure_mssg2 = \"%s\".\n", + fcn_name, failure_mssg2); + + } + + return; + +} /* check_binary_message_format() */ + + +/*************************************************************************** + * Function: verify_journal_msg + * + * Purpose: Verify that the supplied expected journal message is + * the next in the message in the indicated journal file. + * + * Do nothing it the expected message matches the file + * contents. If there is a mismatch, set pass2 to false + * and set the failure message as specified. + * + * Exit without any action if pass2 is false on entry. + * + * Return: void + * + * Programmer: J Mainzer + * + * Changes: None. + * + **************************************************************************/ + +static void +verify_journal_msg(int fd, + uint8_t expected_msg[], + int expected_msg_len, + hbool_t last_msg, + const char * mismatch_failure_msg, + const char * read_failure_msg, + const char * eof_failure_msg, + const char * not_last_msg_msg) +{ + const char * fcn_name = "verify_journal_msg()"; + hbool_t verbose = TRUE; + uint8_t ch; + int i = 0; + ssize_t ret_val; + + if ( pass2 ) { + + if ( ( fd < 0 ) || + ( expected_msg == NULL ) || + ( expected_msg_len <= 0 ) || + ( mismatch_failure_msg == NULL ) || + ( read_failure_msg == NULL ) || + ( eof_failure_msg == NULL ) || + ( ( last_msg) && ( not_last_msg_msg == NULL ) ) ) { + + pass2 = FALSE; + failure_mssg2 = "verify_journal_msg(): Bad params on entry."; + } + } + + while ( ( pass2 ) && ( i < expected_msg_len ) ) + { + ret_val = read(fd, (void *)(&ch), (size_t)1); + + if ( ret_val == 1 ) { + + if ( ch != expected_msg[i] ) { + + pass2 = FALSE; + failure_mssg2 = mismatch_failure_msg; + } + + } else if ( ret_val == -1 ) { + + if ( verbose ) { + + HDfprintf(stdout, "%s: read failed with errno = %d (%s).\n", + fcn_name, errno, strerror(errno)); + } + + pass2 = FALSE; + failure_mssg2 = mismatch_failure_msg; + + } else if ( ret_val == 0 ) { + + if ( verbose ) { + + HDfprintf(stdout, "%s: unexpected EOF.\n", fcn_name); + } + + pass2 = FALSE; + failure_mssg2 = eof_failure_msg; + + } else { + + if ( verbose ) { + + HDfprintf(stdout, "%s: read returned unexpected value (%d).\n", + fcn_name, (int)ret_val); + } + + pass2 = FALSE; + failure_mssg2 = "read returned unexpected value."; + + } + + i++; + + } + + if ( ( pass2 ) && ( last_msg ) ) { + + ret_val = read(fd, (void *)(&ch), (size_t)1); + + if ( ret_val != 0 ) { + + if ( verbose ) { + + HDfprintf(stdout, "%s: msg not at eof as expected.\n", fcn_name); + } + + pass2 = FALSE; + failure_mssg2 = not_last_msg_msg; + } + } + + return; + +} /* verify_journal_msg() */ + + +/*************************************************************************** + * Function: check_legal_calls + * + * Purpose: Verify that all H5C_jb functions prevent use when appropriate. + * + * Return: void + * + * Programmer: Mike McGreevy + * Tuesday, February 26, 2008 + * + * Changes: JRM -- 4/16/09 + * Updated for the addition of new parameters to + * H5C2_jb__init(). + * + **************************************************************************/ + +static void +check_legal_calls(void) +{ + const char * fcn_name = "check_legal_calls(): "; + char filename[512]; + herr_t result; + H5C2_jbrb_t jbrb_struct; + hbool_t show_progress = FALSE; + int32_t checkpoint = 1; + + TESTING("journaling routine compatibility"); + + pass2 = TRUE; + + /* Give structure its magic number */ + jbrb_struct.magic = H5C2__H5C2_JBRB_T_MAGIC; + + /* setup the file name */ + if ( pass2 ) { + + if ( h5_fixname(FILENAMES[1], H5P_DEFAULT, filename, sizeof(filename)) + == NULL ) { + + pass2 = FALSE; + failure_mssg2 = "h5_fixname() failed"; + + } /* end if */ + + } /* end if */ + + if ( show_progress ) /* 1 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* Initialize H5C2_jbrb_t structure. This call should SUCCEED. */ + if ( pass2 ) { + + /* Note that the sizeof_addr & sizeof_size parameters are + * ignored when human_readable is TRUE. + */ + + result = H5C2_jb__init(/* H5C2_jbrb_t */ &jbrb_struct, + /* journal magic */ 123, + /* HDF5 file name */ HDF5_FILE_NAME, + /* journal file name */ filename, + /* Buffer size */ 4000, + /* Number of Buffers */ 3, + /* Use Synchronois I/O */ FALSE, + /* human readable journal */ TRUE, + /* sizeof_addr */ 8, + /* sizeof_size */ 8); + + if ( result != SUCCEED) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb_init failed, check 3"; + + } /* end if */ + + } /* end if */ + + if ( show_progress ) /* 2 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); +#if 0 + /* Start transaction 2. This should FAIL because transaction 1 has + not occurred yet. Ensure that it fails, and flag an error if it + does not. */ + /* transaction numbers need not be sequential, only monitonically + * increasing -- thus this is not an error any more. + * -- JRM + */ + if ( pass2 ) { + + if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, + /* Transaction # */ (uint64_t)2) + == SUCCEED ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__start_transaction should have failed"; + + } /* end if */ + + } /* end if */ +#endif + if ( show_progress ) /* 3 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* End transaction 1. This should FAIL because transaction 1 has + not started yet. Ensure that it fails, and flag an error if it + does not. */ + if ( pass2 ) { + + if ( H5C2_jb__end_transaction(/* H5C2_jbrb_t */ &jbrb_struct, + /* Transaction # */ (uint64_t)1) + == SUCCEED ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__end_transaction should have failed"; + + } /* end if */ + + } /* end if */ + + if ( show_progress ) /* 4 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* Attempt to write a journal entry before transaction has started.. + This should FAIL because transaction 1 has not started yet. Ensure + that it fails, and flag an error if it does not. */ + if ( pass2 ) { + + if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, + /* Transaction # */ (uint64_t)1, + /* Base Address */ (haddr_t)123456789, + /* Length */ 16, + /* Body */ (const uint8_t *)"This should fail") + == SUCCEED ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__journal_entry should have failed"; + + } /* end if */ + + } /* end if */ + + if ( show_progress ) /* 5 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* Start transaction 1. This should SUCCEED. */ + if ( pass2 ) { + + if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, + /* Transaction # */ (uint64_t)1) + != SUCCEED ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__start_transaction failed"; + + } /* end if */ + + } /* end if */ + + if ( show_progress ) /* 6 */ + HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, + checkpoint++, (int)pass2); + + /* Attempt to start transaction 1 again. This should FAIL because + transaction 1 is already open. Ensure that it fails, and flag an + error if it does not. */ + if ( pass2 ) { + + if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, + /* Transaction # */ (uint64_t)1) + == SUCCEED ) { + + pass2 = FALSE; + failure_mssg2 = "H5C2_jb__start_transaction should have failed"; + + } /* end if */ + + } /* end if */ + + if ( show_progress ) /* 7 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); @@ -11764,6 +13012,10 @@ check_legal_calls(void) * * Programmer: Mike McGreevy * Tuesday, February 26, 2008 + * + * Changes: JRM -- 4/16/09 + * Updated for the addition of new parameters to + * H5C2_jb__init(). * **************************************************************************/ static void @@ -11816,6 +13068,10 @@ check_transaction_tracking(void) /* Initialize H5C2_jbrb_t structure. */ if ( pass2 ) { + /* Note that the sizeof_addr & sizeof_size parameters are + * ignored when human_readable is TRUE. + */ + result = H5C2_jb__init(/* H5C2_jbrb_t */ &jbrb_struct, /* journal magic */ 123, /* HDF5 file name */ HDF5_FILE_NAME, @@ -11823,7 +13079,9 @@ check_transaction_tracking(void) /* Buffer size */ 250, /* Number of Buffers */ 4, /* Use Synchronois I/O */ FALSE, - /* human readable journal */ TRUE); + /* human readable journal */ TRUE, + /* sizeof_addr */ 8, + /* sizeof_size */ 8); if ( result != SUCCEED) { @@ -11958,6 +13216,10 @@ check_transaction_tracking(void) /* Initialize H5C2_jbrb_t structure. */ if ( pass2 ) { + /* Note that the sizeof_addr & sizeof_size parameters are + * ignored when human_readable is TRUE. + */ + result = H5C2_jb__init(/* H5C2_jbrb_t */ &jbrb_struct, /* journal magic */ 123, /* HDF5 file name */ HDF5_FILE_NAME, @@ -11965,7 +13227,9 @@ check_transaction_tracking(void) /* Buffer size */ 100, /* Number of Buffers */ 4, /* Use Synchronois I/O */ FALSE, - /* human readable journal */ TRUE); + /* human readable journal */ TRUE, + /* sizeof_addr */ 8, + /* sizeof_size */ 8); if ( result != SUCCEED) { @@ -12074,6 +13338,10 @@ check_transaction_tracking(void) /* Initialize H5C2_jbrb_t structure. */ if ( pass2 ) { + /* Note that the sizeof_addr & sizeof_size parameters are + * ignored when human_readable is TRUE. + */ + result = H5C2_jb__init(/* H5C2_jbrb_t */ &jbrb_struct, /* journal_magic */ 123, /* HDF5 file name */ HDF5_FILE_NAME, @@ -12081,7 +13349,9 @@ check_transaction_tracking(void) /* Buffer size */ 30, /* Number of Buffers */ 10, /* Use Synchronois I/O */ FALSE, - /* human readable journal */ TRUE); + /* human readable journal */ TRUE, + /* sizeof_addr */ 8, + /* sizeof_size */ 8); if ( result != SUCCEED) { @@ -12227,6 +13497,10 @@ check_transaction_tracking(void) /* Initialize H5C2_jbrb_t structure. */ if ( pass2 ) { + /* Note that the sizeof_addr & sizeof_size parameters are + * ignored when human_readable is TRUE. + */ + result = H5C2_jb__init(/* H5C2_jbrb_t */ &jbrb_struct, /* journal_magic */ 123, /* HDF5 file name */ HDF5_FILE_NAME, @@ -12234,7 +13508,9 @@ check_transaction_tracking(void) /* Buffer size */ 1, /* Number of Buffers */ 35, /* Use Synchronois I/O */ FALSE, - /* human readable journal */ TRUE); + /* human readable journal */ TRUE, + /* sizeof_addr */ 8, + /* sizeof_size */ 8); if ( result != SUCCEED) { @@ -12516,23 +13792,42 @@ main(void) } + /* Human readable smoke checks */ +#if 1 + mdj_smoke_check_00(TRUE); +#endif +#if 1 + mdj_smoke_check_01(TRUE); +#endif +#if 1 + mdj_smoke_check_02(TRUE); +#endif +#if 1 + mdj_api_example_test(TRUE); +#endif + + + /* Binary readable smoke checks */ #if 1 - mdj_smoke_check_00(); + mdj_smoke_check_00(FALSE); #endif #if 1 - mdj_smoke_check_01(); + mdj_smoke_check_01(FALSE); #endif #if 1 - mdj_smoke_check_02(); + mdj_smoke_check_02(FALSE); #endif #if 1 - mdj_api_example_test(); + mdj_api_example_test(FALSE); #endif + + /* targeted tests */ #if 1 check_buffer_writes(); check_legal_calls(); check_message_format(); check_transaction_tracking(); + check_binary_message_format(); #endif #if 1 check_superblock_extensions(); diff --git a/test/testfiles/cache2_journal_bsc00_000.jnl.gz b/test/testfiles/cache2_journal_bsc00_000.jnl.gz new file mode 100755 index 0000000..f6e9612 Binary files /dev/null and b/test/testfiles/cache2_journal_bsc00_000.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc00_001.jnl.gz b/test/testfiles/cache2_journal_bsc00_001.jnl.gz new file mode 100755 index 0000000..36f79e0 Binary files /dev/null and b/test/testfiles/cache2_journal_bsc00_001.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc00_002.jnl.gz b/test/testfiles/cache2_journal_bsc00_002.jnl.gz new file mode 100755 index 0000000..f044a69 Binary files /dev/null and b/test/testfiles/cache2_journal_bsc00_002.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc00_003.jnl.gz b/test/testfiles/cache2_journal_bsc00_003.jnl.gz new file mode 100755 index 0000000..4305745 Binary files /dev/null and b/test/testfiles/cache2_journal_bsc00_003.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc00_004.jnl.gz b/test/testfiles/cache2_journal_bsc00_004.jnl.gz new file mode 100755 index 0000000..fc99d59 Binary files /dev/null and b/test/testfiles/cache2_journal_bsc00_004.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc00_005.jnl.gz b/test/testfiles/cache2_journal_bsc00_005.jnl.gz new file mode 100755 index 0000000..16e7eb1 Binary files /dev/null and b/test/testfiles/cache2_journal_bsc00_005.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc00_006.jnl.gz b/test/testfiles/cache2_journal_bsc00_006.jnl.gz new file mode 100755 index 0000000..7744ea0 Binary files /dev/null and b/test/testfiles/cache2_journal_bsc00_006.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc00_007.jnl.gz b/test/testfiles/cache2_journal_bsc00_007.jnl.gz new file mode 100755 index 0000000..e1be66b Binary files /dev/null and b/test/testfiles/cache2_journal_bsc00_007.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc00_008.jnl.gz b/test/testfiles/cache2_journal_bsc00_008.jnl.gz new file mode 100755 index 0000000..d852aad Binary files /dev/null and b/test/testfiles/cache2_journal_bsc00_008.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc00_009.jnl.gz b/test/testfiles/cache2_journal_bsc00_009.jnl.gz new file mode 100755 index 0000000..2429b98 Binary files /dev/null and b/test/testfiles/cache2_journal_bsc00_009.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc00_010.jnl.gz b/test/testfiles/cache2_journal_bsc00_010.jnl.gz new file mode 100755 index 0000000..b36ba56 Binary files /dev/null and b/test/testfiles/cache2_journal_bsc00_010.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc00_011.jnl.gz b/test/testfiles/cache2_journal_bsc00_011.jnl.gz new file mode 100755 index 0000000..3727caa Binary files /dev/null and b/test/testfiles/cache2_journal_bsc00_011.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc00_012.jnl.gz b/test/testfiles/cache2_journal_bsc00_012.jnl.gz new file mode 100755 index 0000000..801d55b Binary files /dev/null and b/test/testfiles/cache2_journal_bsc00_012.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc00_013.jnl.gz b/test/testfiles/cache2_journal_bsc00_013.jnl.gz new file mode 100755 index 0000000..e9212bd Binary files /dev/null and b/test/testfiles/cache2_journal_bsc00_013.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc00_014.jnl.gz b/test/testfiles/cache2_journal_bsc00_014.jnl.gz new file mode 100755 index 0000000..e19f714 Binary files /dev/null and b/test/testfiles/cache2_journal_bsc00_014.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc00_015.jnl.gz b/test/testfiles/cache2_journal_bsc00_015.jnl.gz new file mode 100755 index 0000000..3a06706 Binary files /dev/null and b/test/testfiles/cache2_journal_bsc00_015.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc00_016.jnl.gz b/test/testfiles/cache2_journal_bsc00_016.jnl.gz new file mode 100755 index 0000000..67ed629 Binary files /dev/null and b/test/testfiles/cache2_journal_bsc00_016.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc00_017.jnl.gz b/test/testfiles/cache2_journal_bsc00_017.jnl.gz new file mode 100755 index 0000000..2cbe6d6 Binary files /dev/null and b/test/testfiles/cache2_journal_bsc00_017.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc00_018.jnl.gz b/test/testfiles/cache2_journal_bsc00_018.jnl.gz new file mode 100755 index 0000000..b5aec5c Binary files /dev/null and b/test/testfiles/cache2_journal_bsc00_018.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc01_000.jnl.gz b/test/testfiles/cache2_journal_bsc01_000.jnl.gz new file mode 100755 index 0000000..956e8d9 Binary files /dev/null and b/test/testfiles/cache2_journal_bsc01_000.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc01_001.jnl.gz b/test/testfiles/cache2_journal_bsc01_001.jnl.gz new file mode 100755 index 0000000..0ed6e7f Binary files /dev/null and b/test/testfiles/cache2_journal_bsc01_001.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc01_002.jnl.gz b/test/testfiles/cache2_journal_bsc01_002.jnl.gz new file mode 100755 index 0000000..0491c9a Binary files /dev/null and b/test/testfiles/cache2_journal_bsc01_002.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc01_003.jnl.gz b/test/testfiles/cache2_journal_bsc01_003.jnl.gz new file mode 100755 index 0000000..74fe661 Binary files /dev/null and b/test/testfiles/cache2_journal_bsc01_003.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc01_004.jnl.gz b/test/testfiles/cache2_journal_bsc01_004.jnl.gz new file mode 100755 index 0000000..8a70e66 Binary files /dev/null and b/test/testfiles/cache2_journal_bsc01_004.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc02_000.jnl.gz b/test/testfiles/cache2_journal_bsc02_000.jnl.gz new file mode 100755 index 0000000..3cb36c0 Binary files /dev/null and b/test/testfiles/cache2_journal_bsc02_000.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc02_001.jnl.gz b/test/testfiles/cache2_journal_bsc02_001.jnl.gz new file mode 100755 index 0000000..63e166f Binary files /dev/null and b/test/testfiles/cache2_journal_bsc02_001.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc02_002.jnl.gz b/test/testfiles/cache2_journal_bsc02_002.jnl.gz new file mode 100755 index 0000000..6d993f5 Binary files /dev/null and b/test/testfiles/cache2_journal_bsc02_002.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc02_003.jnl.gz b/test/testfiles/cache2_journal_bsc02_003.jnl.gz new file mode 100755 index 0000000..6b13820 Binary files /dev/null and b/test/testfiles/cache2_journal_bsc02_003.jnl.gz differ diff --git a/test/testfiles/cache2_journal_bsc02_004.jnl.gz b/test/testfiles/cache2_journal_bsc02_004.jnl.gz new file mode 100755 index 0000000..cece9d6 Binary files /dev/null and b/test/testfiles/cache2_journal_bsc02_004.jnl.gz differ diff --git a/tools/h5recover/h5recover.c b/tools/h5recover/h5recover.c index f8ca64a..79449c1 100644 --- a/tools/h5recover/h5recover.c +++ b/tools/h5recover/h5recover.c @@ -17,6 +17,8 @@ #define H5O_PACKAGE /* suppress error about including H5Opkg */ #define H5C2_PACKAGE /* suppress error about including H5C2pkg */ +#define _XOPEN_SOURCE 500 /* for pread() & pwrite() */ + #include "hdf5.h" #include "h5tools.h" #include "h5tools_utils.h" @@ -78,8 +80,9 @@ hbool_t load_buf_from_file(int fd, off_t offset, size_t buf_len, uint8_t *buf_ptr, - hbool_t verbose, - const char * desc); + unsigned int verbosity, + const char * desc, + hbool_t * eof_ptr); /* HDF5 File Investigation Function Declarations: */ @@ -96,7 +99,9 @@ hbool_t get_sb_base_addr(int fd, haddr_t * sb_base_addr_ptr); hbool_t get_journaling_status(char * file_path_ptr, + off_t * file_len_ptr, off_t * sb_offset_ptr, + int * sb_version_ptr, haddr_t * base_addr_ptr, int * offset_size_ptr, int * length_size_ptr, @@ -177,10 +182,13 @@ hbool_t get_sb_version(int fd, hbool_t get_jnl_header_info(char * file_path_ptr, off_t journal_file_len, + size_t * header_length_ptr, int32_t * version_ptr, char * target_file_name_ptr, int32_t * magic_ptr, hbool_t * human_readable_ptr, + int * offset_width_ptr, + int * length_width_ptr, hbool_t examine, unsigned verbosity); @@ -194,13 +202,209 @@ void examine_files(char * hdf5_file_name, /* functions supporting recovery proper */ + +/* at present, this function must be used with binary journal files only. */ +hbool_t apply_journal_file(char * hdf5_file_path_ptr, + off_t hdf5_file_len, + off_t sb_offset, + int sb_ver, + haddr_t hdf5_base_addr, + char * jnl_file_path_ptr, + off_t jnl_file_len, + size_t header_length, + hbool_t human_readable, + int hdf5_offset_width, + int hdf5_length_width, + uint64_t max_trans_num, + haddr_t max_eoa, + size_t max_body_len, + unsigned verbosity); + +hbool_t mark_hdf5_file_recovered(char * hdf5_file_path_ptr); + +/* at present, this function must be used with binary journal files only. */ +hbool_t scan_journal_file(char * file_path_ptr, + off_t file_len, + size_t header_length, + hbool_t human_readable, + int hdf5_offset_width, + int hdf5_length_width, + uint64_t * max_trans_num_ptr, + haddr_t * max_eoa_ptr, + size_t * max_body_len_ptr, + unsigned verbosity); + +hbool_t update_hdf5_eoa(char * hdf5_file_path_ptr, + int hdf5_fd, + off_t hdf5_file_len, + off_t sb_offset, + int hdf5_offset_width, + int sb_ver, + haddr_t base_addr, + haddr_t new_eoa, + unsigned verbosity); + hbool_t verify_files(char * hdf5_file_name, + off_t * hdf5_file_len_ptr, + off_t * hdf5_sb_offset_ptr, + int * hdf5_sb_ver_ptr, + haddr_t * hdf5_base_addr_ptr, char * journal_file_name, + off_t * jnl_file_len_ptr, + size_t * jnl_header_len_ptr, hbool_t force, + hbool_t * human_readable_ptr, + int * offset_width_ptr, + int * length_width_ptr, unsigned verbosity, hbool_t * error_ptr); +/* binary journal file related #defines, function declarations, and global + * variable definitions. + */ + +#define JF__UNDEFINED_MSG 0 +#define JF__BEGIN_TRANS_MSG 1 +#define JF__JNL_ENTRY_MSG 2 +#define JF__END_TRANS_MSG 3 +#define JF__EOA_MSG 4 +#define JF__INVALID_MSG 5 + +hbool_t bjf__chksum_entry_body(int fd, + off_t file_len, + off_t offset, + off_t * new_offset_ptr, + int * msg_type_ptr, + size_t body_length, + uint32_t * chksum_ptr, + unsigned verbosity); + +hbool_t bjf__load_begin_trans_msg(int fd, + off_t file_len, + off_t offset, + off_t * new_offset_ptr, + int * msg_type_ptr, + int msg_ver, + uint64_t * trans_num_ptr, + unsigned verbosity); + +hbool_t bjf__load_chksum(int fd, + off_t file_len, + off_t offset, + off_t * new_offset_ptr, + int * msg_type_ptr, + uint32_t * chksum_ptr, + unsigned verbosity); + +hbool_t bjf__load_end_trans_msg(int fd, + off_t file_len, + off_t offset, + off_t * new_offset_ptr, + int * msg_type_ptr, + int msg_ver, + uint64_t * trans_num_ptr, + unsigned verbosity); + +hbool_t bjf__load_entry_body(int fd, + off_t file_len, + off_t offset, + off_t * new_offset_ptr, + int * msg_type_ptr, + size_t body_length, + char * buf_ptr, + size_t buf_len, + uint32_t * chksum_ptr, + unsigned verbosity); + +hbool_t bjf__load_eoa_msg(int fd, + off_t file_len, + off_t offset, + off_t * new_offset_ptr, + int * msg_type_ptr, + int msg_ver, + haddr_t * eoa_ptr, + int hdf5_offset_width, + unsigned verbosity); + +hbool_t bjf__load_jnl_entry_msg(int fd, + off_t file_len, + off_t offset, + off_t * new_offset_ptr, + int * msg_type_ptr, + int msg_ver, + uint64_t * trans_num_ptr, + haddr_t * hdf5_offset_ptr, + int hdf5_offset_width, + size_t * hdf5_length_ptr, + int hdf5_length_width, + char * buf_ptr, + size_t buf_len, + unsigned verbosity); + +hbool_t bjf__load_length(int fd, + off_t file_len, + off_t offset, + off_t * new_offset_ptr, + int * msg_type_ptr, + size_t * hdf5_length_ptr, + int hdf5_length_width, + uint32_t * chksum_ptr, + unsigned verbosity); + +hbool_t bjf__load_next_msg(int fd, + off_t file_len, + off_t offset, + off_t * new_offset_ptr, + int * msg_type_ptr, + uint64_t * trans_num_ptr, + haddr_t * hdf5_offset_ptr, + int hdf5_offset_width, + size_t * hdf5_length_ptr, + int hdf5_length_width, + haddr_t * eoa_ptr, + char * buf_ptr, + size_t buf_len, + unsigned verbosity); + +hbool_t bjf__load_offset(int fd, + off_t file_len, + off_t offset, + off_t * new_offset_ptr, + int * msg_type_ptr, + haddr_t * hdf5_offset_ptr, + int hdf5_offset_width, + uint32_t * chksum_ptr, + unsigned verbosity); + +hbool_t bjf__load_trans_num(int fd, + off_t file_len, + off_t offset, + off_t * new_offset_ptr, + int * msg_type_ptr, + uint64_t * trans_num_ptr, + uint32_t * chksum_ptr, + unsigned verbosity); + + +/* Unfortunately, H5_checksum_metadata() gives different results depending on + * how the data is fed to it. Hence, to duplicate the checksum computed on the + * library side, we must load the entire metadata journal entry body into RAM + * and compute the checksum in one call. + * + * As we don't know the size of a journal entry body until we read its journal + * entry message, a great deal of mallocing and freeing would be required if + * we allocated each buffer as needed, and then freed it when we were done + * computing the check sum. + * + * Instead, we will allocate a global buffer for this purpose, and then increase + * its size as necessary -- hence the following body_buf and body_buf_len fields. + */ + +char * body_buf = NULL; +size_t body_buf_len = 0; + + /**************************************************************************/ /********************* HDF5 File Investigation Code ***********************/ /**************************************************************************/ @@ -240,7 +444,7 @@ find_super_block(int fd, uint8_t sig_buf[H5F_SIGNATURE_LEN + 1]; hbool_t found = FALSE; hbool_t success = TRUE; - hbool_t verbose = FALSE; + unsigned int verbosity = 0; off_t offset = 0; if ( ( fd < 0 ) || @@ -257,17 +461,17 @@ find_super_block(int fd, success = FALSE; - if ( verbose ) { + if ( verbosity > 0 ) { HDfprintf(stderr, "%s: Target file is not an HDF5 file.\n"); } } else if ( ! load_buf_from_file(fd, file_len, offset, (size_t)H5F_SIGNATURE_LEN, sig_buf, - verbose, fcn_name) ) { + verbosity, fcn_name, NULL) ) { success = FALSE; - if ( verbose ) { + if ( verbosity > 0 ) { HDfprintf(stderr, "%s: load_buf_from_file() failed.\n", fcn_name); @@ -328,7 +532,7 @@ get_sb_base_addr(int fd, uint8_t addr_buf[MAX_ADDR_SIZE + 1]; const uint8_t * buf_ptr = addr_buf; hbool_t success = TRUE; - hbool_t verbose = FALSE; + unsigned int verbosity = 0; off_t sb_base_addr_offset; haddr_t sb_base_addr; @@ -355,11 +559,11 @@ get_sb_base_addr(int fd, if ( ! load_buf_from_file(fd, file_len, sb_base_addr_offset, (size_t)offset_size, addr_buf, - verbose, fcn_name) ) { + verbosity, fcn_name, NULL) ) { success = FALSE; - if ( verbose ) { + if ( verbosity > 0 ) { HDfprintf(stderr, "%s: load_buf_from_file() failed.\n", fcn_name); @@ -372,7 +576,7 @@ get_sb_base_addr(int fd, success = FALSE; - if ( verbose ) { + if ( verbosity > 0 ) { HDfprintf(stdout, "%s: Unexpected buf_ptr after address_decode().\n", @@ -467,16 +671,18 @@ get_sb_base_addr(int fd, hbool_t get_journaling_status(char * file_path_ptr, - off_t * sb_offset_ptr, - haddr_t * base_addr_ptr, - int * offset_size_ptr, - int * length_size_ptr, - off_t * eoa_offset_ptr, - int32_t * magic_ptr, - char * jnl_file_name_ptr, - hbool_t * error_ptr, - hbool_t examine, - unsigned verbosity) + off_t * file_len_ptr, + off_t * sb_offset_ptr, + int * sb_version_ptr, + haddr_t * base_addr_ptr, + int * offset_size_ptr, + int * length_size_ptr, + off_t * eoa_offset_ptr, + int32_t * magic_ptr, + char * jnl_file_name_ptr, + hbool_t * error_ptr, + hbool_t examine, + unsigned verbosity) { const char * fcn_name = "get_journaling_status():"; const char * indent1 = ""; @@ -500,7 +706,9 @@ get_journaling_status(char * file_path_ptr, haddr_t mdj_msg_addr = HADDR_UNDEF; if ( ( file_path_ptr == NULL ) || + ( file_len_ptr == NULL ) || ( sb_offset_ptr == NULL ) || + ( sb_version_ptr == NULL ) || ( base_addr_ptr == NULL ) || ( offset_size_ptr == NULL ) || ( length_size_ptr == NULL ) || @@ -554,6 +762,8 @@ get_journaling_status(char * file_path_ptr, } + *file_len_ptr = file_len; + if ( file_len == 0 ) { success = FALSE; @@ -644,6 +854,8 @@ get_journaling_status(char * file_path_ptr, HDfprintf(stdout, "%ssuper block version = %d.\n", indent2, sb_version); } + + *sb_version_ptr = sb_version; if ( ( sb_version == 0 ) || ( sb_version == 1 ) ) { @@ -1190,7 +1402,6 @@ get_mdj_msg_addr(int fd, hbool_t phase_change_values_stored; /* version 2 header only */ hbool_t times_stored; /* version 2 header only */ hbool_t success = TRUE; - hbool_t verbose = FALSE; uint8_t buf[64]; const uint8_t * p = buf; uint8_t flags; @@ -1242,7 +1453,7 @@ get_mdj_msg_addr(int fd, offset = (off_t)(base_addr + sb_ext_addr + 2); success = load_buf_from_file(fd, file_len, offset, (size_t)10, - buf, verbose, fcn_name); + buf, verbosity, fcn_name, NULL); if ( ! success ) { @@ -1303,7 +1514,8 @@ get_mdj_msg_addr(int fd, offset = (off_t)(base_addr + sb_ext_addr + 5); success = load_buf_from_file(fd, file_len, offset, (size_t)1, - &flags, verbose, fcn_name); + &flags, verbosity, fcn_name, + NULL); } if ( success ) { /* decode the flags we care about */ @@ -1406,7 +1618,7 @@ get_mdj_msg_addr(int fd, success = load_buf_from_file(fd, file_len, offset, (size_t)size_of_chunk_0_size, - buf, verbose, fcn_name); + buf, verbosity, fcn_name, NULL); } if ( success ) { @@ -1593,7 +1805,6 @@ get_mdj_msg_addr__scan_chunk(int fd, uint16_t msg_data_size; int null_msg_count = 0; hbool_t success = TRUE; - hbool_t verbose = FALSE; haddr_t cum_msg_size = 0; haddr_t signature_size = 0; /* version 2 header only */ haddr_t msg_hdr_size; @@ -1662,7 +1873,8 @@ get_mdj_msg_addr__scan_chunk(int fd, success = load_buf_from_file(fd, file_len, offset, (size_t)H5O_SIZEOF_MAGIC, - buf, verbose, fcn_name); + buf, verbosity, fcn_name, + NULL); if ( success ) { @@ -1715,7 +1927,7 @@ get_mdj_msg_addr__scan_chunk(int fd, /* load the message type, size, flags, and possibly creation order */ success = load_buf_from_file(fd, file_len, offset, (size_t)msg_hdr_size, - buf, verbose, fcn_name); + buf, verbosity, fcn_name, NULL); if ( success ) { @@ -1816,7 +2028,7 @@ get_mdj_msg_addr__scan_chunk(int fd, success = load_buf_from_file(fd, file_len, offset, (size_t)(addr_size + length_size + 1), - buf, verbose, fcn_name); + buf, verbosity, fcn_name, NULL); if ( success ) { @@ -1826,7 +2038,7 @@ get_mdj_msg_addr__scan_chunk(int fd, success = FALSE; - if ( verbose ) { + if ( verbosity > 2 ) { HDfprintf(stdout, "%s: %s %s\n", fcn_name, @@ -1844,7 +2056,7 @@ get_mdj_msg_addr__scan_chunk(int fd, success = FALSE; - if ( verbose ) { + if ( verbosity > 2 ) { HDfprintf(stdout, "%s: %s %s\n", fcn_name, @@ -1966,7 +2178,7 @@ get_mdj_msg_addr__scan_chunk(int fd, } } /* end while */ - if ( verbose ) { + if ( verbosity > 2 ) { HDfprintf(stdout, "%s: exiting while loop.\n", fcn_name); HDfprintf(stdout, "%s: chunk_size = 0x%llx\n", fcn_name, @@ -2042,7 +2254,6 @@ get_mdj_msg_data(int fd, const char * indent2 = "\t"; hbool_t journaling_enabled = FALSE; hbool_t success = TRUE; - hbool_t verbose = FALSE; uint8_t buf[MAX_MDJ_MSG_LEN + 1]; uint8_t * p; uint16_t flags; @@ -2086,7 +2297,7 @@ get_mdj_msg_data(int fd, success = load_buf_from_file(fd, file_len, offset, (size_t)MDJ_MSG_HDR_LEN, - buf, verbose, fcn_name); + buf, verbosity, fcn_name, NULL); } if ( success ) { @@ -2164,7 +2375,7 @@ get_mdj_msg_data(int fd, success = load_buf_from_file(fd, file_len, offset, (size_t)(path_len + 1), - buf, verbose, fcn_name); + buf, verbosity, fcn_name, NULL); } if ( ( success ) && ( journaling_enabled ) ) { @@ -2240,8 +2451,8 @@ get_offset_and_length_size(int fd, const char * fcn_name = "get_offset_and_length_size()"; uint8_t buf[2]; hbool_t success = TRUE; - hbool_t verbose = FALSE; off_t offset; + unsigned int verbosity = 0; int offset_size; int length_size; @@ -2265,11 +2476,11 @@ get_offset_and_length_size(int fd, offset = sb_offset + H5F_SIGNATURE_LEN + 1; if ( ! load_buf_from_file(fd, file_len, offset, (size_t)2, - buf, verbose, fcn_name) ) { + buf, verbosity, fcn_name, NULL) ) { success = FALSE; - if ( verbose ) { + if ( verbosity > 2 ) { HDfprintf(stderr, "%s: load_buf_from_file() failed.\n", fcn_name); @@ -2288,7 +2499,7 @@ get_offset_and_length_size(int fd, success = FALSE; - if ( verbose ) { + if ( verbosity > 2 ) { HDfprintf(stderr, "%s found non-positive offset size: %d\n", fcn_name, offset_size); @@ -2306,7 +2517,8 @@ get_offset_and_length_size(int fd, success = FALSE; - if ( verbose ) { + if ( verbosity > 2 ) { + HDfprintf(stderr, "%s found non-positive length size: %d\n", fcn_name, length_size); @@ -2356,7 +2568,7 @@ get_sb_extension_addr(int fd, uint8_t addr_buf[MAX_ADDR_SIZE + 1]; const uint8_t * buf_ptr = addr_buf; hbool_t success = TRUE; - hbool_t verbose = FALSE; + unsigned int verbosity = 0; off_t sb_ext_offset; haddr_t sb_ext_addr; @@ -2383,11 +2595,11 @@ get_sb_extension_addr(int fd, if ( ! load_buf_from_file(fd, file_len, sb_ext_offset, (size_t)offset_size, addr_buf, - verbose, fcn_name) ) { + verbosity, fcn_name, NULL) ) { success = FALSE; - if ( verbose ) { + if ( verbosity > 2 ) { HDfprintf(stderr, "%s: load_buf_from_file() failed.\n", fcn_name); @@ -2400,7 +2612,7 @@ get_sb_extension_addr(int fd, success = FALSE; - if ( verbose ) { + if ( verbosity > 2 ) { HDfprintf(stdout, "%s: Unexpected buf_ptr after address_decode().\n", @@ -2454,7 +2666,7 @@ get_sb_ext_obj_hdr_ver(int fd, */ uint8_t buf[H5O_SIZEOF_MAGIC + 2]; hbool_t success = TRUE; - hbool_t verbose = FALSE; + unsigned int verbosity = 0; int ohdr_ver; off_t ohdr_offset; @@ -2471,11 +2683,11 @@ get_sb_ext_obj_hdr_ver(int fd, if ( ! load_buf_from_file(fd, file_len, ohdr_offset, (size_t)(H5O_SIZEOF_MAGIC + 1), buf, - verbose, fcn_name) ) { + verbosity, fcn_name, NULL) ) { success = FALSE; - if ( verbose ) { + if ( verbosity > 2 ) { HDfprintf(stderr, "%s: load_buf_from_file() failed.\n", fcn_name); @@ -2499,7 +2711,7 @@ get_sb_ext_obj_hdr_ver(int fd, success = FALSE; - if ( verbose ) { + if ( verbosity > 2 ) { HDfprintf(stderr, "%s: sb_ext_addr doesn't seem to reference\n", @@ -2515,7 +2727,7 @@ get_sb_ext_obj_hdr_ver(int fd, if ( success ) { - if ( verbose ) { + if ( verbosity > 2 ) { HDfprintf(stdout, "%s: ohdr_ver = %d.\n", fcn_name, (int)ohdr_ver); } @@ -2557,7 +2769,7 @@ get_sb_version(int fd, const char * fcn_name = "get_sb_version(): "; uint8_t ver_buf; hbool_t success = TRUE; - hbool_t verbose = FALSE; + unsigned int verbosity = 0; off_t version_offset; int version; @@ -2575,11 +2787,11 @@ get_sb_version(int fd, if ( ! load_buf_from_file(fd, file_len, version_offset, (size_t)1, &ver_buf, - verbose, fcn_name) ) { + verbosity, fcn_name, NULL) ) { success = FALSE; - if ( verbose ) { + if ( verbosity > 2 ) { HDfprintf(stderr, "%s: load_buf_from_file() failed.\n", fcn_name); @@ -2593,7 +2805,7 @@ get_sb_version(int fd, if ( success ) { - if ( verbose ) { + if ( verbosity > 2 ) { HDfprintf(stdout, "%s: version = %d.\n", fcn_name, (int)version); } @@ -2625,7 +2837,16 @@ get_sb_version(int fd, * * Programmer: JRM -- 2/26/09 * - * Changes: None. + * Changes: Added io_err_ptr parameter. If defined (i.e. eof_ptr + * isn't NULL), this parameter allows the function to + * inform the caller that the failure was caused by an + * attempt to read beyond the end of file. + * + * This is necessary, as when scanning the journal file, + * we will typically find it to be incomplete, and we need + * to distinguish between an eof error, and a system or + * file I/O error. + * JRM -- 5/22/09 * **************************************************************************/ @@ -2635,8 +2856,9 @@ load_buf_from_file(int fd, off_t offset, size_t buf_len, uint8_t *buf_ptr, - hbool_t verbose, - const char * desc) + unsigned int verbosity, + const char * desc, + hbool_t * eof_ptr) { const char * fcn_name = "load_buf_from_file()"; hbool_t success = TRUE; @@ -2655,7 +2877,12 @@ load_buf_from_file(int fd, success = FALSE; - if ( verbose ) { + if ( eof_ptr != NULL ) { + + *eof_ptr = TRUE; + } + + if ( verbosity > 2 ) { HDfprintf(stderr, "%s:%s: file too short.\n", fcn_name, desc); } @@ -2667,7 +2894,7 @@ load_buf_from_file(int fd, success = FALSE; - if ( verbose ) { + if ( verbosity > 2 ) { HDfprintf(stderr, "%s:%s: lseek() to 0x%llx failed with errno %d(%s).\n", @@ -2685,7 +2912,7 @@ load_buf_from_file(int fd, success = FALSE; - if ( verbose ) { + if ( verbosity > 2 ) { HDfprintf(stderr, "%s:%s: read() at 0x%llx failed with errno %d(%s).\n", @@ -2699,7 +2926,7 @@ load_buf_from_file(int fd, success = FALSE; - if ( verbose ) { + if ( verbosity > 2 ) { HDfprintf(stderr, "%s:%s: read() at 0x%llx read wrong # of bytes: %d(%d).\n", @@ -2757,15 +2984,25 @@ load_buf_from_file(int fd, * Also added file_len parameter -- now we are guaranteed * that the file exists and has positive length on entry. * + * JRM -- 5/15/09 + * Updated function to handle the extra fields that appear + * in the header when human_readable is false. This included + * adding the offset_width_ptr and length_width_ptr fields. + * Note that *offset_width_ptr and *length_width_ptr are + * undefined if *human_readable_ptr is TRUE. + * **************************************************************************/ hbool_t get_jnl_header_info(char * file_path_ptr, off_t file_len, + size_t * header_length_ptr, int32_t * version_ptr, char * target_file_name_ptr, int32_t * magic_ptr, hbool_t * human_readable_ptr, + int * offset_width_ptr, + int * length_width_ptr, hbool_t examine, unsigned verbosity) { @@ -2776,7 +3013,10 @@ get_jnl_header_info(char * file_path_ptr, char target_file_name[MAX_PATH_LEN + 1]; hbool_t human_readable; hbool_t success = TRUE; + size_t header_length; int version; + int offset_width; + int length_width; int32_t magic; FILE * file_ptr = NULL; FILE * err_file_ptr = stderr; @@ -2786,7 +3026,9 @@ get_jnl_header_info(char * file_path_ptr, ( version_ptr == NULL ) || ( target_file_name_ptr == NULL ) || ( magic_ptr == NULL ) || - ( human_readable_ptr == NULL ) ) { + ( human_readable_ptr == NULL ) || + ( offset_width_ptr == NULL ) || + ( length_width_ptr == NULL ) ) { success = FALSE; HDfprintf(stderr, "%s: bad param(s) on entry.\n", fcn_name); @@ -2853,6 +3095,17 @@ get_jnl_header_info(char * file_path_ptr, HDfprintf(err_file_ptr, "%sbad first char of header -- not a journal file.\n", indent1); + } else { + + header_length = strlen(buf); + + if ( buf[(int)header_length - 1] != '\n' ) { + + success = FALSE; + HDfprintf(err_file_ptr, + "%sheader line too long -- not a journal file.\n", + indent1); + } } } @@ -3065,6 +3318,112 @@ get_jnl_header_info(char * file_path_ptr, } } + if ( ( success ) && ( ! human_readable ) ) { /* get offset width */ + + char * offset_width_tag = NULL; + char * offset_width_str = NULL; + long tmp_offset_width; + + offset_width_tag = HDstrtok(NULL, " "); + + if ( ( offset_width_tag == NULL ) || + ( strcmp(offset_width_tag, H5C2_JNL__OFFSET_WIDTH_TAG) != 0 ) ) { + + success = FALSE; + + HDfprintf(err_file_ptr, "%sUnexpected offset width tag \"%s\".\n", + indent1, offset_width_tag ); + + } else if ( (offset_width_str = HDstrtok(NULL, " ")) == NULL ) { + + success = FALSE; + + + HDfprintf(err_file_ptr, "%sno offset width string in header.\n", + indent1); + + } else if ( ( (tmp_offset_width = HDstrtol(offset_width_str, NULL, 10)) + == LONG_MIN ) || + ( tmp_offset_width == LONG_MAX ) ) { + + success = FALSE; + + HDfprintf(err_file_ptr, "%serror reading offset width %s (%d)\n", + indent1, errno, strerror(errno)); + + } else if ( ! ( ( tmp_offset_width == 2 ) || + ( tmp_offset_width == 4 ) || + ( tmp_offset_width == 8 ) ) ) { + + success = FALSE; + + HDfprintf(err_file_ptr, "%sInvalid offset width %d.\n", + indent1, (int)tmp_offset_width); + + } else { + + offset_width = (int)tmp_offset_width; + + if ( verbosity > 0 ) { + + HDfprintf(stdout, "%soffset width = %d\n", indent2, offset_width); + } + } + } + + if ( ( success ) && ( ! human_readable ) ) { /* get length width */ + + char * length_width_tag = NULL; + char * length_width_str = NULL; + long tmp_length_width; + + length_width_tag = HDstrtok(NULL, " "); + + if ( ( length_width_tag == NULL ) || + ( strcmp(length_width_tag, H5C2_JNL__LENGTH_WIDTH_TAG) != 0 ) ) { + + success = FALSE; + + HDfprintf(err_file_ptr, "%sUnexpected length width tag \"%s\".\n", + indent1, length_width_tag ); + + } else if ( (length_width_str = HDstrtok(NULL, " ")) == NULL ) { + + success = FALSE; + + + HDfprintf(err_file_ptr, "%sno length width string in header.\n", + indent1); + + } else if ( ( (tmp_length_width = HDstrtol(length_width_str, NULL, 10)) + == LONG_MIN ) || + ( tmp_length_width == LONG_MAX ) ) { + + success = FALSE; + + HDfprintf(err_file_ptr, "%serror reading length width %s (%d)\n", + indent1, errno, strerror(errno)); + + } else if ( ! ( ( tmp_length_width == 2 ) || + ( tmp_length_width == 4 ) || + ( tmp_length_width == 8 ) ) ) { + + success = FALSE; + + HDfprintf(err_file_ptr, "%sInvalid length width %d.\n", + indent1, (int)tmp_length_width); + + } else { + + length_width = (int)tmp_length_width; + + if ( verbosity > 0 ) { + + HDfprintf(stdout, "%slength width = %d\n", indent2, length_width); + } + } + } + if ( file_ptr != NULL ) { if ( verbosity > 0 ) { @@ -3086,150 +3445,516 @@ get_jnl_header_info(char * file_path_ptr, if ( success ) { /* copy results into provided locations */ + *header_length_ptr = header_length; *version_ptr = version; strcpy(target_file_name_ptr, target_file_name); *magic_ptr = magic; *human_readable_ptr = human_readable; + if ( ! human_readable ) { + + *offset_width_ptr = offset_width; + *length_width_ptr = length_width; + } } return(success); } /* get_jnl_header_info() */ - -/**************************************************************************/ -/*********************** File Examination Code ****************************/ -/**************************************************************************/ -/* The following functions are used to support the examine function -- in */ -/* which the supplied files are examined to determine their status, but */ -/* no action is taken. */ -/**************************************************************************/ - + /************************************************************************** * - * Function: examine_files() + * Function: scan_journal_file * - * Purpose: Scan the supplied file(s) to determine their status, - * and report. Do nothing. + * Purpose: Scan the supplied journal file to determine whether it + * contains any completed transactions. If it does, also + * report the maximum address that appears in an eoa message, + * the size of the largest journal entry body, and the + * number of the last complete transaction. * - * Return: void + * The function assumes that the header has already been + * examined, and that its length is in the header_length. + * If the journal file is binary, it also assumes that the + * offset_width and length_width parameters contain the + * widths of offsets and lengths in the binary journal file + * (and also in the target HDF5 file). * - * Programmer: JRM -- 3/17/09 + * The function also assumes that the journal file is + * closed on entry. + * + * Note: While this function has been designed with both + * human readable and binary journal files in mind, + * in its first incarnation, it only supports binary + * journal files. + * + * Return: TRUE if no errors are detected, and FALSE otherwise. + * + * Programmer: JRM -- 5/20/09 * * Changes: None. * **************************************************************************/ -void -examine_files(char * hdf5_file_name, - char * journal_file_name, - unsigned verbosity) +hbool_t +scan_journal_file(char * file_path_ptr, + off_t file_len, + size_t header_length, + hbool_t human_readable, + int hdf5_offset_width, + int hdf5_length_width, + uint64_t * max_trans_num_ptr, + haddr_t * max_eoa_ptr, + size_t * max_body_len_ptr, + unsigned verbosity) { - /* const char * fcn_name = "examine_files()"; */ - const char * indent1 = "\t"; - const char * indent2 = "\t\t"; - char jnl_file_name[H5C2__MAX_JOURNAL_FILE_NAME_LEN + 1]; - char jnl_target_file_name[MAX_PATH_LEN + 1]; - hbool_t error = FALSE; - hbool_t journal_can_be_run = FALSE; - hbool_t journal_file_exists = FALSE; - hbool_t journal_file_ok = FALSE; - hbool_t jnl_human_readable; - int offset_size; - int length_size; - int jnl_file_version; - int32_t magic; - int32_t jnl_magic; - off_t eoa_offset; - off_t sb_offset; - off_t journal_file_len = 0; - haddr_t base_addr; + const char * fcn_name = "scan_journal_file()"; + hbool_t trans_in_progress = FALSE; + hbool_t proceed = TRUE; + int fd; + int msg_type = JF__UNDEFINED_MSG; + size_t hdf5_length; + size_t max_hdf5_length = 0; + haddr_t eoa; + haddr_t max_eoa = HADDR_UNDEF; + haddr_t hdf5_offset; + uint64_t cur_trans_num; + uint64_t trans_num = 0; + uint64_t max_trans_num = 0; + off_t offset; + off_t new_offset; + - if ( hdf5_file_name == NULL ) { + if ( ( file_path_ptr == NULL ) || + ( file_len <= 0 ) || + ( max_trans_num_ptr == NULL ) || + ( max_eoa_ptr == NULL ) || + ( max_body_len_ptr == NULL ) ) { - HDfprintf(stdout, "No target HDF5 file supplied.\n"); + proceed = FALSE; + HDfprintf(stdout, "%s: bad params on entry.\n", fcn_name); + + } else if ( ( body_buf != NULL ) || ( body_buf_len != 0 ) ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: body buffer already allocated?!?\n", fcn_name); } else { - journal_can_be_run = get_journaling_status(hdf5_file_name, - &sb_offset, - &base_addr, - &offset_size, - &length_size, - &eoa_offset, - &magic, - jnl_file_name, - &error, - TRUE, - verbosity); - if ( error ) { + body_buf_len = 1024; + body_buf = (char *)HDmalloc(body_buf_len); - HDfprintf(stdout, - "\nEncountered errors examining %s -- can't run journal.\n", - hdf5_file_name); + if ( body_buf == NULL ) { + + body_buf_len = 0; + proceed = FALSE; + HDfprintf(stderr, "%s: initial allocation of body buffer failed.\n", + fcn_name); } } - if ( journal_file_name == NULL ) { - - HDfprintf(stdout, "\nNo target journal file supplied -- exiting.\n"); + if ( ( proceed ) && ( verbosity > 0 ) ) { - } else { + HDfprintf(stdout, "Scanning journal file entries:\n"); + } - HDfprintf(stdout, "\nExamining the putative HDF5 journal file %s:\n", - journal_file_name); + if ( proceed ) { if ( verbosity > 0 ) { - HDfprintf(stdout, - "%sattempting to determine journal file length...\n", - indent1); + HDfprintf(stdout, "\tattempting to open %s...\n", file_path_ptr); } - if ( ! get_file_len(journal_file_name, &journal_file_len) ) { - journal_file_exists = FALSE; - journal_file_ok = FALSE; - HDfprintf(stdout, - "%sCan't get journal file length -- does it exist?\n\n", - indent1); + /* In the following call, the mode should be ignored. */ + fd = HDopen(file_path_ptr, O_RDONLY, S_IRUSR); - } else if ( journal_file_len == 0 ) { + if ( fd == -1 ) { - journal_file_exists = TRUE; + proceed = FALSE; + HDfprintf(stderr, "\tcan't open %s.\n", file_path_ptr); - HDfprintf(stdout, "%sthe file %s is empty.\n\n", - indent1, journal_file_name); - } else { - journal_file_exists = TRUE; - if ( verbosity > 0 ) { - HDfprintf(stdout, "%sfile length = %lld\n", - indent2, (long long)journal_file_len); + HDfprintf(stdout, "\topened file successfully.\n"); } } } - if ( ( journal_file_exists) && ( journal_file_len > 0 ) ) { + if ( proceed ) { + offset = (off_t)header_length; + } - journal_file_ok = get_jnl_header_info(journal_file_name, - journal_file_len, - &jnl_file_version, - jnl_target_file_name, - &jnl_magic, - &jnl_human_readable, - TRUE, - verbosity); + while ( ( proceed ) && ( msg_type != JF__INVALID_MSG ) ) { - if ( ! journal_file_ok ) { + if ( human_readable ) { - HDfprintf(stdout, "\nerrors reading %s. Journal un-useable.\n\n", - journal_file_name); + HDfprintf(stderr, "%s: human readable not yet implemented.\n", + fcn_name); + proceed = FALSE; + + } else { + + proceed = bjf__load_next_msg(fd, + file_len, + offset, + &new_offset, + &msg_type, + &trans_num, + &hdf5_offset, + hdf5_offset_width, + &hdf5_length, + hdf5_length_width, + &eoa, + NULL, + (size_t)0, + verbosity); + } + + if ( proceed ) { + + switch ( msg_type ) { + + case JF__UNDEFINED_MSG: + proceed = FALSE; + HDfprintf(stderr, + "%s: bjf__load_next_msg() returned undef msg?!?\n", + fcn_name); + break; + + case JF__BEGIN_TRANS_MSG: + if ( trans_in_progress ) { + + /* At present, nested transaction are forbidden -- + * scream and die if we encounter one. + */ + + proceed = FALSE; + HDfprintf(stderr, "%s -- Exiting.\n", + "Encountered nested transaction in journal"); + + } else if ( trans_num != max_trans_num + 1 ) { + + /* we may decide to drop this invarient eventually, + * but we will check it for now, and scream and die + * if it fails. + */ + proceed = FALSE; + HDfprintf(stderr, "%s -- Exiting.\n", + "Encountered out of sequence transaction in journal"); + + } else { + + trans_in_progress = TRUE; + cur_trans_num = trans_num; + + if ( verbosity > 1 ) { + + HDfprintf(stdout, "\tBegin Trans: %lld.\n", + (long long)cur_trans_num); + } + } + break; + + case JF__JNL_ENTRY_MSG: + if ( ! trans_in_progress ) { + + proceed = FALSE; + HDfprintf(stderr, "%s -- Exiting.\n", + "Encountered jnl entry outside of transaction"); + + } else if ( trans_num != cur_trans_num ) { + + proceed = FALSE; + HDfprintf(stderr, "%s -- Exiting.\n", + "Encountered jnl entry with bad trans num"); + + } else { + + if ( hdf5_length > max_hdf5_length ) { + + max_hdf5_length = hdf5_length; + } + + if ( verbosity > 1 ) { + + HDfprintf(stdout, "\tJnl Entry: trans = %lld, ", + (long long)cur_trans_num); + + HDfprintf(stdout, "offset = 0x%llx, len = 0x%llx.\n", + (unsigned long long)hdf5_offset, + (unsigned long long)hdf5_length); + } + } + break; + + case JF__END_TRANS_MSG: + if ( ! trans_in_progress ) { + + proceed = FALSE; + HDfprintf(stderr, "%s -- Exiting.\n", + "Encountered trans end msg outside of transaction"); + + } else if ( trans_num != cur_trans_num ) { + + proceed = FALSE; + HDfprintf(stderr, "%s -- Exiting.\n", + "Encountered trans end with bad trans num"); + + } else { + + trans_in_progress = FALSE; + max_trans_num = cur_trans_num; + + if ( verbosity > 1 ) { + + HDfprintf(stdout, "\tBegin Trans: %lld.\n", + (long long)cur_trans_num); + } + } + break; + + case JF__EOA_MSG: + if ( ( max_eoa == HADDR_UNDEF ) || + ( max_eoa < eoa ) ) { + + max_eoa = eoa; + } + + if ( verbosity > 1 ) { + + HDfprintf(stdout, "\tEOA message: 0x%llx.\n", + (unsigned long long)eoa); + } + break; + + case JF__INVALID_MSG: + if ( verbosity > 1 ) { + + HDfprintf(stdout, + "\tinvalid message -- end of journal.\n"); + } + break; + + default: + proceed = FALSE; + HDfprintf(stderr, + "%s: bjf__load_next_msg() returned unknown msg?!?\n", + fcn_name); + break; + + } + } + + if ( proceed ) { + + offset = new_offset; + } + } + + if ( fd != -1 ) { + + if ( verbosity > 0 ) { + + HDfprintf(stdout, "\tattempting to close %s...\n", file_path_ptr); + } + + if ( HDclose(fd) != 0 ) { + + HDfprintf(stderr, "%s: Error closing %s. errno = %s (%s).\n", + fcn_name, file_path_ptr, errno, HDstrerror(errno)); + + } else if ( verbosity > 0 ) { + + HDfprintf(stdout, "\tclosed file successfully\n"); + } + } + + + if ( proceed ) { + + *max_trans_num_ptr = max_trans_num; + *max_eoa_ptr = max_eoa; + *max_body_len_ptr = max_hdf5_length; + + if ( verbosity > 0 ) { + + HDfprintf(stdout, "Finished scanning journal file:\n"); + + if ( max_trans_num == 0 ) { + + HDfprintf(stdout, "\tNo complete transactions.\n"); + + } else { + + HDfprintf(stdout, "\t%lld complete transactions.\n", + (unsigned long long)max_trans_num); + HDfprintf(stdout, "\tmax journal entry body length = %lld.\n", + (long long)max_hdf5_length); + } + + HDfprintf(stdout, "\tMax eoa = 0x%llx.\n", + (unsigned long long)max_eoa); + } + } + + if ( body_buf != NULL ) { + + HDfree(body_buf); + body_buf = NULL; + body_buf_len = 0; + } + + return(proceed); + +} /* scan_journal_file() */ + + +/**************************************************************************/ +/*********************** File Examination Code ****************************/ +/**************************************************************************/ +/* The following functions are used to support the examine function -- in */ +/* which the supplied files are examined to determine their status, but */ +/* no action is taken. */ +/**************************************************************************/ + +/************************************************************************** + * + * Function: examine_files() + * + * Purpose: Scan the supplied file(s) to determine their status, + * and report. Do nothing. + * + * Return: void + * + * Programmer: JRM -- 3/17/09 + * + * Changes: None. + * + **************************************************************************/ + +void +examine_files(char * hdf5_file_name, + char * journal_file_name, + unsigned verbosity) +{ + /* const char * fcn_name = "examine_files()"; */ + const char * indent1 = "\t"; + const char * indent2 = "\t\t"; + char jnl_file_name[H5C2__MAX_JOURNAL_FILE_NAME_LEN + 1]; + char jnl_target_file_name[MAX_PATH_LEN + 1]; + hbool_t error = FALSE; + hbool_t journal_can_be_run = FALSE; + hbool_t journal_file_exists = FALSE; + hbool_t journal_file_ok = FALSE; + hbool_t jnl_human_readable; + int sb_version; + int offset_size; + int length_size; + int jnl_offset_size; + int jnl_length_size; + int jnl_file_version; + int32_t magic; + int32_t jnl_magic; + size_t header_length = 0; + off_t eoa_offset; + off_t sb_offset; + off_t hdf5_file_len; + off_t journal_file_len = 0; + haddr_t base_addr; + + if ( hdf5_file_name == NULL ) { + + HDfprintf(stdout, "No target HDF5 file supplied.\n"); + + } else { + + journal_can_be_run = get_journaling_status(hdf5_file_name, + &hdf5_file_len, + &sb_offset, + &sb_version, + &base_addr, + &offset_size, + &length_size, + &eoa_offset, + &magic, + jnl_file_name, + &error, + TRUE, + verbosity); + if ( error ) { + + HDfprintf(stdout, + "\nEncountered errors examining %s -- can't run journal.\n", + hdf5_file_name); + } + } + + if ( journal_file_name == NULL ) { + + HDfprintf(stdout, "\nNo target journal file supplied -- exiting.\n"); + + } else { + + HDfprintf(stdout, "\nExamining the putative HDF5 journal file %s:\n", + journal_file_name); + + if ( verbosity > 0 ) { + + HDfprintf(stdout, + "%sattempting to determine journal file length...\n", + indent1); + } + + if ( ! get_file_len(journal_file_name, &journal_file_len) ) { + + journal_file_exists = FALSE; + journal_file_ok = FALSE; + HDfprintf(stdout, + "%sCan't get journal file length -- does it exist?\n\n", + indent1); + + } else if ( journal_file_len == 0 ) { + + journal_file_exists = TRUE; + + HDfprintf(stdout, "%sthe file %s is empty.\n\n", + indent1, journal_file_name); + + } else { + + journal_file_exists = TRUE; + + if ( verbosity > 0 ) { + + HDfprintf(stdout, "%sfile length = %lld\n", + indent2, (long long)journal_file_len); + } + } + } + + if ( ( journal_file_exists) && ( journal_file_len > 0 ) ) { + + + journal_file_ok = get_jnl_header_info(journal_file_name, + journal_file_len, + &header_length, + &jnl_file_version, + jnl_target_file_name, + &jnl_magic, + &jnl_human_readable, + &jnl_offset_size, + &jnl_length_size, + TRUE, + verbosity); + + if ( ! journal_file_ok ) { + + HDfprintf(stdout, "\nerrors reading %s. Journal un-useable.\n\n", + journal_file_name); } else { @@ -3335,8 +4060,17 @@ If you are sure you have the correct journal file, go ahead and run\n\ hbool_t verify_files(char * hdf5_file_name, + off_t * hdf5_file_len_ptr, + off_t * hdf5_sb_offset_ptr, + int * hdf5_sb_ver_ptr, + haddr_t * hdf5_base_addr_ptr, char * journal_file_name, + off_t * jnl_file_len_ptr, + size_t * jnl_header_len_ptr, hbool_t force, + hbool_t * human_readable_ptr, + int * offset_width_ptr, + int * length_width_ptr, unsigned verbosity, hbool_t * error_ptr) { @@ -3345,19 +4079,29 @@ verify_files(char * hdf5_file_name, char jnl_target_file_name[MAX_PATH_LEN + 1]; hbool_t proceed = TRUE; hbool_t journal_file_exists = FALSE; - hbool_t jnl_human_readable; - int offset_size; - int length_size; + hbool_t jnl_human_readable = TRUE; + int hdf5_offset_size; + int hdf5_length_size; + int jnl_offset_size = 0; /* a convenient, invalid value */ + int jnl_length_size = 0; /* a convenient, invalid value */ int jnl_file_version; int32_t magic; int32_t jnl_magic; + size_t header_length = 0; off_t eoa_offset; - off_t sb_offset; off_t journal_file_len = 0; - haddr_t base_addr; if ( ( hdf5_file_name == NULL ) || + ( hdf5_file_len_ptr == NULL ) || + ( hdf5_sb_offset_ptr == NULL ) || + ( hdf5_sb_ver_ptr == NULL ) || + ( hdf5_base_addr_ptr == NULL ) || ( journal_file_name == NULL ) || + ( jnl_file_len_ptr == NULL ) || + ( jnl_header_len_ptr == NULL ) || + ( human_readable_ptr == NULL ) || + ( offset_width_ptr == NULL ) || + ( length_width_ptr == NULL ) || ( error_ptr == NULL ) || ( *error_ptr != FALSE ) ) { @@ -3369,10 +4113,12 @@ verify_files(char * hdf5_file_name, if ( proceed ) { proceed = get_journaling_status(hdf5_file_name, - &sb_offset, - &base_addr, - &offset_size, - &length_size, + hdf5_file_len_ptr, + hdf5_sb_offset_ptr, + hdf5_sb_ver_ptr, + hdf5_base_addr_ptr, + &hdf5_offset_size, + &hdf5_length_size, &eoa_offset, &magic, jnl_file_name, @@ -3422,6 +4168,7 @@ verify_files(char * hdf5_file_name, journal_file_exists = TRUE; + *jnl_file_len_ptr = journal_file_len; } } @@ -3432,10 +4179,13 @@ verify_files(char * hdf5_file_name, proceed = get_jnl_header_info(journal_file_name, journal_file_len, + &header_length, &jnl_file_version, jnl_target_file_name, &jnl_magic, &jnl_human_readable, + &jnl_offset_size, + &jnl_length_size, FALSE, verbosity); @@ -3448,12 +4198,34 @@ verify_files(char * hdf5_file_name, } else { + *jnl_header_len_ptr = header_length; + *human_readable_ptr = jnl_human_readable; + *offset_width_ptr = jnl_offset_size; + *length_width_ptr = jnl_length_size; + if ( magic == jnl_magic ) { HDfprintf(stdout, "\nthe journal file %s has matching magic.\n\n", journal_file_name); + if ( ( ! jnl_human_readable ) && + ( ( jnl_offset_size != hdf5_offset_size ) || + ( jnl_length_size != hdf5_length_size ) ) ) { + + proceed = FALSE; + *error_ptr = TRUE; + HDfprintf(stderr, "\n%s %s -- %s\n\n", + "journal and hdf5 file offset and/or", + "length size mismatch", + "recovery canceled."); + HDfprintf(stderr, "\thdf5/jnl offset size = %d/%d\n", + hdf5_offset_size, jnl_offset_size); + HDfprintf(stderr, "\thdf5/jnl length size = %d/%d\n", + hdf5_length_size, jnl_length_size); + + } + } else { proceed = FALSE; @@ -3510,6 +4282,8 @@ verify_files(char * hdf5_file_name, } } } + + *human_readable_ptr = TRUE; } } @@ -3518,8 +4292,2256 @@ verify_files(char * hdf5_file_name, } /* verify_files() */ -/*------------------------------------------------------------------------- - * Function: usage() +/**************************************************************************/ +/******************** HDF5 Journal Application Code ***********************/ +/**************************************************************************/ +/* The following functions are used in the actual application of a */ +/* journal file to a corrupted hdf5 file. */ +/**************************************************************************/ + +/************************************************************************** + * + * Function: apply_journal_file() + * + * Purpose: Apply the supplied journal file to the supplied (presumably + * corrupt) HDF5 fie. + * + * The function assumes that: + * + * 1) The supplied journal file and HDF5 file have been + * examined, and that their magic numbers and offset + * and length sizes match. + * + * 2) That the journal file contains at least one complete + * transaction. + * + * 3) The max eoa listed in the journal file is known, as + * is the offset of the eoa in the hdf5 file. + * + * The function opens the supplied HDF5 and journal files, + * applies in order all journal entries from all completed + * transactions, closes the supplied files, and then marks + * the HDF5 file as being recovered. + * + * Note: While this function has been designed with both + * human readable and binary journal files in mind, + * in its first incarnation, it only supports binary + * journal files. + * + * Return: TRUE if no errors are detected, and FALSE otherwise. + * + * Programmer: JRM -- 5/26/09 + * + * Changes: None. + * + **************************************************************************/ + +hbool_t +apply_journal_file(char * hdf5_file_path_ptr, + off_t hdf5_file_len, + off_t sb_offset, + int sb_ver, + haddr_t hdf5_base_addr, + char * jnl_file_path_ptr, + off_t jnl_file_len, + size_t header_length, + hbool_t human_readable, + int hdf5_offset_width, + int hdf5_length_width, + uint64_t max_trans_num, + haddr_t new_eoa, + size_t max_body_len, + unsigned verbosity) +{ + const char * fcn_name = "scan_journal_file()"; + char * buf = NULL; + hbool_t done = FALSE; + hbool_t trans_in_progress = FALSE; + hbool_t proceed = TRUE; + int hdf5_fd; + int jnl_fd; + int msg_type = JF__UNDEFINED_MSG; + ssize_t bytes_written; + size_t hdf5_length; + haddr_t eoa; + haddr_t hdf5_offset; + uint64_t cur_trans_num; + uint64_t last_trans_num = 0; + uint64_t trans_num = 0; + off_t offset; + off_t new_offset; + + + if ( ( hdf5_file_path_ptr == NULL ) || + ( jnl_file_path_ptr == NULL ) || + ( jnl_file_len <= 0 ) || + ( header_length <= 0 ) || + ( max_trans_num <= 0 ) || + ( new_eoa == HADDR_UNDEF ) || + ( max_body_len <= 0 ) ) { + + proceed = FALSE; + HDfprintf(stdout, "%s: bad params on entry.\n", fcn_name); + + } else if ( human_readable ) { + + proceed = FALSE; + HDfprintf(stderr, + "%s: only binary journal files supported at present.\n", + fcn_name); + } + + if ( ( proceed ) && ( verbosity > 0 ) ) { + + HDfprintf(stdout, "Applying journal file %s to HDF5 file %s:\n", + jnl_file_path_ptr, hdf5_file_path_ptr); + } + + if ( proceed ) { + + if ( verbosity > 1 ) { + + HDfprintf(stdout, + "\tattempting to allocate journal entry body buffer...\n"); + } + + buf = (char *)HDmalloc(max_body_len + 1); + + if (buf == NULL) { + + proceed = FALSE; + HDfprintf(stderr, "%s: buffer allocation failed.\n", fcn_name); + + } else { + + if ( verbosity > 0 ) { + + HDfprintf(stdout, "\tbuffer allocation successful.\n"); + } + } + } + + if ( proceed ) { + + if ( verbosity > 0 ) { + + HDfprintf(stdout, "\tattempting to open journal file %s...\n", + jnl_file_path_ptr); + } + + /* In the following call, the mode should be ignored. */ + jnl_fd = HDopen(jnl_file_path_ptr, O_RDONLY, S_IRUSR); + + if ( jnl_fd == -1 ) { + + proceed = FALSE; + HDfprintf(stderr, "\tcan't open jnl file %s.\n", jnl_file_path_ptr); + + } else { + + if ( verbosity > 0 ) { + + HDfprintf(stdout, "\topened jnl file successfully.\n"); + } + } + } + + if ( proceed ) { + + if ( verbosity > 0 ) { + + HDfprintf(stdout, "\tattempting to open HDF5 file %s...\n", + hdf5_file_path_ptr); + } + + + /* In the following call, the mode should be ignored. */ + hdf5_fd = HDopen(hdf5_file_path_ptr, O_RDWR, S_IRUSR); + + if ( hdf5_fd == -1 ) { + + proceed = FALSE; + HDfprintf(stderr, "\tcan't open hdf5 file %s.\n", + hdf5_file_path_ptr); + + } else { + + if ( verbosity > 0 ) { + + HDfprintf(stdout, "\topened hdf5 file successfully.\n"); + } + } + } + + if ( proceed ) { + + offset = (off_t)header_length; + } + + if ( ( proceed ) && ( verbosity > 0 ) ) { + + HDfprintf(stdout, + "Applying %lld completed transaction to the hdf5 file %s:\n", + (long long)max_trans_num, hdf5_file_path_ptr); + } + + while ( ( proceed ) && ( ! done ) ) { + + if ( human_readable ) { + + HDfprintf(stderr, "%s: human readable not yet implemented.\n", + fcn_name); + proceed = FALSE; + + } else { + + proceed = bjf__load_next_msg(jnl_fd, + jnl_file_len, + offset, + &new_offset, + &msg_type, + &trans_num, + &hdf5_offset, + hdf5_offset_width, + &hdf5_length, + hdf5_length_width, + &eoa, + buf, + max_body_len, + verbosity); + } + + if ( proceed ) { + + switch ( msg_type ) { + + case JF__UNDEFINED_MSG: + proceed = FALSE; + HDfprintf(stderr, + "%s: bjf__load_next_msg() returned undef msg?!?\n", + fcn_name); + break; + + case JF__BEGIN_TRANS_MSG: + if ( trans_in_progress ) { + + /* At present, nested transaction are forbidden -- + * scream and die if we encounter one. + */ + + proceed = FALSE; + HDfprintf(stderr, "%s -- Exiting.\n", + "Encountered nested transaction in journal"); + + } else if ( trans_num != last_trans_num + 1 ) { + + /* we may decide to drop this invarient eventually, + * but we will check it for now, and scream and die + * if it fails. + */ + proceed = FALSE; + HDfprintf(stderr, "%s -- Exiting.\n", + "Encountered out of sequence transaction in journal"); + + } else { + + trans_in_progress = TRUE; + cur_trans_num = trans_num; + + if ( verbosity > 1 ) { + + HDfprintf(stdout, "\tBegin Trans: %lld.\n", + (long long)cur_trans_num); + } + } + break; + + case JF__JNL_ENTRY_MSG: + if ( ! trans_in_progress ) { + + proceed = FALSE; + HDfprintf(stderr, "%s -- Exiting.\n", + "Encountered jnl entry outside of transaction"); + + } else if ( trans_num != cur_trans_num ) { + + proceed = FALSE; + HDfprintf(stderr, "%s -- Exiting.\n", + "Encountered jnl entry with bad trans num"); + + } else { + + if ( verbosity > 1 ) { + + HDfprintf(stdout, + "\tApplying Jnl Entry: trans = %lld, ", + (long long)cur_trans_num); + + HDfprintf(stdout, "offset = 0x%llx, len = 0x%llx.\n", + (unsigned long long)hdf5_offset, + (unsigned long long)hdf5_length); + } + + /* apply the journal entry */ + + bytes_written = pwrite(hdf5_fd, + (const void *)buf, + hdf5_length, + (off_t)(hdf5_base_addr + + hdf5_offset)); + + if ( bytes_written != (ssize_t)hdf5_length ) { + + proceed = FALSE; + + HDfprintf(stderr, "%s %lld -- exiting.\n", + "jnl entry write failed applying transaction", + (long long)cur_trans_num); + } + } + break; + + case JF__END_TRANS_MSG: + if ( ! trans_in_progress ) { + + proceed = FALSE; + HDfprintf(stderr, "%s -- Exiting.\n", + "Encountered trans end msg outside of transaction"); + + } else if ( trans_num != cur_trans_num ) { + + proceed = FALSE; + HDfprintf(stderr, "%s -- Exiting.\n", + "Encountered trans end with bad trans num"); + + } else { + + trans_in_progress = FALSE; + last_trans_num = cur_trans_num; + + if ( cur_trans_num == max_trans_num ) { + + done = TRUE; + } + + if ( verbosity > 1 ) { + + HDfprintf(stdout, "\tEnd Trans: %lld.\n", + (long long)cur_trans_num); + + if ( done ) { + + HDfprintf(stdout, + "\tLast complete transaction applied.\n"); + } + } + } + break; + + case JF__EOA_MSG: + if ( verbosity > 1 ) { + + HDfprintf(stdout, "\tEOA message: 0x%llx.\n", + (unsigned long long)eoa); + } + break; + + case JF__INVALID_MSG: + proceed = FALSE; + HDfprintf(stderr, "%s: encountered invalid message.\n", + fcn_name); + break; + + default: + proceed = FALSE; + HDfprintf(stderr, + "%s: bjf__load_next_msg() returned unknown msg?!?\n", + fcn_name); + break; + + } + } + + if ( proceed ) { + + offset = new_offset; + } + } + + + if ( ( proceed ) && ( verbosity > 0 ) ) { + + HDfprintf(stdout, "Updating EOA in the hdf5 file %s:\n", hdf5_file_path_ptr); + } + + + if ( buf != NULL ) { + + if ( verbosity > 0 ) { + + HDfprintf(stdout, "\tFreeing journal entry body buffer.\n"); + } + + HDfree(buf); + + buf = NULL; + + } + + if ( jnl_fd != -1 ) { + + if ( verbosity > 0 ) { + + HDfprintf(stdout, "\tattempting to close jnl file %s...\n", + jnl_file_path_ptr); + } + + if ( HDclose(jnl_fd) != 0 ) { + + HDfprintf(stderr, "%s: Error closing %s. errno = %s (%s).\n", + fcn_name, jnl_file_path_ptr, errno, HDstrerror(errno)); + + } else if ( verbosity > 0 ) { + + HDfprintf(stdout, "\tclosed journal file successfully\n"); + } + } + + if ( proceed ) { + + if ( verbosity > 0 ) { + + HDfprintf(stdout, "Updating EOA in HDF5 file %s.\n", + hdf5_file_path_ptr); + } + + proceed = update_hdf5_eoa(hdf5_file_path_ptr, + hdf5_fd, + hdf5_file_len, + sb_offset, + hdf5_offset_width, + sb_ver, + hdf5_base_addr, + new_eoa, + verbosity); + } + + if ( hdf5_fd != -1 ) { + + if ( verbosity > 0 ) { + + HDfprintf(stdout, "\tattempting to close hdf5 file %s...\n", + hdf5_file_path_ptr); + } + + if ( HDclose(hdf5_fd) != 0 ) { + + HDfprintf(stderr, "%s: Error closing %s. errno = %s (%s).\n", + fcn_name, hdf5_file_path_ptr, errno, HDstrerror(errno)); + + } else if ( verbosity > 0 ) { + + HDfprintf(stdout, "\tclosed hdf5 file successfully\n"); + } + } + + return(proceed); + +} /* apply_journal_file() */ + + +/************************************************************************** + * + * Function: mark_hdf5_file_recovered() + * + * Purpose: Mark the specified hdf5 file as being recovered. + * + * Return: TRUE if no errors are detected, and FALSE otherwise. + * + * Programmer: JRM -- 5/26/09 + * + * Changes: None. + * + **************************************************************************/ + +hbool_t +mark_hdf5_file_recovered(char * hdf5_file_path_ptr) + +{ + const char * fcn_name = "mark_hdf5_file_recovered()"; + hbool_t proceed = TRUE; + hid_t fapl = -1; + hid_t fid = -1; + H5AC2_jnl_config_t config; /* journaling configuration */ + + if ( hdf5_file_path_ptr == NULL ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: bad param(s) on entry.\n", fcn_name); + } + + if ( proceed ) { + + /* set up appropriate fapl */ + fapl = H5Pcreate(H5P_FILE_ACCESS); + + if ( fapl == -1 ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: H5Pcreate() failed.\n", fcn_name); + + } + } + + if ( proceed ) { + + config.version = H5C2__CURR_AUTO_SIZE_CTL_VER; + + /* get H5AC_cache_config_t configuration from fapl */ + if ( H5Pget_jnl_config(fapl, &config) == -1) { + + proceed = FALSE; + HDfprintf(stderr, "%s: couldn't get mdc config from FAPL.\n", + fcn_name); + } + } + + if ( proceed ) { + + /* set journal recovered field to TRUE in mdc_config */ + config.journal_recovered = TRUE; + + /* set H5AC_cache_config_t configuration with file recovered */ + if ( H5Pset_jnl_config(fapl, &config) == -1 ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: couldn't set mdc config in FAPL.\n", + fcn_name); + } + } + + if ( proceed ) { + + /* open HDF5 file with provided fapl */ + fid = H5Fopen(hdf5_file_path_ptr, H5F_ACC_RDWR, fapl); + + if ( fid == -1 ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: couldn't open recovered HDF5 file.\n", + fcn_name); + } + } + + if ( proceed ) { + + /* close HDF5 file */ + if ( H5Fclose(fid) == -1 ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: couldn't close recovered HDF5 file.\n", + fcn_name); + } + } + + return(proceed); + +} /* mark_hdf5_file_recovered() */ + + +/************************************************************************** + * + * Function: update_hdf5_eoa() + * + * Purpose: Modify the eoa field superblock of the supplied hdf5 file + * to the specified value, and update the superblock checksum + * accordingly. + * + * Return: TRUE if no errors are detected, and FALSE otherwise. + * + * Programmer: JRM -- 5/26/09 + * + * Changes: None. + * + **************************************************************************/ + +hbool_t +update_hdf5_eoa(char * hdf5_file_path_ptr, + int hdf5_fd, + off_t hdf5_file_len, + off_t sb_offset, + int hdf5_offset_width, + int sb_ver, + haddr_t base_addr, + haddr_t new_eoa, + unsigned verbosity) +{ + const char * fcn_name = "update_hdf5_eoa()"; + char buf[256]; + hbool_t proceed = TRUE; + uint8_t * p; + int version_disp; + int eoa_disp; + int chksum_disp; + uint32_t chksum; + uint32_t new_chksum; + uint32_t old_chksum; + size_t sb_size; + haddr_t old_eoa; + + if ( ( hdf5_file_path_ptr == NULL ) || + ( hdf5_fd <= -1 ) || + ( sb_ver != 2 ) ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: bad params on entry.\n", fcn_name); + } + + if ( ( proceed ) && ( verbosity > 0 ) ) { + + HDfprintf(stdout, "Updating hdf5 file %s super block for new EOA.\n", + hdf5_file_path_ptr); + } + + if ( proceed ) { + + sb_size = 8 /* signature */ + + 1 /* version */ + + 1 /* size of offsets */ + + 1 /* size of lengths */ + + 1 /* flags */ + + hdf5_offset_width /* base address */ + + hdf5_offset_width /* sb ext address */ + + hdf5_offset_width /* EOF address */ + + hdf5_offset_width /* root group obj hdr address */ + + 4; /* checksum */ + + version_disp = 8; /* signature */ + + eoa_disp = version_disp + + 1 /* version */ + + 1 /* size of offsets */ + + 1 /* size of lengths */ + + 1 /* flags */ + + hdf5_offset_width /* base address */ + + hdf5_offset_width; /* sb ext address */ + + chksum_disp = eoa_disp + + hdf5_offset_width /* EOF address */ + + hdf5_offset_width;/* root group obj hdr address */ + + if ( sb_size >= 256 ) { + + proceed = FALSE; + HDfprintf(stdout, "%s: buf too small for super block.\n", fcn_name); + } + } + + if ( proceed ) { + + if ( verbosity > 1 ) { + + HDfprintf(stdout, "\tLoading super block.\n"); + } + + /* read the super block in from file */ + + proceed = load_buf_from_file(hdf5_fd, + hdf5_file_len, + sb_offset, + sb_size, + (uint8_t *)buf, + verbosity, + fcn_name, + NULL); + } + + if ( proceed ) { + + /* verify signature and version */ + if ( HDmemcmp(buf, + H5F_SIGNATURE, + (size_t)H5F_SIGNATURE_LEN) != 0 ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: bad super block offset?!?!\n", fcn_name); + + } else if ( (int)(buf[version_disp]) != sb_ver ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: Unexpected super block verion?!?!\n", + fcn_name); + } + } + + if ( proceed ) { + + /* read the old eoa and checksum */ + + p = (uint8_t *)(&(buf[eoa_disp])); + + address_decode((size_t)hdf5_offset_width, + (const uint8_t **)(&p), + &old_eoa); + + p = (uint8_t *)(&(buf[chksum_disp])); + + old_chksum = 0; + + UINT32DECODE(p, old_chksum); + + /* verify chksum */ + chksum = H5_checksum_metadata(buf, (size_t)chksum_disp, 0); + + if ( old_chksum != chksum ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: bad SB chksum prior to update.\n", fcn_name); + } + } + + if ( ( proceed ) && ( verbosity > 1 ) ) { + + HDfprintf(stdout, "\tpre-update eoa = 0x%llx\n", + (unsigned long long)old_eoa); + + HDfprintf(stdout, "\tpre-update chksum = 0x%x\n", + (unsigned)old_chksum); + } + + if ( proceed ) { + + /* write the new eoa and chksum to the in core image of the + * super block + */ + + p = (uint8_t *)(&(buf[eoa_disp])); + + address_encode((size_t)hdf5_offset_width, &p, new_eoa); + + new_chksum = H5_checksum_metadata(buf, (size_t)chksum_disp, 0); + + p = (uint8_t *)(&(buf[chksum_disp])); + + UINT32ENCODE(p, new_chksum); + } + + if ( ( proceed ) && ( verbosity > 1 ) ) { + + HDfprintf(stdout, "\tpost-update eoa = 0x%llx\n", + (unsigned long long)new_eoa); + + HDfprintf(stdout, "\tpost-update chksum = 0x%x\n", + (unsigned)new_chksum); + } + + if ( proceed ) { + + if ( verbosity > 1 ) { + + HDfprintf(stdout, "\tUpdating hdf5 file length.\n"); + } + + /* use ftruncate() to set the HDF5 file length to match the + * the new EOA. + */ + + if ( HDftruncate(hdf5_fd, (off_t)(base_addr + new_eoa)) != 0 ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: HDftruncate() failed. errno = %d (%s).\n", + fcn_name, errno, HDstrerror(errno)); + } + } + + if ( proceed ) { + + if ( verbosity > 1 ) { + + HDfprintf(stdout, "\tWriting modified super block to file.\n"); + } + + if ( pwrite(hdf5_fd, (void *)buf, (size_t)sb_size, sb_offset) != + (ssize_t)sb_size ) { + + proceed = FALSE; + HDfprintf(stderr, + "Write of modified super block to hdf5 file %s failed.\n", + hdf5_file_path_ptr); + } + } + + return(proceed); + +} /* update_hdf5_eoa() */ + + +/**************************************************************************/ +/********************** Binary Journal File Code **************************/ +/**************************************************************************/ +/* The following function(s) are used read binary journal file messages. */ +/**************************************************************************/ + +/*------------------------------------------------------------------------- + * Function: bjf__chksum_entry_body() + * + * Purpose: Read the specifice number of bytes from the supplied file + * starting at the indicated offset, checksum them, and update + * *chksum_ptr to reflect the checksum computed. + * + * Set *new_offset_ptr to reference the first byte after the + * entry body. + * + * If an error is detected, set *msg_type_ptr to + * JF__INVALID_MSG, and set *new_offset_ptr to the offset + * at which the error was detected. + * + * Return TRUE if successful, and FALSE otherwise. + * + * Return: TRUE on success + * FALSE otherwise + * + * Programmer: John Mainzer -- 5/15/09 + * + *------------------------------------------------------------------------- + */ + +hbool_t +bjf__chksum_entry_body(int fd, + off_t file_len, + off_t offset, + off_t * new_offset_ptr, + int * msg_type_ptr, + size_t body_length, + uint32_t * chksum_ptr, + unsigned verbosity) +{ + const char * fcn_name = "bjf__chksum_entry_body()"; + hbool_t eof = FALSE; + hbool_t proceed = TRUE; + size_t rmdr; + off_t new_offset; + + if ( ( fd < 0 ) || + ( new_offset_ptr == NULL ) || + ( msg_type_ptr == NULL ) || + ( *msg_type_ptr != JF__UNDEFINED_MSG ) || + ( chksum_ptr == NULL ) ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: Bad parameters on entry.\n", fcn_name); + + } else if ( ( body_buf == NULL ) || + ( body_buf_len <= 0 ) ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: body_buf not set up on entry.\n", fcn_name); + + } else if ( body_length > body_buf_len ) { + + /* double the size of the body buffer until it is big enough */ + while ( body_length > body_buf_len ) { + + body_buf_len *= 2; + } + body_buf = (char *)HDrealloc((void *)body_buf, body_buf_len); + + if ( body_buf == NULL ) { + + proceed = FALSE; + HDfprintf(stderr, + "%s: realloc() of body_buf failed. Desired new size = %d.\n", + fcn_name, (int)body_buf_len); + } + } + + if ( proceed ) { + + proceed = load_buf_from_file(fd, + file_len, + offset, + body_length, + (uint8_t *)body_buf, + verbosity, + fcn_name, + &eof); + + if ( ! proceed ) { + + *msg_type_ptr = JF__INVALID_MSG; + *new_offset_ptr = offset; + + if ( eof ) { + + /* we have encountered the end of file, not a system + * or I/O error. Set proceed back to TRUE, as encountering + * the end of file is not necessarily an error in this + * context. + */ + + proceed = TRUE; + } + } + } + + if ( ( proceed ) && ( ! eof ) ) { + + *new_offset_ptr = offset + (off_t)body_length; + + if ( chksum_ptr != NULL ) { + + *chksum_ptr = H5_checksum_metadata((const void *)body_buf, + body_length, + *chksum_ptr); + + } + } + + return(proceed); + +} /* bjf__chksum_entry_body() */ + + +/*------------------------------------------------------------------------- + * Function: bjf__load_begin_trans_msg() + * + * Purpose: Read and validate the contents of the begin transaction + * message from the supplied file, and set: + * + * *msg_type_ptr to JF__BEGIN_TRANS_MSG, and + * + * *trans_num_ptr to the transaction number listed + * in the message. + * + * *new_offset_ptr to the offset of the byte just + * after the begin transaction message. + * + * The supplied offset is presumed to reference the first + * byte of the message after the signature and version. + * + * If an error is detected, set *msg_type_ptr to + * JF__INVALID_MSG, and set *new_offset_ptr to the offset + * at which the error was detected. + * + * Return TRUE if successful, and FALSE otherwise. + * + * Return: TRUE on success + * FALSE otherwise + * + * Programmer: John Mainzer -- 5/15/09 + * + *------------------------------------------------------------------------- + */ + +hbool_t +bjf__load_begin_trans_msg(int fd, + off_t file_len, + off_t offset, + off_t * new_offset_ptr, + int * msg_type_ptr, + int msg_ver, + uint64_t * trans_num_ptr, + unsigned verbosity) +{ + const char * fcn_name = "bjf__load_begin_trans_msg()"; + hbool_t proceed = TRUE; + + if ( ( fd < 0 ) || + ( new_offset_ptr == NULL ) || + ( msg_type_ptr == NULL ) || + ( *msg_type_ptr != JF__UNDEFINED_MSG ) || + ( trans_num_ptr == NULL ) ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: Bad parameters on entry.\n", fcn_name); + } + + if ( proceed ) { + + switch ( msg_ver ) { + + case 0: + *new_offset_ptr = offset; + + proceed = bjf__load_trans_num(fd, + file_len, + *new_offset_ptr, + new_offset_ptr, + msg_type_ptr, + trans_num_ptr, + NULL, + verbosity); + + if ( ( proceed ) && + ( *msg_type_ptr == JF__UNDEFINED_MSG ) ) { + + *msg_type_ptr = JF__BEGIN_TRANS_MSG; + + } else { + + *msg_type_ptr = JF__INVALID_MSG; + + } + break; + + default: + *msg_type_ptr = JF__INVALID_MSG; + *new_offset_ptr = offset; + + if ( verbosity > 1 ) { + + HDfprintf(stdout, + "Unknown begin trans msg ver detected at offset 0x%llx.\n", + (unsigned long long)offset); + } + break; + } + } + + return(proceed); + +} /* bjf__load_begin_trans_msg() */ + + +/*------------------------------------------------------------------------- + * Function: bjf__load_chksum() + * + * Purpose: Load a checksum from the supplied journal file at the + * specified offset. + * + * If successful, set *chksum_ptr to the newly loaded check + * sum and set *new_offset_ptr to reference the first byte + * in the journal file after the checks sum. + * + * If an error is detected, set *msg_type_ptr to + * JF__INVALID_MSG, and set *new_offset_ptr to the offset + * at which the error was detected. + * + * Return TRUE if successful, and FALSE if any error is + * detected, + * + * Return: TRUE on success + * FALSE otherwise + * + * Programmer: John Mainzer -- 5/15/09 + * + *------------------------------------------------------------------------- + */ + +hbool_t +bjf__load_chksum(int fd, + off_t file_len, + off_t offset, + off_t * new_offset_ptr, + int * msg_type_ptr, + uint32_t * chksum_ptr, + unsigned verbosity) +{ + const char * fcn_name = "bjf__load_chksum()"; + char buf[sizeof(uint32_t) + 1]; + hbool_t eof = FALSE; + hbool_t proceed = TRUE; + uint8_t * p; + uint32_t chksum; + + if ( ( fd < 0 ) || + ( new_offset_ptr == NULL ) || + ( msg_type_ptr == NULL ) || + ( *msg_type_ptr != JF__UNDEFINED_MSG ) || + ( chksum_ptr == NULL ) ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: Bad parameters on entry.\n", fcn_name); + } + + if ( proceed ) { + + proceed = load_buf_from_file(fd, + file_len, + offset, + sizeof(uint32_t), + (uint8_t *)buf, + verbosity, + fcn_name, + &eof); + + if ( proceed ) { + + p = (uint8_t *)buf; + + UINT32DECODE(p, chksum) + + *chksum_ptr = chksum; + *new_offset_ptr = offset + (off_t)(sizeof(uint32_t)); + + } else { + + *msg_type_ptr = JF__INVALID_MSG; + *new_offset_ptr = offset; + + if ( eof ) { + + /* we have encountered the end of file, not a system + * or I/O error. Set proceed back to TRUE, as encountering + * the end of file is not necessarily an error in this + * context. + */ + + proceed = TRUE; + } + } + } + + return(proceed); + +} /* bjf__load_chksum() */ + + +/*------------------------------------------------------------------------- + * Function: bjf__load_end_trans_msg() + * + * Purpose: Read and validate the contents of the end transaction + * message from the supplied file, and set: + * + * *msg_type_ptr to JF__END_TRANS_MSG, and + * + * *trans_num_ptr to the transaction number listed + * in the message. + * + * *new_offset_ptr to the offset of the byte just + * after the end transaction message. + * + * The supplied offset is presumed to reference the first + * byte of the message after the signature and version. + * + * If an error is detected, set *msg_type_ptr to + * JF__INVALID_MSG, and set *new_offset_ptr to the offset + * at which the error was detected. + * + * Return TRUE if successful, and FALSE otherwise. + * + * Return: TRUE on success + * FALSE otherwise + * + * Programmer: John Mainzer -- 5/15/09 + * + *------------------------------------------------------------------------- + */ + +hbool_t +bjf__load_end_trans_msg(int fd, + off_t file_len, + off_t offset, + off_t * new_offset_ptr, + int * msg_type_ptr, + int msg_ver, + uint64_t * trans_num_ptr, + unsigned verbosity) +{ + const char * fcn_name = "bjf__load_end_trans_msg()"; + hbool_t proceed = TRUE; + + if ( ( fd < 0 ) || + ( new_offset_ptr == NULL ) || + ( msg_type_ptr == NULL ) || + ( *msg_type_ptr != JF__UNDEFINED_MSG ) || + ( trans_num_ptr == NULL ) ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: Bad parameters on entry.\n", fcn_name); + } + + if ( proceed ) { + + switch ( msg_ver ) { + + case 0: + *new_offset_ptr = offset; + + proceed = bjf__load_trans_num(fd, + file_len, + *new_offset_ptr, + new_offset_ptr, + msg_type_ptr, + trans_num_ptr, + NULL, + verbosity); + + if ( ( proceed ) && + ( *msg_type_ptr == JF__UNDEFINED_MSG ) ) { + + *msg_type_ptr = JF__END_TRANS_MSG; + + } else { + + *msg_type_ptr = JF__INVALID_MSG; + *new_offset_ptr = offset; + + } + break; + + default: + *msg_type_ptr = JF__INVALID_MSG; + *new_offset_ptr = offset; + + if ( verbosity > 1 ) { + + HDfprintf(stdout, + "Unknown end trans msg ver detected at offset 0x%llx.\n", + (unsigned long long)offset); + } + break; + } + } + + return(proceed); + +} /* bjf__load_end_trans_msg() */ + + +/*------------------------------------------------------------------------- + * Function: bjf__load_entry_body() + * + * Purpose: Read the specifice number of bytes from the supplied file + * starting at the indicated offset, and copy them into the + * supplied buffer. + * + * Set *new_offset_ptr to reference the first byte after the + * entry body. + * + * If chksum_ptr isn't NULL, checksum the data copied into + * the buffer, and update *chksum_ptr accordingly. + * + * If an error is detected, set *msg_type_ptr to + * JF__INVALID_MSG, and set *new_offset_ptr to the offset + * at which the error was detected. + * + * Return TRUE if successful, and FALSE otherwise. + * + * Return: TRUE on success + * FALSE otherwise + * + * Programmer: John Mainzer -- 5/15/09 + * + *------------------------------------------------------------------------- + */ + +hbool_t +bjf__load_entry_body(int fd, + off_t file_len, + off_t offset, + off_t * new_offset_ptr, + int * msg_type_ptr, + size_t body_length, + char * buf_ptr, + size_t buf_len, + uint32_t * chksum_ptr, + unsigned verbosity) +{ + const char * fcn_name = "bjf__load_entry_body()"; + hbool_t eof = FALSE; + hbool_t proceed = TRUE; + + if ( ( fd < 0 ) || + ( new_offset_ptr == NULL ) || + ( msg_type_ptr == NULL ) || + ( *msg_type_ptr != JF__UNDEFINED_MSG ) || + ( buf_ptr == NULL ) ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: Bad parameters on entry.\n", fcn_name); + + } else if ( body_length > buf_len ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: body (%d bytes) too big for buffer (%d bytes).\n", + fcn_name, (int)body_length, (int)buf_len); + } + + if ( proceed ) { + + proceed = load_buf_from_file(fd, + file_len, + offset, + body_length, + (uint8_t *)buf_ptr, + verbosity, + fcn_name, + &eof); + + if ( ! proceed ) { + + *msg_type_ptr = JF__INVALID_MSG; + *new_offset_ptr = offset; + + if ( eof ) { + + /* we have encountered the end of file, not a system + * or I/O error. Set proceed back to TRUE, as encountering + * the end of file is not necessarily an error in this + * context. + */ + + proceed = TRUE; + } + } + } + + if ( ( proceed ) && ( ! eof ) ) { + + *new_offset_ptr = offset + (off_t)body_length; + + if ( chksum_ptr != NULL ) { + + *chksum_ptr = H5_checksum_metadata((const void *)buf_ptr, + body_length, + *chksum_ptr); + + } + } + + return(proceed); + +} /* bjf__load_entry_body() */ + + +/*------------------------------------------------------------------------- + * Function: bjf__load_eoa_msg() + * + * Purpose: Read and validate the contents of the end of address space + * message from the supplied file, and set: + * + * *msg_type_ptr to JF__EOA_MSG, and + * + * *new_offset_ptr to the offset of the byte just + * after the end of address space message. + * + * The supplied offset is presumed to reference the first + * byte of the message after the signature and version. + * + * If an error is detected, set *msg_type_ptr to + * JF__INVALID_MSG, and set *new_offset_ptr to the offset + * at which the error was detected. + * + * Return TRUE if successful, and FALSE otherwise. + * + * Return: TRUE on success + * FALSE otherwise + * + * Programmer: John Mainzer -- 5/15/09 + * + *------------------------------------------------------------------------- + */ + +hbool_t +bjf__load_eoa_msg(int fd, + off_t file_len, + off_t offset, + off_t * new_offset_ptr, + int * msg_type_ptr, + int msg_ver, + haddr_t * eoa_ptr, + int hdf5_offset_width, + unsigned verbosity) +{ + const char * fcn_name = "bjf__load_eoa_msg()"; + hbool_t proceed = TRUE; + + if ( ( fd < 0 ) || + ( new_offset_ptr == NULL ) || + ( msg_type_ptr == NULL ) || + ( *msg_type_ptr != JF__UNDEFINED_MSG ) || + ( eoa_ptr == NULL ) ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: Bad parameters on entry.\n", fcn_name); + } + + if ( proceed ) { + + switch ( msg_ver ) { + + case 0: + + *new_offset_ptr = offset; + + proceed = bjf__load_offset(fd, + file_len, + *new_offset_ptr, + new_offset_ptr, + msg_type_ptr, + eoa_ptr, + hdf5_offset_width, + NULL, + verbosity); + + if ( ( proceed ) && + ( *msg_type_ptr == JF__UNDEFINED_MSG ) ) { + + *msg_type_ptr = JF__EOA_MSG; + + } else { + + *msg_type_ptr = JF__INVALID_MSG; + + } + break; + + default: + *msg_type_ptr = JF__INVALID_MSG; + *new_offset_ptr = offset; + + if ( verbosity > 1 ) { + + HDfprintf(stdout, + "Unknown eoa msg ver detected at offset 0x%llx.\n", + (unsigned long long)offset); + } + break; + } + } + + return(proceed); + +} /* bjf__load_eoa_msg() */ + + +/*------------------------------------------------------------------------- + * Function: bjf__load_jnl_entry_msg() + * + * Purpose: Read and validate the contents of the journal entry + * message from the supplied file, and set: + * + * *msg_type_ptr to JF__JNL_ENTRY_MSG, + * + * *trans_num_ptr to the transaction number listed + * in the message, + * + * *trans_num_ptr to the transaction number listed + * in the message, + * + * *hdf5_offset_ptr to the base address listed in the + * message, + * + * *hdf5_length_ptr to the entry length listed in the message, + * + * if buf_ptr is not NULL, and buf_len is less than + * or equal to the length found in the message, + * load the body of the journal entry into + * *buf_ptr. + * + * *new_offset_ptr to reference the first byte after + * the end of the journal entry message. + * + * The supplied offset is presumed to reference the first + * byte of the message after the signature and version. + * + * If an error is detected, set *msg_type_ptr to + * JF__INVALID_MSG, and set *new_offset_ptr to the offset + * at which the error was detected. + * + * Return TRUE if successful, and FALSE otherwise. + * + * Return: TRUE on success + * FALSE otherwise + * + * Programmer: John Mainzer -- 5/15/09 + * + *------------------------------------------------------------------------- + */ + +hbool_t +bjf__load_jnl_entry_msg(int fd, + off_t file_len, + off_t offset, + off_t * new_offset_ptr, + int * msg_type_ptr, + int msg_ver, + uint64_t * trans_num_ptr, + haddr_t * hdf5_offset_ptr, + int hdf5_offset_width, + size_t * hdf5_length_ptr, + int hdf5_length_width, + char * buf_ptr, + size_t buf_len, + unsigned verbosity) +{ + const char * fcn_name = "bjf__load_jnl_entry_msg()"; + hbool_t proceed = TRUE; + uint32_t chksum = 0; + uint32_t expected_chksum; + + if ( ( fd < 0 ) || + ( new_offset_ptr == NULL ) || + ( msg_type_ptr == NULL ) || + ( *msg_type_ptr != JF__UNDEFINED_MSG ) || + ( trans_num_ptr == NULL ) || + ( hdf5_offset_ptr == NULL ) || + ( hdf5_length_ptr == NULL ) ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: Bad parameters on entry.\n", fcn_name); + } + + if ( proceed ) { + + switch ( msg_ver ) { + + case 0: + *new_offset_ptr = offset; + + proceed = bjf__load_trans_num(fd, + file_len, + *new_offset_ptr, + new_offset_ptr, + msg_type_ptr, + trans_num_ptr, + &chksum, + verbosity); + if ( ( proceed ) && + ( *msg_type_ptr == JF__UNDEFINED_MSG ) ) { + + proceed = bjf__load_offset(fd, + file_len, + *new_offset_ptr, + new_offset_ptr, + msg_type_ptr, + hdf5_offset_ptr, + hdf5_offset_width, + &chksum, + verbosity); + } + + if ( ( proceed ) && + ( *msg_type_ptr == JF__UNDEFINED_MSG ) ) { + + proceed = bjf__load_length(fd, + file_len, + *new_offset_ptr, + new_offset_ptr, + msg_type_ptr, + hdf5_length_ptr, + hdf5_length_width, + &chksum, + verbosity); + } + + if ( ( proceed ) && + ( *msg_type_ptr == JF__UNDEFINED_MSG ) ) { + + if ( buf_ptr != NULL ) { + + proceed = bjf__load_entry_body(fd, + file_len, + *new_offset_ptr, + new_offset_ptr, + msg_type_ptr, + *hdf5_length_ptr, + buf_ptr, + buf_len, + &chksum, + verbosity); + } else { + + proceed = bjf__chksum_entry_body(fd, + file_len, + *new_offset_ptr, + new_offset_ptr, + msg_type_ptr, + *hdf5_length_ptr, + &chksum, + verbosity); + } + } + + if ( ( proceed ) && + ( *msg_type_ptr == JF__UNDEFINED_MSG ) ) { + + proceed = bjf__load_chksum(fd, + file_len, + *new_offset_ptr, + new_offset_ptr, + msg_type_ptr, + &expected_chksum, + verbosity); + } + + if ( ( proceed ) && + ( *msg_type_ptr == JF__UNDEFINED_MSG ) && + ( chksum != expected_chksum ) ) { + + proceed = FALSE; + *msg_type_ptr = JF__INVALID_MSG; + + if ( verbosity > 0 ) { + + HDfprintf(stdout, "Chksum mismatch in jnl entry msg.\n"); + HDfprintf(stdout, "\texpected chksum = 0x%x\n", + expected_chksum); + HDfprintf(stdout, "\tactual chksum = 0x%x\n", chksum); + } + + if ( verbosity > 1 ) { + + HDfprintf(stdout, "\ttrans num = %lld\n", + (long long)(*trans_num_ptr)); + HDfprintf(stdout, "\toffset = 0x%llx\n", + (unsigned long long)(*hdf5_offset_ptr)); + HDfprintf(stdout, "\tlength = 0x%llx\n", + (unsigned long long)(*hdf5_length_ptr)); + } + } + + if ( ( proceed ) && + ( *msg_type_ptr == JF__UNDEFINED_MSG ) ) { + + *msg_type_ptr = JF__JNL_ENTRY_MSG; + } + break; + + default: + *msg_type_ptr = JF__INVALID_MSG; + *new_offset_ptr = offset; + + if ( verbosity > 0 ) { + + HDfprintf(stdout, + "Unknown jnl entry msg ver detected at offset 0x%llx.\n", + (unsigned long long)offset); + } + break; + } + } + + return(proceed); + +} /* bjf__load_jnl_entry_msg() */ + + +/*------------------------------------------------------------------------- + * Function: bjf__load_length() + * + * Purpose: Load the length (i.e. hdf5 object length) from the supplied + * journal file at the specified offset. + * + * If successful, set *length_ptr to the newly loaded HDF5 + * object length and set *new_offset_ptr to reference the + * first byte in the journal file after the HDF5 object length. + * Also, if chksum_ptr is not NULL, compute the checksum on + * the on disc representation of the HDF5 file object length + * and update *chksum_ptr accordingly. + * + * If an error is detected, set *msg_type_ptr to + * JF__INVALID_MSG, and set *new_offset_ptr to the offset + * at which the error was detected. + * + * Return TRUE if successful, and FALSE if any error is + * detected, + * + * Return: TRUE on success + * FALSE otherwise + * + * Programmer: John Mainzer -- 5/15/09 + * + *------------------------------------------------------------------------- + */ + +hbool_t +bjf__load_length(int fd, + off_t file_len, + off_t offset, + off_t * new_offset_ptr, + int * msg_type_ptr, + size_t * hdf5_length_ptr, + int hdf5_length_width, + uint32_t * chksum_ptr, + unsigned verbosity) +{ + const char * fcn_name = "bjf__load_length()"; + char buf[10]; + hbool_t eof = FALSE; + hbool_t proceed = TRUE; + uint8_t * p; + size_t hdf5_length; + + if ( ( fd < 0 ) || + ( new_offset_ptr == NULL ) || + ( msg_type_ptr == NULL ) || + ( *msg_type_ptr != JF__UNDEFINED_MSG ) || + ( hdf5_length_ptr == NULL ) ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: Bad parameters on entry.\n", fcn_name); + } + + if ( proceed ) { + + proceed = load_buf_from_file(fd, + file_len, + offset, + (size_t)hdf5_length_width, + (uint8_t *)buf, + verbosity, + fcn_name, + &eof); + + if ( proceed ) { + + p = (uint8_t *)buf; + + switch ( hdf5_length_width ) { + + case 2: + UINT16DECODE(p, hdf5_length) + *hdf5_length_ptr = hdf5_length; + *new_offset_ptr = offset + 2; + break; + + case 4: + UINT32DECODE(p, hdf5_length) + *hdf5_length_ptr = hdf5_length; + *new_offset_ptr = offset + 4; + break; + + case 8: + UINT64DECODE(p, hdf5_length) + *hdf5_length_ptr = hdf5_length; + *new_offset_ptr = offset + 8; + break; + + default: + proceed = FALSE; + *msg_type_ptr = JF__INVALID_MSG; + *new_offset_ptr = offset; + + if ( verbosity > 2 ) { + + HDfprintf(stdout, "%s: invalid hdf5_length_width.\n", + fcn_name); + } + break; + } + } else { + + *msg_type_ptr = JF__INVALID_MSG; + *new_offset_ptr = offset; + + if ( eof ) { + + /* we have encountered the end of file, not a system + * or I/O error. Set proceed back to TRUE, as encountering + * the end of file is not necessarily an error in this + * context. + */ + + proceed = TRUE; + } + } + } + + if ( ( proceed ) && ( ! eof ) && ( chksum_ptr != NULL ) ) { + + *chksum_ptr = H5_checksum_metadata((const void *)buf, + (size_t)hdf5_length_width, + *chksum_ptr); + } + + return(proceed); + +} /* bjf__load_length() */ + + +/*------------------------------------------------------------------------- + * Function: bjf__load_next_msg() + * + * Purpose: Read the message from the supplied file that starts at + * the supplied offset, and set *msg_type_ptr, *trans_num_ptr, + * *offset_ptr, *length_ptr, and *eoa_ptr as appropriate. + * If the message is a journal entry, buf_ptr is not NULL + * and buf_len is greater than or equal to the length of the + * entry body, load the body into *buf_ptr. + * + * In all cases, set *new_offset_ptr to either the offset at + * which the next message in the journal file is expected to + * begin, or to the offset at which the invalid message was + * detected. + * + * More specifically: + * + * If the the message is invalid, set: + * + * *msg_type_ptr to JF__INVALID_MSG + * + * The targets of all other pointer parameters are + * undefined. + * + * + * If the message is a begin transaction message, set: + * + * *msg_type_ptr to JF__BEGIN_TRANS_MSG, and + * + * *trans_num_ptr to the transaction number listed + * in the message. + * + * The targets of all other pointer parameters are + * undefined. + * + * + * If the message is a journal entry message, set: + * + * *msg_type_ptr to JF__JNL_ENTRY_MSG, + * + * *trans_num_ptr to the transaction number listed + * in the message, + * + * *offset_ptr to the base address listed in the + * message, + * + * *length_ptr to the entry length listed in the + * message, + * + * if buf_ptr is not NULL, and buf_len is less than + * or equal to the length found in the message, + * load the body of the journal entry into + * *buf_ptr. + * + * The targets of all other pointer parameters are + * undefined. + * + * + * If the message is an end transaction message, set: + * + * *msg_type_ptr to JF__END_TRANS_MSG, and + * + * *trans_num_ptr to the transaction number listed + * in the message. + * + * The targets of all other pointer parameters are + * undefined. + * + * + * If the message is an EOA message, set: + * + * *msg_type_ptr to JF__EOA_MSG, and + * + * *eoa_ptr to the end of address space value listed + * in the message + * + * The targets of all other pointer parameters are + * undefined. + * + * In all cases, set *new_offset_ptr to either the offset at + * which the next message in the journal file is expected to + * begin, or to the offset at which the invalid message was + * detected. + * + * Return TRUE if successful, and FALSE otherwise. + * + * Return: TRUE on success + * FALSE otherwise + * + * Programmer: John Mainzer -- 5/15/09 + * + *------------------------------------------------------------------------- + */ + +hbool_t +bjf__load_next_msg(int fd, + off_t file_len, + off_t offset, + off_t * new_offset_ptr, + int * msg_type_ptr, + uint64_t * trans_num_ptr, + haddr_t * hdf5_offset_ptr, + int hdf5_offset_width, + size_t * hdf5_length_ptr, + int hdf5_length_width, + haddr_t * eoa_ptr, + char * buf_ptr, + size_t buf_len, + unsigned verbosity) +{ + const char * fcn_name = "bjf__load_next_msg()"; + char sig_buf[H5C2_BJNL__SIG_LEN + 2]; + char msg_ver; + hbool_t eof = FALSE; + hbool_t proceed = TRUE; + + if ( ( fd < 0 ) || + ( new_offset_ptr == NULL ) || + ( msg_type_ptr == NULL ) || + ( trans_num_ptr == NULL ) || + ( hdf5_offset_ptr == NULL ) || + ( hdf5_length_ptr == NULL ) || + ( eoa_ptr == NULL ) ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: Bad parameters on entry.\n", fcn_name); + } + + if ( proceed ) { + + *msg_type_ptr = JF__UNDEFINED_MSG; + + /* try to load the message signature and version into sig_buf */ + proceed = load_buf_from_file(fd, + file_len, + offset, + (size_t)(H5C2_BJNL__SIG_LEN + 1), + (uint8_t *)sig_buf, + verbosity, + fcn_name, + &eof); + if ( ! proceed ) { + + *msg_type_ptr = JF__INVALID_MSG; + *new_offset_ptr = offset; + + if ( eof ) { + + /* we have encountered the end of file, not a system + * or I/O error. Set proceed back to TRUE, as encountering + * the end of file is not necessarily an error in this + * context. + */ + + proceed = TRUE; + } + } + } + + if ( ( proceed ) && ( ! eof ) ) { + + msg_ver = sig_buf[H5C2_BJNL__SIG_LEN]; + sig_buf[H5C2_BJNL__SIG_LEN] = '\0'; + + if ( verbosity > 2 ) { + + HDfprintf(stdout, + "%s: Read sig = \"%s\", ver = %d at offset 0x%llx.\n", + fcn_name, + sig_buf, + (int)msg_ver, + (unsigned long long)(offset)); + } + + if ( HDstrncmp(sig_buf, H5C2_BJNL__BEGIN_TRANS_SIG, + (size_t)(H5C2_BJNL__SIG_LEN)) == 0 ) { + + proceed = bjf__load_begin_trans_msg(fd, + file_len, + offset + (off_t)(H5C2_BJNL__SIG_LEN + 1), + new_offset_ptr, + msg_type_ptr, + msg_ver, + trans_num_ptr, + verbosity); + + } else if ( HDstrncmp(sig_buf, H5C2_BJNL__JOURNAL_ENTRY_SIG, + (size_t)(H5C2_BJNL__SIG_LEN)) == 0 ) { + + proceed = bjf__load_jnl_entry_msg(fd, + file_len, + offset + (off_t)(H5C2_BJNL__SIG_LEN + 1), + new_offset_ptr, + msg_type_ptr, + msg_ver, + trans_num_ptr, + hdf5_offset_ptr, + hdf5_offset_width, + hdf5_length_ptr, + hdf5_length_width, + buf_ptr, + buf_len, + verbosity); + + } else if ( HDstrncmp(sig_buf, H5C2_BJNL__END_TRANS_SIG, + (size_t)(H5C2_BJNL__SIG_LEN)) == 0 ) { + + proceed = bjf__load_end_trans_msg(fd, + file_len, + offset + (off_t)(H5C2_BJNL__SIG_LEN + 1), + new_offset_ptr, + msg_type_ptr, + msg_ver, + trans_num_ptr, + verbosity); + + + } else if ( HDstrncmp(sig_buf, H5C2_BJNL__END_ADDR_SPACE_SIG, + (size_t)(H5C2_BJNL__SIG_LEN)) == 0 ) { + + proceed = bjf__load_eoa_msg(fd, + file_len, + offset + (off_t)(H5C2_BJNL__SIG_LEN + 1), + new_offset_ptr, + msg_type_ptr, + msg_ver, + eoa_ptr, + hdf5_offset_width, + verbosity); + + } else { + + proceed = FALSE; + *msg_type_ptr = JF__INVALID_MSG; + *new_offset_ptr = offset; + + if ( verbosity > 0 ) { + + HDfprintf(stdout, + "Invalid/unknown binary msg sig detected at offset 0x%llx.\n", + (unsigned long long)offset); + } + } + } + + return(proceed); + +} /* bjf__load_next_msg() */ + + +/*------------------------------------------------------------------------- + * Function: bjf__load_offset() + * + * Purpose: Load the offset (i.e. hdf5 file address) from the supplied + * journal file at the specified offset. + * + * If successful, set *hdf5_offset_ptr to the newly loaded HDF5 + * file address and set *new_offset_ptr to reference the + * first byte in the journal file after the HDF5 file address. + * Also, if chksum_ptr is not NULL, compute the checksum on + * the on disc representation of the HDF5 file offset number, + * and update *chksum_ptr accordingly. + * + * If an error is detected, set *msg_type_ptr to + * JF__INVALID_MSG, and set *new_offset_ptr to the offset + * at which the error was detected. + * + * Return TRUE if successful, and FALSE if any error is + * detected, + * + * Return: TRUE on success + * FALSE otherwise + * + * Programmer: John Mainzer -- 5/15/09 + * + *------------------------------------------------------------------------- + */ + +hbool_t +bjf__load_offset(int fd, + off_t file_len, + off_t offset, + off_t * new_offset_ptr, + int * msg_type_ptr, + haddr_t * hdf5_offset_ptr, + int hdf5_offset_width, + uint32_t * chksum_ptr, + unsigned verbosity) +{ + const char * fcn_name = "bjf__load_offset()"; + char buf[10]; + hbool_t eof = FALSE; + hbool_t proceed = TRUE; + uint8_t * p; + haddr_t hdf5_offset; + + if ( ( fd < 0 ) || + ( new_offset_ptr == NULL ) || + ( msg_type_ptr == NULL ) || + ( *msg_type_ptr != JF__UNDEFINED_MSG ) || + ( hdf5_offset_ptr == NULL ) ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: Bad parameters on entry.\n", fcn_name); + } + + if ( proceed ) { + + proceed = load_buf_from_file(fd, + file_len, + offset, + (size_t)hdf5_offset_width, + (uint8_t *)buf, + verbosity, + fcn_name, + &eof); + + if ( proceed ) { + + p = (uint8_t *)buf; + + switch ( hdf5_offset_width ) { + + case 2: + UINT16DECODE(p, hdf5_offset) + *hdf5_offset_ptr = hdf5_offset; + *new_offset_ptr = offset + 2; + break; + + case 4: + UINT32DECODE(p, hdf5_offset) + *hdf5_offset_ptr = hdf5_offset; + *new_offset_ptr = offset + 4; + break; + + case 8: + UINT64DECODE(p, hdf5_offset) + *hdf5_offset_ptr = hdf5_offset; + *new_offset_ptr = offset + 8; + break; + + default: + proceed = FALSE; + *msg_type_ptr = JF__INVALID_MSG; + *new_offset_ptr = offset; + + if ( verbosity > 1 ) { + + HDfprintf(stdout, "%s: invalid offset_width.\n", + fcn_name); + } + break; + } + } else { + + *msg_type_ptr = JF__INVALID_MSG; + *new_offset_ptr = offset; + + if ( eof ) { + + /* we have encountered the end of file, not a system + * or I/O error. Set proceed back to TRUE, as encountering + * the end of file is not necessarily an error in this + * context. + */ + + proceed = TRUE; + } + } + } + + if ( ( proceed ) && ( ! eof ) && ( chksum_ptr != NULL ) ) { + + *chksum_ptr = H5_checksum_metadata((const void *)buf, + (size_t)hdf5_offset_width, + *chksum_ptr); + } + + return(proceed); + +} /* bjf__load_offset() */ + + +/*------------------------------------------------------------------------- + * Function: bjf__load_trans_num() + * + * Purpose: Load the transaction number from the supplied file at the + * specified offset. + * + * If successful, set *trans_num_ptr to the newly loaded + * transaction number, and set *new_offset_ptr to reference the + * first byte in the file after the transaction. Also, if + * chksum_ptr is not NULL, compute the checksum on the on disc + * representation of the transaction number, and update * + * chksum_ptr accordingly. + * + * If an error is detected, set *msg_type_ptr to + * JF__INVALID_MSG, and set *new_offset_ptr to the offset + * at which the error was detected. + * + * Return TRUE if successful, and FALSE if any error is + * detected, + * + * Return: TRUE on success + * FALSE otherwise + * + * Programmer: John Mainzer -- 5/15/09 + * + *------------------------------------------------------------------------- + */ + +hbool_t +bjf__load_trans_num(int fd, + off_t file_len, + off_t offset, + off_t * new_offset_ptr, + int * msg_type_ptr, + uint64_t * trans_num_ptr, + uint32_t * chksum_ptr, + unsigned verbosity) +{ + const char * fcn_name = "bjf__load_trans_num()"; + char buf[sizeof(uint64_t) + 1]; + hbool_t eof = FALSE; + hbool_t proceed = TRUE; + uint8_t * p; + uint64_t trans_num; + + if ( ( fd < 0 ) || + ( new_offset_ptr == NULL ) || + ( msg_type_ptr == NULL ) || + ( *msg_type_ptr != JF__UNDEFINED_MSG ) || + ( trans_num_ptr == NULL ) ) { + + proceed = FALSE; + HDfprintf(stderr, "%s: Bad parameters on entry.\n", fcn_name); + } + + if ( proceed ) { + + proceed = load_buf_from_file(fd, + file_len, + offset, + sizeof(uint64_t), + (uint8_t *)buf, + verbosity, + fcn_name, + &eof); + + if ( proceed ) { + + p = (uint8_t *)buf; + + UINT64DECODE(p, trans_num) + + *trans_num_ptr = trans_num; + + *new_offset_ptr = offset + (off_t)(sizeof(uint64_t)); + + if ( chksum_ptr != NULL ) { + + *chksum_ptr = H5_checksum_metadata((const void *)buf, + sizeof(uint64_t), + *chksum_ptr); + } + + } else { + + *msg_type_ptr = JF__INVALID_MSG; + *new_offset_ptr = offset; + + if ( eof ) { + + /* we have encountered the end of file, not a system + * or I/O error. Set proceed back to TRUE, as encountering + * the end of file is not necessarily an error in this + * context. + */ + + proceed = TRUE; + } + } + } + + return(proceed); + +} /* bjf__load_trans_num() */ + + +/*------------------------------------------------------------------------- + * Function: usage() * * Purpose: Prints a usage message and then returns. * @@ -3805,6 +6827,11 @@ length_encode(size_t sizeof_length, } /* length_encode() */ + + + + + /*------------------------------------------------------------------------- * Function: main() * @@ -3832,8 +6859,17 @@ main(int argc, hid_t fid = -1; /* file id number */ hid_t fapl = -1; /* file access property list */ char * file_name = NULL; /* file name */ + off_t hdf5_file_len; + off_t hdf5_sb_offset; + int hdf5_sb_ver; + haddr_t hdf5_base_addr; char * file_name_backup = NULL; /* name of backup file */ char * journal_name = NULL; /* journal name */ + off_t jnl_file_len; + size_t jnl_header_len; + hbool_t jnl_human_readable = TRUE; + int offset_width; + int length_width; unsigned verbose = 0; /* verbose boolean */ int opt; /* option number */ FILE * journal_fp; /* journal file pointer */ @@ -3991,7 +7027,20 @@ main(int argc, /* if this is not the case. */ /* ================================================================ */ - if ( ! verify_files(file_name, journal_name, force, verbose, &error) ) { + if ( ! verify_files(file_name, + &hdf5_file_len, + &hdf5_sb_offset, + &hdf5_sb_ver, + &hdf5_base_addr, + journal_name, + &jnl_file_len, + &jnl_header_len, + force, + &jnl_human_readable, + &offset_width, + &length_width, + verbose, + &error) ) { if ( error ) { @@ -4032,640 +7081,685 @@ main(int argc, } /* end if */ - /* =========================== */ - /* Open HDF5 and Journal Files */ - /* =========================== */ - - /* open the journal file for reading */ - journal_fp = fopen(journal_name, "r"); + if ( jnl_human_readable ) { - if (journal_fp == NULL) { - - error_msg(progname, "Could not open specified journal file\n"); - usage(); - leave( EXIT_FAILURE ); - - } /* end if */ + /* =========================== */ + /* Open HDF5 and Journal Files */ + /* =========================== */ - /* open hdf5 file for reading and writing */ - hdf5_fd = open(file_name, O_RDWR); + /* open the journal file for reading */ + journal_fp = fopen(journal_name, "r"); + + if (journal_fp == NULL) { - if (hdf5_fd == -1) { + error_msg(progname, "Could not open specified journal file\n"); + usage(); + leave( EXIT_FAILURE ); - error_msg(progname, "Could not open specified hdf5 file\n"); - usage(); - leave( EXIT_FAILURE ); - - } /* end if */ - - /* allocate temporary space to store and transaction messages */ - last_trans_msg = HDmalloc((size_t)50); - if (last_trans_msg == NULL) { - - error_msg(progname, "Could not allocate space\n"); - leave( EXIT_FAILURE); - - } /* end if */ - - if ( verbose ) printf("Recovering file <%s> from journal <%s>\n\n", - file_name, journal_name); - - /* ====================================================== */ - /* Find the last complete transaction in the journal file */ - /* ====================================================== */ - - fseek(journal_fp, 0, SEEK_END); - - while (last_trans_found == 0) { - - while (fgetc(journal_fp) != '\n') { - - if (ftell(journal_fp) <= 1) { - - jrnl_has_transactions = FALSE; - printf("Journal file has no complete transactions. Nothing to recover!\n"); - break; + } /* end if */ + + /* open hdf5 file for reading and writing */ + hdf5_fd = open(file_name, O_RDWR); + + if (hdf5_fd == -1) { + error_msg(progname, "Could not open specified hdf5 file\n"); + usage(); + leave( EXIT_FAILURE ); + + } /* end if */ + + /* allocate temporary space to store and transaction messages */ + last_trans_msg = HDmalloc((size_t)50); + if (last_trans_msg == NULL) { + + error_msg(progname, "Could not allocate space\n"); + leave( EXIT_FAILURE); + + } /* end if */ + + if ( verbose ) printf("Recovering file <%s> from journal <%s>\n\n", + file_name, journal_name); + + /* ====================================================== */ + /* Find the last complete transaction in the journal file */ + /* ====================================================== */ + + fseek(journal_fp, 0, SEEK_END); + + while (last_trans_found == 0) { + + while (fgetc(journal_fp) != '\n') { + + if (ftell(journal_fp) <= 1) { + + jrnl_has_transactions = FALSE; + printf("Journal file has no complete transactions. Nothing to recover!\n"); + break; + + } /* end if */ + + fseek(journal_fp, -2, SEEK_CUR); + + } /* end while */ + + if (jrnl_has_transactions == FALSE) break; + + if ( fgetc(journal_fp) == '3' ) { + + last_trans_found = 1; + pos_end = ftell(journal_fp); + fseek(journal_fp, -1, SEEK_CUR); + fgets(last_trans_msg, 50, journal_fp); + } /* end if */ - - fseek(journal_fp, -2, SEEK_CUR); - + + else { + + fseek(journal_fp, -3, SEEK_CUR); + + } /* end else */ + } /* end while */ - - if (jrnl_has_transactions == FALSE) break; - - if ( fgetc(journal_fp) == '3' ) { - - last_trans_found = 1; - pos_end = ftell(journal_fp); - fseek(journal_fp, -1, SEEK_CUR); - fgets(last_trans_msg, 50, journal_fp); - - } /* end if */ - - else { - - fseek(journal_fp, -3, SEEK_CUR); - - } /* end else */ - - } /* end while */ - - /* ================================================================== */ - /* Only do the recovery procedure if there is something to recover in */ - /* the journal file. Otherwise, skip over these steps and mark */ - /* the file as recovered. */ - /* ================================================================== */ - if (jrnl_has_transactions == TRUE) { - - /* ================================================================= */ - /* Pre-parse of journal file to pull information needed before doing */ - /* the recovery. */ - /* - max journal size (for buffer allocation) */ - /* - max EOA size (for superblock update, to preserve raw data) */ - /* ================================================================= */ - - fseek(journal_fp, 0, SEEK_SET); + /* ================================================================== */ + /* Only do the recovery procedure if there is something to recover in */ + /* the journal file. Otherwise, skip over these steps and mark */ + /* the file as recovered. */ + /* ================================================================== */ + + if (jrnl_has_transactions == TRUE) { - c_new = 0; - c_old = 0; - max_size = 0; - - if ( verbose ) printf("Pre-parsing journal file to pull needed data ... \n"); - - /* while journal is not at end of file */ - while (ftell(journal_fp) != pos_end) { - - c_old = c_new; - c_new = fgetc(journal_fp); + /* ================================================================= */ + /* Pre-parse of journal file to pull information needed before doing */ + /* the recovery. */ + /* - max journal size (for buffer allocation) */ + /* - max EOA size (for superblock update, to preserve raw data) */ + /* ================================================================= */ + + fseek(journal_fp, 0, SEEK_SET); - /* if position is at the start of a line */ - if (c_old == '\n') { - - /* ========================================================== */ - /* if the line is a journal entry, determine its size. update */ - /* max size value if needed. */ - /* ========================================================== */ - if (c_new == '2') { - - pos = ftell(journal_fp); - - fgets(temp, 100, journal_fp); - tok[0] = HDstrtok(temp, " "); + c_new = 0; + c_old = 0; + max_size = 0; + + if ( verbose ) printf("Pre-parsing journal file to pull needed data ... \n"); + + /* while journal is not at end of file */ + while (ftell(journal_fp) != pos_end) { + + c_old = c_new; + c_new = fgetc(journal_fp); + + /* if position is at the start of a line */ + if (c_old == '\n') { + + /* ========================================================== */ + /* if the line is a journal entry, determine its size. update */ + /* max size value if needed. */ + /* ========================================================== */ + if (c_new == '2') { + + pos = ftell(journal_fp); + + fgets(temp, 100, journal_fp); + tok[0] = HDstrtok(temp, " "); + if (tok[0] == NULL) { + + error_msg(progname, "Could not tokenize entry\n"); + leave( EXIT_FAILURE); + + } /* end if */ + for (i=1; i<8; i++) { + + tok[i] = HDstrtok(NULL, " "); + if (tok[i] == NULL) { + + error_msg(progname, "Could not tokenize entry\n"); + leave( EXIT_FAILURE); + + } /* end if */ + + } /* end for */ + + size = (size_t)HDstrtoll(tok[3], NULL, 10); + + if (max_size < size) { + + max_size = size; + + } /* end if */ + + /* jump back to start of line */ + fseek(journal_fp, pos, SEEK_SET); + + } /* end if */ + + /* =========================================================== */ + /* If the line is an EOA entry, determine its value and update */ + /* if it exceeds the current max length */ + /* =========================================================== */ + + if (c_new == 'E') { + + pos = ftell(journal_fp); + + fgets(temp, 100, journal_fp); + p = &temp[11]; + + /* according to the man page, strtoll() should accept a + * "0x" prefix on any base 16 value -- seems this is + * not the case. Deal with this by incrementing p + * past the prefix. + */ + + while ( HDisspace(*(p)) ) { p++; } + + if ( ( *(p) == '0' ) && + ( *(p + 1) == 'x' ) ) { + + p += 2; + } + + eoa = (haddr_t)HDstrtoll(p, NULL, 16); + if (eoa == 0) { + + error_msg(progname, + "Could not convert eoa to integer\n"); + leave( EXIT_FAILURE); + + } /* end if */ + + if (update_eoa < eoa) { + + update_eoa = eoa; + + } /* end if */ + + /* jump back to start of line */ + fseek(journal_fp, pos, SEEK_SET); + + } /* end if */ + + } /* end if */ + + } /* end while */ + + if ( verbose ) printf(" - Maximum journal entry size = %d\n", max_size); + if ( verbose ) printf(" - Journaled EOA value = 0x%llx\n", update_eoa); + + /* =================================== */ + /* Update EOA value in HDF5 superblock */ + /* =================================== */ + + if (update_eoa != 0) { + + if ( verbose ) printf("\nLooking for HDF5 superblock ... \n"); + /* Jump through possible locations of superblock */ + for(n = 8; n < 16; n++) { + + sb_addr = (8 == n) ? 0 : 1 << n; + + /* read from HDF5 file */ + pread(hdf5_fd, buf, H5F_SIGNATURE_LEN, sb_addr); + + /* Check to see if superblock has been found. */ + if(!HDmemcmp(buf, H5F_SIGNATURE, (size_t)H5F_SIGNATURE_LEN)) { + + if ( verbose ) printf(" - Superblock signature found at location %d\n", sb_addr); + + if ( verbose ) printf(" - Reading in entire superblock\n"); + + /* Read in entire superblock */ + pread(hdf5_fd, sbuf, H5F_MAX_SUPERBLOCK_SIZE, sb_addr/* + H5F_SIGNATURE_LEN */); + + /* Use p as a pointer into superblock buffer */ + p = sbuf; + + /* Skip over signature */ + p += H5F_SIGNATURE_LEN; + + /* Get superblock version number */ + super_vers = *p++; + + /* add printfs to verbose */ + if ( verbose ) printf(" - Superblock version number = %d\n", super_vers); + + /* ==================================== */ + /* Point to EOA value in the superblock */ + /* ==================================== */ + + /* First part of superblock may be of differing versions */ + if(super_vers < 2) { + /* skip over unneeded data */ + p += 1 + /* freespace version */ + 1 + /* root group version */ + 1 + /* reserved byte */ + 1; /* shared header version */ + + sizeof_addr = *p++; /* size of file addresses */ + + p += 1 + /* size of file sizes */ + 1 + /* reserved byte */ + 2 + /* 1/2 rank for symtable leaf nodes */ + 2 + /* 1/2 rank for btree internal nodes */ + 4 + /* file status flags */ + 2; /* b-tree internal k value */ + + if (super_vers == 1) + p += 2; /* reserved bytes */ + + } /* end if */ + + /* Superblock version number > 2 */ + else { + + sizeof_addr = *p++; /* size of file addresses */ + + p += 1 + /* size of file sizes */ + 1; /* file status flags */ + + p_front = p; + p_end = p; + + } /* end else */ + + /* Skip over various variable portions of superblock */ + address_decode((size_t)sizeof_addr, &p_end, &addr); /* base address */ + address_decode((size_t)sizeof_addr, &p_end, &addr); /* extension address */ + + /* ============================ */ + /* Update EOA in the superblock */ + /* ============================ */ + + p_front = p_end; + + /* Decode the EOA address */ + address_decode((size_t)sizeof_addr, &p_end, &addr); + + if ( verbose ) printf(" - Current value of EOA in superblock is 0x%llx\n", addr); + + /* Set the EOA to the address pulled from the journal */ + addr = (haddr_t)update_eoa; + p_end = p_front; + + /* encode new EOA value into superblock buffer */ + address_encode((size_t)sizeof_addr, &p_end, addr); + + if ( verbose ) printf(" - EOA value has been updated to 0x%llx in superblock\n", update_eoa); + + /* skip over root group object header */ + address_decode((size_t)sizeof_addr, &p_end, &addr); /* root group object header */ + + p_front = p_end; + + if ( verbose ) printf(" - Updating checksum value of superblock\n"); + + /* decode checksum */ + read_chksum = 0; + UINT32DECODE(p_end, read_chksum); + + p_end = p_front; + + /* Update the CHECKSUM VALUE */ + /* Compute superblock checksum */ + chksum = H5_checksum_metadata(sbuf, (size_t)(p_end - sbuf), 0); + + /* Superblock checksum */ + UINT32ENCODE(p_end, chksum); + + new_eoa = (haddr_t)update_eoa; + + /* verify new EOA value in buffer is correct */ + address_decode((size_t)sizeof_addr, &p_front, &addr); + + /* Extend file to be EOA bytes */ + HDftruncate(hdf5_fd, new_eoa); + + /* Write out new updated superblock to the file */ + status = pwrite(hdf5_fd, sbuf, (size_t)H5F_MAX_SUPERBLOCK_SIZE, sb_addr /*+ H5F_SIGNATURE_LEN */); + + if (status == -1) { + error_msg(progname, "pwrite failed when trying to update superblock\n"); + leave( EXIT_FAILURE ); + } + + if (status == 0) { + error_msg(progname, "pwrite did not write anything to superblock!\n"); + leave( EXIT_FAILURE); + } + + if ( verbose ) printf(" - New superblock written to HDF5 file\n"); + + } /* end if */ + + } /* end for */ + + } /* end if (update_eoa != 0)*/ + + if ( verbose ) printf("\nBeginning recovery process ... \n\n"); + + /* ==================================================================== */ + /* Main Recovery Procedure: */ + /* Read through the journal file and recover any journal entries found. */ + /* ==================================================================== */ + + max_size = max_size * 3 + 200; + + /* allocate space large enough to hold largest journal entry */ + readback = HDmalloc( max_size ); + if (readback == NULL) { + + error_msg(progname, "Could not allocate space to hold entries\n"); + leave( EXIT_FAILURE); + + } /* end if */ + + /* read through journal file. recover any journal entries found, up + * through the last transaction number */ + fseek(journal_fp, 0, SEEK_SET); + + while ( fgets(readback, max_size, journal_fp) != NULL ) { + + if (HDstrcmp(readback, last_trans_msg) == 0) { + + /* done reading from file */ + break; + + } /* end if */ + + /* ===================================================== */ + /* If journal entry is found, write entry into HDF5 file */ + /* ===================================================== */ + + if ( readback[0] == '2') { /* journal entry found */ + + if ( verbose ) printf("Journal entry found.\n"); + if ( verbose ) printf("Tokenizing journal entry.\n"); + + /* ================================================= */ + /* Tokenize the journal entry in order to grab data */ + /* ================================================= */ + + /* divide the journal entry into tokens */ + tok[0] = HDstrtok(readback, " "); if (tok[0] == NULL) { - - error_msg(progname, "Could not tokenize entry\n"); - leave( EXIT_FAILURE); + error_msg(progname, "Could not tokenize journal entry\n"); + leave( EXIT_FAILURE); + } /* end if */ + + if ( verbose ) printf(" token[0] : <%s>\n", tok[0]); + for (i=1; i<8; i++) { - + tok[i] = HDstrtok(NULL, " "); if (tok[i] == NULL) { - - error_msg(progname, "Could not tokenize entry\n"); + + error_msg(progname, "Could not tokenize journal entry\n"); leave( EXIT_FAILURE); - + } /* end if */ - + + if ( verbose ) printf(" token[%d] : <%s>\n", i, tok[i]); + } /* end for */ - - size = (size_t)HDstrtoll(tok[3], NULL, 10); - - if (max_size < size) { - - max_size = size; - - } /* end if */ - - /* jump back to start of line */ - fseek(journal_fp, pos, SEEK_SET); - - } /* end if */ - - /* =========================================================== */ - /* If the line is an EOA entry, determine its value and update */ - /* if it exceeds the current max length */ - /* =========================================================== */ - - if (c_new == 'E') { - - pos = ftell(journal_fp); - - fgets(temp, 100, journal_fp); - p = &temp[11]; - - /* according to the man page, strtoll() should accept a - * "0x" prefix on any base 16 value -- seems this is - * not the case. Deal with this by incrementing p - * past the prefix. - */ - - while ( HDisspace(*(p)) ) { p++; } - - if ( ( *(p) == '0' ) && - ( *(p + 1) == 'x' ) ) { - - p += 2; - } - - eoa = (haddr_t)HDstrtoll(p, NULL, 16); - if (eoa == 0) { - error_msg(progname, - "Could not convert eoa to integer\n"); + /* put all remaining data into last token. */ + /* This contains all of the journal entry body */ + tok[8] = HDstrtok(NULL, "\n"); + if (tok[8] == NULL) { + + error_msg(progname, "Could not tokenize journal entry\n"); leave( EXIT_FAILURE); - - } /* end if */ - - if (update_eoa < eoa) { - - update_eoa = eoa; - + } /* end if */ - - /* jump back to start of line */ - fseek(journal_fp, pos, SEEK_SET); - - } /* end if */ - - } /* end if */ - - } /* end while */ - - if ( verbose ) printf(" - Maximum journal entry size = %d\n", max_size); - if ( verbose ) printf(" - Journaled EOA value = 0x%llx\n", update_eoa); - - /* =================================== */ - /* Update EOA value in HDF5 superblock */ - /* =================================== */ - - if (update_eoa != 0) { - - if ( verbose ) printf("\nLooking for HDF5 superblock ... \n"); - /* Jump through possible locations of superblock */ - for(n = 8; n < 16; n++) { - sb_addr = (8 == n) ? 0 : 1 << n; + if ( verbose ) printf(" token[8] : \n"); - /* read from HDF5 file */ - pread(hdf5_fd, buf, H5F_SIGNATURE_LEN, sb_addr); + /* =================================== */ + /* Convert Items from Character Arrays */ + /* =================================== */ - /* Check to see if superblock has been found. */ - if(!HDmemcmp(buf, H5F_SIGNATURE, (size_t)H5F_SIGNATURE_LEN)) { + if ( verbose ) printf("Converting data from character strings.\n"); - if ( verbose ) printf(" - Superblock signature found at location %d\n", sb_addr); + /* convert address from character character string */ - if ( verbose ) printf(" - Reading in entire superblock\n"); + /* according to the man page, strtoll() should accept a + * "0x" prefix on any base 16 value -- seems this is + * not the case. Deal with this by incrementing tok[6] + * past the prefix. + */ + while ( HDisspace(*(tok[6])) ) { (tok[6])++; } + if ( ( *(tok[6]) == '0' ) && + ( *(tok[6] + 1) == 'x' ) ) { - /* Read in entire superblock */ - pread(hdf5_fd, sbuf, H5F_MAX_SUPERBLOCK_SIZE, sb_addr/* + H5F_SIGNATURE_LEN */); + (tok[6]) += 2; + } + address = (off_t)HDstrtoll(tok[6], NULL, 16); + if (address == 0) { + + error_msg(progname, "Could not convert address to integer\n"); + leave( EXIT_FAILURE); - /* Use p as a pointer into superblock buffer */ - p = sbuf; + } /* end if */ - /* Skip over signature */ - p += H5F_SIGNATURE_LEN; - - /* Get superblock version number */ - super_vers = *p++; + if ( verbose ) printf(" address : %llx\n", address); + + /* convert size from character string*/ + size = (size_t)HDstrtoll(tok[4], NULL, 10); + if (size == 0) { + + error_msg(progname, "Could not convert size to double\n"); + leave( EXIT_FAILURE); + + } /* end if */ + + if ( verbose ) printf(" length : %d\n", size); + + /* transform body out of hexadecimal character string */ + body = HDmalloc(size + 1); + if (body == NULL) { + + error_msg(progname, "Could not allocate space for body\n"); + leave( EXIT_FAILURE); - /* add printfs to verbose */ - if ( verbose ) printf(" - Superblock version number = %d\n", super_vers); - - /* ==================================== */ - /* Point to EOA value in the superblock */ - /* ==================================== */ - - /* First part of superblock may be of differing versions */ - if(super_vers < 2) { - /* skip over unneeded data */ - p += 1 + /* freespace version */ - 1 + /* root group version */ - 1 + /* reserved byte */ - 1; /* shared header version */ - - sizeof_addr = *p++; /* size of file addresses */ - - p += 1 + /* size of file sizes */ - 1 + /* reserved byte */ - 2 + /* 1/2 rank for symtable leaf nodes */ - 2 + /* 1/2 rank for btree internal nodes */ - 4 + /* file status flags */ - 2; /* b-tree internal k value */ - - if (super_vers == 1) - p += 2; /* reserved bytes */ - } /* end if */ - - /* Superblock version number > 2 */ - else { - - sizeof_addr = *p++; /* size of file addresses */ - - p += 1 + /* size of file sizes */ - 1; /* file status flags */ - - p_front = p; - p_end = p; - - } /* end else */ - - /* Skip over various variable portions of superblock */ - address_decode((size_t)sizeof_addr, &p_end, &addr); /* base address */ - address_decode((size_t)sizeof_addr, &p_end, &addr); /* extension address */ - - /* ============================ */ - /* Update EOA in the superblock */ - /* ============================ */ - - p_front = p_end; - - /* Decode the EOA address */ - address_decode((size_t)sizeof_addr, &p_end, &addr); - - if ( verbose ) printf(" - Current value of EOA in superblock is 0x%llx\n", addr); - /* Set the EOA to the address pulled from the journal */ - addr = (haddr_t)update_eoa; - p_end = p_front; - - /* encode new EOA value into superblock buffer */ - address_encode((size_t)sizeof_addr, &p_end, addr); - - if ( verbose ) printf(" - EOA value has been updated to 0x%llx in superblock\n", update_eoa); - - /* skip over root group object header */ - address_decode((size_t)sizeof_addr, &p_end, &addr); /* root group object header */ - - p_front = p_end; - - if ( verbose ) printf(" - Updating checksum value of superblock\n"); - - /* decode checksum */ - read_chksum = 0; - UINT32DECODE(p_end, read_chksum); - - p_end = p_front; - - /* Update the CHECKSUM VALUE */ - /* Compute superblock checksum */ - chksum = H5_checksum_metadata(sbuf, (size_t)(p_end - sbuf), 0); - - /* Superblock checksum */ - UINT32ENCODE(p_end, chksum); - - new_eoa = (haddr_t)update_eoa; - - /* verify new EOA value in buffer is correct */ - address_decode((size_t)sizeof_addr, &p_front, &addr); + p = &(tok[8])[0]; - /* Extend file to be EOA bytes */ - HDftruncate(hdf5_fd, new_eoa); - - /* Write out new updated superblock to the file */ - status = pwrite(hdf5_fd, sbuf, (size_t)H5F_MAX_SUPERBLOCK_SIZE, sb_addr /*+ H5F_SIGNATURE_LEN */); - - if (status == -1) { - error_msg(progname, "pwrite failed when trying to update superblock\n"); - leave( EXIT_FAILURE ); - } - - if (status == 0) { - error_msg(progname, "pwrite did not write anything to superblock!\n"); - leave( EXIT_FAILURE); - } - - if ( verbose ) printf(" - New superblock written to HDF5 file\n"); + for (i = 0; i < size; i++) { - } /* end if */ + body[i] = HDstrtoul(p, NULL, 16); + p = &p[3]; - } /* end for */ - - } /* end if (update_eoa != 0)*/ - - if ( verbose ) printf("\nBeginning recovery process ... \n\n"); - - /* ==================================================================== */ - /* Main Recovery Procedure: */ - /* Read through the journal file and recover any journal entries found. */ - /* ==================================================================== */ - - max_size = max_size * 3 + 200; - - /* allocate space large enough to hold largest journal entry */ - readback = HDmalloc( max_size ); - if (readback == NULL) { - - error_msg(progname, "Could not allocate space to hold entries\n"); - leave( EXIT_FAILURE); - - } /* end if */ - - /* read through journal file. recover any journal entries found, up - * through the last transaction number */ - fseek(journal_fp, 0, SEEK_SET); - - while ( fgets(readback, max_size, journal_fp) != NULL ) { + } /* end for */ - if (HDstrcmp(readback, last_trans_msg) == 0) { + body[i] = 0; - /* done reading from file */ - break; - - } /* end if */ + if ( verbose ) printf(" body : binary body data\n"); - /* ===================================================== */ - /* If journal entry is found, write entry into HDF5 file */ - /* ===================================================== */ - - if ( readback[0] == '2') { /* journal entry found */ - - if ( verbose ) printf("Journal entry found.\n"); - if ( verbose ) printf("Tokenizing journal entry.\n"); - - /* ================================================= */ - /* Tokenize the journal entry in order to grab data */ - /* ================================================= */ - - /* divide the journal entry into tokens */ - tok[0] = HDstrtok(readback, " "); - if (tok[0] == NULL) { - - error_msg(progname, "Could not tokenize journal entry\n"); - leave( EXIT_FAILURE); + /* ================================================ */ + /* Write into HDF5 file the recovered journal entry */ + /* ================================================ */ - } /* end if */ - - if ( verbose ) printf(" token[0] : <%s>\n", tok[0]); - - for (i=1; i<8; i++) { - - tok[i] = HDstrtok(NULL, " "); - if (tok[i] == NULL) { - - error_msg(progname, "Could not tokenize journal entry\n"); + if ( verbose ) printf("Writing entry to HDF5 file.\n"); + + /* perform a write */ + status = pwrite(hdf5_fd, body, size, address); + + if (status == -1) { + error_msg(progname, "pwrite failed\n"); + leave( EXIT_FAILURE ); + } + + if (status == 0) { + error_msg(progname, "pwrite did not write anything!\n"); leave( EXIT_FAILURE); - - } /* end if */ - - if ( verbose ) printf(" token[%d] : <%s>\n", i, tok[i]); - - } /* end for */ - - /* put all remaining data into last token. */ - /* This contains all of the journal entry body */ - tok[8] = HDstrtok(NULL, "\n"); - if (tok[8] == NULL) { - - error_msg(progname, "Could not tokenize journal entry\n"); - leave( EXIT_FAILURE); - - } /* end if */ - - if ( verbose ) printf(" token[8] : \n"); - - /* =================================== */ - /* Convert Items from Character Arrays */ - /* =================================== */ - - if ( verbose ) printf("Converting data from character strings.\n"); - - /* convert address from character character string */ - - /* according to the man page, strtoll() should accept a - * "0x" prefix on any base 16 value -- seems this is - * not the case. Deal with this by incrementing tok[6] - * past the prefix. - */ - while ( HDisspace(*(tok[6])) ) { (tok[6])++; } - if ( ( *(tok[6]) == '0' ) && - ( *(tok[6] + 1) == 'x' ) ) { - - (tok[6]) += 2; - } - address = (off_t)HDstrtoll(tok[6], NULL, 16); - if (address == 0) { + } - error_msg(progname, "Could not convert address to integer\n"); - leave( EXIT_FAILURE); - - } /* end if */ - - if ( verbose ) printf(" address : %llx\n", address); - - /* convert size from character string*/ - size = (size_t)HDstrtoll(tok[4], NULL, 10); - if (size == 0) { - - error_msg(progname, "Could not convert size to double\n"); - leave( EXIT_FAILURE); - - } /* end if */ - - if ( verbose ) printf(" length : %d\n", size); - - /* transform body out of hexadecimal character string */ - body = HDmalloc(size + 1); - if (body == NULL) { - - error_msg(progname, "Could not allocate space for body\n"); - leave( EXIT_FAILURE); - - } /* end if */ - - p = &(tok[8])[0]; - - for (i = 0; i < size; i++) { - - body[i] = HDstrtoul(p, NULL, 16); - p = &p[3]; - - } /* end for */ - - body[i] = 0; - - if ( verbose ) printf(" body : binary body data\n"); - - /* ================================================ */ - /* Write into HDF5 file the recovered journal entry */ - /* ================================================ */ - - if ( verbose ) printf("Writing entry to HDF5 file.\n"); - - /* perform a write */ - status = pwrite(hdf5_fd, body, size, address); - - if (status == -1) { - error_msg(progname, "pwrite failed\n"); - leave( EXIT_FAILURE ); - } - - if (status == 0) { - error_msg(progname, "pwrite did not write anything!\n"); - leave( EXIT_FAILURE); - } - - /* Verify that write occurred correctly */ - if ( check_file == 1) { - - if ( verbose ) printf("Verifying success of write"); - - compare_buf = HDmalloc(size + 1); + /* Verify that write occurred correctly */ + if ( check_file == 1) { - if (compare_buf == NULL) { - error_msg(progname, "Could not allocate space\n"); - leave( EXIT_FAILURE); - } /* end if */ + if ( verbose ) printf("Verifying success of write"); - pread(hdf5_fd, compare_buf, size, address); - - /* do a quick string compare on two items */ - if (HDstrcmp((const char *)body, (const char *)compare_buf) != 0) { - error_msg(progname, "Entry incorrectly written into HDF5 file. Exiting.\n"); - printf("Address %llx:\n", (unsigned long_long)address); - printf(" -- from journal: '%s'\n", body); - printf(" -- from HDF5 file: '%s'\n", compare_buf); - leave( EXIT_FAILURE ); - } /* end if */ - - /* compare each individual value of entry */ - for (i=0; i 0 ) ) { + + proceed = apply_journal_file(file_name, + hdf5_file_len, + hdf5_sb_offset, + hdf5_sb_ver, + hdf5_base_addr, + journal_name, + jnl_file_len, + jnl_header_len, + jnl_human_readable, + offset_width, + length_width, + max_trans_num, + max_eoa, + max_body_len, + verbose); + } + + if ( proceed ) { - if (jrnl_has_transactions == TRUE) - printf("HDF5 file successfuly recovered.\n"); - else - printf("File marked as recovered.\n"); + proceed = mark_hdf5_file_recovered(file_name); + } + } - if ( verbose ) printf("==============================================\n\n"); free(file_name); return 0; diff --git a/tools/h5recover/testh5recover.sh.in b/tools/h5recover/testh5recover.sh.in index 9fbf886..67d93dc 100644 --- a/tools/h5recover/testh5recover.sh.in +++ b/tools/h5recover/testh5recover.sh.in @@ -504,6 +504,7 @@ test_point() { pass=1 seconds=$1 usecs=$2 + trecover_options=$3 if [ $usecs -lt 10 ] then @@ -548,13 +549,13 @@ test_point() { fi fi - echo "trecover -a $delay" + echo "trecover -a $delay $trecover_options" # Generate the data, journal and the control files. # The testing shell will still print "Terminated" though the signal is # trapped. Need to find a way to block or filter it out. trap true 15 - $RUNSERIAL ./trecover -a $delay > /dev/null 2>&1 + $RUNSERIAL ./trecover -a $delay $trecover_options > /dev/null 2>&1 if [ -f trecover.h5 ] then @@ -671,6 +672,8 @@ run_jnl_invarient_test() { echo "Testing journaling invarients...." echo "" + trecover_options=$1 + finished=0; sec=0; usec=0; @@ -687,7 +690,7 @@ run_jnl_invarient_test() { fi - test_point $sec $usec + test_point $sec $usec $trecover_options pass=$? @@ -743,6 +746,9 @@ run_jnl_invarient_test() { # default test setting TOOLTEST default.txt +# repeat using the binary journal file format +TOOLTEST default.txt -b + # h5recover output and journal rejection tests # @@ -806,8 +812,14 @@ run_h5recover_output_test test38 "-x -v" "38 verbose examine bad HDF5 file" # basic idea is to scan the execution time of a journaled process to # look for points in time at which the journaling invarients are not # maintained. see comments for details. +# +# Run the test twice -- once with human readable journal file format, and +# once with binary journal file format. + run_jnl_invarient_test +run_jnl_invarient_test -b + if test $nerrors -eq 0 ; then echo "All $TOOL tests passed." diff --git a/tools/h5recover/trecover.h b/tools/h5recover/trecover.h index 16092d8..3705929 100644 --- a/tools/h5recover/trecover.h +++ b/tools/h5recover/trecover.h @@ -77,7 +77,7 @@ void parser(int ac, char **av); /* command option parser */ void init(void); /* initialization */ void help(void); /* initialization */ int create_files(const char *filename, const char *ctl_filename); -int journal_files(const char *filename, const char *ctl_filename, const char *jnl_filename, int patch); +int journal_files(const char *filename, const char *ctl_filename, const char *jnl_filename, int patch, hbool_t human_readable); int close_file(hid_t fid); diff --git a/tools/h5recover/trecover_main.c b/tools/h5recover/trecover_main.c index 4a940b8..fc941ab 100644 --- a/tools/h5recover/trecover_main.c +++ b/tools/h5recover/trecover_main.c @@ -33,6 +33,7 @@ CrasherParam_t AsyncCrashParam; int CrashMode = SyncCrash; /* default to synchronous crash */ hid_t datafile, ctl_file; /* data and control file ids */ +hbool_t humanReadableJnl = 1; /* local variables */ #if 0 @@ -66,6 +67,9 @@ parser(int ac, char **av) exit(1); } break; + case 'b': /* binary journal file option */ + humanReadableJnl = 0; + break; case 'd': /* -d dataset type */ if (--ac > 0){ av++; @@ -155,17 +159,18 @@ void help(void) { fprintf(stderr, - "Usage: trecover ([-a ] [-d ] [-h]) | [-v]\n" - "\t-a\tAsync crash seconds where is a real number.\n" - "\t-d\tDataset to create. can be:\n" - "\t\t A\tAll datasets\n" - "\t\t C\tContingous datasets\n" - "\t\t G\tGzip compressed datasets\n" - "\t\t K\tChunked datasets\n" - "\t\t S\tSzip compressed datasets\n" - "\t\tDefault is all datasets\n" - "\t\tTemp Default is Chunked datasets\n" - "\t-v\tVerify recovery -- may not be combined with any other option.\n" + "Usage: trecover ([-a ] [-b] [-d ] [-h]) | [-v]\n" + "\t-a\tAsync crash seconds where is a real number.\n" + "\t-b\tUse binary journal file (default human readable).\n" + "\t-d\tDataset to create. can be:\n" + "\t\t A\tAll datasets\n" + "\t\t C\tContingous datasets\n" + "\t\t G\tGzip compressed datasets\n" + "\t\t K\tChunked datasets\n" + "\t\t S\tSzip compressed datasets\n" + "\t\tDefault is all datasets\n" + "\t\tTemp Default is Chunked datasets\n" + "\t-v\tVerify recovery -- may not be combined with any other option.\n" ); } @@ -200,7 +205,8 @@ main (int ac, char **av) } /* Open data file with Journaling and control file without. */ - journal_files(H5FILE_NAME, CTL_H5FILE_NAME, JNL_H5FILE_NAME, PatchMode); + journal_files(H5FILE_NAME, CTL_H5FILE_NAME, JNL_H5FILE_NAME, + PatchMode, humanReadableJnl); if (PatchMode){ /* extend the datafile again without writing data, then close it. */ diff --git a/tools/h5recover/trecover_writer.c b/tools/h5recover/trecover_writer.c index 950f4b9..7779f5b 100644 --- a/tools/h5recover/trecover_writer.c +++ b/tools/h5recover/trecover_writer.c @@ -46,7 +46,7 @@ create_files(const char *filename, const char *ctl_filename) } int -journal_files(const char *filename, const char *ctl_filename, const char *jnl_filename, int patch) +journal_files(const char *filename, const char *ctl_filename, const char *jnl_filename, int patch, hbool_t human_readable) { /* * Create a new file and the control file using H5F_ACC_TRUNC access, @@ -82,7 +82,7 @@ journal_files(const char *filename, const char *ctl_filename, const char *jnl_fi jnl_config.jbrb_buf_size = 8*1024; /* multiples of sys buffer size*/ jnl_config.jbrb_num_bufs = 2; jnl_config.jbrb_use_aio = 0; /* only sync IO is supported */ - jnl_config.jbrb_human_readable = 1; /* only readable form is supported */ + jnl_config.jbrb_human_readable = human_readable; strcpy(jnl_config.journal_file_path, jnl_filename); if ( H5Pset_jnl_config(faccpl, &jnl_config) < 0 ) { -- cgit v0.12