summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJohn Mainzer <mainzer@hdfgroup.org>2009-04-04 03:58:27 (GMT)
committerJohn Mainzer <mainzer@hdfgroup.org>2009-04-04 03:58:27 (GMT)
commit2bb8a8044afbaa3312dd9dae279b14fab1a6884d (patch)
tree15096c73eabe92d7621411e2a43a5ae920a911d7 /src
parent7788ad94856eeefbc06d521f0b7351131cd7a140 (diff)
downloadhdf5-2bb8a8044afbaa3312dd9dae279b14fab1a6884d.zip
hdf5-2bb8a8044afbaa3312dd9dae279b14fab1a6884d.tar.gz
hdf5-2bb8a8044afbaa3312dd9dae279b14fab1a6884d.tar.bz2
[svn-r16670] Interrim checkin of journal file modifications supporting recognition
and rejection of attempts to apply the wrong journal file to a corrupt HDF5 file. Specifically, I made the following changes: 1) Moved all journaling data into the journaling in progress superblock extension message. 2) Added a "magic number" to the journaling in progress message, with the same "magic number being added to the header of the associated journal file. 3) Modifications to library test code to support the above. 4) Modified h5recover to examine the supplied hdf5 file, determine if it is in fact a HDF5 file, if so determine if it is marked as having journaling in progress, and if it does, extract the contents of the journaling in progress super block extension message. 5) Modified h5recover to examine the supplied journal file, determine if it is in fact a HDF5 journal file, and if so, extract the data from its header. 6) Modified h5recover to refuse to apply the supplied journal file to the supplied HDF5 file unless the "magic numbers" obtained from these files matches. 7) Added an examine option to h5recover that causes it to examine and report on the supplied files, but do nothing. This option exists primarily to facilitate testing, but I expect that some users will find it useful as well. 8) Added test code to exercise items 4-7. Note that while I have tried to cover the more likely cases, this test code is extremely cursory. In particular, the code to examine the supplied HDF5 file is barely tested at all. Need a library of HDF5 files exibiting the full range of possible super block and super block extension message structures to test this properly. 9) In passing, tighened up the code that controls dumps of "possibly significant" differences between the contents of the control and recovered data sets in the h5recover. It should now ignore one integer matches in what appears to be garbage raw data. Tested: serial and parallel on Phoenix serial and parallel on Jam serial on Linew serial on Liberty All tests were done in debug mode.
Diffstat (limited to 'src')
-rw-r--r--src/H5C2.c9
-rw-r--r--src/H5C2journal.c2269
-rw-r--r--src/H5C2pkg.h88
-rw-r--r--src/H5C2private.h74
-rw-r--r--src/H5Fpkg.h7
-rw-r--r--src/H5Fsuper.c286
-rw-r--r--src/H5Ochunk.c2
-rw-r--r--src/H5Omdj_msg.c190
-rw-r--r--src/H5Omessage.c15
-rw-r--r--src/H5Oprivate.h38
10 files changed, 1507 insertions, 1471 deletions
diff --git a/src/H5C2.c b/src/H5C2.c
index 64fa9fd..d8e4a51 100644
--- a/src/H5C2.c
+++ b/src/H5C2.c
@@ -656,10 +656,9 @@ H5C2_create(size_t max_cache_size,
cache_ptr->trans_api_name[0] = '\0';
cache_ptr->trans_num = 0;
cache_ptr->last_trans_on_disk = 0;
- cache_ptr->mdj_file_name_ptr = NULL;
- cache_ptr->mdj_conf_block_addr = HADDR_UNDEF;
- cache_ptr->mdj_conf_block_len = 0;
- cache_ptr->mdj_conf_block_ptr = NULL;
+ cache_ptr->jnl_magic = 0;
+ cache_ptr->jnl_file_name_len = 0;
+ (cache_ptr->jnl_file_name)[0] = '\0';
(cache_ptr->mdj_jbrb).magic =
H5C2__H5C2_JBRB_T_MAGIC;
cache_ptr->tl_len = 0;
@@ -712,7 +711,7 @@ H5C2_create(size_t max_cache_size,
/* We used to check for journaling here, but the super block hasn't
* been read in yet at cache creation time -- thus the check for
* journaling has been moved to H5AC2_check_for_journaling(), which
- * is simply a * wrapper for H5C2_check_for_journaling().
+ * is simply a wrapper for H5C2_check_for_journaling().
*
* H5AC2_check_for_journaling() is called at the end of H5Fopen() --
* at which point the superblock has been read.
diff --git a/src/H5C2journal.c b/src/H5C2journal.c
index ab79a7b..339eb00 100644
--- a/src/H5C2journal.c
+++ b/src/H5C2journal.c
@@ -97,6 +97,14 @@ static herr_t H5C2_shrink_mdjsc_callback_table(H5C2_t * cache_ptr);
* starts, and to call the metadata journaling status
* change callbacks after journaling has been started.
*
+ * JRM -- 2/10/09
+ * Added journal_magic variable and supporting code.
+ *
+ * The idea is to assign a random magic number to both the
+ * journal file, and to the journal configuration information
+ * information in the super block so that it will be hard to
+ * apply the wrong journal file to a corrupted hdf5 file.
+ *
*-------------------------------------------------------------------------
*/
@@ -108,6 +116,7 @@ H5C2_begin_journaling(H5F_t * f,
{
herr_t result;
herr_t ret_value = SUCCEED; /* Return value */
+ int32_t journal_magic;
H5C2_mdj_config_t config;
FUNC_ENTER_NOAPI(H5C2_begin_journaling, FAIL)
@@ -159,11 +168,18 @@ H5C2_begin_journaling(H5F_t * f,
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,
config_ptr->journal_file_path,
config_ptr->jbrb_buf_size,
@@ -185,7 +201,7 @@ H5C2_begin_journaling(H5F_t * f,
#endif /* JRM */
/* Note that this call flushes the HDF5 file in passing */
- result = H5C2_mark_journaling_in_progress(f, dxpl_id,
+ result = H5C2_mark_journaling_in_progress(f, dxpl_id, journal_magic,
config_ptr->journal_file_path);
if ( result != SUCCEED ) {
@@ -373,7 +389,8 @@ H5C2_end_journaling(H5F_t * f,
cache_ptr->mdj_enabled = FALSE;
/* Remove the journal configuration information from the superblock
- * extension.
+ * extension. In passing, also discard the cache's copies of the
+ * metadata journaling magic, and the journal file name.
*/
result = H5C2_unmark_journaling_in_progress(f, dxpl_id, cache_ptr);
@@ -411,7 +428,7 @@ H5C2_end_journaling(H5F_t * f,
done:
#if 0 /* JRM */
- HDfprintf(stdout, "%s: entering.\n", FUNC);
+ HDfprintf(stdout, "%s: exiting.\n", FUNC);
#endif /* JRM */
FUNC_LEAVE_NOAPI(ret_value)
@@ -593,7 +610,7 @@ H5C2_get_journal_config(H5C2_t * cache_ptr,
config_ptr->enable_journaling = TRUE;
HDstrncpy(&(config_ptr->journal_file_path[0]),
- cache_ptr->mdj_file_name_ptr,
+ cache_ptr->jnl_file_name,
H5C2__MAX_JOURNAL_FILE_NAME_LEN);
config_ptr->journal_file_path[H5C2__MAX_JOURNAL_FILE_NAME_LEN] = '\0';
@@ -1161,7 +1178,7 @@ done:
/**************************************************************************/
-/***************** journal config block management code *******************/
+/************* superblock journaling message management code **************/
/**************************************************************************/
/*-------------------------------------------------------------------------
@@ -1216,10 +1233,8 @@ H5C2_check_for_journaling(H5F_t * f,
HDassert( f );
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC );
- HDassert( cache_ptr->mdj_conf_block_addr == HADDR_UNDEF );
- HDassert( cache_ptr->mdj_conf_block_len == 0 );
- HDassert( cache_ptr->mdj_conf_block_ptr == NULL );
- HDassert( cache_ptr->mdj_file_name_ptr == NULL );
+ HDassert( cache_ptr->jnl_magic == 0 );
+ HDassert( cache_ptr->jnl_file_name_len == 0 );
if ( H5C2__check_for_journaling ) {
@@ -1231,8 +1246,8 @@ H5C2_check_for_journaling(H5F_t * f,
"H5C2_get_journaling_in_progress() failed.")
}
- if ( cache_ptr->mdj_file_name_ptr != NULL ) /* journaling was in */
- /* progress */
+ if ( cache_ptr->jnl_file_name_len > 0 ) /* journaling was in */
+ /* progress */
{
#if 0 /* JRM */
HDfprintf(stdout, "%s: journaling was in progress.\n", FUNC);
@@ -1240,8 +1255,9 @@ H5C2_check_for_journaling(H5F_t * f,
if ( journal_recovered ) {
- /* delete the metadata journaling config block and the
- * superblock extenstion refering to it.
+ /* Just forget that we were journaling. Do this by
+ * deleting the superblock extension message that says
+ * we were.
*/
result = H5C2_unmark_journaling_in_progress(f, dxpl_id, cache_ptr);
@@ -1261,7 +1277,7 @@ H5C2_check_for_journaling(H5F_t * f,
(void)H5Epush2(H5E_DEFAULT, __FILE__, FUNC, __LINE__,
H5E_ERR_CLS_g, H5E_CACHE, H5E_CANTJOURNAL,
"%s%s%s%s%s%s", l0, l1, l2, l3,
- cache_ptr->mdj_file_name_ptr, l4);
+ cache_ptr->jnl_file_name, l4);
(void)H5E_dump_api_stack((int)H5_IS_API(FUNC));
HGOTO_DONE(FAIL)
@@ -1285,217 +1301,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5C2_create_journal_config_block()
- *
- * Purpose: Given a string containing a journal file name and a pointer
- * to the associated instance of H5C2_t, allocate a journal
- * configuration block, write it to file, and update the
- * instance of H5C2_t.
- *
- * Note that the method assumes that mdj_conf_block_addr is
- * NULL on entry.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: John Mainzer
- * March 7, 2008
- *
- *-------------------------------------------------------------------------
- */
-
-herr_t
-H5C2_create_journal_config_block(const H5F_t * f,
- hid_t dxpl_id,
- const char * journal_file_name_ptr)
-{
- H5C2_t * cache_ptr;
- size_t path_len = 0;
- hsize_t block_len = 0;
- haddr_t block_addr = HADDR_UNDEF;
- void * block_ptr = NULL;
- uint8_t version = H5C2__JOURNAL_CONF_VERSION;
- uint8_t * p = NULL;
- char * jfn_ptr = NULL;
- uint32_t chksum;
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5C2_create_journal_config_block, FAIL)
-
- HDassert( f );
- HDassert( f->shared );
- cache_ptr = f->shared->cache2;
- HDassert( cache_ptr );
- HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC );
-
- if ( cache_ptr->mdj_conf_block_ptr != NULL ) {
-
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
- "cache_ptr->mdj_conf_block_ptr != NULL on entry?!?")
- }
-
- HDassert( journal_file_name_ptr != NULL );
-
- path_len = HDstrlen(journal_file_name_ptr) + 1;
-
- HDassert( path_len > 0 );
-
- block_len = H5C2__JOURNAL_BLOCK_LEN(path_len, f);
-
- block_ptr = (void *)H5MM_malloc((size_t)block_len);
-
- if ( block_ptr == NULL ) {
-
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \
- "allocation of in core journal config block failed.");
- }
-
- p = (uint8_t *)block_ptr;
-
- /* copy the signature into the config block */
- HDmemcpy(p, H5C2__JOURNAL_CONF_MAGIC, H5C2__JOURNAL_MAGIC_LEN);
- p += H5C2__JOURNAL_MAGIC_LEN;
-
- /* copy the version into the config block */
- HDmemcpy(p, &version, 1);
- p++;
-
- /* copy the length of the journal file path into the config block */
- H5F_ENCODE_LENGTH(f, p, path_len);
-
- /* copy the path to the journal file into the config block, including
- * the terminalting null. Before we do so, make note of p, as its
- * value will be the address of our copy of the journal file path.
- */
- jfn_ptr = (char *)p;
- HDmemcpy(p, journal_file_name_ptr, path_len + 1);
- p += path_len + 1;
-
- HDassert( strcmp(jfn_ptr, journal_file_name_ptr) == 0 );
-
- /* compute and save checksum */
- chksum = H5_checksum_metadata(block_ptr, (size_t)(block_len - 4), 0);
- UINT32ENCODE(p, chksum);
-
- HDassert( (unsigned)(p - (uint8_t *)block_ptr) == block_len );
-
-
- /* having created an in core image of the journaling configuration block,
- * we must now allocate space for it in file, and write it to disk.
- */
-
- block_addr = H5MF_alloc(f,
- H5FD_MEM_MDJCONFIG,
- dxpl_id,
- block_len);
-
- if ( block_addr == HADDR_UNDEF ) {
-
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \
- "allocation of file journal config block failed.");
- }
-
- /* now write the block to disk -- note that we don't sync. We will
- * have to do that later.
- */
- if ( H5F_block_write(f, H5FD_MEM_MDJCONFIG, block_addr,
- (size_t)block_len, dxpl_id, block_ptr) < 0 )
- {
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "Can't write metadata journaling config block to file.")
- }
-
- /* finally, if we we get this far, update the cache data structure to
- * record the metadata journaling configuration block.
- */
- cache_ptr->mdj_file_name_ptr = jfn_ptr;
- cache_ptr->mdj_conf_block_addr = block_addr;
- cache_ptr->mdj_conf_block_len = block_len;
- cache_ptr->mdj_conf_block_ptr = block_ptr;
-
-done:
-
- FUNC_LEAVE_NOAPI(ret_value)
-
-} /* H5AC2__create_journal_config_block() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5C2_discard_journal_config_block()
- *
- * Purpose: Free the file and core space allocated to the metadata
- * journaling configuration block, and re-set all the associated
- * fields in the cache's instance of H5C2_t.
- *
- * Note that the method assumes that
- *
- * struct_ptr->mdj_file_name_ptr,
- * struct_ptr->mdj_conf_block_addr,
- * struct_ptr->mdj_conf_block_len, and
- * struct_ptr->mdj_conf_block_ptr
- *
- * are all set up for the current metadata journaling
- * configuration block on entry. On successful exit, these
- * fields will all be reset to their initial values.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: John Mainzer
- * March 7, 2008
- *
- *-------------------------------------------------------------------------
- */
-
-herr_t
-H5C2_discard_journal_config_block(const H5F_t * f,
- hid_t dxpl_id)
-{
- H5C2_t * cache_ptr;
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5C2_discard_journal_config_block, FAIL)
-
- HDassert( f );
- HDassert( f->shared );
- cache_ptr = f->shared->cache2;
- HDassert( cache_ptr );
- HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC );
-
- if ( ( cache_ptr->mdj_conf_block_addr == HADDR_UNDEF ) ||
- ( cache_ptr->mdj_conf_block_len == 0 ) ||
- ( cache_ptr->mdj_conf_block_ptr == NULL ) ||
- ( cache_ptr->mdj_file_name_ptr == NULL ) ) {
-
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
- "metadata journaling config block undefined on entry?!?")
- }
-
- if ( H5MF_xfree(f, H5FD_MEM_MDJCONFIG, dxpl_id,
- cache_ptr->mdj_conf_block_addr,
- cache_ptr->mdj_conf_block_len) < 0 ) {
-
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \
- "deallocation of file journal config block failed.");
- }
-
- H5MM_xfree(cache_ptr->mdj_conf_block_ptr);
-
- /* if we get this far, go ahead and null out the fields in *cache_ptr */
-
- cache_ptr->mdj_conf_block_addr = HADDR_UNDEF;
- cache_ptr->mdj_conf_block_len = 0;
- cache_ptr->mdj_conf_block_ptr = NULL;
- cache_ptr->mdj_file_name_ptr = NULL;
-
-done:
-
- FUNC_LEAVE_NOAPI(ret_value)
-
-} /* H5AC2_discard_journal_config_block() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5C2_get_journaling_in_progress()
*
* Purpose: Query the HDF5 file to see if it is marked as having
@@ -1524,6 +1329,13 @@ done:
* Programmer: John Mainzer
* March 11, 2008
*
+ * Changes: JRM -- 2/20/09
+ * Reworked to reflect the move of the journal file name
+ * and magic from the journaling configuration block to
+ * the metadata journaling superblock extension message.
+ * Note that the journaling configuration block no longer
+ * exists.
+ *
*-------------------------------------------------------------------------
*/
@@ -1532,7 +1344,6 @@ H5C2_get_journaling_in_progress(const H5F_t * f,
hid_t dxpl_id,
H5C2_t * cache_ptr)
{
- herr_t result;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5C2_get_journaling_in_progress, FAIL)
@@ -1545,31 +1356,42 @@ H5C2_get_journaling_in_progress(const H5F_t * f,
HDassert( f->shared != NULL );
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC );
- HDassert( cache_ptr->mdj_conf_block_addr == HADDR_UNDEF );
- HDassert( cache_ptr->mdj_conf_block_len == 0 );
- HDassert( cache_ptr->mdj_conf_block_ptr == NULL );
- HDassert( cache_ptr->mdj_file_name_ptr == NULL );
+ HDassert( cache_ptr->jnl_file_name_len == 0 );
#if 0 /* JRM */
- HDfprintf(stdout, "%s: f->shared->mdc_jrnl_enabled = %d.\n", FUNC,
- (int)(f->shared->mdc_jrnl_enabled));
+ HDfprintf(stdout, "%s: f->shared->mdc_jnl_enabled = %d.\n", FUNC,
+ (int)(f->shared->mdc_jnl_enabled));
#endif /* JRM */
- if ( f->shared->mdc_jrnl_enabled == TRUE ) {
+ if ( f->shared->mdc_jnl_enabled == TRUE ) {
- cache_ptr->mdj_conf_block_addr = f->shared->mdc_jrnl_block_loc;
- cache_ptr->mdj_conf_block_len = f->shared->mdc_jrnl_block_len;
-
- result = H5C2_load_journal_config_block(f,
- dxpl_id,
- cache_ptr,
- cache_ptr->mdj_conf_block_addr,
- cache_ptr->mdj_conf_block_len);
- if ( result != SUCCEED ) {
+ if ( f->shared->mdc_jnl_file_name_len <= 0 ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "H5C2_load_journal_config_block() failed.")
- }
+ "journaling enabled but jnl file name empty?!?.")
+ }
+
+ if ( f->shared->mdc_jnl_file_name_len >
+ H5C2__MAX_JOURNAL_FILE_NAME_LEN ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "journal file name too long?!?.")
+ }
+
+ cache_ptr->jnl_magic = f->shared->mdc_jnl_magic;
+ cache_ptr->jnl_file_name_len = f->shared->mdc_jnl_file_name_len;
+ HDstrncpy(cache_ptr->jnl_file_name,
+ f->shared->mdc_jnl_file_name,
+ f->shared->mdc_jnl_file_name_len + 1);
+
+ if ( ( (cache_ptr->jnl_file_name)[cache_ptr->jnl_file_name_len]
+ != '\0' ) ||
+ ( strlen(cache_ptr->jnl_file_name) !=
+ (size_t)(cache_ptr->jnl_file_name_len) ) ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "bad jnl file name or name len?!?.")
+ }
}
#if 0 /* JRM */
@@ -1588,140 +1410,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5C2_load_journal_config_block()
- *
- * Purpose: Given the base address and lenght of a journal configuration
- * block, attempt to load it, and store it in the cache structure.
- *
- * Note that the method assumes that mdj_conf_block_addr is
- * NULL on entry.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: John Mainzer
- * March 11, 2008
- *
- *-------------------------------------------------------------------------
- */
-
-herr_t
-H5C2_load_journal_config_block(const H5F_t * f,
- hid_t dxpl_id,
- H5C2_t * cache_ptr,
- haddr_t block_addr,
- hsize_t block_len)
-{
- size_t path_len = 0;
- void * block_ptr = NULL;
- uint8_t version;
- uint8_t * p = NULL;
- char * jfn_ptr = NULL;
- uint32_t computed_chksum;
- uint32_t read_chksum;
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5C2_load_journal_config_block, FAIL)
-
- HDassert( f );
- HDassert( f->shared );
- HDassert( cache_ptr );
- HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC );
-
- if ( cache_ptr->mdj_conf_block_ptr != NULL ) {
-
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
- "cache_ptr->mdj_conf_block_ptr != NULL on entry?!?")
- }
-
- block_ptr = (void *)H5MM_malloc((size_t)block_len);
-
- if ( block_ptr == NULL ) {
-
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \
- "allocation of in core journal config block failed.");
- }
-
- p = (uint8_t *)block_ptr;
-
- /* read the metadata journaling block from file */
- if ( H5F_block_read(f, H5FD_MEM_MDJCONFIG, block_addr,
- (size_t)block_len, dxpl_id, block_ptr) < 0 ) {
-
-#if 0 /* JRM */
- HDfprintf(stdout, "%s: block_addr = %lld, block_len = %lld.\n",
- FUNC, (long long)block_addr, (long long)block_len);
-#endif /* JRM */
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "Can't read metadata journaling configuration block.")
- }
-
- /* verify the signature */
- if ( HDmemcmp(p, H5C2__JOURNAL_CONF_MAGIC, H5C2__JOURNAL_MAGIC_LEN) != 0 ) {
-
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "Bad signature on metadata journaling configuration block.")
- }
- p += H5C2__JOURNAL_MAGIC_LEN;
-
- /* get the version of the config block */
- version = *p++;
-
- if ( version != H5C2__JOURNAL_CONF_VERSION ) {
-
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "Bad version on metadata journaling configuration block.")
- }
-
- /* get the length of the journal file path into the config block */
- H5F_DECODE_LENGTH(f, p, path_len);
-
- /* Verify that the length matches the actual path length. Also,
- * make note of p, as its value will be the address of our copy of
- * the journal file path.
- */
- jfn_ptr = (char *)p;
- if ( HDstrlen(jfn_ptr) != path_len - 1 ) {
-
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "Bad path_len in metadata journaling configuration block.")
- }
-
- p += path_len + 1;
-
- /* get the checksum from the block */
- UINT32DECODE(p, read_chksum);
-
- /* compute the actual checksum */
- computed_chksum =
- H5_checksum_metadata(block_ptr, (size_t)(block_len - 4), 0);
-
- /* verify that the computed and read checksums match */
- if ( computed_chksum != read_chksum ) {
-
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "Bad checksum in metadata journaling configuration block.")
- }
-
- HDassert( (unsigned)(p - (uint8_t *)block_ptr) == block_len );
-
- /* finally, if we we get this far, we have read the metadata journaling
- * configuration block successfully. Record the data in the cache
- * structure.
- */
- cache_ptr->mdj_file_name_ptr = jfn_ptr;
- cache_ptr->mdj_conf_block_addr = block_addr;
- cache_ptr->mdj_conf_block_len = block_len;
- cache_ptr->mdj_conf_block_ptr = block_ptr;
-
-done:
-
- FUNC_LEAVE_NOAPI(ret_value)
-
-} /* H5C2_load_journal_config_block() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5C2_mark_journaling_in_progress()
*
* Purpose: Modify the HDF5 file to indicate that journaling is
@@ -1740,12 +1428,22 @@ done:
* Programmer: John Mainzer
* March 11, 2008
*
+ * Changes: JRM -- 2/10/09
+ * Added the journal_magic parameter and related code.
+ *
+ * JRM -- 2/20/09
+ * Reworked function to reflect the move of the journal
+ * file name and magic to the super block extension message
+ * and out of the metadata journaling configuration block
+ * which no longer exists.
+ *
*-------------------------------------------------------------------------
*/
herr_t
H5C2_mark_journaling_in_progress(H5F_t * f,
hid_t dxpl_id,
+ const int32_t journal_magic,
const char * journal_file_name_ptr)
{
H5C2_t * cache_ptr;
@@ -1758,16 +1456,13 @@ H5C2_mark_journaling_in_progress(H5F_t * f,
#endif /* JRM */
HDassert( f != NULL );
HDassert( f->shared != NULL );
- HDassert( ! f->shared->mdc_jrnl_enabled );
+ HDassert( ! f->shared->mdc_jnl_enabled );
cache_ptr = f->shared->cache2;
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC );
- HDassert( cache_ptr->mdj_conf_block_addr == HADDR_UNDEF );
- HDassert( cache_ptr->mdj_conf_block_len == 0 );
- HDassert( cache_ptr->mdj_conf_block_ptr == NULL );
- HDassert( cache_ptr->mdj_file_name_ptr == NULL );
+ HDassert( cache_ptr->jnl_file_name_len == 0 );
HDassert( journal_file_name_ptr != NULL );
/* Can't journal a read only file, so verify that we are
@@ -1779,32 +1474,35 @@ H5C2_mark_journaling_in_progress(H5F_t * f,
"File is opened read only.")
}
- /* first, create a metadata journaling configuration block */
-#if 0 /* JRM */
- HDfprintf(stdout, "%s: creating mdj config block.\n", FUNC);
-#endif /* JRM */
- result = H5C2_create_journal_config_block(f,
- dxpl_id,
- journal_file_name_ptr);
+ cache_ptr->jnl_magic = journal_magic;
+ cache_ptr->jnl_file_name_len = strlen(journal_file_name_ptr);
- if ( result != SUCCEED ) {
+ if ( cache_ptr->jnl_file_name_len <= 0 ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "H5C2_create_journal_config_block() failed.")
+ "length of journal file name is zero.")
}
- HDassert( cache_ptr->mdj_conf_block_addr != HADDR_UNDEF );
- HDassert( cache_ptr->mdj_conf_block_len != 0 );
- HDassert( cache_ptr->mdj_conf_block_ptr != NULL );
- HDassert( cache_ptr->mdj_file_name_ptr != NULL );
+ if ( cache_ptr->jnl_file_name_len > H5C2__MAX_JOURNAL_FILE_NAME_LEN ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "journal file name too long.")
+ }
- /* now, load the base addr and length of the configuration block
- * into shared, and then call H5F_super_write_mdj_msg() to write
- * the metadata journaling superblock extension message to file.
+ HDstrncpy(cache_ptr->jnl_file_name,
+ journal_file_name_ptr,
+ (size_t)(cache_ptr->jnl_file_name_len + 1));
+
+ /* now, load the journaling information into shared, and then call
+ * H5F_super_write_mdj_msg() to write the metadata journaling
+ * superblock extension message to file.
*/
- f->shared->mdc_jrnl_enabled = TRUE;
- f->shared->mdc_jrnl_block_loc = cache_ptr->mdj_conf_block_addr;
- f->shared->mdc_jrnl_block_len = cache_ptr->mdj_conf_block_len;
+ f->shared->mdc_jnl_enabled = TRUE;
+ f->shared->mdc_jnl_magic = journal_magic;
+ f->shared->mdc_jnl_file_name_len = (size_t)(cache_ptr->jnl_file_name_len);
+ HDstrncpy(f->shared->mdc_jnl_file_name,
+ journal_file_name_ptr,
+ (size_t)(cache_ptr->jnl_file_name_len + 1));
#if 0 /* JRM */
HDfprintf(stdout, "%s: writing superblock extension.\n", FUNC);
@@ -1868,6 +1566,13 @@ done:
* Programmer: John Mainzer
* March 11, 2008
*
+ * Changes: JRM -- 2/20/09
+ * Reworked function to reflect the move of the journal
+ * file name and magic from the metadata journaling config
+ * block and into a superblock extension message. Note that
+ * the metadata journaling configuration block no longer
+ * exists.
+ *
*-------------------------------------------------------------------------
*/
@@ -1890,18 +1595,11 @@ H5C2_unmark_journaling_in_progress(H5F_t * f,
#endif /* JRM */
HDassert( f != NULL );
HDassert( f->shared != NULL );
- HDassert( f->shared->mdc_jrnl_enabled );
+ HDassert( f->shared->mdc_jnl_enabled );
HDassert( f->shared->cache2 == cache_ptr );
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C2__H5C2_T_MAGIC );
- HDassert( cache_ptr->mdj_conf_block_addr != HADDR_UNDEF );
- HDassert( cache_ptr->mdj_conf_block_len > 0 );
- HDassert( cache_ptr->mdj_conf_block_ptr != NULL );
- HDassert( cache_ptr->mdj_file_name_ptr != NULL );
- HDassert( f->shared->mdc_jrnl_block_loc ==
- cache_ptr->mdj_conf_block_addr );
- HDassert( f->shared->mdc_jrnl_block_len ==
- cache_ptr->mdj_conf_block_len );
+ HDassert( cache_ptr->jnl_file_name_len > 0 );
/* Can't journal a read only file, so verify that we are
@@ -1913,27 +1611,19 @@ H5C2_unmark_journaling_in_progress(H5F_t * f,
"File is opened read only.")
}
- /* next, discard the metadata journaling configuration block */
- result = H5C2_discard_journal_config_block(f, dxpl_id);
-
- if ( result != SUCCEED ) {
-
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "H5C2_discard_journal_config_block() failed.")
- }
-
- HDassert( cache_ptr->mdj_conf_block_addr == HADDR_UNDEF );
- HDassert( cache_ptr->mdj_conf_block_len == 0 );
- HDassert( cache_ptr->mdj_conf_block_ptr == NULL );
- HDassert( cache_ptr->mdj_file_name_ptr == NULL );
+ /* Discard the journal file name and magic in *cache_ptr */
+ cache_ptr->jnl_magic = 0;
+ cache_ptr->jnl_file_name_len = 0;
+ (cache_ptr->jnl_file_name)[0] = '\0';
/* now, mark f->shared to indicate that journaling is not in
* progress, and then call H5F_super_write_mdj_msg() to write
* the changes to disk.
*/
- f->shared->mdc_jrnl_enabled = FALSE;
- f->shared->mdc_jrnl_block_loc = HADDR_UNDEF;
- f->shared->mdc_jrnl_block_len = 0;
+ f->shared->mdc_jnl_enabled = FALSE;
+ f->shared->mdc_jnl_magic = 0;
+ f->shared->mdc_jnl_file_name_len = 0;
+ (f->shared->mdc_jnl_file_name)[0] = '\0';
if ( H5F_super_write_mdj_msg(f, dxpl_id) < 0 ) {
@@ -2655,134 +2345,277 @@ done:
} /* H5C2_shrink_mdjsc_callback_table() */
-
+
/**************************************************************************/
/********************** journal file management code **********************/
/**************************************************************************/
/******************************************************************************
*
- * Function: H5C2_jb__flush_full_buffers
+ * Function: H5C2_jb__bin2hex
+ *
+ * Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
+ * 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 <mcgreevy@hdfgroup.org>
* Wednesday, February 6, 2008
*
- * Purpose: Flush all the dirtied buffers in the ring buffer
- * starting with the buffer referenced by struct_ptr->get
- * and ending with the buffer right before the one
- * referenced by struct_ptr->put.
+ * 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.
*
******************************************************************************/
herr_t
-H5C2_jb__flush_full_buffers(H5C2_jbrb_t * struct_ptr)
+H5C2_jb__comment(H5C2_jbrb_t * struct_ptr,
+ const char * comment_ptr)
{
- hbool_t verbose = FALSE;
- int result;
+ char * temp = NULL;
+ size_t temp_len;
herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI(H5C2_jb__flush_full_buffers, FAIL)
-
- if ( verbose ) { HDfprintf(stdout, "%s: entering.\n", FUNC); }
+ FUNC_ENTER_NOAPI(H5C2_jb__comment, 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) {
+ /* Check Arguments */
+ HDassert(struct_ptr);
+ HDassert(comment_ptr);
+ HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC);
+ HDassert(struct_ptr->hdf5_file_name);
- /* 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);
+ /* Verify that header message is present in journal file or ring buffer.
+ * If not, write it.
+ */
+ if ( struct_ptr->header_present == FALSE ) {
- if ( result == -1 ) {
+ if ( H5C2_jb__write_header_entry(struct_ptr) != SUCCEED ) {
- if ( verbose ) { HDfprintf(stdout, "%s: write failed 1.\n", FUNC); }
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
- "Journal file write failed (1).")
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "H5C2_jb__write_header_entry() failed.\n")
}
- 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 */
+
+ temp_len = HDstrlen(comment_ptr) + 11;
+ if ( ( temp = H5MM_malloc(HDstrlen(comment_ptr) + 11) ) == NULL ) {
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \
+ "allocation of temp buffer failed.");
} /* end if */
- else {
+ /* Write comment message */
+ HDsnprintf(temp, temp_len, "C comment %s", comment_ptr);
- /* 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 ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(temp), temp, FALSE, struct_ptr->cur_trans ) < 0 ) {
- if ( result == -1 ) {
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "H5C2_jb__write_to_buffer() failed.\n")
+ } /* end if */
- if ( verbose ) { HDfprintf(stdout, "%s: write failed 2.\n", FUNC); }
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
- "Journal file write failed (2).")
- }
+ if ( H5C2_jb__write_to_buffer(struct_ptr, 1, "\n", FALSE, struct_ptr->cur_trans ) < 0 ) {
- 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;
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "H5C2_jb__write_to_buffer() failed.\n")
+ } /* end if */
- /* 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) {
+done:
- result = HDwrite(struct_ptr->journal_file_fd,
- (*struct_ptr->buf)[0],
- (struct_ptr->put) * struct_ptr->buf_size);
+ if ( temp != NULL ) {
- if ( result == -1 ) {
+ temp = H5MM_xfree(temp);
+ if ( temp != NULL ) {
- if ( verbose ) {
- HDfprintf(stdout, "%s: write failed 3.\n", FUNC);
- }
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
- "Journal file write failed(3).")
- } /* end if */
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \
+ "free of assembly buffer failed.");
+ }
+ }
- struct_ptr->rb_free_space += (struct_ptr->put * struct_ptr->buf_size);
+ FUNC_LEAVE_NOAPI(ret_value)
- } /* end if */
+} /* end H5C2_jb__comment */
- struct_ptr->bufs_in_use -= struct_ptr->put;
+
+/*****************************************************************************
+ *
+ * Function: H5C2_jb__end_transaction
+ *
+ * Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
+ * 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.
+ *
+ *****************************************************************************/
+herr_t
+H5C2_jb__end_transaction(H5C2_jbrb_t * struct_ptr,
+ uint64_t trans_num)
+{
+ char temp[25];
+ herr_t ret_value = SUCCEED;
- } /* end else */
+ FUNC_ENTER_NOAPI(H5C2_jb__end_transaction, FAIL)
+#if 0 /* JRM */
+ HDfprintf(stdout, "%s trans_num = %lld.\n", FUNC, trans_num);
+#endif /* JRM */
+ /* Check Arguments */
+ HDassert(struct_ptr);
+ HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC);
- HDassert(struct_ptr->bufs_in_use <= 1);
+ /* Verify that the supplied transaction is in progress */
+ if ( ( struct_ptr->trans_in_prog != TRUE ) ||
+ ( struct_ptr->cur_trans != trans_num ) ) {
- /* update get index */
- struct_ptr->get = struct_ptr->put;
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "Transaction not in progress or bad transaction number.")
+ } /* end if */
- /* record last transaction number that made it to disk */
- if (struct_ptr->put == 0) {
+ /* Verify that at least one journal entry has been written under
+ * the current transaction
+ */
+ if ( struct_ptr->jentry_written != TRUE ) {
- struct_ptr->last_trans_on_disk =
- (*struct_ptr->trans_tracking)[struct_ptr->num_bufs - 1];
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "Empty transaction -- at least one journal entry required.")
+ } /* end if */
- } else {
- struct_ptr->last_trans_on_disk =
- (*struct_ptr->trans_tracking)[struct_ptr->put - 1];
- }
+ /* 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)
- if ( verbose ) { HDfprintf(stdout, "%s: exiting.\n", FUNC); }
+} /* end H5C2_jb__end_transaction */
+
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb__eoa
+ *
+ * Programmer: Mike McGreevy <mamcgree@hdfgroup.org>
+ * 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 ) {
+
+ 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", 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__flush_full_buffers */
+} /* end H5C2_jb__eoa */
/******************************************************************************
@@ -2934,279 +2767,188 @@ done:
/******************************************************************************
*
- * Function: H5C2_jb__write_to_buffer
+ * Function: H5C2_jb__flush_full_buffers
*
* Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
* Wednesday, February 6, 2008
*
- * Purpose: Put the contents of data into the journal buffers. This
- * is done as follows: While the data to be written is
- * larger than the amount of space left in the ring buffer,
- * the ring buffer is filled to capacity with data and
- * flushed. This repeats until the unwritten data remaining
- * can fit in the ring buffer without having to loop around
- * to the top.
- *
- * At this point, the rest of the data can just be written
- * without having to break it up further. In the event
- * the data covers more than one journal buffer, the get
- * and put indices are updated to state this fact. Any
- * journal buffers that were filled during the write are
- * flushed.
+ * 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__write_to_buffer(H5C2_jbrb_t * struct_ptr,
- size_t size,
- const char * data,
- hbool_t is_end_trans,
- uint64_t trans_num)
+H5C2_jb__flush_full_buffers(H5C2_jbrb_t * struct_ptr)
{
+ hbool_t verbose = FALSE;
+ int result;
herr_t ret_value = SUCCEED;
- unsigned long track_last_trans = 0;
- int oldput = 0;
- int i;
-
- FUNC_ENTER_NOAPI(H5C2_jb__write_to_buffer, FAIL)
- /* Check Arguments */
- HDassert(struct_ptr);
- HDassert(data);
- HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC);
- HDassert(HDstrlen(data) == size);
- HDassert(struct_ptr->rb_space_to_rollover <=
- struct_ptr->num_bufs * struct_ptr->buf_size);
- HDassert(struct_ptr->rb_space_to_rollover > 0);
-
- /* If the data size exceeds the bounds of the ring buffer's allocated
- * memory, loop around to top
- */
- if (size >= struct_ptr->rb_space_to_rollover) {
-
- while (size >= struct_ptr->rb_space_to_rollover) {
-
- /* Assertions */
- HDassert(size != 0);
- HDassert(HDstrlen(data) >= struct_ptr->rb_space_to_rollover);
-
- /* fill up remaining space in the ring buffer */
- HDmemcpy(struct_ptr->head, data, struct_ptr->rb_space_to_rollover);
-
- /* move head to point to start of ring buffer */
- struct_ptr->head = (*struct_ptr->buf)[0];
-
- /* make note of last transaction on disk */
- track_last_trans = (*struct_ptr->trans_tracking)[struct_ptr->put];
-
- /* update rb_free_space */
- struct_ptr->rb_free_space -= struct_ptr->rb_space_to_rollover;
-
- /* Fill out the remainder of the trans_tracking array with
- the most recent transaction in the array.*/
- (*struct_ptr->trans_tracking)[0] = track_last_trans;
- for (i=struct_ptr->put; i<struct_ptr->num_bufs; i++)
- {
- (*struct_ptr->trans_tracking)[i] = track_last_trans;
- }
-
- /* reset put index */
- struct_ptr->put = 0;
-
- /* update bufs_in_use as necessary */
- struct_ptr->bufs_in_use = struct_ptr->num_bufs - struct_ptr->get;
-
- /* check to see if trans_tracking needs to be updated. If so,
- then update it */
- if ((size == struct_ptr->rb_space_to_rollover) &&
- (is_end_trans == TRUE)) {
-
- (*struct_ptr->trans_tracking)[struct_ptr->num_bufs - 1]
- = trans_num;
- (*struct_ptr->trans_tracking)[0] = trans_num;
- }
-
- /* flush buffers */
- if ( H5C2_jb__flush_full_buffers(struct_ptr) < 0 ) {
-
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "H5C2_jb__flush_full_buffers() failed.\n")
- }
-
- /* update remaining size of data to be written */
- size = size - struct_ptr->rb_space_to_rollover;
-
- /* update the data pointer to point to the remaining data to be
- * written
- */
- data = &data[struct_ptr->rb_space_to_rollover];
-
- /* update the amount of space left at end of ring buffer */
- struct_ptr->rb_space_to_rollover =
- struct_ptr->buf_size * struct_ptr->num_bufs;
-
- /* update the amount of space in the current buffer */
- struct_ptr->cur_buf_free_space = struct_ptr->buf_size;
+ FUNC_ENTER_NOAPI(H5C2_jb__flush_full_buffers, FAIL)
- } /* end while */
- } /* end if */
+ if ( verbose ) { HDfprintf(stdout, "%s: entering.\n", FUNC); }
- /* If the size of the data exceeds the bounds of a single journal
- * buffer, will write into multiple
- */
- if (size > struct_ptr->cur_buf_free_space) {
+ /* 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->cur_buf_free_space != 0);
+ /* flush all full, dirtied journal buffers to disk */
+ if (struct_ptr->get < struct_ptr->put) {
- /* write data into journal buffers */
- HDmemcpy(struct_ptr->head, data, size);
+ /* 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);
- /* update head pointer */
- struct_ptr->head = &struct_ptr->head[size];
+ if ( result == -1 ) {
- /* make note of last transaction on disk */
- track_last_trans = (*struct_ptr->trans_tracking)[struct_ptr->put];
- oldput = struct_ptr->put;
+ if ( verbose ) { HDfprintf(stdout, "%s: write failed 1.\n", FUNC); }
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
+ "Journal file write failed (1).")
+ }
- /* update rb_free_space */
- struct_ptr->rb_free_space -= size;
+ 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;
- /* update put index */
- struct_ptr->put +=
- (size-struct_ptr->cur_buf_free_space)/(struct_ptr->buf_size) + 1;
+ } /* end if */
- /* Drag the last transaction in a filled buffer value residing in the
- old put location through the trans_tracking array to the new
- corresponding put position. */
- for (i=oldput; i<struct_ptr->put+1; i++)
- {
- (*struct_ptr->trans_tracking)[i] = track_last_trans;
- }
+ else {
- /* update current buffer usage */
- struct_ptr->cur_buf_free_space =
- struct_ptr->rb_space_to_rollover - size -
- (struct_ptr->num_bufs - (struct_ptr->put + 1)) *
- (struct_ptr->buf_size );
+ /* 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);
- /* update bufs_in_use as necessary */
- struct_ptr->bufs_in_use = struct_ptr->put - struct_ptr->get;
- if (struct_ptr->cur_buf_free_space < struct_ptr->buf_size) {
+ if ( result == -1 ) {
- struct_ptr->bufs_in_use++;
+ if ( verbose ) { HDfprintf(stdout, "%s: write failed 2.\n", FUNC); }
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
+ "Journal file write failed (2).")
}
- /* check to see if trans_tracking needs to be updated. If so,
- then update it */
- if (is_end_trans == TRUE) {
-
- if (struct_ptr->cur_buf_free_space == struct_ptr->buf_size) {
- (*struct_ptr->trans_tracking)[struct_ptr->put - 1] = trans_num;
- }
- else {
- (*struct_ptr->trans_tracking)[struct_ptr->put] = trans_num;
- }
-
- } /* end if */
+ 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;
- /* flush buffers */
- if ( H5C2_jb__flush_full_buffers(struct_ptr) < 0 ) {
+ /* 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) {
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "H5C2_jb__flush_full_buffers() failed.\n")
- }
+ result = HDwrite(struct_ptr->journal_file_fd,
+ (*struct_ptr->buf)[0],
+ (struct_ptr->put) * struct_ptr->buf_size);
- /* update space left at end of ring buffer */
- struct_ptr->rb_space_to_rollover -= size;
+ if ( result == -1 ) {
- } /* end if */
+ if ( verbose ) {
+ HDfprintf(stdout, "%s: write failed 3.\n", FUNC);
+ }
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, \
+ "Journal file write failed(3).")
+ } /* end if */
- /* if the data can fit in the remaining space in the current journal
- * buffer indexed by put
- */
- else if (size > 0) {
+ struct_ptr->rb_free_space += (struct_ptr->put * struct_ptr->buf_size);
- HDassert(size <= struct_ptr->cur_buf_free_space);
-
- /* write data into journal buffer */
- HDmemcpy(struct_ptr->head, data, size);
+ } /* end if */
- /* increment bufs_in_use as necessary */
- if ( ( struct_ptr->bufs_in_use == 0 ) ) {
+ struct_ptr->bufs_in_use -= struct_ptr->put;
- struct_ptr->bufs_in_use++;
- }
+ } /* end else */
+
+ HDassert(struct_ptr->bufs_in_use <= 1);
- /* update head pointer */
- struct_ptr->head = &struct_ptr->head[size];
+ /* update get index */
+ struct_ptr->get = struct_ptr->put;
+
+ /* record last transaction number that made it to disk */
+ if (struct_ptr->put == 0) {
- /* update rb_free_space */
- struct_ptr->rb_free_space -= size;
+ struct_ptr->last_trans_on_disk =
+ (*struct_ptr->trans_tracking)[struct_ptr->num_bufs - 1];
- /* update current buffer usage */
- struct_ptr->cur_buf_free_space -= size;
+ } else {
- /* update end of buffer space */
- struct_ptr->rb_space_to_rollover -= size;
-
- /* check to see if trans_tracking needs to be updated. If so,
- then update it */
- if (is_end_trans == TRUE) {
-
- (*struct_ptr->trans_tracking)[struct_ptr->put]
- = trans_num;
- } /* end if */
+ struct_ptr->last_trans_on_disk =
+ (*struct_ptr->trans_tracking)[struct_ptr->put - 1];
+ }
- /* if buffer is full, flush it, and loop to the top of the
- * ring buffer if at the end.
- */
- if (struct_ptr->cur_buf_free_space == 0) {
+done:
- if ( struct_ptr->put != (struct_ptr->num_bufs - 1) ) {
- struct_ptr->put += 1;
+ if ( verbose ) { HDfprintf(stdout, "%s: exiting.\n", FUNC); }
- /* Drag trans_tracking value into next buffer */
- (*struct_ptr->trans_tracking)[struct_ptr->put]
- = (*struct_ptr->trans_tracking)[struct_ptr->put - 1];
+ FUNC_LEAVE_NOAPI(ret_value)
- } /* end if */
-
- else {
+} /* end H5C2_jb__flush_full_buffers */
- struct_ptr->put = 0;
+
+/******************************************************************************
+ *
+ * Function: H5C2_jb__get_last_transaction_on_disk
+ *
+ * Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
+ * Wednesday, February 6, 2008
+ *
+ * Purpose: Lookup the number of the last transaction to have been
+ * fully written to disk, and place its transaction
+ * number in *trans_num_ptr. If no transaction has made
+ * it to disk, load zero into *trans_num_ptr.
+ *
+ * Returns: SUCCEED on success.
+ *
+ ******************************************************************************/
- /* Drag trans_tracking value into next buffer */
- (*struct_ptr->trans_tracking)[0]
- = (*struct_ptr->trans_tracking)[struct_ptr->num_bufs - 1];
+herr_t
+H5C2_jb__get_last_transaction_on_disk(H5C2_jbrb_t * struct_ptr,
+ uint64_t * trans_num_ptr)
+{
+ herr_t ret_value = SUCCEED;
- /* reset head pointer and free space values */
- struct_ptr->head = (*struct_ptr->buf)[0];
- struct_ptr->rb_space_to_rollover =
- struct_ptr->buf_size * struct_ptr->num_bufs;
+ FUNC_ENTER_NOAPI(H5C2_jb__get_last_transaction_on_disk, FAIL)
+
+ /* Check Arguments */
+ HDassert( trans_num_ptr != NULL );
- } /* end else */
+ /* This should really be an assert, but the func enter/exit
+ * macros get testy if there isn't at least one goto error
+ * macro call in the funtion.
+ */
+ if ( ( struct_ptr == NULL ) ||
+ ( struct_ptr->magic != H5C2__H5C2_JBRB_T_MAGIC ) ) {
- if ( H5C2_jb__flush_full_buffers(struct_ptr) < 0 ) {
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "bad struct_ptr.")
+ }
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "H5C2_jb__flush_full_buffers() failed.\n")
- } /* end if */
+ /* 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 ) {
- struct_ptr->cur_buf_free_space = struct_ptr->buf_size;
+ HGOTO_ERROR(H5E_IO, H5E_SYNCFAIL, FAIL, "Jounal file sync failed.")
- } /* end if */
+ } /* end if */
- } /* end else */
-
- HDassert(struct_ptr->bufs_in_use <= struct_ptr->num_bufs);
+ * trans_num_ptr = struct_ptr->last_trans_on_disk;
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5C2_jb__write_to_buffer */
+} /* end H5C2_jb__get_last_transaction_on_disk */
/******************************************************************************
@@ -3224,10 +2966,19 @@ done:
*
* Returns: SUCCEED on success.
*
+ * Changes: JRM -- 2/10/09
+ * Added the journal_magic parameter and related code.
+ *
+ * Also deleted code to write the header message.
+ * Since the base address of the journal magic in
+ * the HDF5 file isn't available at this time, wait
+ * until our first real entry to write the header.
+ *
******************************************************************************/
herr_t
H5C2_jb__init(H5C2_jbrb_t * struct_ptr,
+ const int32_t journal_magic,
const char * HDF5_file_name,
const char * journal_file_name,
size_t buf_size,
@@ -3243,16 +2994,60 @@ H5C2_jb__init(H5C2_jbrb_t * struct_ptr,
FUNC_ENTER_NOAPI(H5C2_jb__init, FAIL)
/* Check Arguments */
- HDassert(struct_ptr);
- HDassert(HDF5_file_name);
- HDassert(journal_file_name);
- HDassert(buf_size > 0);
- HDassert(num_bufs > 0);
- HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC);
+ HDassert( struct_ptr );
+ HDassert( HDF5_file_name );
+ HDassert( journal_file_name );
+ HDassert( buf_size > 0 );
+ HDassert( num_bufs > 0 );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+
+ /* Initialize Fields of H5C2_jbrb_t structure. Note that we will
+ * overwrite some of these initializations almost immediately.
+ */
+ struct_ptr->journal_magic = journal_magic;
+ struct_ptr->journal_file_fd = -1;
+ struct_ptr->num_bufs = num_bufs;
+ struct_ptr->buf_size = buf_size;
+ struct_ptr->bufs_in_use = 0;
+ struct_ptr->jvers = H5C2__JOURNAL_VERSION;
+ struct_ptr->get = 0;
+ struct_ptr->put = 0;
+ struct_ptr->jentry_written = FALSE;
+ struct_ptr->use_aio = use_aio;
+ struct_ptr->human_readable = human_readable;
+ struct_ptr->journal_is_empty = TRUE;
+ struct_ptr->cur_trans = 0;
+ struct_ptr->last_trans_on_disk = 0;
+ struct_ptr->trans_in_prog = FALSE;
+ struct_ptr->jname = HDstrdup(journal_file_name);
+
+ if ( struct_ptr->jname == NULL ) {
+
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \
+ "allocation of space for copy of journal_file_name failed.");
+ }
+
+ struct_ptr->hdf5_file_name = HDstrdup(HDF5_file_name);
+
+ if ( struct_ptr->jname == NULL ) {
+
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \
+ "allocation of space for copy of HDF5_file_name failed.");
+ }
+
+ struct_ptr->header_present = FALSE;
+ struct_ptr->cur_buf_free_space = buf_size;
+ struct_ptr->rb_space_to_rollover = num_bufs * buf_size;
+ struct_ptr->rb_free_space = num_bufs * buf_size;
+ struct_ptr->head = NULL;
+ struct_ptr->trans_tracking = NULL;
+ struct_ptr->buf = NULL;
+
/* Open journal file */
struct_ptr->journal_file_fd =
HDopen(journal_file_name, O_WRONLY|O_CREAT|O_EXCL, 0777);
+
if ( struct_ptr->journal_file_fd == -1) {
HDfprintf(stdout,
@@ -3262,28 +3057,6 @@ H5C2_jb__init(H5C2_jbrb_t * struct_ptr,
"Can't create journal file. Does it already exist?")
} /* end if */
- /* Initialize Fields of H5C2_jbrb_t structure */
- /* this should be modified to check error returns, etc. Also, should
- * probably do the same with the HDF5 file name.
- */
- struct_ptr->jname = HDstrdup(journal_file_name);
- struct_ptr->hdf5_file_name = HDF5_file_name;
- struct_ptr->buf_size = buf_size;
- struct_ptr->num_bufs = num_bufs;
- struct_ptr->use_aio = use_aio;
- struct_ptr->human_readable = human_readable;
- struct_ptr->bufs_in_use = 0;
- struct_ptr->trans_in_prog = FALSE;
- struct_ptr->get = 0;
- struct_ptr->put = 0;
- struct_ptr->jvers = H5C2__JOURNAL_VERSION;
- struct_ptr->cur_trans = 0;
- struct_ptr->last_trans_on_disk = 0;
- struct_ptr->cur_buf_free_space = struct_ptr->buf_size;
- struct_ptr->rb_free_space = struct_ptr->num_bufs * struct_ptr->buf_size;
- struct_ptr->rb_space_to_rollover = struct_ptr->num_bufs * struct_ptr->buf_size;
- struct_ptr->jentry_written = FALSE;
- struct_ptr->journal_is_empty = TRUE;
/* Allocate space for the ring buffer's journal buffer pointers */
struct_ptr->buf = H5MM_malloc(struct_ptr->num_bufs * sizeof(char *));
@@ -3334,7 +3107,7 @@ H5C2_jb__init(H5C2_jbrb_t * struct_ptr,
/* Make journal buffer pointers point to the right location in
* chunk of allocated memory above
*/
- for (i=1; i<struct_ptr->num_bufs; i++)
+ for ( i = 1; i < struct_ptr->num_bufs; i++ )
{
(*struct_ptr->buf)[i] =
&((*struct_ptr->buf)[0])[i * struct_ptr->buf_size];
@@ -3342,141 +3115,18 @@ 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];
-
- /* Get the current date */
- current_date = time(NULL);
-
- /* Format the header message into a temporary buffer */
- HDsnprintf(temp,
- (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(&current_date),
- struct_ptr->human_readable);
-
- /* Write the header message into the ring buffer */
- if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(temp), temp, FALSE,
- (uint64_t)0) < 0) {
-
- HDfprintf(stdout,
- "%s: H5C2_jb__write_to_buffer() failed.\n",
- FUNC);
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "H5C2_jb__write_to_buffer() failed.\n")
- } /* end if */
-
- /* Update boolean flags */
- struct_ptr->header_present = TRUE;
- struct_ptr->journal_is_empty = FALSE;
-
-done:
-
- FUNC_LEAVE_NOAPI(ret_value)
-
-} /* end H5C2_jb__init */
-
-
-/******************************************************************************
- *
- * Function: H5C2_jb__start_transaction
- *
- * Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
- * Wednesday, February 6, 2008
- *
- * Purpose: Verify that there is no transaction in progress, and
- * that the supplied transaction number greater than
- * the last. Then construct a start transaction message,
- * and write it to the current journal buffer. Make note
- * of the fact that the supplied transaction is in
- * progress.
- *
- * Returns: SUCCEED on success.
- *
- ******************************************************************************/
-
-herr_t
-H5C2_jb__start_transaction(H5C2_jbrb_t * struct_ptr,
- uint64_t trans_num)
-
-{
- char temp[150];
- herr_t ret_value = SUCCEED;
- time_t current_date;
-
- 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 */
-
- /* Verify that header message is present in journal file or ring buffer.
- * If not, write it.
- */
- if ( struct_ptr->header_present == FALSE ) {
-
- /* Get the current date */
- current_date = time(NULL);
-
- HDsnprintf(temp,
- (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(&current_date),
- struct_ptr->human_readable);
-
- 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 */
-
- struct_ptr->header_present = 1;
- struct_ptr->journal_is_empty = 0;
- } /* 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 ) {
+ if ( H5C2_jb__write_header_entry(struct_ptr) != SUCCEED ) {
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;
-
+ "H5C2_jb__write_header_entry() failed.\n")
+ }
+#endif /* JRM */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5C2_jb__start_transaction */
+} /* end H5C2_jb__init */
/******************************************************************************
@@ -3615,31 +3265,34 @@ done:
} /* end H5C2_jb__journal_entry */
-/*****************************************************************************
+/******************************************************************************
*
- * Function: H5C2_jb__end_transaction
+ * Function: H5C2_jb__start_transaction
*
* Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
* 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,
+ * 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
- * that the supplied transaction is closed, and that no
- * transaction is in progress.
+ * of the fact that the supplied transaction is in
+ * progress.
*
* Returns: SUCCEED on success.
*
- *****************************************************************************/
-herr_t
-H5C2_jb__end_transaction(H5C2_jbrb_t * struct_ptr,
- uint64_t trans_num)
+ ******************************************************************************/
+
+herr_t
+H5C2_jb__start_transaction(H5C2_jbrb_t * struct_ptr,
+ uint64_t trans_num)
+
{
- char temp[25];
+ char temp[150];
herr_t ret_value = SUCCEED;
+ time_t current_date;
- FUNC_ENTER_NOAPI(H5C2_jb__end_transaction, FAIL)
+ FUNC_ENTER_NOAPI(H5C2_jb__start_transaction, FAIL)
#if 0 /* JRM */
HDfprintf(stdout, "%s trans_num = %lld.\n", FUNC, trans_num);
#endif /* JRM */
@@ -3647,286 +3300,229 @@ H5C2_jb__end_transaction(H5C2_jbrb_t * struct_ptr,
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 ) ) {
+ /* Verify that there is no transaction in progress */
+ if ( struct_ptr->trans_in_prog != FALSE ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
- "Transaction not in progress or bad transaction number.")
+ "Transaction already in progress.")
} /* end if */
-
- /* Verify that at least one journal entry has been written under
- * the current transaction
+
+ /* 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?
*/
- if ( struct_ptr->jentry_written != TRUE ) {
+
+ /* Verify that the supplied transaction number greater than the last */
+ if ( (struct_ptr->cur_trans) >= trans_num ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
- "Empty transaction -- at least one journal entry required.")
+ "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 ) {
- /* Prepare end transaction message */
- HDsnprintf(temp, (size_t)25, "3 end_trans %llu\n", trans_num);
+ if ( H5C2_jb__write_header_entry(struct_ptr) != SUCCEED ) {
- /* Write end transaction message */
+ 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,
- TRUE, trans_num ) < 0 ) {
+ FALSE, 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;
+
+ /* 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__end_transaction */
+} /* end H5C2_jb__start_transaction */
/******************************************************************************
*
- * Function: H5C2_jb__comment
+ * Function: H5C2_jb__takedown
*
* Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
- * Wednesday, February 6, 2008
+ * Thursday, February 7, 2008
*
- * Purpose: Insert the supplied comment in the journal file. This
- * call may be ignored if the journal file is machine
- * readable.
+ * Purpose: Verify that the journal buffers are empty, and that the
+ * journal file has been truncated. Then close and delete
+ * the journal file associated with *struct_ptr, and free
+ * all dynamically allocated memory associated with
+ * *struct_ptr.
*
* Returns: SUCCEED on success.
*
******************************************************************************/
herr_t
-H5C2_jb__comment(H5C2_jbrb_t * struct_ptr,
- const char * comment_ptr)
+H5C2_jb__takedown(H5C2_jbrb_t * struct_ptr)
+
{
- char * temp = NULL;
- size_t temp_len;
herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(H5C2_jb__comment, FAIL)
+ hbool_t verbose = FALSE;
+ FUNC_ENTER_NOAPI(H5C2_jb__takedown, FAIL)
+
+ if ( verbose ) {
+
+ HDfprintf(stdout, "%s: entering.\n", FUNC);
+ }
+
/* 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 ) {
-
- char buf[150];
- time_t current_date;
+
+ /* Verify that the journal buffers are empty */
+ if ( struct_ptr->bufs_in_use != 0 ) {
- /* Get the current date */
- current_date = time(NULL);
+ if ( verbose ) {
+ HDfprintf(stdout, "%s: Attempt to takedown with non-empty buffers.\n",
+ FUNC);
+ }
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "Attempt to takedown with non-empty buffers.")
+ } /* end if */
- 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(&current_date),
- struct_ptr->human_readable);
+ /* Verify that the journal file has been truncated */
+ if (struct_ptr->journal_is_empty != TRUE) {
- if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(buf), buf,
- FALSE, struct_ptr->cur_trans) < 0 ) {
+ if ( verbose ) {
+ HDfprintf(stdout,
+ "%s: Attempt to takedown with journal file not truncated.\n",
+ FUNC);
+ }
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "Attempt to takedown with journal file not truncated.")
+ } /* end if */
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "H5C2_jb__write_to_buffer() failed.\n")
- } /* end if */
+ /* Close and delete the journal file associated with struct_ptr */
+ if ( HDclose(struct_ptr->journal_file_fd) < 0 ) {
- struct_ptr->header_present = 1;
- struct_ptr->journal_is_empty = 0;
+ if ( verbose ) {
+ HDfprintf(stdout,
+ "%s: journal file close failed. errno = %d(%s), fd = %d.\n",
+ FUNC, errno, strerror(errno), struct_ptr->journal_file_fd);
+ }
+ HGOTO_ERROR(H5E_IO, H5E_CLOSEERROR, FAIL, "Jounal file close failed.")
} /* end if */
- temp_len = HDstrlen(comment_ptr) + 11;
- if ( ( temp = H5MM_malloc(HDstrlen(comment_ptr) + 11) ) == NULL ) {
+ if ( HDremove(struct_ptr->jname) < 0) {
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \
- "allocation of temp buffer failed.");
+ if ( verbose ) {
+ HDfprintf(stdout,
+ "%s: journal file remove failed. errno = %d(%s).\n",
+ FUNC, errno, strerror(errno));
+ }
+ HGOTO_ERROR(H5E_IO, H5E_REMOVEFAIL, FAIL, "Jounal file close failed.")
} /* end if */
- /* Write comment message */
- HDsnprintf(temp, temp_len, "C comment %s", comment_ptr);
-
- if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(temp), temp, FALSE, struct_ptr->cur_trans ) < 0 ) {
+ /* Free all memory associated with struct_ptr */
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "H5C2_jb__write_to_buffer() failed.\n")
- } /* end if */
+ if ( struct_ptr->jname != NULL ) {
- if ( H5C2_jb__write_to_buffer(struct_ptr, 1, "\n", FALSE, struct_ptr->cur_trans ) < 0 ) {
+ struct_ptr->jname = H5MM_xfree(struct_ptr->jname);
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "H5C2_jb__write_to_buffer() failed.\n")
- } /* end if */
+ if ( struct_ptr->jname != NULL ) {
-done:
+ if ( verbose ) {
- if ( temp != NULL ) {
+ HDfprintf(stdout, "%s: free of jname failed.\n", FUNC);
- temp = H5MM_xfree(temp);
- if ( temp != NULL ) {
+ }
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \
- "free of assembly buffer failed.");
+ "free of jname failed.");
}
}
- FUNC_LEAVE_NOAPI(ret_value)
+ if ( struct_ptr->hdf5_file_name != NULL ) {
-} /* end H5C2_jb__comment */
+ struct_ptr->hdf5_file_name = H5MM_xfree(struct_ptr->hdf5_file_name);
-
-/******************************************************************************
- *
- * Function: H5C2_jb__eoa
- *
- * Programmer: Mike McGreevy <mamcgree@hdfgroup.org>
- * July 29, 2008
- *
- * Purpose: Insert the supplied EOA into the journal file.
- *
- * Returns: SUCCEED on success.
- *
- ******************************************************************************/
+ if ( struct_ptr->hdf5_file_name != NULL ) {
-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(&current_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 */
+ if ( verbose ) {
- struct_ptr->header_present = 1;
- struct_ptr->journal_is_empty = 0;
- } /* end if */
+ HDfprintf(stdout, "%s: free of hdf5_file_name failed.\n", FUNC);
- /* Write EOA message */
- HDsnprintf(temp, temp_len, "E eoa_value 0x%llx", eoa);
+ }
- if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(temp), temp, FALSE, struct_ptr->cur_trans ) < 0 ) {
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \
+ "free of hdf5_file_name failed.");
+ }
+ }
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "H5C2_jb__write_to_buffer() failed.\n")
- } /* end if */
+ if ( (*struct_ptr->buf)[0] != NULL ) {
- if ( H5C2_jb__write_to_buffer(struct_ptr, 1, "\n", FALSE, struct_ptr->cur_trans ) < 0 ) {
+ (*struct_ptr->buf)[0] = H5MM_xfree((*struct_ptr->buf)[0]);
+ if ( (*struct_ptr->buf)[0] != NULL ) {
- HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
- "H5C2_jb__write_to_buffer() failed.\n")
- } /* end if */
+ if ( verbose ) {
+ HDfprintf(stdout, "%s: free of buffers failed.\n", FUNC);
+ }
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \
+ "free of buffers failed.");
+ }
+ }
-done:
+ if ( struct_ptr->buf != NULL ) {
- FUNC_LEAVE_NOAPI(ret_value)
+ struct_ptr->buf = H5MM_xfree(struct_ptr->buf);
+ if ( struct_ptr->buf != NULL ) {
-} /* end H5C2_jb__eoa */
+ if ( verbose ) {
+ HDfprintf(stdout, "%s: free of buffer ptr array faileid.\n",
+ FUNC);
+ }
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \
+ "free of buffer pointer array failed.");
+ }
+ }
-
-/******************************************************************************
- *
- * Function: H5C2_jb__get_last_transaction_on_disk
- *
- * Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
- * Wednesday, February 6, 2008
- *
- * Purpose: Lookup the number of the last transaction to have been
- * fully written to disk, and place its transaction
- * number in *trans_num_ptr. If no transaction has made
- * it to disk, load zero into *trans_num_ptr.
- *
- * Returns: SUCCEED on success.
- *
- ******************************************************************************/
+ if ( struct_ptr->trans_tracking != NULL ) {
-herr_t
-H5C2_jb__get_last_transaction_on_disk(H5C2_jbrb_t * struct_ptr,
- uint64_t * trans_num_ptr)
-{
- herr_t ret_value = SUCCEED;
+ struct_ptr->trans_tracking = H5MM_xfree(struct_ptr->trans_tracking);
- FUNC_ENTER_NOAPI(H5C2_jb__get_last_transaction_on_disk, FAIL)
-
- /* Check Arguments */
- HDassert( trans_num_ptr != NULL );
+ if ( struct_ptr->trans_tracking != NULL ) {
- /* This should really be an assert, but the func enter/exit
- * macros get testy if there isn't at least one goto error
- * macro call in the funtion.
- */
- if ( ( struct_ptr == NULL ) ||
- ( struct_ptr->magic != H5C2__H5C2_JBRB_T_MAGIC ) ) {
+ if ( verbose ) {
+ HDfprintf(stdout,
+ "%s: free of trans tracking array faileid.\n",
+ FUNC);
+ }
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "bad struct_ptr.")
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \
+ "free of transaction tracking array failed.");
+ }
}
- /* 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.")
-
- } /* end if */
+done:
- * trans_num_ptr = struct_ptr->last_trans_on_disk;
+ if ( verbose ) {
-done:
+ HDfprintf(stdout, "%s: exiting.\n", FUNC);
+ fflush(stdout);
+ }
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5C2_jb__get_last_transaction_on_disk */
+} /* end H5C2_jb__takedown */
/******************************************************************************
@@ -4006,193 +3602,456 @@ done:
/******************************************************************************
*
- * Function: H5C2_jb__takedown
+ * Function: H5C2_jb__write_header_entry
*
- * Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
- * Thursday, February 7, 2008
+ * Programmer: John Mainzer
+ * 2/12/09
*
- * Purpose: Verify that the journal buffers are empty, and that the
- * journal file has been truncated. Then close and delete
- * the journal file associated with *struct_ptr, and free
- * all dynamically allocated memory associated with
- * *struct_ptr.
+ * Purpose: Write the header message to the journal file.
+ *
+ * This message appear exactly once in every journal
+ * file, and is always the first message in the file.
+ * It identifies the journal file, and contains
+ * information required to run the journal, should
+ * that be necessary.
*
+ * It is always in human readable format.
+ *
* Returns: SUCCEED on success.
+ * FAIL on failure.
+ *
+ * Changes: JRM -- 3/21/09
+ * Moved the entry tag strings into #defines.
+ * Replaced all white space in the creation date
+ * string with underscores.
*
******************************************************************************/
herr_t
-H5C2_jb__takedown(H5C2_jbrb_t * struct_ptr)
+H5C2_jb__write_header_entry(H5C2_jbrb_t * struct_ptr)
{
- herr_t ret_value = SUCCEED;
- hbool_t verbose = FALSE;
+ herr_t ret_value = SUCCEED;
+ hbool_t verbose = FALSE;
+ char *buf;
+ char * p;
+ char time_buf[32];
+ int chars_written;
+ int i;
+ size_t file_name_len;
+ size_t buf_len;
+ time_t current_date;
- FUNC_ENTER_NOAPI(H5C2_jb__takedown, FAIL)
+ FUNC_ENTER_NOAPI(H5C2_jb__write_header_entry, FAIL)
- if ( verbose ) {
+ /* Check Arguments */
+ HDassert( struct_ptr );
+ HDassert( struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC );
+ HDassert( struct_ptr->hdf5_file_name != NULL );
+ HDassert( struct_ptr->header_present == FALSE );
+ HDassert( struct_ptr->journal_is_empty == TRUE );
- HDfprintf(stdout, "%s: entering.\n", FUNC);
- }
+ file_name_len = strlen(struct_ptr->hdf5_file_name);
- /* Check Arguments */
- HDassert(struct_ptr);
- HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC);
+ HDassert( file_name_len > 0 );
+
+ buf_len = file_name_len + 256;
- /* Verify that the journal buffers are empty */
- if ( struct_ptr->bufs_in_use != 0 ) {
+ /* Allocate space for journal buffers */
+ buf = H5MM_malloc(buf_len);
- if ( verbose ) {
- HDfprintf(stdout, "%s: Attempt to takedown with non-empty buffers.\n",
- FUNC);
- }
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
- "Attempt to takedown with non-empty buffers.")
- } /* end if */
+ if ( buf == NULL ) {
- /* Verify that the journal file has been truncated */
- if (struct_ptr->journal_is_empty != TRUE) {
+ if ( verbose ) {
- if ( verbose ) {
- HDfprintf(stdout,
- "%s: Attempt to takedown with journal file not truncated.\n",
- FUNC);
- }
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
- "Attempt to takedown with journal file not truncated.")
+ HDfprintf(stdout, "%s: buffer allocation failed.\n", FUNC);
+ }
+
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \
+ "buffer allocation failed.");
} /* end if */
+
+ /* Get the current date */
+ current_date = time(NULL);
- /* Close and delete the journal file associated with struct_ptr */
- if ( HDclose(struct_ptr->journal_file_fd) < 0 ) {
+ /* load ascii representation of current_date into time_buf[],
+ * replacing white space with underscores.
+ */
+ time_buf[31] = '\0'; /* just to be safe */
- if ( verbose ) {
- HDfprintf(stdout,
- "%s: journal file close failed. errno = %d(%s), fd = %d.\n",
- FUNC, errno, strerror(errno), struct_ptr->journal_file_fd);
- }
- HGOTO_ERROR(H5E_IO, H5E_CLOSEERROR, FAIL, "Jounal file close failed.")
- } /* end if */
+ if ( (p = HDctime(&current_date)) == NULL ) {
- if ( HDremove(struct_ptr->jname) < 0) {
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "Can't get ascii representation of current date.")
- if ( verbose ) {
- HDfprintf(stdout,
- "%s: journal file remove failed. errno = %d(%s).\n",
- FUNC, errno, strerror(errno));
- }
- HGOTO_ERROR(H5E_IO, H5E_REMOVEFAIL, FAIL, "Jounal file close failed.")
- } /* end if */
+ } else {
- /* Free all memory associated with struct_ptr */
+ /* copy the string into time_buf, replacing white space with
+ * underscores.
+ *
+ * Do this to make parsing the header easier.
+ */
+ i = 0;
- if ( struct_ptr->jname != NULL ) {
+ while ( ( i < 31 ) && ( *p != '\0' ) ) {
- struct_ptr->jname = H5MM_xfree(struct_ptr->jname);
- if ( struct_ptr->jname != NULL ) {
+ if ( isspace(*p) ) {
- if ( verbose ) {
- HDfprintf(stdout, "%s: free of jname failed.\n", FUNC);
- }
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \
- "free of jname failed.");
- }
- }
+ time_buf[i] = '_';
- if ( (*struct_ptr->buf)[0] != NULL ) {
+ } else {
- (*struct_ptr->buf)[0] = H5MM_xfree((*struct_ptr->buf)[0]);
- if ( (*struct_ptr->buf)[0] != NULL ) {
+ time_buf[i] = *p;
+ }
- if ( verbose ) {
- HDfprintf(stdout, "%s: free of buffers failed.\n", FUNC);
- }
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \
- "free of buffers failed.");
+ i++;
+ p++;
}
+
+ time_buf[i] = '\0';
}
- if ( struct_ptr->buf != NULL ) {
+ /* Format the header message in the temporary buffer */
- struct_ptr->buf = H5MM_xfree(struct_ptr->buf);
- if ( struct_ptr->buf != NULL ) {
+ 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 ( verbose ) {
- HDfprintf(stdout, "%s: free of buffer ptr array faileid.\n",
- FUNC);
- }
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \
- "free of buffer pointer array failed.");
+ if ( chars_written >= buf_len - 1 ) {
+
+ if ( verbose ) {
+
+ HDfprintf(stdout, "%s: tried to overwrite buffer.\n", FUNC);
}
+
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCOPY, FAIL, \
+ "tried to overwrite buffer.");
}
- if ( struct_ptr->trans_tracking != NULL ) {
+ HDassert( strlen(buf) < buf_len );
- struct_ptr->trans_tracking = H5MM_xfree(struct_ptr->trans_tracking);
- if ( struct_ptr->trans_tracking != NULL ) {
+ /* Write the header message into the ring buffer */
+ if ( H5C2_jb__write_to_buffer(struct_ptr, HDstrlen(buf), buf, FALSE,
+ (uint64_t)0) < 0) {
- if ( verbose ) {
- HDfprintf(stdout, "%s: free of trans tracking array faileid.\n",
- FUNC);
- }
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \
- "free of transaction tracking array failed.");
+ if ( verbose ) {
+
+ HDfprintf(stdout,
+ "%s: H5C2_jb__write_to_buffer() failed.\n",
+ FUNC);
}
- }
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "H5C2_jb__write_to_buffer() failed.\n")
+ } /* end if */
+
+ /* Update boolean flags */
+ struct_ptr->header_present = TRUE;
+ struct_ptr->journal_is_empty = FALSE;
done:
- if ( verbose ) {
+ if ( buf != NULL ) {
- HDfprintf(stdout, "%s: exiting.\n", FUNC);
- fflush(stdout);
+ buf = H5MM_xfree(buf);
+
+ if ( buf != NULL ) {
+
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \
+ "free of buf failed.");
+ }
}
+
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5C2_jb__takedown */
+} /* end H5C2_jb__write_header_entry() */
/******************************************************************************
*
- * Function: H5C2_jb__bin2hex
+ * Function: H5C2_jb__write_to_buffer
*
* Programmer: Mike McGreevy <mcgreevy@hdfgroup.org>
- * Tuesday, March 4, 2008
+ * Wednesday, February 6, 2008
*
- * Purpose: Convert binary data into hexadecimal.
+ * Purpose: Put the contents of data into the journal buffers. This
+ * is done as follows: While the data to be written is
+ * larger than the amount of space left in the ring buffer,
+ * the ring buffer is filled to capacity with data and
+ * flushed. This repeats until the unwritten data remaining
+ * can fit in the ring buffer without having to loop around
+ * to the top.
+ *
+ * At this point, the rest of the data can just be written
+ * without having to break it up further. In the event
+ * the data covers more than one journal buffer, the get
+ * and put indices are updated to state this fact. Any
+ * journal buffers that were filled during the write are
+ * flushed.
*
* Returns: SUCCEED on success.
*
******************************************************************************/
herr_t
-H5C2_jb__bin2hex(const uint8_t * buf,
- char * hexdata,
- size_t * hexlength,
- size_t buf_size)
-
+H5C2_jb__write_to_buffer(H5C2_jbrb_t * struct_ptr,
+ size_t size,
+ const char * data,
+ hbool_t is_end_trans,
+ uint64_t trans_num)
{
- size_t v; /* Local index variable */
- uint8_t c;
- char * t;
+ herr_t ret_value = SUCCEED;
+ unsigned long track_last_trans = 0;
+ int oldput = 0;
+ int i;
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5C2_jb__bin2hex)
+ FUNC_ENTER_NOAPI(H5C2_jb__write_to_buffer, FAIL)
- t = hexdata;
- t[0] = ' ';
- for (v = 0; v < buf_size; v++) {
+ /* Check Arguments */
+ HDassert(struct_ptr);
+ HDassert(data);
+ HDassert(struct_ptr->magic == H5C2__H5C2_JBRB_T_MAGIC);
+ HDassert(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);
- t = &hexdata[v * 3 + 1];
- c = buf[v];
- HDsnprintf(t, (size_t)3, "%02x ", c);
- t[2] = ' ';
+ /* If the data size exceeds the bounds of the ring buffer's allocated
+ * memory, loop around to top
+ */
+ if (size >= struct_ptr->rb_space_to_rollover) {
- } /* end for */
- t[3] = '\n';
- t[4] = 0;
+ while (size >= struct_ptr->rb_space_to_rollover) {
+
+ /* Assertions */
+ HDassert(size != 0);
+ HDassert(HDstrlen(data) >= struct_ptr->rb_space_to_rollover);
- * hexlength = v * 3 + 2;
+ /* fill up remaining space in the ring buffer */
+ HDmemcpy(struct_ptr->head, data, struct_ptr->rb_space_to_rollover);
+
+ /* move head to point to start of ring buffer */
+ struct_ptr->head = (*struct_ptr->buf)[0];
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5C2_jb__bin2hex*/
+ /* make note of last transaction on disk */
+ track_last_trans = (*struct_ptr->trans_tracking)[struct_ptr->put];
+
+ /* update rb_free_space */
+ struct_ptr->rb_free_space -= struct_ptr->rb_space_to_rollover;
+
+ /* Fill out the remainder of the trans_tracking array with
+ the most recent transaction in the array.*/
+ (*struct_ptr->trans_tracking)[0] = track_last_trans;
+ for (i=struct_ptr->put; i<struct_ptr->num_bufs; i++)
+ {
+ (*struct_ptr->trans_tracking)[i] = track_last_trans;
+ }
+
+ /* reset put index */
+ struct_ptr->put = 0;
+
+ /* update bufs_in_use as necessary */
+ struct_ptr->bufs_in_use = struct_ptr->num_bufs - struct_ptr->get;
+
+ /* check to see if trans_tracking needs to be updated. If so,
+ then update it */
+ if ((size == struct_ptr->rb_space_to_rollover) &&
+ (is_end_trans == TRUE)) {
+
+ (*struct_ptr->trans_tracking)[struct_ptr->num_bufs - 1]
+ = trans_num;
+ (*struct_ptr->trans_tracking)[0] = trans_num;
+ }
+
+ /* flush buffers */
+ if ( H5C2_jb__flush_full_buffers(struct_ptr) < 0 ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "H5C2_jb__flush_full_buffers() failed.\n")
+ }
+
+ /* update remaining size of data to be written */
+ size = size - struct_ptr->rb_space_to_rollover;
+
+ /* update the data pointer to point to the remaining data to be
+ * written
+ */
+ data = &data[struct_ptr->rb_space_to_rollover];
+
+ /* update the amount of space left at end of ring buffer */
+ struct_ptr->rb_space_to_rollover =
+ struct_ptr->buf_size * struct_ptr->num_bufs;
+
+ /* update the amount of space in the current buffer */
+ struct_ptr->cur_buf_free_space = struct_ptr->buf_size;
+
+ } /* end while */
+ } /* end if */
+
+ /* If the size of the data exceeds the bounds of a single journal
+ * buffer, will write into multiple
+ */
+ if (size > struct_ptr->cur_buf_free_space) {
+
+ HDassert(struct_ptr->cur_buf_free_space != 0);
+
+ /* write data into journal buffers */
+ HDmemcpy(struct_ptr->head, data, size);
+
+ /* update head pointer */
+ struct_ptr->head = &struct_ptr->head[size];
+
+ /* make note of last transaction on disk */
+ track_last_trans = (*struct_ptr->trans_tracking)[struct_ptr->put];
+ oldput = struct_ptr->put;
+
+ /* update rb_free_space */
+ struct_ptr->rb_free_space -= size;
+
+ /* update put index */
+ struct_ptr->put +=
+ (size-struct_ptr->cur_buf_free_space)/(struct_ptr->buf_size) + 1;
+
+ /* Drag the last transaction in a filled buffer value residing in the
+ old put location through the trans_tracking array to the new
+ corresponding put position. */
+ for (i=oldput; i<struct_ptr->put+1; i++)
+ {
+ (*struct_ptr->trans_tracking)[i] = track_last_trans;
+ }
+
+ /* update current buffer usage */
+ struct_ptr->cur_buf_free_space =
+ struct_ptr->rb_space_to_rollover - size -
+ (struct_ptr->num_bufs - (struct_ptr->put + 1)) *
+ (struct_ptr->buf_size );
+
+ /* update bufs_in_use as necessary */
+ struct_ptr->bufs_in_use = struct_ptr->put - struct_ptr->get;
+ if (struct_ptr->cur_buf_free_space < struct_ptr->buf_size) {
+
+ struct_ptr->bufs_in_use++;
+ }
+
+ /* check to see if trans_tracking needs to be updated. If so,
+ then update it */
+ if (is_end_trans == TRUE) {
+
+ if (struct_ptr->cur_buf_free_space == struct_ptr->buf_size) {
+ (*struct_ptr->trans_tracking)[struct_ptr->put - 1] = trans_num;
+ }
+ else {
+ (*struct_ptr->trans_tracking)[struct_ptr->put] = trans_num;
+ }
+
+ } /* end if */
+
+ /* flush buffers */
+ if ( H5C2_jb__flush_full_buffers(struct_ptr) < 0 ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "H5C2_jb__flush_full_buffers() failed.\n")
+ }
+
+ /* update space left at end of ring buffer */
+ struct_ptr->rb_space_to_rollover -= size;
+
+ } /* end if */
+
+ /* if the data can fit in the remaining space in the current journal
+ * buffer indexed by put
+ */
+ else if (size > 0) {
+
+ HDassert(size <= struct_ptr->cur_buf_free_space);
+
+ /* write data into journal buffer */
+ HDmemcpy(struct_ptr->head, data, size);
+
+ /* increment bufs_in_use as necessary */
+ if ( ( struct_ptr->bufs_in_use == 0 ) ) {
+
+ struct_ptr->bufs_in_use++;
+ }
+
+ /* update head pointer */
+ struct_ptr->head = &struct_ptr->head[size];
+
+ /* update rb_free_space */
+ struct_ptr->rb_free_space -= size;
+
+ /* update current buffer usage */
+ struct_ptr->cur_buf_free_space -= size;
+
+ /* update end of buffer space */
+ struct_ptr->rb_space_to_rollover -= size;
+
+ /* check to see if trans_tracking needs to be updated. If so,
+ then update it */
+ if (is_end_trans == TRUE) {
+
+ (*struct_ptr->trans_tracking)[struct_ptr->put]
+ = trans_num;
+ } /* end if */
+
+ /* if buffer is full, flush it, and loop to the top of the
+ * ring buffer if at the end.
+ */
+ if (struct_ptr->cur_buf_free_space == 0) {
+
+ if ( struct_ptr->put != (struct_ptr->num_bufs - 1) ) {
+ struct_ptr->put += 1;
+
+ /* Drag trans_tracking value into next buffer */
+ (*struct_ptr->trans_tracking)[struct_ptr->put]
+ = (*struct_ptr->trans_tracking)[struct_ptr->put - 1];
+
+ } /* end if */
+
+ else {
+
+ struct_ptr->put = 0;
+
+ /* Drag trans_tracking value into next buffer */
+ (*struct_ptr->trans_tracking)[0]
+ = (*struct_ptr->trans_tracking)[struct_ptr->num_bufs - 1];
+
+ /* reset head pointer and free space values */
+ struct_ptr->head = (*struct_ptr->buf)[0];
+ struct_ptr->rb_space_to_rollover =
+ struct_ptr->buf_size * struct_ptr->num_bufs;
+
+ } /* end else */
+
+ if ( H5C2_jb__flush_full_buffers(struct_ptr) < 0 ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTJOURNAL, FAIL, \
+ "H5C2_jb__flush_full_buffers() failed.\n")
+ } /* end if */
+
+ struct_ptr->cur_buf_free_space = struct_ptr->buf_size;
+
+ } /* end if */
+
+ } /* end else */
+
+ HDassert(struct_ptr->bufs_in_use <= struct_ptr->num_bufs);
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5C2_jb__write_to_buffer */
diff --git a/src/H5C2pkg.h b/src/H5C2pkg.h
index 3510dc7..af3ac81 100644
--- a/src/H5C2pkg.h
+++ b/src/H5C2pkg.h
@@ -62,9 +62,17 @@
*
*
* magic: Unsigned 32-bit integer always set to
- * H5C2__H5C2_JBRB_T_MAGIC. This field is used to validate
- * pointers to instances of H5C_jbrb_t.
- *
+ * H5C2__H5C2_JBRB_T_MAGIC. This field is used to
+ * validate pointers to instances of H5C_jbrb_t.
+ *
+ * journal_magic: int32_t used to store a randomly selected integer
+ * used to tag both the journal file and the
+ * mdj_config_block. Should the journal ever be
+ * run, we will check to see if the magic number
+ * from the target HDF5 file matches that in the
+ * journal, and refuse to run the journal if it does
+ * not.
+ *
* journal_file_fd: File Descriptor of the journal file that is being
* written to from this ring buffer.
*
@@ -157,9 +165,17 @@
#define H5C2__H5C2_JBRB_T_MAGIC (unsigned)0x00D0A03
#define H5C2__JOURNAL_VERSION 1
+/* tags used to mark entries in the journal file header */
+#define H5C2_JNL__VER_NUM_TAG "ver_num"
+#define H5C2_JNL__TGT_FILE_NAME_TAG "target_file_name"
+#define H5C2_JNL__JNL_MAGIC_TAG "journal_magic"
+#define H5C2_JNL__CREATION_DATE_TAG "creation_date"
+#define H5C2_JNL__HUMAN_READABLE_TAG "human_readable"
+
struct H5C2_jbrb_t
{
uint32_t magic;
+ int32_t journal_magic;
int journal_file_fd;
int num_bufs;
size_t buf_size;
@@ -794,45 +810,17 @@ typedef struct H5C2_mdjsc_record_t
* been modified have been written to disk in the journal
* file.
*
- * mdj_file_name_ptr: Pointer to a string containing the path of the
- * journal file, or NULL if this path is undefined.
- * At present, the journal will always be stored in an
- * external file, so this field must be defined if
- * journaling is enabled.
- *
- * To avoid allocating extra memory, mdj_file_name_ptr
- * points into the approprite location in the in core
- * image of the metadata journaling configuration block.
- *
- * mdj_conf_block_addr: Address of the metadata journaling configuration
- * block on disk, or HADDR_UNDEF if that block is undefined.
- *
- * mdj_conf_block_len: Length (in bytes) of the metadata journaling
- * configuration block, or 0 if that block is undefined.
- *
- * mdj_conf_block_ptr: Pointer to a dynamically allocated chunk of
- * memory of size mdj_conf_block_len used to construct
- * an image of the on disk metadata journaling configuration
- * block. This block is used to record the path of the
- * journal file in the HDF5 file, so that it can be
- * found in the event of a crash.
+ * jnl_magic: Randomly selected int32_t used to reduce the possibility
+ * of running the wrong journal on an HDF5 file. The basic
+ * idea is to pick a random number, store it in both the HDF5
+ * file and the journal file, and then refuse to run the
+ * journal unless the numbers match.
*
- * The metadata journaling configuration block has the
- * following format:
+ * jnl_file_name_len: Length of the journal file name, or zero if the
+ * journal file name is undefined.
*
- * 4 bytes signature
- *
- * 1 byte version
- *
- * 4 bytes path length
- *
- * variable string containing path of journal file
- *
- * 4 bytes checksum
- *
- * The base address and lenth of the metadata journaling
- * configuration block is stored in the mdj_msg superblock
- * extension message.
+ * jnl_file_name: Array of char of length H5C2__MAX_JOURNAL_FILE_NAME_LEN
+ * + 1 used to store the journal file path.
*
* mdj_jbrb: Instance of H5C2_jbrb_t used to manage logging of journal
* entries to the journal file.
@@ -1160,16 +1148,6 @@ typedef struct H5C2_mdjsc_record_t
#define H5C2__PREFIX_LEN 32
#define H5C2__MAX_API_NAME_LEN 128
-#define H5C2__JOURNAL_MAGIC_LEN (size_t)4
-#define H5C2__JOURNAL_CONF_MAGIC "MDJC"
-#define H5C2__JOURNAL_CONF_VERSION ((uint8_t)1)
-#define H5C2__JOURNAL_BLOCK_LEN(pathLen, f) \
- ( H5C2__JOURNAL_MAGIC_LEN + \
- 1 + /* version */ \
- H5F_SIZEOF_SIZE(f) + \
- ((pathLen) + 1) + \
- 4 /* checksum */ )
-
#define H5C2__MIN_MDJSC_CB_TBL_LEN 16
#define H5C2__MDJSC_CB_TBL_MIN_ACTIVE_RATIO 0.25
@@ -1216,7 +1194,7 @@ struct H5C2_t
int32_t pel_len;
size_t pel_size;
- H5C2_cache_entry_t * pel_head_ptr;
+ H5C2_cache_entry_t * pel_head_ptr;
H5C2_cache_entry_t * pel_tail_ptr;
int32_t LRU_list_len;
@@ -1259,10 +1237,10 @@ struct H5C2_t
char trans_api_name[H5C2__MAX_API_NAME_LEN];
uint64_t trans_num;
uint64_t last_trans_on_disk;
- char * mdj_file_name_ptr;
- haddr_t mdj_conf_block_addr;
- hsize_t mdj_conf_block_len;
- void * mdj_conf_block_ptr;
+ int32_t jnl_magic;
+ int32_t jnl_file_name_len;
+ char jnl_file_name[H5C2__MAX_JOURNAL_FILE_NAME_LEN
+ + 1];
struct H5C2_jbrb_t mdj_jbrb;
int32_t tl_len;
size_t tl_size;
diff --git a/src/H5C2private.h b/src/H5C2private.h
index 833bfa1..c9e55ca 100644
--- a/src/H5C2private.h
+++ b/src/H5C2private.h
@@ -1591,17 +1591,35 @@ H5_DLL herr_t H5C2_update_for_new_last_trans_on_disk(H5C2_t * cache_ptr,
typedef struct H5C2_jbrb_t H5C2_jbrb_t;
+H5_DLL herr_t H5C2_jb__bin2hex(const uint8_t * buf,
+ char * hexdata,
+ size_t * hexlength,
+ size_t buf_size);
+
+H5_DLL herr_t H5C2_jb__comment(H5C2_jbrb_t * struct_ptr,
+ const char * comment_ptr);
+
+H5_DLL herr_t H5C2_jb__end_transaction(H5C2_jbrb_t * struct_ptr,
+ uint64_t trans_num);
+
+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);
+
H5_DLL herr_t H5C2_jb__flush_full_buffers(H5C2_jbrb_t * struct_ptr);
H5_DLL herr_t H5C2_jb__flush(H5C2_jbrb_t * struct_ptr);
-H5_DLL herr_t H5C2_jb__write_to_buffer(H5C2_jbrb_t * struct_ptr,
- size_t size,
- const char * data,
- hbool_t is_end_trans,
- uint64_t trans_num);
+H5_DLL herr_t H5C2_jb__journal_entry(H5C2_jbrb_t * struct_ptr,
+ uint64_t trans_num,
+ haddr_t base_addr,
+ size_t length,
+ const uint8_t * body);
H5_DLL herr_t H5C2_jb__init(H5C2_jbrb_t * struct_ptr,
+ const int32_t journal_magic,
const char * HDF5_file_name,
const char * journal_file_name,
size_t buf_size,
@@ -1612,35 +1630,21 @@ H5_DLL herr_t H5C2_jb__init(H5C2_jbrb_t * struct_ptr,
H5_DLL herr_t H5C2_jb__start_transaction(H5C2_jbrb_t * struct_ptr,
uint64_t trans_num);
-H5_DLL herr_t H5C2_jb__journal_entry(H5C2_jbrb_t * struct_ptr,
- uint64_t trans_num,
- haddr_t base_addr,
- size_t length,
- const uint8_t * body);
-
-H5_DLL herr_t H5C2_jb__end_transaction(H5C2_jbrb_t * struct_ptr,
- uint64_t trans_num);
-
-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);
+H5_DLL herr_t H5C2_jb__takedown(H5C2_jbrb_t * struct_ptr);
H5_DLL herr_t H5C2_jb__trunc(H5C2_jbrb_t * struct_ptr);
-H5_DLL herr_t H5C2_jb__takedown(H5C2_jbrb_t * struct_ptr);
+H5_DLL herr_t H5C2_jb__write_header_entry(H5C2_jbrb_t * struct_ptr);
+
+H5_DLL herr_t H5C2_jb__write_to_buffer(H5C2_jbrb_t * struct_ptr,
+ size_t size,
+ const char * data,
+ hbool_t is_end_trans,
+ uint64_t trans_num);
-H5_DLL herr_t H5C2_jb__bin2hex(const uint8_t * buf,
- char * hexdata,
- size_t * hexlength,
- size_t buf_size);
/*****************************************************************************/
-/********** journal config block management function definitions: ************/
+/***** superblock journaling message management function definitions: ********/
/*****************************************************************************/
H5_DLL herr_t H5C2_check_for_journaling(H5F_t * f,
@@ -1648,25 +1652,13 @@ H5_DLL herr_t H5C2_check_for_journaling(H5F_t * f,
H5C2_t * cache_ptr,
hbool_t journal_recovered);
-H5_DLL herr_t H5C2_create_journal_config_block(const H5F_t *f,
- hid_t dxpl_id,
- const char * journal_file_name_ptr);
-
-H5_DLL herr_t H5C2_discard_journal_config_block(const H5F_t * f,
- hid_t dxpl_id);
-
H5_DLL herr_t H5C2_get_journaling_in_progress(const H5F_t * f,
hid_t dxpl_id,
H5C2_t * cache_ptr);
-H5_DLL herr_t H5C2_load_journal_config_block(const H5F_t * f,
- hid_t dxpl_id,
- H5C2_t * cache_ptr,
- haddr_t block_addr,
- hsize_t block_len);
-
H5_DLL herr_t H5C2_mark_journaling_in_progress(H5F_t * f,
hid_t dxpl_id,
+ const int32_t journal_magic,
const char * journal_file_name_ptr);
H5_DLL herr_t H5C2_unmark_journaling_in_progress(H5F_t * f,
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index 08a53a5..1318eb8 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -138,7 +138,12 @@ typedef struct H5F_file_t {
struct H5G_t *root_grp; /* Open root group */
H5FO_t *open_objs; /* Open objects in file */
H5RC_t *grp_btree_shared; /* Ref-counted group B-tree node info */
- hbool_t mdc_jrnl_enabled; /* TRUE iff journaling is in progress */
+ hbool_t mdc_jnl_enabled; /* TRUE iff journaling is in progress */
+ int32_t mdc_jnl_magic; /* journal file magic -- if defined */
+ size_t mdc_jnl_file_name_len; /* journal file name length */
+ char mdc_jnl_file_name[H5C2__MAX_JOURNAL_FILE_NAME_LEN + 1];
+ /* journal file name -- if defined */
+/* todo -- delete the following lines. -- JRM */
haddr_t mdc_jrnl_block_loc; /* Rel addr of mdc journal block */
hsize_t mdc_jrnl_block_len; /* Length of mdc journal block */
} H5F_file_t;
diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c
index 2df6ac1..2e1f564 100644
--- a/src/H5Fsuper.c
+++ b/src/H5Fsuper.c
@@ -356,9 +356,10 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
* super block to indicate that journaling is not turned on at
* present. These initialization may be overridden shortly.
*/
- shared->mdc_jrnl_enabled = FALSE;
- shared->mdc_jrnl_block_loc = HADDR_UNDEF;
- shared->mdc_jrnl_block_len = 0;
+ shared->mdc_jnl_enabled = FALSE;
+ shared->mdc_jnl_magic = 0;
+ shared->mdc_jnl_file_name_len = 0;
+ (shared->mdc_jnl_file_name)[0] = '\0';
/* Get the shared file creation property list */
if(NULL == (c_plist = H5I_object(shared->fcpl_id)))
@@ -744,17 +745,44 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
} /* end if */
else {
- shared->mdc_jrnl_enabled = mdj_msg.mdc_jrnl_enabled;
+ shared->mdc_jnl_enabled = mdj_msg.mdc_jnl_enabled;
- if ( shared->mdc_jrnl_enabled ) {
+ if ( shared->mdc_jnl_enabled ) {
- shared->mdc_jrnl_block_loc = mdj_msg.mdc_jrnl_block_loc;
- shared->mdc_jrnl_block_len = mdj_msg.mdc_jrnl_block_len;
+ shared->mdc_jnl_magic = mdj_msg.mdc_jnl_magic;
+ shared->mdc_jnl_file_name_len = mdj_msg.mdc_jnl_file_name_len;
+
+ if ( shared->mdc_jnl_file_name_len <= 0 ) {
+
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, \
+ "journaling enabled, but journal file path empty?!?")
+ }
+
+ if ( shared->mdc_jnl_file_name_len >
+ H5C2__MAX_JOURNAL_FILE_NAME_LEN ) {
+
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, \
+ "journal file path too long")
+ }
+
+ HDstrncpy(shared->mdc_jnl_file_name,
+ mdj_msg.mdc_jnl_file_name,
+ mdj_msg.mdc_jnl_file_name_len + 1);
+
+ if ( ( (shared->mdc_jnl_file_name)
+ [shared->mdc_jnl_file_name_len] != '\0' ) ||
+ ( HDstrlen(shared->mdc_jnl_file_name) !=
+ shared->mdc_jnl_file_name_len ) ) {
+
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, \
+ "bad journal file path and/or path len???")
+ }
}
else
{
- shared->mdc_jrnl_block_loc = HADDR_UNDEF;
- shared->mdc_jrnl_block_len = 0;
+ shared->mdc_jnl_magic = 0;
+ shared->mdc_jnl_file_name_len = 0;
+ (shared->mdc_jnl_file_name)[0] = '\0';
}
/* Reset metadata journaling config message */
@@ -765,9 +793,15 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
* closing the file (since this will be the only open object).
*/
f->nopen_objs++;
- if(H5O_close(&ext_loc) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENFILE, FAIL, "unable to close superblock extension")
+
+ if(H5O_close(&ext_loc) < 0) {
+
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENFILE, FAIL, \
+ "unable to close superblock extension")
+ }
+
f->nopen_objs--;
+
} /* end if */
done:
@@ -962,15 +996,35 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to update driver info header message")
} /* end if */
- /* check for journaling config data to store */
- if ( f->shared->mdc_jrnl_enabled ) {
- struct H5O_mdj_msg_t mdj_conf;
+ /* One might expect us to check to see if journaling is enabled
+ * at this point, and write a metadata journaling message to the
+ * super block extension if it is.
+ *
+ * However, the cache has not been initialized at this point,
+ * so we don't know if we will be successful in creating the
+ * journal file (the journal file may already exist, or some
+ * directory on the journal path may not exist.
+ *
+ * Further, the cache should refuse to allow the file to open if
+ * it detects journaling in progress -- so marking journaling in
+ * progress here would introduce some complexities.
+ * status now
+ *
+ * Thus, don't write the metadata journaling message now. Instead,
+ * initialize the metadata journaling related fields to indicate
+ * that journaling is not in progress. If journaling is requested,
+ * we will write the metadata journaling message after we have
+ * successfully opened the journal file and started journaling.
+ *
+ * JRM -- 2/19/09
+ */
+
+ f->shared->mdc_jnl_enabled = FALSE;
+ f->shared->mdc_jnl_magic = 0;
+ f->shared->mdc_jnl_file_name_len = 0;
+ (f->shared->mdc_jnl_file_name)[0] = '\0';
- mdj_conf.mdc_jrnl_enabled = f->shared->mdc_jrnl_enabled;
- mdj_conf.mdc_jrnl_block_loc = f->shared->mdc_jrnl_block_loc;
- mdj_conf.mdc_jrnl_block_len = f->shared->mdc_jrnl_block_len;
- }
/* Twiddle the number of open objects to avoid closing the file
* (since this will be the only open object currently).
@@ -1139,14 +1193,13 @@ done:
} /* end H5F_super_write() */
-
/*-------------------------------------------------------------------------
* Function: H5F_super_write_mdj_msg
*
* If journaling is enabled, create a superblock extension
* if necessary and then write the current contents of
- * the mdc_jrnl_enabled, mdc_jrnl_block_loc, and
+ * the mdc_jnl_enabled, mdc_jrnl_block_loc, and
* mdc_jrnl_block_len fields of the shared structure to the
* mdj_msg in the superblock extention, overwriting the old
* message if it exists.
@@ -1162,6 +1215,17 @@ done:
*
* Programmer: John Mainzer
* 3/3/08
+ *
+ * Changes: JRM -- 2/17/09
+ * Heavily re-worked the function to move the journal file
+ * name and journal file magic into the metadata journaling
+ * message.
+ *
+ * Note that this makes the metadata journaling message
+ * variable length, so we now delete any existing metadata
+ * journaling message, and then replace it with a new
+ * message if metadata journaling is enabled.
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -1204,111 +1268,133 @@ H5F_super_write_mdj_msg(H5F_t *f,
}
}
+ /* The metadata journaling message is a variable length message.
+ * This raises the question of how to deal with any pre-existing
+ * message.
+ *
+ * While in theory we could try to re-size it, after looking through
+ * the code and talking to Quincey, it appears that the standard
+ * practice in such cases seems to be to delete the old message,
+ * and then replace it with a new message.
+ *
+ * Add to this the fact that the metadata journaling message
+ * should not exist unless journaling is enabled (or to put it
+ * another way, the message should never appear in a valid HDF5
+ * file).
+ *
+ * Thus, here we check to see if a metadata jouraling message exists,
+ * and delete it if it does. If metadata data journaling is enabled,
+ * we will replace it with a new message shortly.
+ */
+
tri_result = H5O_msg_exists(&ext_loc, H5O_MDJ_MSG_ID, dxpl_id);
if ( tri_result < 0 ) { /* failure */
HGOTO_ERROR(H5E_SYSTEM, H5E_SYSERRSTR, FAIL, \
- "unable to open superblock extension?!?!");
+ "unable to determine if metadata journaling message exists?!?!");
- } else if ( tri_result == 0 ) {
- /* metadata journaling message doesn't exist */
+ } else if ( tri_result == TRUE ) {
- if ( f->shared->mdc_jrnl_enabled ) {
+ /* metadata journaling message exists -- delete it from the
+ * super block extension now. We will replace it later if
+ * metadata journaling is enabled.
+ */
- /* create a metadata journaling message and insert it in
- * the superblock extension.
- */
- mdj_msg.mdc_jrnl_enabled = f->shared->mdc_jrnl_enabled;
- mdj_msg.mdc_jrnl_block_loc = f->shared->mdc_jrnl_block_loc;
- mdj_msg.mdc_jrnl_block_len = f->shared->mdc_jrnl_block_len;
+ result = H5O_msg_remove(&ext_loc,
+ H5O_MDJ_MSG_ID,
+ H5O_ALL,
+ /* the next parameter is the "adj_link" parameter, which is
+ * boolean. Unfortunately, its meaning is not documented
+ * in the code. The value gets stuffed into an instance of
+ * H5O_iter_rm_t, and then passed along somehow to a function
+ * whose address appears to be picked out of a table somewhere.
+ *
+ * The documentation on the adj_link field of H5O_iter_rm_t
+ * simply says that the value specifies "Whether to adjust
+ * links when removing messages" -- but unfortunately, I
+ * don't know what a "link" is in this context.
+ *
+ * Bottom line is that after spending over an hour dredging
+ * through the code, I haven't a clue as to what the value
+ * of this parameter should be. We will set it to FALSE and
+ * see if anything blows up.
+ *
+ * JRM -- 3/5/08
+ */
+ FALSE,
+ dxpl_id);
- result = H5O_msg_create(&ext_loc,
- H5O_MDJ_MSG_ID,
- H5O_MSG_FLAG_DONTSHARE,
- H5O_UPDATE_TIME,
- &mdj_msg,
- dxpl_id);
+ } else if ( tri_result != FALSE ) {
- if ( result < 0 ) {
+ HGOTO_ERROR(H5E_SYSTEM, H5E_SYSERRSTR, FAIL, \
+ "unexpected return value from H5O_msg_exists()");
+ }
- HGOTO_ERROR(H5E_SYSTEM, H5E_SYSERRSTR, FAIL, \
- "unable to add mdj_msg to superblock extension?!?!");
- }
+ if ( f->shared->mdc_jnl_enabled ) {
- } else {
+ /* create a metadata journaling message and insert it in
+ * the superblock extension.
+ */
+ mdj_msg.mdc_jnl_enabled = f->shared->mdc_jnl_enabled;
+ mdj_msg.mdc_jnl_magic = f->shared->mdc_jnl_magic;
+ mdj_msg.mdc_jnl_file_name_len = f->shared->mdc_jnl_file_name_len;
- /* do nothing */
- }
+ if ( f->shared->mdc_jnl_file_name_len == 0 ) {
- } else {
- /* metadata journaling message exists */
-
- if ( f->shared->mdc_jrnl_enabled ) {
-
- /* overwrite the old metadata journaling message with a
- * new one in the superblock extension.
- */
- mdj_msg.mdc_jrnl_enabled = f->shared->mdc_jrnl_enabled;
- mdj_msg.mdc_jrnl_block_loc = f->shared->mdc_jrnl_block_loc;
- mdj_msg.mdc_jrnl_block_len = f->shared->mdc_jrnl_block_len;
-
- result = H5O_msg_write(&ext_loc,
- H5O_MDJ_MSG_ID,
- H5O_MSG_FLAG_DONTSHARE,
- H5O_UPDATE_TIME,
- &mdj_msg,
- dxpl_id);
-
- if ( result < 0 ) {
-
- HGOTO_ERROR(H5E_SYSTEM, H5E_SYSERRSTR, FAIL, \
- "unable to overwrite mdj_msg in superblock extension?!?!");
- }
-
-
- } else {
-
- /* delete the old metadata journaling message from the
- * superblock extension.
- */
-
- result = H5O_msg_remove(&ext_loc,
- H5O_MDJ_MSG_ID,
- H5O_ALL,
- /* the next parameter is the "adj_link" parameter, which is
- * boolean. Unfortunately, its meaning is not documented
- * in the code. The value gets stuffed into an instance of
- * H5O_iter_rm_t, and then passed along somehow to a funcition
- * whose address appears to be picked out of a table somewhere.
- *
- * The documentation on the adj_link field of H5O_iter_rm_t
- * simply says that the value specifies "Whether to adjust
- * links when removing messages" -- but unfortunately, I
- * don't know what a "link" is in this context.
- *
- * Bottom line is that after spending over an hour dredging
- * through the code, I haven't a clue as to what the value
- * of this parameter should be. We will set it to FALSE and
- * see if anything blows up.
- *
- * JRM -- 3/5/08
- */
- FALSE,
- dxpl_id);
- }
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, \
+ "journaling enabled, but journal file path empty?!?")
- }
+ }
+
+ if ( f->shared->mdc_jnl_file_name_len >
+ H5C2__MAX_JOURNAL_FILE_NAME_LEN ) {
+
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, \
+ "journal file path too long?!?")
+
+ }
+
+ HDstrncpy(mdj_msg.mdc_jnl_file_name,
+ f->shared->mdc_jnl_file_name,
+ f->shared->mdc_jnl_file_name_len + 1);
+
+ if ( ( (mdj_msg.mdc_jnl_file_name)[mdj_msg.mdc_jnl_file_name_len]
+ != '\0' ) ||
+ ( HDstrlen(mdj_msg.mdc_jnl_file_name) !=
+ mdj_msg.mdc_jnl_file_name_len ) ) {
+
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, \
+ "bad journal file path and/or path len???")
+ }
+
+ result = H5O_msg_create(&ext_loc,
+ H5O_MDJ_MSG_ID,
+ H5O_MSG_FLAG_DONTSHARE,
+ H5O_UPDATE_TIME,
+ &mdj_msg,
+ dxpl_id);
+
+ if ( result < 0 ) {
+
+ HGOTO_ERROR(H5E_SYSTEM, H5E_SYSERRSTR, FAIL, \
+ "unable to add mdj_msg to superblock extension?!?!");
+ }
+
+ }
/* Close the extension. Twiddle the number of open objects to avoid
* closing the file (since this may be the only open object).
*/
+
f->nopen_objs++;
+
if(H5O_close(&ext_loc) < 0) {
HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENFILE, FAIL,
"unable to close superblock extension")
}
+
f->nopen_objs--;
done:
diff --git a/src/H5Ochunk.c b/src/H5Ochunk.c
index 634c628..813006e 100644
--- a/src/H5Ochunk.c
+++ b/src/H5Ochunk.c
@@ -234,8 +234,10 @@ H5O_chunk_unprotect(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5O_chunk_proxy_t *chk_p
HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, FAIL, "unable to mark object header as dirty")
} /* end else/if */
else
+ {
/* Sanity check */
HDassert(0 && "Unknown chunk proxy flag(s)?!?");
+ }
/* Free fake chunk proxy */
H5FL_FREE(H5O_chunk_proxy_t, chk_proxy);
diff --git a/src/H5Omdj_msg.c b/src/H5Omdj_msg.c
index 044ce4a..6ba1774 100644
--- a/src/H5Omdj_msg.c
+++ b/src/H5Omdj_msg.c
@@ -20,29 +20,34 @@
* John Mainzer
*
* Purpose: A message detailing whether metadata jouraling is enabled,
- * and if so, the base address in file and length of the block
- * that contains the journaling configuration data.
+ * and if so, the journal file magic and journal file path.
+ *
+ * Note that the size of this message is variable.
*
* The mdj_msg only appears in the superblock extension.
*
* Modifications:
*
- * None.
+ * Re-worked message to include the journal file name and
+ * magic, instead of simply containing a pointer to a
+ * journal configuration block containing this data.
*
*-------------------------------------------------------------------------
*/
-#define H5O_PACKAGE /*suppress error about including H5Opkg */
+#define H5O_PACKAGE /* suppress error about including H5Opkg */
-#include "H5private.h" /* Generic Functions */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5Opkg.h" /* Object headers */
-#include "H5MMprivate.h" /* Memory management */
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Opkg.h" /* Object headers */
+#include "H5MMprivate.h" /* Memory management */
-#define MDJ_MSG_LEN(f) ( 1 + /* Version number */ \
- 2 + /* flags */ \
- H5F_SIZEOF_ADDR(f) + /* addr of journal config block */ \
- H5F_SIZEOF_SIZE(f) ) /* journal config block len */
+#define MDJ_MSG_LEN(f, pathlen) \
+ ( 1 + /* Version number */ \
+ 2 + /* flags */ \
+ 4 + /* magic -- sizeof(int32_t) */ \
+ 4 + /* jnl file path len - sizeof(int32_t) */ \
+ pathlen + 1 ) /* jnl file path */
static void * H5O_mdj_msg_decode(H5F_t UNUSED *f,
hid_t UNUSED dxpl_id,
@@ -95,12 +100,6 @@ const H5O_msg_class_t H5O_MSG_MDJ_CONF[1] = {{
H5O_mdj_msg_debug /* debug the message */
}};
-
-/* Current version of the metadata journaling configuration information */
-#define H5O_MDJ_CONF_VERSION 0
-
-#define MDJ_MSG__JOURNALING_ENABLED_FLAG 0x0001
-
/*-------------------------------------------------------------------------
* Function: H5O_mdj_msg_decode
@@ -123,8 +122,12 @@ H5O_mdj_msg_decode(H5F_t *f,
unsigned UNUSED mesg_flags,
const uint8_t *p)
{
+ char ch;
uint16_t flags = 0; /* packed boolean fields */
- H5O_mdj_msg_t *mesg; /* Native message */
+ int i;
+ int32_t journal_magic; /* magic number -- if defined */
+ int32_t path_len; /* journal file path length */
+ H5O_mdj_msg_t *mesg; /* Native message */
void *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_mdj_msg_decode)
@@ -142,7 +145,8 @@ H5O_mdj_msg_decode(H5F_t *f,
/* Allocate space for message */
- if( NULL == ( mesg = H5MM_calloc(sizeof(H5O_mdj_msg_t)))) {
+ if ( NULL ==
+ (mesg = (H5O_mdj_msg_t *)H5MM_calloc(sizeof(H5O_mdj_msg_t))) ) {
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, \
"memory allocation failed for metadata journaling message.");
@@ -154,21 +158,51 @@ H5O_mdj_msg_decode(H5F_t *f,
if ( (flags & MDJ_MSG__JOURNALING_ENABLED_FLAG) != 0 ) {
- mesg->mdc_jrnl_enabled = TRUE;
+ mesg->mdc_jnl_enabled = TRUE;
} else {
- mesg->mdc_jrnl_enabled = FALSE;
+ mesg->mdc_jnl_enabled = FALSE;
+
+ }
+
+
+ /* get the journal file magic number */
+ INT32DECODE(p, journal_magic);
+
+ mesg->mdc_jnl_magic = journal_magic;
+
+
+ /* get the journal file path length */
+ INT32DECODE(p, path_len);
+
+ if ( path_len > H5C2__MAX_JOURNAL_FILE_NAME_LEN ) {
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "path length too big.")
}
- /* retrieve the journal block location */
+ mesg->mdc_jnl_file_name_len = (size_t)path_len;
- H5F_addr_decode(f, &p, &(mesg->mdc_jrnl_block_loc));
- /* retrieve the journal block length */
+ /* copy out the journal file path -- check length in passing.
+ *
+ * we could probably do this faster with a memcpy(), but this
+ * operation happens very infrequently, and doing it this way
+ * adds a bit of sanity checking.
+ */
+ i = 0;
+ do {
- H5F_DECODE_LENGTH(f, p, mesg->mdc_jrnl_block_len);
+ ch = (char)(*p++);
+ mesg->mdc_jnl_file_name[i++] = ch;
+
+ } while ( ( ch != '\0' ) && ( i <= path_len ) );
+
+ if ( ( ch != '\0' ) || ( i != path_len + 1 ) ) {
+
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, \
+ "bad path and/or path len")
+ }
/* Set return value */
ret_value = (void *)mesg;
@@ -201,6 +235,8 @@ H5O_mdj_msg_encode(H5F_t *f,
{
const H5O_mdj_msg_t *mesg = (const H5O_mdj_msg_t *)_mesg;
uint16_t flags = 0;
+ int32_t magic;
+ int32_t path_len;
herr_t ret_value;
FUNC_ENTER_NOAPI_NOINIT(H5O_mdj_msg_encode)
@@ -210,28 +246,40 @@ H5O_mdj_msg_encode(H5F_t *f,
HDassert(p);
HDassert(mesg);
- /* this error check exists to keep the compiler happy */
if ( ( f == NULL ) || ( p == NULL ) || ( mesg == NULL ) ) {
HGOTO_ERROR(H5E_SYSTEM, H5E_SYSERRSTR, FAIL, "Bad params on entry.");
}
+ if ( mesg->mdc_jnl_file_name_len > H5C2__MAX_JOURNAL_FILE_NAME_LEN ) {
+
+ HGOTO_ERROR(H5E_SYSTEM, H5E_SYSERRSTR, FAIL, \
+ "Bad params on entry -- path len too long.");
+ }
+
/* setup the flags */
- if ( mesg->mdc_jrnl_enabled ) {
+ if ( mesg->mdc_jnl_enabled ) {
flags |= MDJ_MSG__JOURNALING_ENABLED_FLAG;
}
- /* Store version, flags, internal_loc, path_len, & path buffer */
+ magic = mesg->mdc_jnl_magic;
+
+ path_len = (int32_t)(mesg->mdc_jnl_file_name_len);
+
+ /* Store version, flags, magic, path_len, & path */
*p++ = H5O_MDJ_CONF_VERSION;
UINT16ENCODE(p, flags);
- H5F_addr_encode(f, &p, mesg->mdc_jrnl_block_loc);
-
- H5F_ENCODE_LENGTH(f, p, mesg->mdc_jrnl_block_len);
+ INT32ENCODE(p, magic);
+
+ INT32ENCODE(p, path_len);
+
+ HDmemcpy(p, mesg->mdc_jnl_file_name, path_len + 1);
+ p += path_len + 1;
done:
@@ -267,6 +315,11 @@ H5O_mdj_msg_copy(const void *_mesg, void *_dest)
/* Sanity check */
HDassert(mesg);
+ if ( mesg->mdc_jnl_file_name_len > H5C2__MAX_JOURNAL_FILE_NAME_LEN ) {
+
+ HGOTO_ERROR(H5E_SYSTEM, H5E_SYSERRSTR, FAIL, "path len too long.");
+ }
+
if ( ( ! dest ) &&
( NULL == (dest = H5MM_malloc(sizeof(H5O_mdj_msg_t))) ) ) {
@@ -276,9 +329,41 @@ H5O_mdj_msg_copy(const void *_mesg, void *_dest)
}
/* now copy the message */
- dest->mdc_jrnl_enabled = mesg->mdc_jrnl_enabled;
- dest->mdc_jrnl_block_loc = mesg->mdc_jrnl_block_loc;
- dest->mdc_jrnl_block_len = mesg->mdc_jrnl_block_len;
+ dest->mdc_jnl_enabled = mesg->mdc_jnl_enabled;
+ dest->mdc_jnl_magic = mesg->mdc_jnl_magic;
+ dest->mdc_jnl_file_name_len = mesg->mdc_jnl_file_name_len;
+
+ /* copy the journal file path -- check length in passing.
+ *
+ * we could probably do this faster with a memcpy(), but this
+ * operation happens very infrequently, and doing it this way
+ * adds a bit of sanity checking.
+ */
+ if ( mesg->mdc_jnl_file_name_len == 0 ) {
+
+ (dest->mdc_jnl_file_name)[0] = '\0';
+
+ } else {
+
+ char ch;
+ int i = 0;
+ size_t path_len;
+
+ path_len = mesg->mdc_jnl_file_name_len;
+
+ do {
+
+ ch = (mesg->mdc_jnl_file_name)[i];
+ (dest->mdc_jnl_file_name)[i++] = ch;
+
+ } while ( ( ch != '\0' ) && ( i <= path_len ) );
+
+ if ( ( ch != '\0' ) || ( i != path_len + 1 ) ) {
+
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, \
+ "bad path and/or path len???")
+ }
+ }
/* Set return value */
ret_value = dest;
@@ -314,10 +399,12 @@ H5O_mdj_msg_size(const H5F_t *f,
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_mdj_msg_size)
/* Sanity check */
- HDassert(f);
- HDassert(mesg);
+ HDassert( f );
+ HDassert( mesg );
+ HDassert( mesg->mdc_jnl_file_name_len >= 0 );
+
+ FUNC_LEAVE_NOAPI(MDJ_MSG_LEN(f, mesg->mdc_jnl_file_name_len))
- FUNC_LEAVE_NOAPI(MDJ_MSG_LEN(f))
} /* end H5O_mdj_msg_size() */
@@ -348,11 +435,13 @@ H5O_mdj_msg_reset(void *_mesg)
HDassert(mesg);
/* reset */
- mesg->mdc_jrnl_enabled = FALSE;
- mesg->mdc_jrnl_block_loc = HADDR_UNDEF;
- mesg->mdc_jrnl_block_len = 0;
+ mesg->mdc_jnl_enabled = FALSE;
+ mesg->mdc_jnl_magic = 0;
+ mesg->mdc_jnl_file_name_len = 0;
+ (mesg->mdc_jnl_file_name)[0] = '\0';
FUNC_LEAVE_NOAPI(SUCCEED)
+
} /* H5O_mdj_msg_reset() */
@@ -389,17 +478,22 @@ H5O_mdj_msg_debug(H5F_t UNUSED *f,
HDassert(fwidth >= 0);
HDfprintf(stream, "%*s%-*s %d\n", indent, "", fwidth,
- "mdc_jrnl_enabled:",
- (int)(mesg->mdc_jrnl_enabled));
+ "mdc_jnl_enabled:",
+ (int)(mesg->mdc_jnl_enabled));
- HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
- "mdc_jrnl_bloc_loc:",
- mesg->mdc_jrnl_block_loc);
+ HDfprintf(stream, "%*s%-*s %d\n", indent, "", fwidth,
+ "mdc_jnl_magic:",
+ (int)(mesg->mdc_jnl_magic));
HDfprintf(stream, "%*s%-*s %d\n", indent, "", fwidth,
- "mdc_jrnl_block_len:",
- (int)(mesg->mdc_jrnl_block_len));
+ "mdc_jnl_file_name_len:",
+ (int)(mesg->mdc_jnl_file_name_len));
+
+ HDfprintf(stream, "%*s%-*s \"%s\"\n", indent, "", fwidth,
+ "mdc_jnl_file_name:",
+ (char *)(mesg->mdc_jnl_file_name));
FUNC_LEAVE_NOAPI(SUCCEED)
+
} /* end H5O_mdj_msg_debug() */
diff --git a/src/H5Omessage.c b/src/H5Omessage.c
index 3c29c24..9bfe756 100644
--- a/src/H5Omessage.c
+++ b/src/H5Omessage.c
@@ -2012,15 +2012,22 @@ H5O_copy_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx,
HDassert(mesg);
/* Protect chunk */
- if(NULL == (chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, idx_msg->chunkno)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
+ if ( NULL ==
+ (chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, idx_msg->chunkno)) ) {
+
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, \
+ "unable to load object header chunk")
+ }
/* Reset existing native information for the header's message */
H5O_msg_reset_real(type, idx_msg->native);
/* Copy the native object for the message */
- if(NULL == (idx_msg->native = (type->copy)(mesg, idx_msg->native)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy message to object header")
+ if ( NULL == (idx_msg->native = (type->copy)(mesg, idx_msg->native)) ) {
+
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, \
+ "unable to copy message to object header")
+ }
/* Update the message flags */
idx_msg->flags = mesg_flags;
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 2b3710c..4cac29d 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -509,30 +509,44 @@ typedef uint32_t H5O_refcount_t; /* Contains # of links to object, if >1
/*
* Metadata journaling message
*
- * Information on whether are being journaled, and if so, the size and
- * location of the on disk block containing the deatils of the journaling.
+ * Information on whether are being journaled, and if so, the magic
+ * number (if defined) and path to the journal file.
* (Data structure in memory)
*
* The fields of the H5O_mdj_msg_t structure are discussed individually
* below:
*
- * mdc_jrnl_enabled: Boolean flag indicating whether metadata journaling
+ * mdc_jnl_enabled: Boolean flag indicating whether metadata journaling
* is currently enabled.
*
- * mdc_jrnl_block_loc: haddr_t containing the base address of the
- * of the block containing the configuration details of the
- * journaling.
+ * mdc_jnl_magic: Randomly selected int32_t used to reduce the possibility
+ * of running the wrong journal on an HDF5 file. The basic idea is
+ * to pick a random number, store it in both the HDF5 file and the
+ * journal file, and then refuse to run the journal unless the numbers
+ * match.
*
- * mdc_jrnl_block_len: hsize_t containing the size of the buffer needed to
- * contain the journaling configuration block
+ * The value of this field is undefined unless mdc_jnl_enabled is TRUE.
*
- * If the journal is internal, this field must be NULL.
+ * mdc_jnl_file_name_len: Length of the journal file name.
+ *
+ * The value of this field is undefined unless mdc_jnl_enabled is TRUE.
+ *
+ * mdc_jnl_file_name: Array of char of length
+ * H5C2__MAX_JOURNAL_FILE_NAME_LEN + 1 used to store the journal
+ * file path.
+ *
+ * The value of this field is undefined unless mdc_jnl_enabled is TRUE.
*/
+
+#define H5O_MDJ_CONF_VERSION 0
+#define MDJ_MSG__JOURNALING_ENABLED_FLAG 0x0001
+
typedef struct H5O_mdj_msg_t {
- hbool_t mdc_jrnl_enabled;
- haddr_t mdc_jrnl_block_loc;
- hsize_t mdc_jrnl_block_len;
+ hbool_t mdc_jnl_enabled;
+ int32_t mdc_jnl_magic;
+ size_t mdc_jnl_file_name_len;
+ char mdc_jnl_file_name[H5C2__MAX_JOURNAL_FILE_NAME_LEN + 1];
} H5O_mdj_msg_t;