From 5a50fca18dd2ffd58160c38486cc4f0de8fdc460 Mon Sep 17 00:00:00 2001 From: Mike McGreevy Date: Thu, 21 Aug 2008 16:54:44 -0500 Subject: [svn-r15514] Purpose: - EOA logging update Description: - EOA values will now be written to the journal file in their own transaction when the EOA changes. - The EOA will be udpated in the HDF5 file's superblock before the recovery process begins. This should prevent some loss of raw data as the file won't be getting truncated upon file open as it will read the correct EOA value from the superblock. - Removed storing of EOA in journal entry messages since they're in their own transaction. - Updated tests to reflect change of transaction formats. Regenerated smoke test files to account for new entry types, and tweaked transaction number tests to reflect change in size of journal entries. - Large testfiles (in test/testfiles) should now unzip when ./configure is run. - When journal file is supplied but contains no complete transactions, instead of reporting an error, h5recover now informs the user of said nonexistant transactions, and opens/closes the hdf5 file with the journal recovered flag set. - Other various organizational changes to h5recover, included a bit more added to verbose output. Tested: - kagiso, smirom --- configure | 11 +- configure.in | 10 + src/H5C2journal.c | 90 ++- src/H5C2private.h | 4 +- src/H5MF.c | 19 +- src/Makefile.in | 8 +- test/cache2_journal.c | 35 +- test/testfiles/cache2_journal_sc00_000.jnl.gz | Bin 218 -> 222 bytes test/testfiles/cache2_journal_sc00_001.jnl.gz | Bin 250 -> 237 bytes test/testfiles/cache2_journal_sc00_002.jnl.gz | Bin 249 -> 239 bytes test/testfiles/cache2_journal_sc00_003.jnl.gz | Bin 284 -> 274 bytes test/testfiles/cache2_journal_sc00_004.jnl.gz | Bin 317 -> 309 bytes test/testfiles/cache2_journal_sc00_005.jnl.gz | Bin 374 -> 364 bytes test/testfiles/cache2_journal_sc00_006.jnl.gz | Bin 392 -> 383 bytes test/testfiles/cache2_journal_sc00_007.jnl.gz | Bin 646 -> 630 bytes test/testfiles/cache2_journal_sc00_008.jnl.gz | Bin 1026 -> 1012 bytes test/testfiles/cache2_journal_sc00_009.jnl.gz | Bin 1431 -> 1414 bytes test/testfiles/cache2_journal_sc00_010.jnl.gz | Bin 1823 -> 1805 bytes test/testfiles/cache2_journal_sc00_011.jnl.gz | Bin 345 -> 331 bytes test/testfiles/cache2_journal_sc00_012.jnl.gz | Bin 417 -> 404 bytes test/testfiles/cache2_journal_sc00_013.jnl.gz | Bin 533 -> 522 bytes test/testfiles/cache2_journal_sc00_014.jnl.gz | Bin 780 -> 767 bytes test/testfiles/cache2_journal_sc00_015.jnl.gz | Bin 223 -> 210 bytes test/testfiles/cache2_journal_sc00_016.jnl.gz | Bin 241 -> 231 bytes test/testfiles/cache2_journal_sc00_017.jnl.gz | Bin 217 -> 204 bytes test/testfiles/cache2_journal_sc00_018.jnl.gz | Bin 218 -> 209 bytes test/testfiles/cache2_journal_sc01_000.jnl.gz | Bin 9610 -> 9227 bytes test/testfiles/cache2_journal_sc01_001.jnl.gz | Bin 9608 -> 9207 bytes test/testfiles/cache2_journal_sc01_002.jnl.gz | Bin 9124 -> 8721 bytes test/testfiles/cache2_journal_sc01_003.jnl.gz | Bin 27070 -> 25997 bytes test/testfiles/cache2_journal_sc01_004.jnl.gz | Bin 25108 -> 24104 bytes test/testfiles/cache2_journal_sc02_000.jnl.gz | Bin 13594 -> 13030 bytes test/testfiles/cache2_journal_sc02_001.jnl.gz | Bin 24175 -> 23080 bytes test/testfiles/cache2_journal_sc02_002.jnl.gz | Bin 24519 -> 23449 bytes test/testfiles/cache2_journal_sc02_003.jnl.gz | Bin 103469 -> 99109 bytes test/testfiles/cache2_journal_sc02_004.jnl.gz | Bin 100534 -> 96391 bytes tools/h5recover/h5recover.c | 759 ++++++++++++++++++-------- 37 files changed, 660 insertions(+), 276 deletions(-) diff --git a/configure b/configure index 3f9b53b..34360c3 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Id: configure.in 15300 2008-06-30 19:05:39Z koziol . +# From configure.in Id: configure.in 15369 2008-07-15 22:03:33Z acheng . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for HDF5 1.9.8-metadata_journaling1. # @@ -50520,6 +50520,15 @@ echo "$as_me: error: Removing old public API symbols not allowed when using them { (exit 1); exit 1; }; } fi +{ echo "$as_me:$LINENO: checking for and unzipping large test files" >&5 +echo $ECHO_N "checking for and unzipping large test files... $ECHO_C" >&6; } +for f in $srcdir/test/testfiles/*.gz; do + if test -f $f; then + gunzip -f $f + fi +done +{ echo "$as_me:$LINENO: result: done" >&5 +echo "${ECHO_T}done" >&6; } { echo "$as_me:$LINENO: checking Whether to perform strict file format checks" >&5 diff --git a/configure.in b/configure.in index 460b4da..c4166a3 100644 --- a/configure.in +++ b/configure.in @@ -3715,6 +3715,16 @@ if test "X${DEFAULT_API_VERSION}" != "Xv18" -a "X${DEPRECATED_SYMBOLS}" = "Xno" AC_MSG_ERROR([Removing old public API symbols not allowed when using them as default public API symbols]) fi +dnl ---------------------------------------------------------------------- +dnl Unzip large test files +dnl +AC_MSG_CHECKING([for and unzipping large test files]) +for f in $srcdir/test/testfiles/*.gz; do + if test -f $f; then + gunzip -f $f + fi +done +AC_MSG_RESULT([done]) dnl ---------------------------------------------------------------------- dnl Enable strict file format checks diff --git a/src/H5C2journal.c b/src/H5C2journal.c index 4eaab9e..5350d6d 100644 --- a/src/H5C2journal.c +++ b/src/H5C2journal.c @@ -788,7 +788,6 @@ H5C2_journal_transaction(H5F_t * f, void * new_image_ptr; void * thing; herr_t result; - haddr_t eoa; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5C2_journal_transaction, FAIL) @@ -973,13 +972,8 @@ H5C2_journal_transaction(H5F_t * f, */ if ( ( ! resized ) && ( ! renamed ) ) { - if(HADDR_UNDEF == (eoa = H5FDget_eoa(f->shared->lf, H5FD_MEM_DEFAULT))) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, \ - "file get eoa request failed") - result = H5C2_jb__journal_entry(&(cache_ptr->mdj_jbrb), cache_ptr->trans_num, - eoa, entry_ptr->addr, entry_ptr->size, entry_ptr->image_ptr); @@ -2768,7 +2762,6 @@ done: herr_t H5C2_jb__journal_entry(H5C2_jbrb_t * struct_ptr, uint64_t trans_num, - haddr_t eoa, haddr_t base_addr, size_t length, const uint8_t * body) @@ -2821,9 +2814,8 @@ H5C2_jb__journal_entry(H5C2_jbrb_t * struct_ptr, /* Write journal entry */ HDsnprintf(temp, (size_t)(length + 100), - "2 trans_num %llu eoa 0x%lx length %zu base_addr 0x%lx body ", + "2 trans_num %llu length %zu base_addr 0x%lx body ", trans_num, - (unsigned long)eoa, length, (unsigned long)base_addr); @@ -3065,6 +3057,86 @@ done: /****************************************************************************** * + * Function: H5C2_jb__eoa + * + * Programmer: Mike McGreevy + * July 29, 2008 + * + * Purpose: Insert the supplied EOA into the journal file. + * + * Returns: SUCCEED on success. + * + ******************************************************************************/ + +herr_t +H5C2_jb__eoa(H5C2_jbrb_t * struct_ptr, + haddr_t eoa) +{ + char temp[40]; + size_t temp_len = 40; + 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); + + /* Verify that header message is present in journal file or ring buffer. + * If not, write it. + */ + if ( struct_ptr->header_present == FALSE ) { + + char buf[150]; + time_t current_date; + + /* Get the current date */ + current_date = time(NULL); + + HDsnprintf(buf, + (size_t)150, + "0 ver_num %ld target_file_name %s creation_date %10.10s human_readable %d\n", + struct_ptr->jvers, + struct_ptr->hdf5_file_name, + ctime(¤t_date), + struct_ptr->human_readable); + + if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(buf), buf, + FALSE, struct_ptr->cur_trans) < 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__write_to_buffer() failed.\n") + } /* end if */ + + struct_ptr->header_present = 1; + struct_ptr->journal_is_empty = 0; + } /* end if */ + + /* Write EOA message */ + HDsnprintf(temp, temp_len, "E eoa_value 0x%lx", eoa); + + 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") + } /* end if */ + + if ( H5C2_jb__write_to_buffer(struct_ptr, 1, "\n", FALSE, struct_ptr->cur_trans ) < 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__write_to_buffer() failed.\n") + } /* end if */ + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* end H5C2_jb__eoa */ + + +/****************************************************************************** + * * Function: H5C2_jb__get_last_transaction_on_disk * * Programmer: Mike McGreevy diff --git a/src/H5C2private.h b/src/H5C2private.h index 1e4dbb3..f25fe4f 100644 --- a/src/H5C2private.h +++ b/src/H5C2private.h @@ -1531,7 +1531,6 @@ H5_DLL herr_t H5C2_jb__start_transaction(H5C2_jbrb_t * struct_ptr, H5_DLL herr_t H5C2_jb__journal_entry(H5C2_jbrb_t * struct_ptr, uint64_t trans_num, - haddr_t eoa, haddr_t base_addr, size_t length, const uint8_t * body); @@ -1542,6 +1541,9 @@ H5_DLL herr_t H5C2_jb__end_transaction(H5C2_jbrb_t * struct_ptr, H5_DLL herr_t H5C2_jb__comment(H5C2_jbrb_t * struct_ptr, const char * comment_ptr); +H5_DLL herr_t H5C2_jb__eoa(H5C2_jbrb_t * struct_ptr, + haddr_t eoa); + H5_DLL herr_t H5C2_jb__get_last_transaction_on_disk(H5C2_jbrb_t * struct_ptr, uint64_t * trans_num_ptr); diff --git a/src/H5MF.c b/src/H5MF.c index df4531e..953726a 100644 --- a/src/H5MF.c +++ b/src/H5MF.c @@ -28,6 +28,7 @@ /* Module Setup */ /****************/ +#define H5C2_PACKAGE /*suppress error about including H5C2pkg */ #define H5F_PACKAGE /*suppress error about including H5Fpkg */ @@ -35,6 +36,7 @@ /* Headers */ /***********/ #include "H5private.h" /* Generic Functions */ +#include "H5C2pkg.h" /* Metadata cache */ #include "H5Eprivate.h" /* Error handling */ #include "H5Fpkg.h" /* File access */ #include "H5MFprivate.h" /* File memory management */ @@ -96,7 +98,8 @@ static hbool_t H5MF_alloc_overflow(const H5F_t *f, hsize_t size); haddr_t H5MF_alloc(const H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, hsize_t size) { - haddr_t ret_value; + haddr_t ret_value, new_eoa; + herr_t result; FUNC_ENTER_NOAPI(H5MF_alloc, HADDR_UNDEF) @@ -111,6 +114,20 @@ H5MF_alloc(const H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, hsize_t size) /* Allocate space from the virtual file layer */ if(HADDR_UNDEF == (ret_value = H5FD_alloc(f->shared->lf, type, dxpl_id, size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "file allocation failed") + + /* Check for journaling in progress */ + if (f->shared->cache2->mdj_enabled == 1) { + + /* get updated EOA value */ + if (HADDR_UNDEF ==(new_eoa = H5FDget_eoa(f->shared->lf, H5FD_MEM_DEFAULT))) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, \ + "file get eoa request failed") + + /* journal the updated EOA value */ + if(SUCCEED != H5C2_jb__eoa(&(f->shared->cache2->mdj_jbrb), new_eoa)) + HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \ + "H5C2_jb__eoa() failed.") + } /* end if */ /* Convert absolute file address to relative file address */ HDassert(ret_value >= f->shared->base_addr); diff --git a/src/Makefile.in b/src/Makefile.in index b96bdb0..51417eb 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -102,10 +102,10 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \ H5I.lo H5L.lo H5Lexternal.lo H5MF.lo H5MM.lo H5MP.lo \ H5MPtest.lo H5O.lo H5Oainfo.lo H5Oalloc.lo H5Oattr.lo \ H5Oattribute.lo H5Obogus.lo H5Obtreek.lo H5Ocache.lo \ - H5Ochunk.lo H5Ocont.lo H5Ocopy.lo H5Odbg.lo H5Odrvinfo.lo H5Odtype.lo \ - H5Oefl.lo H5Ofill.lo H5Oginfo.lo H5Olayout.lo H5Olinfo.lo \ - H5Olink.lo H5Omdj_msg.lo H5Omessage.lo H5Omtime.lo H5Oname.lo \ - H5Onull.lo H5Opline.lo H5Orefcount.lo H5Osdspace.lo \ + H5Ochunk.lo H5Ocont.lo H5Ocopy.lo H5Odbg.lo H5Odrvinfo.lo \ + H5Odtype.lo H5Oefl.lo H5Ofill.lo H5Oginfo.lo H5Olayout.lo \ + H5Olinfo.lo H5Olink.lo H5Omdj_msg.lo H5Omessage.lo H5Omtime.lo \ + H5Oname.lo H5Onull.lo H5Opline.lo H5Orefcount.lo H5Osdspace.lo \ H5Oshared.lo H5Ostab.lo H5Oshmesg.lo H5Otest.lo H5Ounknown.lo \ H5P.lo H5Pacpl.lo H5Pdcpl.lo H5Pdeprec.lo H5Pdxpl.lo \ H5Pfapl.lo H5Pfcpl.lo H5Pfmpl.lo H5Pgcpl.lo H5Pint.lo \ diff --git a/test/cache2_journal.c b/test/cache2_journal.c index 633414e..fb199d5 100644 --- a/test/cache2_journal.c +++ b/test/cache2_journal.c @@ -9336,7 +9336,6 @@ check_message_format(void) if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, /* trans number */ (uint64_t)1, - /* eoa */ (haddr_t)1, /* base address */ (haddr_t)0, /* data length */ 1, /* data */ (const uint8_t *)"A") @@ -9358,7 +9357,6 @@ check_message_format(void) if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, /* trans number */ (uint64_t)1, - /* eoa */ (haddr_t)1, /* base address */ (haddr_t)1, /* data length */ 2, /* data */ (const uint8_t *)"AB") @@ -9380,7 +9378,6 @@ check_message_format(void) if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, /* trans number */ (uint64_t)1, - /* eoa */ (haddr_t)1, /* base address */ (haddr_t)3, /* data length */ 4, /* data */ (const uint8_t *)"CDEF") @@ -9437,7 +9434,6 @@ check_message_format(void) if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, /* trans number */ (uint64_t)2, - /* eoa */ (haddr_t)1, /* base address */ (haddr_t)285, /* data length */ 11, /* data */ (const uint8_t *)"Test Data?!") @@ -9493,12 +9489,12 @@ check_message_format(void) /* Fill out verify array with expected messages */ sprintf(verify[0], "0 ver_num 1 target_file_name HDF5.file creation_date %10.10s human_readable 1\n", ctime(¤t_date)); sprintf(verify[1], "1 bgn_trans 1\n"); - sprintf(verify[2], "2 trans_num 1 eoa 0x1 length 1 base_addr 0x0 body 41 \n"); - sprintf(verify[3], "2 trans_num 1 eoa 0x1 length 2 base_addr 0x1 body 41 42 \n"); - sprintf(verify[4], "2 trans_num 1 eoa 0x1 length 4 base_addr 0x3 body 43 44 45 46 \n"); + sprintf(verify[2], "2 trans_num 1 length 1 base_addr 0x0 body 41 \n"); + sprintf(verify[3], "2 trans_num 1 length 2 base_addr 0x1 body 41 42 \n"); + sprintf(verify[4], "2 trans_num 1 length 4 base_addr 0x3 body 43 44 45 46 \n"); sprintf(verify[5], "3 end_trans 1\n"); sprintf(verify[6], "1 bgn_trans 2\n"); - sprintf(verify[7], "2 trans_num 2 eoa 0x1 length 11 base_addr 0x11d body 54 65 73 74 20 44 61 74 61 3f 21 \n"); + sprintf(verify[7], "2 trans_num 2 length 11 base_addr 0x11d body 54 65 73 74 20 44 61 74 61 3f 21 \n"); sprintf(verify[8], "3 end_trans 2\n"); /* verify that messages in journal are same as expected */ @@ -9560,7 +9556,6 @@ check_message_format(void) if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, /* trans number */ (uint64_t)3, - /* eoa */ (haddr_t)1, /* base address */ (haddr_t)28591, /* data length */ 6, /* data */ (const uint8_t *)"#1nN`}") @@ -9650,7 +9645,7 @@ check_message_format(void) /* Fill out verify array with expected messages */ sprintf(verify[0], "0 ver_num 1 target_file_name HDF5.file creation_date %10.10s human_readable 1\n", ctime(¤t_date)); sprintf(verify[1], "1 bgn_trans 3\n"); - sprintf(verify[2], "2 trans_num 3 eoa 0x1 length 6 base_addr 0x6faf body 23 31 6e 4e 60 7d \n"); + sprintf(verify[2], "2 trans_num 3 length 6 base_addr 0x6faf body 23 31 6e 4e 60 7d \n"); sprintf(verify[3], "3 end_trans 3\n"); sprintf(verify[4], "C comment This is a comment!\n"); sprintf(verify[5], "C comment This is another comment!\n"); @@ -9840,7 +9835,6 @@ check_legal_calls(void) if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, /* Transaction # */ (uint64_t)1, - /* eoa */ (haddr_t)1, /* Base Address */ (haddr_t)123456789, /* Length */ 16, /* Body */ (const uint8_t *)"This should fail") @@ -9921,7 +9915,6 @@ check_legal_calls(void) if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, /* Transaction # */ (uint64_t)2, - /* eoa */ (haddr_t)1, /* Base Address */ (haddr_t)123456789, /* Length */ 16, /* Body */ (const uint8_t *)"This should fail") @@ -9943,7 +9936,6 @@ check_legal_calls(void) if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, /* Transaction # */ (uint64_t)1, - /* eoa */ (haddr_t)1, /* Base Address */ (haddr_t)123456789, /* Length */ 51, /* Body */ (const uint8_t *)"This is the first transaction during transaction 1.") @@ -10040,7 +10032,6 @@ check_legal_calls(void) if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, /* Transaction # */ (uint64_t)2, - /* eoa */ (haddr_t)1, /* Base Address */ (haddr_t)7465, /* Length */ 51, /* Body */ (const uint8_t *)"This is the first transaction during transaction 2!") @@ -10062,7 +10053,6 @@ check_legal_calls(void) if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, /* Transaction # */ (uint64_t)2, - /* eoa */ (haddr_t)1, /* Base Address */ (haddr_t)123456789, /* Length */ 60, /* Body */ (const uint8_t *)"... And here's your second transaction during transaction 2.") @@ -10812,10 +10802,9 @@ write_verify_trans_num(H5C2_jbrb_t * struct_ptr, if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ struct_ptr, /* Transaction # */ trans_num, - /* eoa */ (haddr_t)16, /* Base Address */ (haddr_t)16, - /* Length */ 6, - /* Body */ (const uint8_t *)"XXXXXX") + /* Length */ 9, + /* Body */ (const uint8_t *)"XXXXXXXXX") != SUCCEED ) { pass2 = FALSE; @@ -10829,10 +10818,9 @@ write_verify_trans_num(H5C2_jbrb_t * struct_ptr, if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ struct_ptr, /* Transaction # */ trans_num, - /* eoa */ (haddr_t)16, /* Base Address */ (haddr_t)16, - /* Length */ 5, - /* Body */ (const uint8_t *)"XXXXX") + /* Length */ 8, + /* Body */ (const uint8_t *)"XXXXXXXX") != SUCCEED ) { pass2 = FALSE; @@ -10846,10 +10834,9 @@ write_verify_trans_num(H5C2_jbrb_t * struct_ptr, if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ struct_ptr, /* Transaction # */ trans_num, - /* eoa */ (haddr_t)16, /* Base Address */ (haddr_t)16, - /* Length */ 4, - /* Body */ (const uint8_t *)"XXXX") + /* Length */ 7, + /* Body */ (const uint8_t *)"XXXXXXX") != SUCCEED ) { pass2 = FALSE; diff --git a/test/testfiles/cache2_journal_sc00_000.jnl.gz b/test/testfiles/cache2_journal_sc00_000.jnl.gz index 5f4311e..2b1646d 100755 Binary files a/test/testfiles/cache2_journal_sc00_000.jnl.gz and b/test/testfiles/cache2_journal_sc00_000.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc00_001.jnl.gz b/test/testfiles/cache2_journal_sc00_001.jnl.gz index 7f711dc..4989b62 100755 Binary files a/test/testfiles/cache2_journal_sc00_001.jnl.gz and b/test/testfiles/cache2_journal_sc00_001.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc00_002.jnl.gz b/test/testfiles/cache2_journal_sc00_002.jnl.gz index 62d6929..ad81f72 100755 Binary files a/test/testfiles/cache2_journal_sc00_002.jnl.gz and b/test/testfiles/cache2_journal_sc00_002.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc00_003.jnl.gz b/test/testfiles/cache2_journal_sc00_003.jnl.gz index cd60e35..44512bb 100755 Binary files a/test/testfiles/cache2_journal_sc00_003.jnl.gz and b/test/testfiles/cache2_journal_sc00_003.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc00_004.jnl.gz b/test/testfiles/cache2_journal_sc00_004.jnl.gz index ffacdc0..87ae0f0 100755 Binary files a/test/testfiles/cache2_journal_sc00_004.jnl.gz and b/test/testfiles/cache2_journal_sc00_004.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc00_005.jnl.gz b/test/testfiles/cache2_journal_sc00_005.jnl.gz index e777a18..c1550f0 100755 Binary files a/test/testfiles/cache2_journal_sc00_005.jnl.gz and b/test/testfiles/cache2_journal_sc00_005.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc00_006.jnl.gz b/test/testfiles/cache2_journal_sc00_006.jnl.gz index bfab587..a845a4f 100755 Binary files a/test/testfiles/cache2_journal_sc00_006.jnl.gz and b/test/testfiles/cache2_journal_sc00_006.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc00_007.jnl.gz b/test/testfiles/cache2_journal_sc00_007.jnl.gz index d2d8e5f..02fbaff 100755 Binary files a/test/testfiles/cache2_journal_sc00_007.jnl.gz and b/test/testfiles/cache2_journal_sc00_007.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc00_008.jnl.gz b/test/testfiles/cache2_journal_sc00_008.jnl.gz index 8ea7164..97e2444 100755 Binary files a/test/testfiles/cache2_journal_sc00_008.jnl.gz and b/test/testfiles/cache2_journal_sc00_008.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc00_009.jnl.gz b/test/testfiles/cache2_journal_sc00_009.jnl.gz index f345dcb..b3c9be1 100755 Binary files a/test/testfiles/cache2_journal_sc00_009.jnl.gz and b/test/testfiles/cache2_journal_sc00_009.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc00_010.jnl.gz b/test/testfiles/cache2_journal_sc00_010.jnl.gz index d761163..f3134fc 100755 Binary files a/test/testfiles/cache2_journal_sc00_010.jnl.gz and b/test/testfiles/cache2_journal_sc00_010.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc00_011.jnl.gz b/test/testfiles/cache2_journal_sc00_011.jnl.gz index 176fc0c..bd2de80 100755 Binary files a/test/testfiles/cache2_journal_sc00_011.jnl.gz and b/test/testfiles/cache2_journal_sc00_011.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc00_012.jnl.gz b/test/testfiles/cache2_journal_sc00_012.jnl.gz index b8cf81a..a8ac645 100755 Binary files a/test/testfiles/cache2_journal_sc00_012.jnl.gz and b/test/testfiles/cache2_journal_sc00_012.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc00_013.jnl.gz b/test/testfiles/cache2_journal_sc00_013.jnl.gz index 7fb6958..9898d8c 100755 Binary files a/test/testfiles/cache2_journal_sc00_013.jnl.gz and b/test/testfiles/cache2_journal_sc00_013.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc00_014.jnl.gz b/test/testfiles/cache2_journal_sc00_014.jnl.gz index 6a6eb10..fcd6826 100755 Binary files a/test/testfiles/cache2_journal_sc00_014.jnl.gz and b/test/testfiles/cache2_journal_sc00_014.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc00_015.jnl.gz b/test/testfiles/cache2_journal_sc00_015.jnl.gz index 2af775b..fd8b45f 100755 Binary files a/test/testfiles/cache2_journal_sc00_015.jnl.gz and b/test/testfiles/cache2_journal_sc00_015.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc00_016.jnl.gz b/test/testfiles/cache2_journal_sc00_016.jnl.gz index 2de5c38..6f89ad1 100755 Binary files a/test/testfiles/cache2_journal_sc00_016.jnl.gz and b/test/testfiles/cache2_journal_sc00_016.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc00_017.jnl.gz b/test/testfiles/cache2_journal_sc00_017.jnl.gz index f60aed8..79a96ae 100755 Binary files a/test/testfiles/cache2_journal_sc00_017.jnl.gz and b/test/testfiles/cache2_journal_sc00_017.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc00_018.jnl.gz b/test/testfiles/cache2_journal_sc00_018.jnl.gz index c6f10ee..50c8dc3 100755 Binary files a/test/testfiles/cache2_journal_sc00_018.jnl.gz and b/test/testfiles/cache2_journal_sc00_018.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc01_000.jnl.gz b/test/testfiles/cache2_journal_sc01_000.jnl.gz index 5d37f04..3244641 100755 Binary files a/test/testfiles/cache2_journal_sc01_000.jnl.gz and b/test/testfiles/cache2_journal_sc01_000.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc01_001.jnl.gz b/test/testfiles/cache2_journal_sc01_001.jnl.gz index 669a307..9563e51 100755 Binary files a/test/testfiles/cache2_journal_sc01_001.jnl.gz and b/test/testfiles/cache2_journal_sc01_001.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc01_002.jnl.gz b/test/testfiles/cache2_journal_sc01_002.jnl.gz index a684d6d..cac45ff 100755 Binary files a/test/testfiles/cache2_journal_sc01_002.jnl.gz and b/test/testfiles/cache2_journal_sc01_002.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc01_003.jnl.gz b/test/testfiles/cache2_journal_sc01_003.jnl.gz index c9265ff..a3cfa45 100755 Binary files a/test/testfiles/cache2_journal_sc01_003.jnl.gz and b/test/testfiles/cache2_journal_sc01_003.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc01_004.jnl.gz b/test/testfiles/cache2_journal_sc01_004.jnl.gz index aacc153..9ce7738 100755 Binary files a/test/testfiles/cache2_journal_sc01_004.jnl.gz and b/test/testfiles/cache2_journal_sc01_004.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc02_000.jnl.gz b/test/testfiles/cache2_journal_sc02_000.jnl.gz index d5675ed..e3906ad 100755 Binary files a/test/testfiles/cache2_journal_sc02_000.jnl.gz and b/test/testfiles/cache2_journal_sc02_000.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc02_001.jnl.gz b/test/testfiles/cache2_journal_sc02_001.jnl.gz index 6a8fbf7..3990c93 100755 Binary files a/test/testfiles/cache2_journal_sc02_001.jnl.gz and b/test/testfiles/cache2_journal_sc02_001.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc02_002.jnl.gz b/test/testfiles/cache2_journal_sc02_002.jnl.gz index 121017e..5e0cd42 100755 Binary files a/test/testfiles/cache2_journal_sc02_002.jnl.gz and b/test/testfiles/cache2_journal_sc02_002.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc02_003.jnl.gz b/test/testfiles/cache2_journal_sc02_003.jnl.gz index b5dbf0a..ef6df83 100755 Binary files a/test/testfiles/cache2_journal_sc02_003.jnl.gz and b/test/testfiles/cache2_journal_sc02_003.jnl.gz differ diff --git a/test/testfiles/cache2_journal_sc02_004.jnl.gz b/test/testfiles/cache2_journal_sc02_004.jnl.gz index 6b16e37..833438e 100755 Binary files a/test/testfiles/cache2_journal_sc02_004.jnl.gz and b/test/testfiles/cache2_journal_sc02_004.jnl.gz differ diff --git a/tools/h5recover/h5recover.c b/tools/h5recover/h5recover.c index 692ba8b..bf6c1b7 100644 --- a/tools/h5recover/h5recover.c +++ b/tools/h5recover/h5recover.c @@ -26,6 +26,8 @@ #include #include "H5Fpkg.h" +#define H5F_MAX_SUPERBLOCK_SIZE 134 + const char * progname="h5recover"; int d_status; @@ -48,7 +50,7 @@ static struct long_options l_opts[] = { * * Return: void * - * Programmer: Mike McGreevy + * Programmer: Mike McGreevy * Monday, March 10, 2008 * *------------------------------------------------------------------------- @@ -99,7 +101,7 @@ leave(int ret) * * Return: 0 on success * - * Programmer: Mike McGreevy + * Programmer: Mike McGreevy * Monday, March 10, 2008 * *------------------------------------------------------------------------- @@ -159,15 +161,93 @@ file_copy(char * file_from, char * file_to) return 0; } +/*------------------------------------------------------------------------- + * Function: address_decode + * + * Purpose: Decodes an address from the buffer pointed to by *pp and + * updates the pointer to point to the next byte after the + * address. + * + * If the value read is all 1's, then the address is + * returned with an undefined value. + * + * Programmer: Mike McGreevy (utilizing code from Robb Matzke) + * Thursday, August 7, 2008 + * + *------------------------------------------------------------------------- + */ +void +address_decode(size_t sizeof_addr, const uint8_t **pp/*in,out*/, haddr_t *addr_p/*out*/) +{ + + unsigned i; + haddr_t tmp; + uint8_t c; + hbool_t all_zero = TRUE; + + assert(pp && *pp); + assert(addr_p); + + *addr_p = 0; + + for (i=0; i>= 8; + } /* end for */ + + assert("overflow" && 0 == addr); + +} /*------------------------------------------------------------------------- * Function: main() * * Purpose: main h5recover program. * - * Programmer: Mike McGreevy + * Programmer: Mike McGreevy * Monday, March 10, 2008 * + * Modifications: + * Mike McGreevy, August 7, 2008 + * Parses superblock to update EOA value + * *------------------------------------------------------------------------- */ @@ -194,7 +274,8 @@ main (int argc, const char *argv[]) char * tok[11]; /* string tokens */ int i; /* iterator */ off_t address; /* address to write to */ - haddr_t eoa; /* end of address of file */ + haddr_t eoa = 0; /* end of address of file */ + haddr_t update_eoa = 0; /* new end of address */ uint8_t * body; /* body of journal entry */ size_t size; /* size of journal entry body */ size_t max_size; /* maximum size of journal entry body */ @@ -210,6 +291,24 @@ main (int argc, const char *argv[]) long pos_end; /* file descriptor position indicator */ char temp[100]; /* temporary buffer */ H5F_t * f; /* File pointer */ + hbool_t jrnl_has_transactions = TRUE; + + /* ================================================ */ + /* Variables needed for superblock parse and update */ + /* ================================================ */ + + int n; /* iterator */ + haddr_t sb_addr; /* address of superblock */ + uint8_t buf[H5F_SIGNATURE_LEN]; /* buf to get superblock signature */ + uint8_t sbuf[H5F_MAX_SUPERBLOCK_SIZE]; /* buf to store superblock */ + int super_vers = 0; /* superblock version number */ + int sizeof_addr = 0; /* size of addresses */ + haddr_t addr = NULL; /* address buffer to hold haddr_t values */ + uint8_t * p_front = NULL; /* reference pointer into superblock buffer */ + uint8_t * p_end = NULL; /* reference pointer into superblock buffer */ + haddr_t new_eoa; /* new value of EOA to be written into superblock */ + uint32_t chksum; /* calculated checksum value */ + uint32_t read_chksum; /* checksum value read from superblock */ /* ==================== */ /* Command Line Parsing */ @@ -297,51 +396,6 @@ main (int argc, const char *argv[]) } /* end if */ - /* ========================================== */ - /* Open HDF5 File with Journal Recovered Flag */ - /* ========================================== */ - - /* set up appropriate fapl */ - fapl = H5Pcreate(H5P_FILE_ACCESS); - - if ( fapl == -1 ) { - - error_msg(progname, "Could not create FAPL.\n"); - leave( EXIT_FAILURE ); - - } /* end if */ - - config.version = 1; /* should be H5C2__CURR_AUTO_SIZE_CTL_VER */ - - /* get H5AC_cache_config_t configuration from fapl */ - if ( H5Pget_jnl_config(fapl, &config) == -1) { - - error_msg(progname, "Could not get mdc config from FAPL.\n"); - leave( EXIT_FAILURE ); - - } - - /* make sure journal recovered field is set 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) { - - error_msg(progname, "Could not set jnl config on FAPL.\n"); - leave( EXIT_FAILURE ); - - } /* end if */ - - /* open HDF5 file with provided fapl */ - fid = H5Fopen(file_name, H5F_ACC_RDWR, fapl); - - if ( fid == -1 ) { - - error_msg(progname, "Could not open recovered HDF5 file.\n"); - leave( EXIT_FAILURE ); - - } /* end if */ - /* =============================== */ /* Make a Backup Copy of HDF5 File */ /* =============================== */ @@ -420,9 +474,9 @@ main (int argc, const char *argv[]) if (ftell(journal_fp) <= 1) { - error_msg(progname, "Journal has no complete transactions\n"); - usage(); - leave( EXIT_FAILURE ); + jrnl_has_transactions = FALSE; + printf("Journal file has no complete transactions. Nothing to recover!\n"); + break; } /* end if */ @@ -430,6 +484,8 @@ main (int argc, const char *argv[]) } /* end while */ + if (jrnl_has_transactions == FALSE) break; + if ( fgetc(journal_fp) == '3' ) { last_trans_found = 1; @@ -446,287 +502,517 @@ main (int argc, const char *argv[]) } /* end while */ - /* ======================================= */ - /* Determine Size of Biggest Journal Entry */ - /* ======================================= */ + /* ================================================================== */ + /* 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) { - fseek(journal_fp, 0, SEEK_END); - pos_end = ftell(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_END); + pos_end = ftell(journal_fp); - fseek(journal_fp, 0, SEEK_SET); + fseek(journal_fp, 0, SEEK_SET); - c_new = 0; - c_old = 0; - max_size = 0; + c_new = 0; + c_old = 0; + max_size = 0; - /* while journal is not at end of file */ - while (ftell(journal_fp) != pos_end) { + if ( verbose ) printf("Pre-parsing journal file to pull needed data ... \n"); - c_old = c_new; - c_new = fgetc(journal_fp); + /* 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 position is at the start of a line */ + if (c_old == '\n') { - /* if the line starts with a '2', find out size of entry */ - if (c_new == '2') { + /* ========================================================== */ + /* if the line is a journal entry, determine its size. update */ + /* max size value if needed. */ + /* ========================================================== */ + if (c_new == '2') { - pos = ftell(journal_fp); + pos = ftell(journal_fp); - fgets(temp, 100, journal_fp); - tok[0] = HDstrtok(temp, " "); - if (tok[0] == NULL) { + fgets(temp, 100, journal_fp); + tok[0] = HDstrtok(temp, " "); + if (tok[0] == NULL) { - error_msg(progname, "Could not tokenize entry\n"); - leave( EXIT_FAILURE); + error_msg(progname, "Could not tokenize entry\n"); + leave( EXIT_FAILURE); - } /* end if */ - for (i=1; i<8; i++) { + } /* end if */ + for (i=1; i<8; i++) { - tok[i] = HDstrtok(NULL, " "); - if (tok[i] == NULL) { + tok[i] = HDstrtok(NULL, " "); + if (tok[i] == NULL) { - error_msg(progname, "Could not tokenize entry\n"); - leave( EXIT_FAILURE); + error_msg(progname, "Could not tokenize entry\n"); + leave( EXIT_FAILURE); - } /* end if */ + } /* end if */ - } /* end for */ + } /* end for */ - size = HDstrtod(tok[3], NULL); + size = HDstrtod(tok[5], NULL); - if (max_size < size) { + if (max_size < size) { - max_size = size; + max_size = size; + + } /* end if */ + + /* jump back to start of line */ + fseek(journal_fp, pos, SEEK_SET); } /* end if */ - /* jump back to start of line */ - fseek(journal_fp, pos, SEEK_SET); + /* =========================================================== */ + /* If the line is an EOA entry, determine its value and update */ + /* if it exceeds the current max length */ + /* =========================================================== */ - } /* end if */ + if (c_new == 'E') { + + pos = ftell(journal_fp); - } /* end if */ + fgets(temp, 100, journal_fp); + p = &temp[11]; + + eoa = HDstrtod(p, NULL); + if (eoa == 0) { + + error_msg(progname, "Could not convert eoa to integer\n"); + leave( EXIT_FAILURE); - } /* end while */ + } /* end if */ + + if (update_eoa < eoa) { - /* ================================================= */ - /* Tokenize each journal entry in order to grab data */ - /* ================================================= */ + update_eoa = eoa; - max_size = max_size * 3 + 200; + } /* end if */ - /* allocate space large enough to hold largest journal entry */ - readback = HDmalloc( max_size ); - if (readback == NULL) { + /* jump back to start of line */ + fseek(journal_fp, pos, SEEK_SET); - error_msg(progname, "Could not allocate space to hold entries\n"); - leave( EXIT_FAILURE); + } /* end if */ - } /* end if */ + } /* end if */ - /* read through journal file. recover any journal entries found, up - * through the last transaction number */ - fseek(journal_fp, 0, SEEK_SET); + } /* 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) { - while ( fgets(readback, max_size, journal_fp) != NULL ) { + 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 (HDstrcmp(readback, last_trans_msg) == 0) { + if ( verbose ) printf(" - Reading in entire superblock\n"); - /* done reading from file */ - break; + /* 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; - } /* end if */ + /* Get superblock version number */ + super_vers = *p++; - if ( readback[0] == '2') { /* journal entry found */ + /* 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 */ - if ( verbose ) printf("Journal entry found.\n"); - if ( verbose ) printf("Tokenizing journal entry.\n"); + /* 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(sizeof_addr, &p_end, &addr); /* base address */ + address_decode(sizeof_addr, &p_end, &addr); /* extension address */ - /* divide the journal entry into tokens */ - tok[0] = HDstrtok(readback, " "); - if (tok[0] == NULL) { + /* ============================ */ + /* Update EOA in the superblock */ + /* ============================ */ - error_msg(progname, "Could not tokenize journal entry\n"); - leave( EXIT_FAILURE); - - } /* end if */ + p_front = p_end; - if ( verbose ) printf(" token[0] : <%s>\n", tok[0]); + /* Decode the EOA address */ + address_decode(sizeof_addr, &p_end, &addr); - for (i=1; i<10; i++) { + 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; - tok[i] = HDstrtok(NULL, " "); - if (tok[i] == NULL) { + /* encode new EOA value into superblock buffer */ + address_encode(sizeof_addr, &p_end, addr); - error_msg(progname, "Could not tokenize journal entry\n"); - leave( EXIT_FAILURE); + if ( verbose ) printf(" - EOA value has been updated to 0x%llx in superblock\n", update_eoa); - } /* end if */ + /* skip over root group object header */ + address_decode(sizeof_addr, &p_end, &addr); /* root group object header */ - if ( verbose ) printf(" token[%d] : <%s>\n", i, tok[i]); + 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(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 */ - /* put all remaining data into last token. */ - /* This contains all of the journal entry body */ - tok[10] = HDstrtok(NULL, "\n"); - if (tok[10] == NULL) { + } /* end if (update_eoa != 0)*/ - error_msg(progname, "Could not tokenize journal entry\n"); - leave( EXIT_FAILURE); + if ( verbose ) printf("\nBeginning recovery process ... \n\n"); - } /* end if */ + /* ==================================================================== */ + /* Main Recovery Procedure: */ + /* Read through the journal file and recover any journal entries found. */ + /* ==================================================================== */ + + max_size = max_size * 3 + 200; - if ( verbose ) printf(" token[8] : \n"); + /* allocate space large enough to hold largest journal entry */ + readback = HDmalloc( max_size ); + if (readback == NULL) { - /* ================================== */ - /* Convert Items from Character Array */ - /* ================================== */ + error_msg(progname, "Could not allocate space to hold entries\n"); + leave( EXIT_FAILURE); + + } /* end if */ - if ( verbose ) printf("Converting data from character strings.\n"); + /* read through journal file. recover any journal entries found, up + * through the last transaction number */ + fseek(journal_fp, 0, SEEK_SET); - /* convert address from character character string */ - address = HDstrtod(tok[8], NULL); - if (address == 0) { + while ( fgets(readback, max_size, journal_fp) != NULL ) { - error_msg(progname, "Could not convert address to integer\n"); - leave( EXIT_FAILURE); + 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 ( verbose ) printf(" address : %llx\n", address); + if ( readback[0] == '2') { /* journal entry found */ - /* convert size from character string*/ - size = HDstrtod(tok[6], NULL); - if (size == 0) { + if ( verbose ) printf("Journal entry found.\n"); + if ( verbose ) printf("Tokenizing journal entry.\n"); - error_msg(progname, "Could not convert size to double\n"); - leave( EXIT_FAILURE); + /* ================================================= */ + /* Tokenize the journal entry in order to grab data */ + /* ================================================= */ - } /* end if */ + /* divide the journal entry into tokens */ + tok[0] = HDstrtok(readback, " "); + if (tok[0] == NULL) { - /* convert eoa from character character string */ - eoa = HDstrtod(tok[4], NULL); - if (eoa == 0) { + error_msg(progname, "Could not tokenize journal entry\n"); + leave( EXIT_FAILURE); - error_msg(progname, "Could not convert eoa to integer\n"); - leave( EXIT_FAILURE); + } /* end if */ - } /* 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) { - if ( verbose ) printf(" length : %d\n", size); + error_msg(progname, "Could not tokenize journal entry\n"); + leave( EXIT_FAILURE); - /* transform body out of hexadecimal character string */ - body = HDmalloc(size + 1); - if (body == NULL) { + } /* end if */ - error_msg(progname, "Could not allocate space for body\n"); - leave( EXIT_FAILURE); + if ( verbose ) printf(" token[%d] : <%s>\n", i, tok[i]); - } /* end if */ + } /* 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 */ + address = HDstrtod(tok[6], NULL); + 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 = HDstrtod(tok[4], NULL); + 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[10])[0]; + p = &(tok[8])[0]; - for (i = 0; i < size; i++) { + for (i = 0; i < size; i++) { - body[i] = HDstrtoul(p, NULL, 16); - p = &p[3]; + body[i] = HDstrtoul(p, NULL, 16); + p = &p[3]; - } /* end for */ + } /* end for */ - body[i] = 0; + body[i] = 0; - if ( verbose ) printf(" body : binary body data\n"); + if ( verbose ) printf(" body : binary body data\n"); - /* ================================================ */ - /* Write into HDF5 file the recovered journal entry */ - /* ================================================ */ + /* ================================================ */ + /* 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 ( 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); - } + if (status == -1) { + error_msg(progname, "pwrite failed\n"); + leave( EXIT_FAILURE ); + } - /* Verify that write occurred correctly */ - if ( check_file == 1) { + if (status == 0) { + error_msg(progname, "pwrite did not write anything!\n"); + leave( EXIT_FAILURE); + } - if ( verbose ) printf("Verifying success of write"); + /* Verify that write occurred correctly */ + if ( check_file == 1) { + + if ( verbose ) printf("Verifying success of write"); - compare_buf = HDmalloc(size + 1); + compare_buf = HDmalloc(size + 1); - if (compare_buf == NULL) { - error_msg(progname, "Could not allocate space\n"); - leave( EXIT_FAILURE); - } /* end if */ + if (compare_buf == NULL) { + error_msg(progname, "Could not allocate space\n"); + leave( EXIT_FAILURE); + } /* end if */ - 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 */ + pread(hdf5_fd, compare_buf, size, address); - /* compare each individual value of entry */ - for (i=0; ishared->lf, H5FD_MEM_DEFAULT, eoa) == -1) { - - error_msg(progname, "Driver set eoa request failed"); + + config.version = 1; /* should be H5C2__CURR_AUTO_SIZE_CTL_VER */ + + /* get H5AC_cache_config_t configuration from fapl */ + if ( H5Pget_jnl_config(fapl, &config) == -1) { + + error_msg(progname, "Could not get mdc config from FAPL.\n"); leave( EXIT_FAILURE ); + + } + + /* make sure journal recovered field is set 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) { + + error_msg(progname, "Could not set mdc config on FAPL.\n"); + leave( EXIT_FAILURE ); + + } /* end if */ + /* open HDF5 file with provided fapl */ + fid = H5Fopen(file_name, H5F_ACC_RDWR, fapl); + + if ( fid == -1 ) { + + error_msg(progname, "Could not open recovered HDF5 file.\n"); + leave( EXIT_FAILURE ); + } /* end if */ /* close HDF5 file */ @@ -736,15 +1022,16 @@ main (int argc, const char *argv[]) leave( EXIT_FAILURE ); } /* end if */ - + /* ================ */ /* Cleanup and Exit */ /* ================ */ - - /* MIKE: Should I remove journal file here, or should that happen - on file close? */ - printf("HDF5 file successfuly recovered.\n"); + if (jrnl_has_transactions == TRUE) + printf("HDF5 file successfuly recovered.\n"); + else + printf("File marked as recovered.\n"); + if ( verbose ) printf("==============================================\n\n"); free(file_name); -- cgit v0.12