summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVailin Choi <vchoi@hdfgroup.org>2013-06-26 20:35:42 (GMT)
committerVailin Choi <vchoi@hdfgroup.org>2013-06-26 20:35:42 (GMT)
commit5845fed5cb1dad347d71ccd2a7c9091ffaccff0a (patch)
tree796fe4a86905b9dd8a8cc7d8e1990a6ce26378b7 /src
parentd9517c14af7bc68bd093b14eb8eeaab87d1ea80e (diff)
downloadhdf5-5845fed5cb1dad347d71ccd2a7c9091ffaccff0a.zip
hdf5-5845fed5cb1dad347d71ccd2a7c9091ffaccff0a.tar.gz
hdf5-5845fed5cb1dad347d71ccd2a7c9091ffaccff0a.tar.bz2
[svn-r23828] Fix 2 bugs for SWMR access:
1) H5O_load() in H5Ocache.c: when reading a block that is > spec_read siez, read the whole block in again and possibly decode the header. 2) H5F_accum_write() in H5Faccum.c: for a large write that is >= H5F_ACCUM_MAX_SIZE, flush the metadata in the accumulator first before the write. Tests are added to test/ohdr.c and test/accum.c. h5committested.
Diffstat (limited to 'src')
-rw-r--r--src/H5Faccum.c11
-rw-r--r--src/H5Ocache.c196
2 files changed, 137 insertions, 70 deletions
diff --git a/src/H5Faccum.c b/src/H5Faccum.c
index 0e549fa..529384b 100644
--- a/src/H5Faccum.c
+++ b/src/H5Faccum.c
@@ -413,6 +413,11 @@ done:
* koziol@hdfgroup.org
* Jan 10 2008
*
+ * Modifications:
+ * Vailin Choi; June 2013
+ * This is a fix for SWMR:
+ * For a large write that is >= than H5F_ACCUM_MAX_SIZE,
+ * flush the metadata in the accumulator first before the write.
*-------------------------------------------------------------------------
*/
herr_t
@@ -726,6 +731,12 @@ HDmemset(f->shared->accum.buf + size, 0, (f->shared->accum.alloc_size - size));
} /* end else */
} /* end if */
else {
+ if((f->intent & H5F_ACC_SWMR_WRITE) > 0) {
+ /* Flush if dirty and reset accumulator */
+ if(H5F_accum_reset(f, dxpl_id, TRUE) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTRESET, FAIL, "can't reset accumulator")
+ }
+
/* Write the data */
if(H5FD_write(f->shared->lf, dxpl_id, map_type, addr, size, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
diff --git a/src/H5Ocache.c b/src/H5Ocache.c
index 856a5bc..80f5c05 100644
--- a/src/H5Ocache.c
+++ b/src/H5Ocache.c
@@ -93,6 +93,8 @@ static herr_t H5O_chunk_serialize(const H5F_t *f, H5O_t *oh, unsigned chunkno);
static herr_t H5O_add_cont_msg(H5O_cont_msgs_t *cont_msg_info,
const H5O_cont_t *cont);
+static herr_t H5O_decode_prefix(H5F_t *f, H5O_t *oh, const uint8_t *buf, void *_udata);
+
/*********************/
/* Package Variables */
@@ -139,76 +141,34 @@ H5FL_SEQ_DEFINE(H5O_cont_t);
/* Local Variables */
/*******************/
-
/*-------------------------------------------------------------------------
- * Function: H5O_load
+ * Function: H5O_decode_prefix
*
- * Purpose: Loads an object header from disk.
+ * Purpose: To decode the object header prefix.
+ * The coding is extracted fromt H5O_load() to this routine.
*
- * Return: Success: Pointer to the new object header.
+ * Return: Non-negative on success/Negative on failure
*
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Aug 5 1997
+ * Programmer: Vailin Choi; June 2013
*
*-------------------------------------------------------------------------
*/
-static H5O_t *
-H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
+static herr_t
+H5O_decode_prefix(H5F_t *f, H5O_t *oh, const uint8_t *buf, void *_udata)
{
- H5O_t *oh = NULL; /* Object header read in */
H5O_cache_ud_t *udata = (H5O_cache_ud_t *)_udata; /* User data for callback */
- H5WB_t *wb = NULL; /* Wrapped buffer for prefix data */
- uint8_t read_buf[H5O_SPEC_READ_SIZE]; /* Buffer for speculative read */
- const uint8_t *p; /* Pointer into buffer to decode */
- uint8_t *buf; /* Buffer to decode */
- size_t spec_read_size; /* Size of buffer to speculatively read in */
- size_t prefix_size; /* Size of object header prefix */
- size_t buf_size; /* Size of prefix+chunk #0 buffer */
- haddr_t eoa; /* Relative end of file address */
- H5O_t *ret_value; /* Return value */
+ const uint8_t *p = buf; /* Pointer into buffer to decode */
+ size_t prefix_size; /* Size of object header prefix */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
/* Check arguments */
HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ HDassert(oh);
+ HDassert(buf);
HDassert(udata);
- HDassert(udata->common.f);
- HDassert(udata->common.cont_msg_info);
-
- /* Make certain we don't speculatively read off the end of the file */
- if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_OHDR)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to determine file size")
-
- /* Compute the size of the speculative object header buffer */
- H5_ASSIGN_OVERFLOW(spec_read_size, MIN(eoa - addr, H5O_SPEC_READ_SIZE), /* From: */ hsize_t, /* To: */ size_t);
-
- /* Attempt to speculatively read both object header prefix and first chunk */
- if(H5F_block_read(f, H5FD_MEM_OHDR, addr, spec_read_size, dxpl_id, read_buf) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header")
- p = read_buf;
-
- /* Allocate space for the object header data structure */
- if(NULL == (oh = H5FL_CALLOC(H5O_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- /* File-specific, non-stored information */
- oh->sizeof_size = H5F_SIZEOF_SIZE(udata->common.f);
- oh->sizeof_addr = H5F_SIZEOF_ADDR(udata->common.f);
- oh->swmr_write = !!(H5F_INTENT(udata->common.f) & H5F_ACC_SWMR_WRITE);
-
- /* Create object header proxy if doing SWMR writes */
- HDassert(!oh->proxy_present);
- if(H5F_INTENT(f) & H5F_ACC_SWMR_WRITE) {
- if(H5O_proxy_create(f, dxpl_id, oh) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, NULL, "can't create object header proxy")
- } /* end if */
- else
- oh->proxy_addr = HADDR_UNDEF;
/* Check for presence of magic number */
/* (indicates version 2 or later) */
@@ -219,12 +179,12 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
/* Version */
oh->version = *p++;
if(H5O_VERSION_2 != oh->version)
- HGOTO_ERROR(H5E_OHDR, H5E_VERSION, NULL, "bad object header version number")
+ HGOTO_ERROR(H5E_OHDR, H5E_VERSION, FAIL, "bad object header version number")
/* Flags */
oh->flags = *p++;
if(oh->flags & ~H5O_HDR_ALL_FLAGS)
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "unknown object header status flag(s)")
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unknown object header status flag(s)")
/* Number of links to object (unless overridden by refcount message) */
oh->nlink = 1;
@@ -250,7 +210,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
UINT16DECODE(p, oh->max_compact);
UINT16DECODE(p, oh->min_dense);
if(oh->max_compact < oh->min_dense)
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad object header attribute phase change values")
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad object header attribute phase change values")
} /* end if */
else {
oh->max_compact = H5O_CRT_ATTR_MAX_COMPACT_DEF;
@@ -276,16 +236,16 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
break;
default:
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad size for chunk 0")
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad size for chunk 0")
} /* end switch */
if(oh->chunk0_size > 0 && oh->chunk0_size < H5O_SIZEOF_MSGHDR_OH(oh))
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad object header chunk size")
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad object header chunk size")
} /* end if */
else {
/* Version */
oh->version = *p++;
if(H5O_VERSION_1 != oh->version)
- HGOTO_ERROR(H5E_OHDR, H5E_VERSION, NULL, "bad object header version number")
+ HGOTO_ERROR(H5E_OHDR, H5E_VERSION, FAIL, "bad object header version number")
/* Flags */
oh->flags = H5O_CRT_OHDR_FLAGS_DEF;
@@ -310,16 +270,100 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
UINT32DECODE(p, oh->chunk0_size);
if((udata->v1_pfx_nmesgs > 0 && oh->chunk0_size < H5O_SIZEOF_MSGHDR_OH(oh)) ||
(udata->v1_pfx_nmesgs == 0 && oh->chunk0_size > 0))
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad object header chunk size")
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad object header chunk size")
/* Reserved, in version 1 (for 8-byte alignment padding) */
p += 4;
} /* end else */
/* Determine object header prefix length */
- prefix_size = (size_t)(p - (const uint8_t *)read_buf);
+ prefix_size = (size_t)(p - buf);
HDassert((size_t)prefix_size == (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh)));
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5O_decode_prefix() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_load
+ *
+ * Purpose: Loads an object header from disk.
+ *
+ * Return: Success: Pointer to the new object header.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Aug 5 1997
+ *
+ * Modifications:
+ * Vailin Choi; June 2013
+ * This is a fix for SWMR:
+ * When reading a block that is > spec_read_size, read the whole block in
+ * again and possibly decode the header.
+ * Move the coding for decoding the object header prefix to another routine
+ * H5O_decode_prefix().
+ *-------------------------------------------------------------------------
+ */
+static H5O_t *
+H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
+{
+ H5O_t *oh = NULL; /* Object header read in */
+ H5O_cache_ud_t *udata = (H5O_cache_ud_t *)_udata; /* User data for callback */
+ H5WB_t *wb = NULL; /* Wrapped buffer for prefix data */
+ uint8_t read_buf[H5O_SPEC_READ_SIZE]; /* Buffer for speculative read */
+ const uint8_t *p; /* Pointer into buffer to decode */
+ uint8_t *buf; /* Buffer to decode */
+ size_t spec_read_size; /* Size of buffer to speculatively read in */
+ size_t buf_size; /* Size of prefix+chunk #0 buffer */
+ haddr_t eoa; /* Relative end of file address */
+ H5O_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(udata);
+ HDassert(udata->common.f);
+ HDassert(udata->common.cont_msg_info);
+
+ /* Make certain we don't speculatively read off the end of the file */
+ if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_OHDR)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to determine file size")
+
+ /* Compute the size of the speculative object header buffer */
+ H5_ASSIGN_OVERFLOW(spec_read_size, MIN(eoa - addr, H5O_SPEC_READ_SIZE), /* From: */ hsize_t, /* To: */ size_t);
+
+ /* Attempt to speculatively read both object header prefix and first chunk */
+ if(H5F_block_read(f, H5FD_MEM_OHDR, addr, spec_read_size, dxpl_id, read_buf) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header")
+ p = read_buf;
+
+ /* Allocate space for the object header data structure */
+ if(NULL == (oh = H5FL_CALLOC(H5O_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* File-specific, non-stored information */
+ oh->sizeof_size = H5F_SIZEOF_SIZE(udata->common.f);
+ oh->sizeof_addr = H5F_SIZEOF_ADDR(udata->common.f);
+ oh->swmr_write = !!(H5F_INTENT(udata->common.f) & H5F_ACC_SWMR_WRITE);
+
+ /* Create object header proxy if doing SWMR writes */
+ HDassert(!oh->proxy_present);
+ if(H5F_INTENT(f) & H5F_ACC_SWMR_WRITE) {
+ if(H5O_proxy_create(f, dxpl_id, oh) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, NULL, "can't create object header proxy")
+ } /* end if */
+ else
+ oh->proxy_addr = HADDR_UNDEF;
+
+ if(H5O_decode_prefix(f, oh, read_buf, udata) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't decode object header prefix")
+
/* Compute the size of the buffer used */
buf_size = oh->chunk0_size + (size_t)H5O_SIZEOF_HDR(oh);
@@ -333,14 +377,26 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
if(NULL == (buf = (uint8_t *)H5WB_actual(wb, buf_size)))
HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "can't get actual buffer")
- /* Copy existing raw data into new buffer */
- HDmemcpy(buf, read_buf, spec_read_size);
-
- /* Read rest of the raw data */
- if(H5F_block_read(f, H5FD_MEM_OHDR, (addr + spec_read_size), (buf_size - spec_read_size), dxpl_id, (buf + spec_read_size)) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header data")
- } /* end if */
- else
+ /* SWMR access */
+ if(H5F_INTENT(f) & H5F_ACC_SWMR_READ || H5F_INTENT(f) & H5F_ACC_SWMR_WRITE) {
+ /* Read the chunk that is bigger than the speculative read size */
+ if(H5F_block_read(f, H5FD_MEM_OHDR, addr, buf_size, dxpl_id, buf) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header")
+ /* See if the data read now is the same as what is read initially */
+ if(HDmemcmp(buf, read_buf, spec_read_size)) {
+ HDmemset(oh, 0, sizeof(oh));
+ if(H5O_decode_prefix(f, oh, buf, udata) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't decode object header prefix")
+ }
+ } else {
+ /* Copy existing raw data into new buffer */
+ HDmemcpy(buf, read_buf, spec_read_size);
+
+ /* Read rest of the raw data */
+ if(H5F_block_read(f, H5FD_MEM_OHDR, (addr + spec_read_size), (buf_size - spec_read_size), dxpl_id, (buf + spec_read_size)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header data")
+ }
+ } else
buf = read_buf;
/* Parse the first chunk */