summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike McGreevy <mamcgree@hdfgroup.org>2010-10-15 19:16:41 (GMT)
committerMike McGreevy <mamcgree@hdfgroup.org>2010-10-15 19:16:41 (GMT)
commitc002883bcc008a4274433ed8e8275669c09dcfe6 (patch)
treec2290aca7bed508bd952eb29ef04fb0adc9642f2
parent9f6fb53aa6941dbc67e40f47c8e27a12255cd123 (diff)
downloadhdf5-c002883bcc008a4274433ed8e8275669c09dcfe6.zip
hdf5-c002883bcc008a4274433ed8e8275669c09dcfe6.tar.gz
hdf5-c002883bcc008a4274433ed8e8275669c09dcfe6.tar.bz2
[svn-r19617] Purpose:
Merge accum_tests branch back to the trunk. Description: Changes consist of addition of tests for H5Faccum.c source code, as well as some fixes that address some discovered bugs in the metadata accumulator on several corner cases. Tested: h5committested
-rw-r--r--MANIFEST1
-rwxr-xr-xconfigure2
-rw-r--r--src/H5F.c2
-rw-r--r--src/H5Faccum.c721
-rw-r--r--src/H5Fio.c24
-rw-r--r--src/H5Fpkg.h8
-rw-r--r--test/CMakeLists.txt1
-rw-r--r--test/Makefile.am6
-rw-r--r--test/Makefile.in67
-rw-r--r--test/accum.c1809
10 files changed, 2290 insertions, 351 deletions
diff --git a/MANIFEST b/MANIFEST
index 5f8434f..f90202c 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -806,6 +806,7 @@
./test/H5srcdir_str.h.in
./test/Makefile.am
./test/Makefile.in
+./test/accum.c
./test/app_ref.c
./test/be_data.h5
./test/be_extlink1.h5
diff --git a/configure b/configure
index 9ff7efe..6a0954b 100755
--- a/configure
+++ b/configure
@@ -1,5 +1,5 @@
#! /bin/sh
-# From configure.in Id: configure.in 19512 2010-10-05 13:37:04Z hdftest .
+# From configure.in Id: configure.in 19578 2010-10-11 22:15:54Z songyulu .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.67 for HDF5 1.9.77.
#
diff --git a/src/H5F.c b/src/H5F.c
index ebd3b78..46d9407 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -1048,7 +1048,7 @@ H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush)
} /* end if */
/* Destroy other components of the file */
- if(H5F_accum_reset(f, dxpl_id) < 0)
+ if(H5F_accum_reset(f, dxpl_id, TRUE) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
if(H5FO_dest(f) < 0)
diff --git a/src/H5Faccum.c b/src/H5Faccum.c
index 600c3f3..6c9eb67 100644
--- a/src/H5Faccum.c
+++ b/src/H5Faccum.c
@@ -111,11 +111,11 @@ H5FL_BLK_DEFINE_STATIC(meta_accum);
*
*-------------------------------------------------------------------------
*/
-htri_t
+herr_t
H5F_accum_read(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
size_t size, void *buf/*out*/)
{
- htri_t ret_value = FALSE; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5F_accum_read, FAIL)
@@ -124,90 +124,135 @@ H5F_accum_read(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
HDassert(buf);
/* Check if this information is in the metadata accumulator */
- if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && type != H5FD_MEM_DRAW
- && size < H5F_ACCUM_MAX_SIZE) {
- /* Sanity check */
- HDassert(!f->shared->accum.buf || (f->shared->accum.alloc_size >= f->shared->accum.size));
-
- /* Current read adjoins or overlaps with metadata accumulator */
- if(H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size)
- || ((addr + size) == f->shared->accum.loc)
- || (f->shared->accum.loc + f->shared->accum.size) == addr) {
- size_t amount_before; /* Amount to read before current accumulator */
- haddr_t new_addr; /* New address of the accumulator buffer */
- size_t new_size; /* New size of the accumulator buffer */
-
- /* Compute new values for accumulator */
- new_addr = MIN(addr, f->shared->accum.loc);
- new_size = (size_t)(MAX((addr + size), (f->shared->accum.loc + f->shared->accum.size))
- - new_addr);
-
- /* Check if we need more buffer space */
- if(new_size > f->shared->accum.alloc_size) {
- size_t new_alloc_size; /* New size of accumulator */
-
- /* Adjust the buffer size to be a power of 2 that is large enough to hold data */
- new_alloc_size = (size_t)1 << (1 + H5V_log2_gen((uint64_t)(new_size - 1)));
-
- /* Reallocate the metadata accumulator buffer */
- if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, new_alloc_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-
- /* Note the new buffer size */
- f->shared->accum.alloc_size = new_alloc_size;
+ if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && type != H5FD_MEM_DRAW) {
+ if(size < H5F_ACCUM_MAX_SIZE) {
+ /* Sanity check */
+ HDassert(!f->shared->accum.buf || (f->shared->accum.alloc_size >= f->shared->accum.size));
+
+ /* Current read adjoins or overlaps with metadata accumulator */
+ if(H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size)
+ || ((addr + size) == f->shared->accum.loc)
+ || (f->shared->accum.loc + f->shared->accum.size) == addr) {
+ size_t amount_before; /* Amount to read before current accumulator */
+ haddr_t new_addr; /* New address of the accumulator buffer */
+ size_t new_size; /* New size of the accumulator buffer */
+
+ /* Compute new values for accumulator */
+ new_addr = MIN(addr, f->shared->accum.loc);
+ new_size = (size_t)(MAX((addr + size), (f->shared->accum.loc + f->shared->accum.size))
+ - new_addr);
+
+ /* Check if we need more buffer space */
+ if(new_size > f->shared->accum.alloc_size) {
+ size_t new_alloc_size; /* New size of accumulator */
+
+ /* Adjust the buffer size to be a power of 2 that is large enough to hold data */
+ new_alloc_size = (size_t)1 << (1 + H5V_log2_gen((uint64_t)(new_size - 1)));
+
+ /* Reallocate the metadata accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, new_alloc_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+
+ /* Note the new buffer size */
+ f->shared->accum.alloc_size = new_alloc_size;
#ifdef H5_CLEAR_MEMORY
-HDmemset(f->shared->accum.buf + f->shared->accum.size, 0, (f->shared->accum.alloc_size - f->shared->accum.size));
+ HDmemset(f->shared->accum.buf + f->shared->accum.size, 0, (f->shared->accum.alloc_size - f->shared->accum.size));
#endif /* H5_CLEAR_MEMORY */
- } /* end if */
+ } /* end if */
- /* Read the part before the metadata accumulator */
- if(addr < f->shared->accum.loc) {
- /* Set the amount to read */
- H5_ASSIGN_OVERFLOW(amount_before, (f->shared->accum.loc - addr), hsize_t, size_t);
+ /* Read the part before the metadata accumulator */
+ if(addr < f->shared->accum.loc) {
+ /* Set the amount to read */
+ H5_ASSIGN_OVERFLOW(amount_before, (f->shared->accum.loc - addr), hsize_t, size_t);
- /* Make room for the metadata to read in */
- HDmemmove(f->shared->accum.buf + amount_before, f->shared->accum.buf, f->shared->accum.size);
+ /* Make room for the metadata to read in */
+ HDmemmove(f->shared->accum.buf + amount_before, f->shared->accum.buf, f->shared->accum.size);
- /* Adjust dirty region tracking info, if present */
- if(f->shared->accum.dirty)
- f->shared->accum.dirty_off += amount_before;
+ /* Adjust dirty region tracking info, if present */
+ if(f->shared->accum.dirty)
+ f->shared->accum.dirty_off += amount_before;
- /* Dispatch to driver */
- if(H5FD_read(f->shared->lf, dxpl_id, type, addr, amount_before, f->shared->accum.buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
- } /* end if */
- else
- amount_before = 0;
+ /* Dispatch to driver */
+ if(H5FD_read(f->shared->lf, dxpl_id, type, addr, amount_before, f->shared->accum.buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
+ } /* end if */
+ else
+ amount_before = 0;
- /* Read the part after the metadata accumulator */
- if((addr + size) > (f->shared->accum.loc + f->shared->accum.size)) {
- size_t amount_after; /* Amount to read at a time */
+ /* Read the part after the metadata accumulator */
+ if((addr + size) > (f->shared->accum.loc + f->shared->accum.size)) {
+ size_t amount_after; /* Amount to read at a time */
- /* Set the amount to read */
- H5_ASSIGN_OVERFLOW(amount_after, ((addr + size) - (f->shared->accum.loc + f->shared->accum.size)), hsize_t, size_t);
+ /* Set the amount to read */
+ H5_ASSIGN_OVERFLOW(amount_after, ((addr + size) - (f->shared->accum.loc + f->shared->accum.size)), hsize_t, size_t);
- /* Dispatch to driver */
- if(H5FD_read(f->shared->lf, dxpl_id, type, (f->shared->accum.loc + f->shared->accum.size), amount_after, (f->shared->accum.buf + f->shared->accum.size + amount_before)) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
- } /* end if */
+ /* Dispatch to driver */
+ if(H5FD_read(f->shared->lf, dxpl_id, type, (f->shared->accum.loc + f->shared->accum.size), amount_after, (f->shared->accum.buf + f->shared->accum.size + amount_before)) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
+ } /* end if */
- /* Copy the data out of the buffer */
- HDmemcpy(buf, f->shared->accum.buf + (addr - new_addr), size);
+ /* Copy the data out of the buffer */
+ HDmemcpy(buf, f->shared->accum.buf + (addr - new_addr), size);
- /* Adjust the accumulator address & size */
- f->shared->accum.loc = new_addr;
- f->shared->accum.size = new_size;
+ /* Adjust the accumulator address & size */
+ f->shared->accum.loc = new_addr;
+ f->shared->accum.size = new_size;
+ } /* end if */
+ /* Current read doesn't overlap with metadata accumulator, read it from file */
+ else {
+ /* Dispatch to driver */
+ if(H5FD_read(f->shared->lf, dxpl_id, type, addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
+ } /* end else */
} /* end if */
- /* Current read doesn't overlap with metadata accumulator, read it from file */
else {
- /* Dispatch to driver */
+ /* Read the data */
if(H5FD_read(f->shared->lf, dxpl_id, type, addr, size, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
- } /* end else */
- /* Indicate success */
- HGOTO_DONE(TRUE);
+ /* Check for overlap w/dirty accumulator */
+ /* (Note that this could be improved by updating the non-dirty
+ * information in the accumulator with [some of] the information
+ * just read in. -QAK)
+ */
+ if(f->shared->accum.dirty &&
+ H5F_addr_overlap(addr, size, f->shared->accum.loc + f->shared->accum.dirty_off, f->shared->accum.dirty_len)) {
+ haddr_t dirty_loc = f->shared->accum.loc + f->shared->accum.dirty_off; /* File offset of dirty information */
+ size_t buf_off; /* Offset of dirty region in buffer */
+ size_t dirty_off; /* Offset within dirty region */
+ size_t overlap_size; /* Size of overlap with dirty region */
+
+ /* Check for read starting before beginning dirty region */
+ if(H5F_addr_le(addr, dirty_loc)) {
+ /* Compute offset of dirty region within buffer */
+ buf_off = (size_t)(dirty_loc - addr);
+
+ /* Compute offset within dirty region */
+ dirty_off = 0;
+
+ /* Check for read ending within dirty region */
+ if(H5F_addr_le(addr + size, dirty_loc + f->shared->accum.dirty_len))
+ overlap_size = (size_t)((addr + size) - buf_off);
+ else /* Access covers whole dirty region */
+ overlap_size = f->shared->accum.dirty_len;
+ } /* end if */
+ else { /* Read starts after beginning of dirty region */
+ /* Compute dirty offset within buffer and overlap size */
+ buf_off = 0;
+ dirty_off = (size_t)(addr - dirty_loc);
+ overlap_size = (size_t)((dirty_loc + f->shared->accum.dirty_len) - addr);
+ } /* end else */
+
+ /* Copy the dirty region to buffer */
+ HDmemcpy((unsigned char *)buf + buf_off, (unsigned char *)f->shared->accum.buf + f->shared->accum.dirty_off + dirty_off, overlap_size);
+ } /* end if */
+ } /* end else */
} /* end if */
+ else {
+ /* Read the data */
+ if(H5FD_read(f->shared->lf, dxpl_id, type, addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
+ } /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -355,8 +400,8 @@ done:
/*-------------------------------------------------------------------------
* Function: H5F_accum_write
*
- * Purpose: Attempts to read some data from the metadata accumulator for
- * a file into a buffer.
+ * Purpose: Attempts to write some data to the metadata accumulator for
+ * a file from a buffer.
*
* Return: Non-negative on success/Negative on failure
*
@@ -366,11 +411,11 @@ done:
*
*-------------------------------------------------------------------------
*/
-htri_t
+herr_t
H5F_accum_write(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
size_t size, const void *buf)
{
- htri_t ret_value = FALSE; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5F_accum_write, FAIL)
@@ -380,248 +425,284 @@ H5F_accum_write(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
HDassert(buf);
/* Check for accumulating metadata */
- if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && type != H5FD_MEM_DRAW
- && size < H5F_ACCUM_MAX_SIZE) {
- /* Sanity check */
- HDassert(!f->shared->accum.buf || (f->shared->accum.alloc_size >= f->shared->accum.size));
-
- /* Check if there is already metadata in the accumulator */
- if(f->shared->accum.size > 0) {
- /* Check if the new metadata adjoins the beginning of the current accumulator */
- if((addr + size) == f->shared->accum.loc) {
- /* Check if we need to adjust accumulator size */
- if(H5F_accum_adjust(&f->shared->accum, f->shared->lf, dxpl_id, H5F_ACCUM_PREPEND, size) < 0)
- HGOTO_ERROR(H5E_IO, H5E_CANTRESIZE, FAIL, "can't adjust metadata accumulator")
-
- /* Move the existing metadata to the proper location */
- HDmemmove(f->shared->accum.buf + size, f->shared->accum.buf, f->shared->accum.size);
-
- /* Copy the new metadata at the front */
- HDmemcpy(f->shared->accum.buf, buf, size);
-
- /* Set the new size & location of the metadata accumulator */
- f->shared->accum.loc = addr;
- f->shared->accum.size += size;
-
- /* Adjust the dirty region and mark accumulator dirty */
- if(f->shared->accum.dirty)
- f->shared->accum.dirty_len = size + f->shared->accum.dirty_off
- + f->shared->accum.dirty_len;
- else {
- f->shared->accum.dirty_len = size;
- f->shared->accum.dirty = TRUE;
- } /* end else */
- f->shared->accum.dirty_off = 0;
- } /* end if */
- /* Check if the new metadata adjoins the end of the current accumulator */
- else if(addr == (f->shared->accum.loc + f->shared->accum.size)) {
- /* Check if we need to adjust accumulator size */
- if(H5F_accum_adjust(&f->shared->accum, f->shared->lf, dxpl_id, H5F_ACCUM_APPEND, size) < 0)
- HGOTO_ERROR(H5E_IO, H5E_CANTRESIZE, FAIL, "can't adjust metadata accumulator")
+ if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && type != H5FD_MEM_DRAW) {
+ if(size < H5F_ACCUM_MAX_SIZE) {
+ /* Sanity check */
+ HDassert(!f->shared->accum.buf || (f->shared->accum.alloc_size >= f->shared->accum.size));
+
+ /* Check if there is already metadata in the accumulator */
+ if(f->shared->accum.size > 0) {
+ /* Check if the new metadata adjoins the beginning of the current accumulator */
+ if((addr + size) == f->shared->accum.loc) {
+ /* Check if we need to adjust accumulator size */
+ if(H5F_accum_adjust(&f->shared->accum, f->shared->lf, dxpl_id, H5F_ACCUM_PREPEND, size) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTRESIZE, FAIL, "can't adjust metadata accumulator")
- /* Copy the new metadata to the end */
- HDmemcpy(f->shared->accum.buf + f->shared->accum.size, buf, size);
+ /* Move the existing metadata to the proper location */
+ HDmemmove(f->shared->accum.buf + size, f->shared->accum.buf, f->shared->accum.size);
- /* Adjust the dirty region and mark accumulator dirty */
- if(f->shared->accum.dirty)
- f->shared->accum.dirty_len = size + (f->shared->accum.size -
- f->shared->accum.dirty_off);
- else {
- f->shared->accum.dirty_off = f->shared->accum.size;
- f->shared->accum.dirty_len = size;
- f->shared->accum.dirty = TRUE;
- } /* end else */
+ /* Copy the new metadata at the front */
+ HDmemcpy(f->shared->accum.buf, buf, size);
- /* Set the new size of the metadata accumulator */
- f->shared->accum.size += size;
- } /* end if */
- /* Check if the piece of metadata being written overlaps the metadata accumulator */
- else if(H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size)) {
- size_t add_size; /* New size of the accumulator buffer */
+ /* Set the new size & location of the metadata accumulator */
+ f->shared->accum.loc = addr;
+ f->shared->accum.size += size;
- /* Check if the new metadata is entirely within the current accumulator */
- if(addr >= f->shared->accum.loc && (addr + size) <= (f->shared->accum.loc + f->shared->accum.size)) {
- size_t dirty_off = (size_t)(addr - f->shared->accum.loc);
+ /* Adjust the dirty region and mark accumulator dirty */
+ if(f->shared->accum.dirty)
+ f->shared->accum.dirty_len = size + f->shared->accum.dirty_off
+ + f->shared->accum.dirty_len;
+ else {
+ f->shared->accum.dirty_len = size;
+ f->shared->accum.dirty = TRUE;
+ } /* end else */
+ f->shared->accum.dirty_off = 0;
+ } /* end if */
+ /* Check if the new metadata adjoins the end of the current accumulator */
+ else if(addr == (f->shared->accum.loc + f->shared->accum.size)) {
+ /* Check if we need to adjust accumulator size */
+ if(H5F_accum_adjust(&f->shared->accum, f->shared->lf, dxpl_id, H5F_ACCUM_APPEND, size) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTRESIZE, FAIL, "can't adjust metadata accumulator")
- /* Copy the new metadata to the proper location within the accumulator */
- HDmemcpy(f->shared->accum.buf + dirty_off, buf, size);
+ /* Copy the new metadata to the end */
+ HDmemcpy(f->shared->accum.buf + f->shared->accum.size, buf, size);
/* Adjust the dirty region and mark accumulator dirty */
- if(f->shared->accum.dirty) {
- /* Check for new metadata starting before current dirty region */
- if(dirty_off <= f->shared->accum.dirty_off) {
- if((dirty_off + size) <= (f->shared->accum.dirty_off + f->shared->accum.dirty_len))
- f->shared->accum.dirty_len = (f->shared->accum.dirty_off + f->shared->accum.dirty_len) - dirty_off;
- else
- f->shared->accum.dirty_len = size;
- f->shared->accum.dirty_off = dirty_off;
- } /* end if */
- else {
- if((dirty_off + size) <= (f->shared->accum.dirty_off + f->shared->accum.dirty_len))
- ; /* f->shared->accum.dirty_len doesn't change */
- else
- f->shared->accum.dirty_len = (dirty_off + size) - f->shared->accum.dirty_off;
- } /* end else */
- } /* end if */
+ if(f->shared->accum.dirty)
+ f->shared->accum.dirty_len = size + (f->shared->accum.size -
+ f->shared->accum.dirty_off);
else {
- f->shared->accum.dirty_off = dirty_off;
+ f->shared->accum.dirty_off = f->shared->accum.size;
f->shared->accum.dirty_len = size;
f->shared->accum.dirty = TRUE;
} /* end else */
+
+ /* Set the new size of the metadata accumulator */
+ f->shared->accum.size += size;
} /* end if */
- /* Check if the new metadata overlaps the beginning of the current accumulator */
- else if(addr < f->shared->accum.loc && (addr + size) <= (f->shared->accum.loc + f->shared->accum.size)) {
- size_t old_offset; /* Offset of old data within the accumulator buffer */
+ /* Check if the piece of metadata being written overlaps the metadata accumulator */
+ else if(H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size)) {
+ size_t add_size; /* New size of the accumulator buffer */
+
+ /* Check if the new metadata is entirely within the current accumulator */
+ if(addr >= f->shared->accum.loc && (addr + size) <= (f->shared->accum.loc + f->shared->accum.size)) {
+ size_t dirty_off = (size_t)(addr - f->shared->accum.loc);
+
+ /* Copy the new metadata to the proper location within the accumulator */
+ HDmemcpy(f->shared->accum.buf + dirty_off, buf, size);
+
+ /* Adjust the dirty region and mark accumulator dirty */
+ if(f->shared->accum.dirty) {
+ /* Check for new metadata starting before current dirty region */
+ if(dirty_off <= f->shared->accum.dirty_off) {
+ if((dirty_off + size) <= (f->shared->accum.dirty_off + f->shared->accum.dirty_len))
+ f->shared->accum.dirty_len = (f->shared->accum.dirty_off + f->shared->accum.dirty_len) - dirty_off;
+ else
+ f->shared->accum.dirty_len = size;
+ f->shared->accum.dirty_off = dirty_off;
+ } /* end if */
+ else {
+ if((dirty_off + size) <= (f->shared->accum.dirty_off + f->shared->accum.dirty_len))
+ ; /* f->shared->accum.dirty_len doesn't change */
+ else
+ f->shared->accum.dirty_len = (dirty_off + size) - f->shared->accum.dirty_off;
+ } /* end else */
+ } /* end if */
+ else {
+ f->shared->accum.dirty_off = dirty_off;
+ f->shared->accum.dirty_len = size;
+ f->shared->accum.dirty = TRUE;
+ } /* end else */
+ } /* end if */
+ /* Check if the new metadata overlaps the beginning of the current accumulator */
+ else if(addr < f->shared->accum.loc && (addr + size) <= (f->shared->accum.loc + f->shared->accum.size)) {
+ size_t old_offset; /* Offset of old data within the accumulator buffer */
- /* Calculate the amount we will need to add to the accumulator size, based on the amount of overlap */
- H5_ASSIGN_OVERFLOW(add_size, (f->shared->accum.loc - addr), hsize_t, size_t);
+ /* Calculate the amount we will need to add to the accumulator size, based on the amount of overlap */
+ H5_ASSIGN_OVERFLOW(add_size, (f->shared->accum.loc - addr), hsize_t, size_t);
- /* Check if we need to adjust accumulator size */
- if(H5F_accum_adjust(&f->shared->accum, f->shared->lf, dxpl_id, H5F_ACCUM_PREPEND, add_size) < 0)
- HGOTO_ERROR(H5E_IO, H5E_CANTRESIZE, FAIL, "can't adjust metadata accumulator")
+ /* Check if we need to adjust accumulator size */
+ if(H5F_accum_adjust(&f->shared->accum, f->shared->lf, dxpl_id, H5F_ACCUM_PREPEND, add_size) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTRESIZE, FAIL, "can't adjust metadata accumulator")
- /* Calculate the proper offset of the existing metadata */
- H5_ASSIGN_OVERFLOW(old_offset, (addr + size) - f->shared->accum.loc, hsize_t, size_t);
+ /* Calculate the proper offset of the existing metadata */
+ H5_ASSIGN_OVERFLOW(old_offset, (addr + size) - f->shared->accum.loc, hsize_t, size_t);
- /* Move the existing metadata to the proper location */
- HDmemmove(f->shared->accum.buf + size, f->shared->accum.buf + old_offset, (f->shared->accum.size - old_offset));
+ /* Move the existing metadata to the proper location */
+ HDmemmove(f->shared->accum.buf + size, f->shared->accum.buf + old_offset, (f->shared->accum.size - old_offset));
- /* Copy the new metadata at the front */
- HDmemcpy(f->shared->accum.buf, buf, size);
+ /* Copy the new metadata at the front */
+ HDmemcpy(f->shared->accum.buf, buf, size);
- /* Set the new size & location of the metadata accumulator */
- f->shared->accum.loc = addr;
- f->shared->accum.size += add_size;
+ /* Set the new size & location of the metadata accumulator */
+ f->shared->accum.loc = addr;
+ f->shared->accum.size += add_size;
- /* Adjust the dirty region and mark accumulator dirty */
- if(f->shared->accum.dirty) {
- size_t curr_dirty_end = add_size + f->shared->accum.dirty_off + f->shared->accum.dirty_len;
+ /* Adjust the dirty region and mark accumulator dirty */
+ if(f->shared->accum.dirty) {
+ size_t curr_dirty_end = add_size + f->shared->accum.dirty_off + f->shared->accum.dirty_len;
- f->shared->accum.dirty_off = 0;
- if(size <= curr_dirty_end)
- f->shared->accum.dirty_len = curr_dirty_end;
- else
+ f->shared->accum.dirty_off = 0;
+ if(size <= curr_dirty_end)
+ f->shared->accum.dirty_len = curr_dirty_end;
+ else
+ f->shared->accum.dirty_len = size;
+ } /* end if */
+ else {
+ f->shared->accum.dirty_off = 0;
f->shared->accum.dirty_len = size;
+ f->shared->accum.dirty = TRUE;
+ } /* end else */
} /* end if */
- else {
- f->shared->accum.dirty_off = 0;
- f->shared->accum.dirty_len = size;
- f->shared->accum.dirty = TRUE;
- } /* end else */
- } /* end if */
- /* Check if the new metadata overlaps the end of the current accumulator */
- else if(addr >= f->shared->accum.loc && (addr + size) > (f->shared->accum.loc + f->shared->accum.size)) {
- size_t dirty_off = (size_t)(addr - f->shared->accum.loc);
+ /* Check if the new metadata overlaps the end of the current accumulator */
+ else if(addr >= f->shared->accum.loc && (addr + size) > (f->shared->accum.loc + f->shared->accum.size)) {
+ size_t dirty_off; /* Offset of dirty region */
- /* Calculate the amount we will need to add to the accumulator size, based on the amount of overlap */
- H5_ASSIGN_OVERFLOW(add_size, (addr + size) - (f->shared->accum.loc + f->shared->accum.size), hsize_t, size_t);
+ /* Calculate the amount we will need to add to the accumulator size, based on the amount of overlap */
+ H5_ASSIGN_OVERFLOW(add_size, (addr + size) - (f->shared->accum.loc + f->shared->accum.size), hsize_t, size_t);
- /* Check if we need to adjust accumulator size */
- if(H5F_accum_adjust(&f->shared->accum, f->shared->lf, dxpl_id, H5F_ACCUM_APPEND, add_size) < 0)
- HGOTO_ERROR(H5E_IO, H5E_CANTRESIZE, FAIL, "can't adjust metadata accumulator")
+ /* Check if we need to adjust accumulator size */
+ if(H5F_accum_adjust(&f->shared->accum, f->shared->lf, dxpl_id, H5F_ACCUM_APPEND, add_size) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTRESIZE, FAIL, "can't adjust metadata accumulator")
- /* Copy the new metadata to the end */
- HDmemcpy(f->shared->accum.buf + dirty_off, buf, size);
+ /* Compute offset of dirty region (after adjusting accumulator) */
+ dirty_off = (size_t)(addr - f->shared->accum.loc);
- /* Set the new size of the metadata accumulator */
- f->shared->accum.size += add_size;
+ /* Copy the new metadata to the end */
+ HDmemcpy(f->shared->accum.buf + dirty_off, buf, size);
- /* Adjust the dirty region and mark accumulator dirty */
- if(f->shared->accum.dirty) {
- /* Check for new metadata starting before current dirty region */
- if(dirty_off <= f->shared->accum.dirty_off) {
- f->shared->accum.dirty_off = dirty_off;
- f->shared->accum.dirty_len = size;
+ /* Set the new size of the metadata accumulator */
+ f->shared->accum.size += add_size;
+
+ /* Adjust the dirty region and mark accumulator dirty */
+ if(f->shared->accum.dirty) {
+ /* Check for new metadata starting before current dirty region */
+ if(dirty_off <= f->shared->accum.dirty_off) {
+ f->shared->accum.dirty_off = dirty_off;
+ f->shared->accum.dirty_len = size;
+ } /* end if */
+ else {
+ f->shared->accum.dirty_len = (dirty_off + size) - f->shared->accum.dirty_off;
+ } /* end else */
} /* end if */
else {
- f->shared->accum.dirty_len = (dirty_off + size) - f->shared->accum.dirty_off;
+ f->shared->accum.dirty_off = dirty_off;
+ f->shared->accum.dirty_len = size;
+ f->shared->accum.dirty = TRUE;
} /* end else */
} /* end if */
+ /* New metadata overlaps both ends of the current accumulator */
else {
- f->shared->accum.dirty_off = dirty_off;
+ /* Check if we need more buffer space */
+ if(size > f->shared->accum.alloc_size) {
+ size_t new_alloc_size; /* New size of accumulator */
+
+ /* Adjust the buffer size to be a power of 2 that is large enough to hold data */
+ new_alloc_size = (size_t)1 << (1 + H5V_log2_gen((uint64_t)(size - 1)));
+
+ /* Reallocate the metadata accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, new_alloc_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+
+ /* Note the new buffer size */
+ f->shared->accum.alloc_size = new_alloc_size;
+#ifdef H5_CLEAR_MEMORY
+HDmemset(f->shared->accum.buf + size, 0, (f->shared->accum.alloc_size - size));
+#endif /* H5_CLEAR_MEMORY */
+ } /* end if */
+
+ /* Copy the new metadata to the buffer */
+ HDmemcpy(f->shared->accum.buf, buf, size);
+
+ /* Set the new size & location of the metadata accumulator */
+ f->shared->accum.loc = addr;
+ f->shared->accum.size = size;
+
+ /* Adjust the dirty region and mark accumulator dirty */
+ f->shared->accum.dirty_off = 0;
f->shared->accum.dirty_len = size;
f->shared->accum.dirty = TRUE;
} /* end else */
} /* end if */
- /* New metadata overlaps both ends of the current accumulator */
+ /* New piece of metadata doesn't adjoin or overlap the existing accumulator */
else {
- /* Check if we need more buffer space */
+ /* Write out the existing metadata accumulator, with dispatch to driver */
+ if(f->shared->accum.dirty) {
+ if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, f->shared->accum.loc + f->shared->accum.dirty_off, f->shared->accum.dirty_len, f->shared->accum.buf + f->shared->accum.dirty_off) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
+
+ /* Reset accumulator dirty flag */
+ f->shared->accum.dirty = FALSE;
+ } /* end if */
+
+ /* Cache the new piece of metadata */
+ /* Check if we need to resize the buffer */
if(size > f->shared->accum.alloc_size) {
- size_t new_alloc_size; /* New size of accumulator */
+ size_t new_size; /* New size of accumulator */
/* Adjust the buffer size to be a power of 2 that is large enough to hold data */
- new_alloc_size = (size_t)1 << (1 + H5V_log2_gen((uint64_t)(size - 1)));
+ new_size = (size_t)1 << (1 + H5V_log2_gen((uint64_t)(size - 1)));
- /* Reallocate the metadata accumulator buffer */
- if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, new_alloc_size)))
+ /* Grow the metadata accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, new_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
/* Note the new buffer size */
- f->shared->accum.alloc_size = new_alloc_size;
+ f->shared->accum.alloc_size = new_size;
#ifdef H5_CLEAR_MEMORY
-HDmemset(f->shared->accum.buf + size, 0, (f->shared->accum.alloc_size - size));
+{
+size_t clear_size = MAX(f->shared->accum.size, size);
+HDmemset(f->shared->accum.buf + clear_size, 0, (f->shared->accum.alloc_size - clear_size));
+}
#endif /* H5_CLEAR_MEMORY */
} /* end if */
+ else {
+ /* Check if we should shrink the accumulator buffer */
+ if(size < (f->shared->accum.alloc_size / H5F_ACCUM_THROTTLE) &&
+ f->shared->accum.alloc_size > H5F_ACCUM_THRESHOLD) {
+ size_t tmp_size = (f->shared->accum.alloc_size / H5F_ACCUM_THROTTLE); /* New size of accumulator buffer */
- /* Copy the new metadata to the buffer */
- HDmemcpy(f->shared->accum.buf, buf, size);
+ /* Shrink the accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, tmp_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
- /* Set the new size & location of the metadata accumulator */
+ /* Note the new buffer size */
+ f->shared->accum.alloc_size = tmp_size;
+ } /* end if */
+ } /* end else */
+
+ /* Update the metadata accumulator information */
f->shared->accum.loc = addr;
f->shared->accum.size = size;
+ /* Store the piece of metadata in the accumulator */
+ HDmemcpy(f->shared->accum.buf, buf, size);
+
/* Adjust the dirty region and mark accumulator dirty */
f->shared->accum.dirty_off = 0;
f->shared->accum.dirty_len = size;
f->shared->accum.dirty = TRUE;
} /* end else */
} /* end if */
- /* New piece of metadata doesn't adjoin or overlap the existing accumulator */
+ /* No metadata in the accumulator, grab this piece and keep it */
else {
- /* Write out the existing metadata accumulator, with dispatch to driver */
- if(f->shared->accum.dirty) {
- if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, f->shared->accum.loc + f->shared->accum.dirty_off, f->shared->accum.dirty_len, f->shared->accum.buf + f->shared->accum.dirty_off) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
-
- /* Reset accumulator dirty flag */
- f->shared->accum.dirty = FALSE;
- } /* end if */
-
- /* Cache the new piece of metadata */
- /* Check if we need to resize the buffer */
+ /* Check if we need to reallocate the buffer */
if(size > f->shared->accum.alloc_size) {
size_t new_size; /* New size of accumulator */
/* Adjust the buffer size to be a power of 2 that is large enough to hold data */
new_size = (size_t)1 << (1 + H5V_log2_gen((uint64_t)(size - 1)));
- /* Grow the metadata accumulator buffer */
+ /* Reallocate the metadata accumulator buffer */
if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, new_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
/* Note the new buffer size */
f->shared->accum.alloc_size = new_size;
#ifdef H5_CLEAR_MEMORY
-{
-size_t clear_size = MAX(f->shared->accum.size, size);
-HDmemset(f->shared->accum.buf + clear_size, 0, (f->shared->accum.alloc_size - clear_size));
-}
+HDmemset(f->shared->accum.buf + size, 0, (f->shared->accum.alloc_size - size));
#endif /* H5_CLEAR_MEMORY */
} /* end if */
- else {
- /* Check if we should shrink the accumulator buffer */
- if(size < (f->shared->accum.alloc_size / H5F_ACCUM_THROTTLE) &&
- f->shared->accum.alloc_size > H5F_ACCUM_THRESHOLD) {
- size_t tmp_size = (f->shared->accum.alloc_size / H5F_ACCUM_THROTTLE); /* New size of accumulator buffer */
-
- /* Shrink the accumulator buffer */
- if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, tmp_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-
- /* Note the new buffer size */
- f->shared->accum.alloc_size = tmp_size;
- } /* end if */
- } /* end else */
/* Update the metadata accumulator information */
f->shared->accum.loc = addr;
@@ -636,42 +717,96 @@ HDmemset(f->shared->accum.buf + clear_size, 0, (f->shared->accum.alloc_size - cl
f->shared->accum.dirty = TRUE;
} /* end else */
} /* end if */
- /* No metadata in the accumulator, grab this piece and keep it */
else {
- /* Check if we need to reallocate the buffer */
- if(size > f->shared->accum.alloc_size) {
- size_t new_size; /* New size of accumulator */
+ /* Write the data */
+ if(H5FD_write(f->shared->lf, dxpl_id, type, addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
+
+ /* Check for overlap w/accumulator */
+ /* (Note that this could be improved by updating the accumulator
+ * with [some of] the information just read in. -QAK)
+ */
+ if(H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size)) {
+ /* Check for write starting before beginning of accumulator */
+ if(H5F_addr_le(addr, f->shared->accum.loc)) {
+ /* Check for write ending within accumulator */
+ if(H5F_addr_le(addr + size, f->shared->accum.loc + f->shared->accum.size)) {
+ size_t overlap_size; /* Size of overlapping region */
+
+ /* Compute overlap size */
+ overlap_size = (size_t)((addr + size) - f->shared->accum.loc);
+
+ /* Check for dirty region */
+ if(f->shared->accum.dirty) {
+ haddr_t dirty_start = f->shared->accum.loc + f->shared->accum.dirty_off; /* File address of start of dirty region */
+ haddr_t dirty_end = dirty_start + f->shared->accum.dirty_len; /* File address of end of dirty region */
+
+ /* Check if entire dirty region is overwritten */
+ if(H5F_addr_le(dirty_end, addr + size)) {
+ f->shared->accum.dirty = FALSE;
+ f->shared->accum.dirty_len = 0;
+ } /* end if */
+ else {
+ /* Check for dirty region falling after write */
+ if(H5F_addr_le(addr + size, dirty_start))
+ f->shared->accum.dirty_off = overlap_size;
+ else { /* Dirty region overlaps w/written region */
+ f->shared->accum.dirty_off = 0;
+ f->shared->accum.dirty_len -= (size_t)((addr + size) - dirty_start);
+ } /* end else */
+ } /* end if */
+ } /* end if */
- /* Adjust the buffer size to be a power of 2 that is large enough to hold data */
- new_size = (size_t)1 << (1 + H5V_log2_gen((uint64_t)(size - 1)));
+ /* Trim bottom of accumulator off */
+ f->shared->accum.loc += overlap_size;
+ f->shared->accum.size -= overlap_size;
+ HDmemmove(f->shared->accum.buf, f->shared->accum.buf + overlap_size, f->shared->accum.size);
+ } /* end if */
+ else { /* Access covers whole accumulator */
+ /* Reset accumulator, but don't flush */
+ if(H5F_accum_reset(f, dxpl_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTRESET, FAIL, "can't reset accumulator")
+ } /* end else */
+ } /* end if */
+ else { /* Write starts after beginning of accumulator */
+ size_t overlap_size; /* Size of overlapping region */
- /* Reallocate the metadata accumulator buffer */
- if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, new_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+ /* Sanity check */
+ HDassert(H5F_addr_gt(addr + size, f->shared->accum.loc + f->shared->accum.size));
- /* Note the new buffer size */
- f->shared->accum.alloc_size = new_size;
-#ifdef H5_CLEAR_MEMORY
-HDmemset(f->shared->accum.buf + size, 0, (f->shared->accum.alloc_size - size));
-#endif /* H5_CLEAR_MEMORY */
- } /* end if */
+ /* Compute overlap size */
+ overlap_size = (size_t)((f->shared->accum.loc + f->shared->accum.size) - addr);
- /* Update the metadata accumulator information */
- f->shared->accum.loc = addr;
- f->shared->accum.size = size;
+ /* Check for dirty region */
+ if(f->shared->accum.dirty) {
+ haddr_t dirty_start = f->shared->accum.loc + f->shared->accum.dirty_off; /* File address of start of dirty region */
+ haddr_t dirty_end = dirty_start + f->shared->accum.dirty_len; /* File address of end of dirty region */
- /* Store the piece of metadata in the accumulator */
- HDmemcpy(f->shared->accum.buf, buf, size);
+ /* Check if entire dirty region is overwritten */
+ if(H5F_addr_ge(dirty_start, addr)) {
+ f->shared->accum.dirty = FALSE;
+ f->shared->accum.dirty_len = 0;
+ } /* end if */
+ else {
+ /* Check for dirty region falling before write */
+ if(H5F_addr_le(dirty_end, addr))
+ ; /* noop */
+ else /* Dirty region overlaps w/written region */
+ f->shared->accum.dirty_len = (size_t)(addr - dirty_start);
+ } /* end if */
+ } /* end if */
- /* Adjust the dirty region and mark accumulator dirty */
- f->shared->accum.dirty_off = 0;
- f->shared->accum.dirty_len = size;
- f->shared->accum.dirty = TRUE;
+ /* Trim top of accumulator off */
+ f->shared->accum.size -= overlap_size;
+ } /* end else */
+ } /* end if */
} /* end else */
-
- /* Indicate success */
- HGOTO_DONE(TRUE);
} /* end if */
+ else {
+ /* Write the data */
+ if(H5FD_write(f->shared->lf, dxpl_id, type, addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
+ } /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -778,22 +913,20 @@ H5F_accum_free(H5F_t *f, hid_t dxpl_id, H5FD_mem_t UNUSED type, haddr_t addr,
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
} /* end if */
/* Block to free overlaps with some/all of dirty region */
- else {
+ /* Check for unfreed dirty region to write */
+ else if(H5F_addr_lt(tail_addr, dirty_end)) {
size_t write_size;
+ size_t dirty_delta;
write_size = (size_t)(dirty_end - tail_addr);
+ dirty_delta = f->shared->accum.dirty_len - write_size;
- /* Check for unfreed dirty region to write */
- if(write_size > 0) {
- size_t dirty_delta;
-
- dirty_delta = f->shared->accum.dirty_len - write_size;
+ HDassert(write_size > 0);
- /* Write out the unfreed dirty region of the accumulator */
- if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, dirty_start + dirty_delta, write_size, f->shared->accum.buf + f->shared->accum.dirty_off + dirty_delta) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
- } /* end if */
- } /* end else */
+ /* Write out the unfreed dirty region of the accumulator */
+ if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, dirty_start + dirty_delta, write_size, f->shared->accum.buf + f->shared->accum.dirty_off + dirty_delta) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
+ } /* end if */
/* Reset dirty flag */
f->shared->accum.dirty = FALSE;
@@ -803,19 +936,16 @@ H5F_accum_free(H5F_t *f, hid_t dxpl_id, H5FD_mem_t UNUSED type, haddr_t addr,
/* Check if block to free ends before end of dirty region */
if(H5F_addr_lt(tail_addr, dirty_end)) {
size_t write_size;
+ size_t dirty_delta;
write_size = (size_t)(dirty_end - tail_addr);
+ dirty_delta = f->shared->accum.dirty_len - write_size;
- /* Check for unfreed dirty region to write */
- if(write_size > 0) {
- size_t dirty_delta;
+ HDassert(write_size > 0);
- dirty_delta = f->shared->accum.dirty_len - write_size;
-
- /* Write out the unfreed end of the dirty region of the accumulator */
- if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, dirty_start + dirty_delta, write_size, f->shared->accum.buf + f->shared->accum.dirty_off + dirty_delta) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
- } /* end if */
+ /* Write out the unfreed end of the dirty region of the accumulator */
+ if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, dirty_start + dirty_delta, write_size, f->shared->accum.buf + f->shared->accum.dirty_off + dirty_delta) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
} /* end if */
/* Check for block to free beginning at same location as dirty region */
@@ -825,7 +955,7 @@ H5F_accum_free(H5F_t *f, hid_t dxpl_id, H5FD_mem_t UNUSED type, haddr_t addr,
} /* end if */
/* Block to free eliminates end of dirty region */
else {
- f->shared->accum.dirty_len = (addr - dirty_start);
+ f->shared->accum.dirty_len = (size_t)(addr - dirty_start);
} /* end else */
} /* end else */
@@ -855,7 +985,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5F_accum_flush(H5F_t *f, hid_t dxpl_id)
+H5F_accum_flush(const H5F_t *f, hid_t dxpl_id)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -893,7 +1023,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5F_accum_reset(H5F_t *f, hid_t dxpl_id)
+H5F_accum_reset(const H5F_t *f, hid_t dxpl_id, hbool_t flush)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -902,9 +1032,10 @@ H5F_accum_reset(H5F_t *f, hid_t dxpl_id)
HDassert(f);
HDassert(f->shared);
- /* Flush any dirty data in accumulator */
- if(H5F_accum_flush(f, dxpl_id) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "can't flush metadata accumulator")
+ /* Flush any dirty data in accumulator, if requested */
+ if(flush)
+ if(H5F_accum_flush(f, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "can't flush metadata accumulator")
/* Check if we need to reset the metadata accumulator information */
if(f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) {
diff --git a/src/H5Fio.c b/src/H5Fio.c
index 407f950..231c4c9 100644
--- a/src/H5Fio.c
+++ b/src/H5Fio.c
@@ -95,7 +95,6 @@ herr_t
H5F_block_read(const H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
hid_t dxpl_id, void *buf/*out*/)
{
- htri_t accumulated; /* Whether the data was accepted by the metadata accumulator */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5F_block_read, FAIL)
@@ -108,14 +107,9 @@ H5F_block_read(const H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
if(H5F_addr_le(f->shared->tmp_addr, (addr + size)))
HGOTO_ERROR(H5E_IO, H5E_BADRANGE, FAIL, "attempting I/O in temporary file space")
- /* Check if this I/O can be satisfied by the metadata accumulator */
- if((accumulated = H5F_accum_read(f, dxpl_id, type, addr, size, buf)) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "read from metadata accumulator failed")
- else if(accumulated == FALSE) {
- /* Read the data */
- if(H5FD_read(f->shared->lf, dxpl_id, type, addr, size, buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
- } /* end else */
+ /* Pass through metadata accumulator layer */
+ if(H5F_accum_read(f, dxpl_id, type, addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "read through metadata accumulator failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -141,7 +135,6 @@ herr_t
H5F_block_write(const H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
hid_t dxpl_id, const void *buf)
{
- htri_t accumulated; /* Whether the data was accepted by the metadata accumulator */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5F_block_write, FAIL)
@@ -158,14 +151,9 @@ HDfprintf(stderr, "%s: write to addr = %a, size = %Zu\n", FUNC, addr, size);
if(H5F_addr_le(f->shared->tmp_addr, (addr + size)))
HGOTO_ERROR(H5E_IO, H5E_BADRANGE, FAIL, "attempting I/O in temporary file space")
- /* Check for accumulating metadata */
- if((accumulated = H5F_accum_write(f, dxpl_id, type, addr, size, buf)) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "write to metadata accumulator failed")
- else if(accumulated == FALSE) {
- /* Write the data */
- if(H5FD_write(f->shared->lf, dxpl_id, type, addr, size, buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
- } /* end else */
+ /* Pass through metadata accumulator layer */
+ if(H5F_accum_write(f, dxpl_id, type, addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "write through metadata accumulator failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index 4a4d49c..c98bda4 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -314,14 +314,14 @@ H5_DLL herr_t H5F_super_ext_close(H5F_t *f, H5O_loc_t *ext_ptr, hid_t dxpl_id,
hbool_t was_created);
/* Metadata accumulator routines */
-H5_DLL htri_t H5F_accum_read(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type,
+H5_DLL herr_t H5F_accum_read(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type,
haddr_t addr, size_t size, void *buf);
-H5_DLL htri_t H5F_accum_write(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type,
+H5_DLL herr_t H5F_accum_write(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type,
haddr_t addr, size_t size, const void *buf);
H5_DLL herr_t H5F_accum_free(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type,
haddr_t addr, hsize_t size);
-H5_DLL herr_t H5F_accum_flush(H5F_t *f, hid_t dxpl_id);
-H5_DLL herr_t H5F_accum_reset(H5F_t *f, hid_t dxpl_id);
+H5_DLL herr_t H5F_accum_flush(const H5F_t *f, hid_t dxpl_id);
+H5_DLL herr_t H5F_accum_reset(const H5F_t *f, hid_t dxpl_id, hbool_t flush);
/* Shared file list related routines */
H5_DLL herr_t H5F_sfile_add(H5F_file_t *shared);
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 7e12026..2bed576 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -241,6 +241,7 @@ ADD_TEST (
)
SET (H5_TESTS
+ accum
lheap
ohdr
stab
diff --git a/test/Makefile.am b/test/Makefile.am
index cef0165..9464d46 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -36,8 +36,8 @@ SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT)
# These tests (fheap, btree2) are under development and are not used by
# the library yet. Move them to the end so that their failure do not block
# other current library code tests.
-TEST_PROG=testhdf5 lheap ohdr stab gheap cache cache_api cache_tagging \
- pool hyperslab istore bittests dt_arith \
+TEST_PROG= testhdf5 lheap ohdr stab gheap cache cache_api cache_tagging \
+ pool accum hyperslab istore bittests dt_arith \
dtypes dsets cmpd_dset filter_fail extend external objcopy links unlink \
big mtime fillval mount flush1 flush2 app_ref enum \
set_extent ttsafe \
@@ -104,7 +104,7 @@ flush2.chkexe_: flush1.chkexe_
# specifying a file prefix or low-level driver. Changing the file
# prefix or low-level driver with environment variables will influence
# the temporary file name in ways that the makefile is not aware of.
-CHECK_CLEANFILES+=cmpd_dset.h5 compact_dataset.h5 dataset.h5 dset_offset.h5 \
+CHECK_CLEANFILES+=accum.h5 cmpd_dset.h5 compact_dataset.h5 dataset.h5 dset_offset.h5 \
max_compact_dataset.h5 simple.h5 set_local.h5 random_chunks.h5 \
huge_chunks.h5 chunk_cache.h5 big_chunk.h5 chunk_expand.h5 \
copy_dcpl_newfile.h5 extend.h5 istore.h5 extlinks*.h5 frspace.h5 links*.h5 \
diff --git a/test/Makefile.in b/test/Makefile.in
index 493a684..8748032 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -77,18 +77,18 @@ am_libh5test_la_OBJECTS = h5test.lo testframe.lo cache_common.lo
libh5test_la_OBJECTS = $(am_libh5test_la_OBJECTS)
am__EXEEXT_1 = testhdf5$(EXEEXT) lheap$(EXEEXT) ohdr$(EXEEXT) \
stab$(EXEEXT) gheap$(EXEEXT) cache$(EXEEXT) cache_api$(EXEEXT) \
- cache_tagging$(EXEEXT) pool$(EXEEXT) hyperslab$(EXEEXT) \
- istore$(EXEEXT) bittests$(EXEEXT) dt_arith$(EXEEXT) \
- dtypes$(EXEEXT) dsets$(EXEEXT) cmpd_dset$(EXEEXT) \
- filter_fail$(EXEEXT) extend$(EXEEXT) external$(EXEEXT) \
- objcopy$(EXEEXT) links$(EXEEXT) unlink$(EXEEXT) big$(EXEEXT) \
- mtime$(EXEEXT) fillval$(EXEEXT) mount$(EXEEXT) flush1$(EXEEXT) \
- flush2$(EXEEXT) app_ref$(EXEEXT) enum$(EXEEXT) \
- set_extent$(EXEEXT) ttsafe$(EXEEXT) getname$(EXEEXT) \
- vfd$(EXEEXT) ntypes$(EXEEXT) dangle$(EXEEXT) \
- dtransform$(EXEEXT) reserved$(EXEEXT) cross_read$(EXEEXT) \
- freespace$(EXEEXT) mf$(EXEEXT) farray$(EXEEXT) earray$(EXEEXT) \
- btree2$(EXEEXT) fheap$(EXEEXT)
+ cache_tagging$(EXEEXT) pool$(EXEEXT) accum$(EXEEXT) \
+ hyperslab$(EXEEXT) istore$(EXEEXT) bittests$(EXEEXT) \
+ dt_arith$(EXEEXT) dtypes$(EXEEXT) dsets$(EXEEXT) \
+ cmpd_dset$(EXEEXT) filter_fail$(EXEEXT) extend$(EXEEXT) \
+ external$(EXEEXT) objcopy$(EXEEXT) links$(EXEEXT) \
+ unlink$(EXEEXT) big$(EXEEXT) mtime$(EXEEXT) fillval$(EXEEXT) \
+ mount$(EXEEXT) flush1$(EXEEXT) flush2$(EXEEXT) \
+ app_ref$(EXEEXT) enum$(EXEEXT) set_extent$(EXEEXT) \
+ ttsafe$(EXEEXT) getname$(EXEEXT) vfd$(EXEEXT) ntypes$(EXEEXT) \
+ dangle$(EXEEXT) dtransform$(EXEEXT) reserved$(EXEEXT) \
+ cross_read$(EXEEXT) freespace$(EXEEXT) mf$(EXEEXT) \
+ farray$(EXEEXT) earray$(EXEEXT) btree2$(EXEEXT) fheap$(EXEEXT)
am__EXEEXT_2 = gen_bad_ohdr$(EXEEXT) gen_bogus$(EXEEXT) \
gen_cross$(EXEEXT) gen_deflate$(EXEEXT) gen_filters$(EXEEXT) \
gen_new_array$(EXEEXT) gen_new_fill$(EXEEXT) \
@@ -98,6 +98,10 @@ am__EXEEXT_2 = gen_bad_ohdr$(EXEEXT) gen_bogus$(EXEEXT) \
space_overflow$(EXEEXT) gen_filespace$(EXEEXT) \
gen_specmetaread$(EXEEXT) gen_sizes_lheap$(EXEEXT)
PROGRAMS = $(noinst_PROGRAMS)
+accum_SOURCES = accum.c
+accum_OBJECTS = accum.$(OBJEXT)
+accum_LDADD = $(LDADD)
+accum_DEPENDENCIES = libh5test.la $(LIBHDF5)
app_ref_SOURCES = app_ref.c
app_ref_OBJECTS = app_ref.$(OBJEXT)
app_ref_LDADD = $(LDADD)
@@ -385,21 +389,7 @@ CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
-SOURCES = $(libh5test_la_SOURCES) app_ref.c big.c bittests.c btree2.c \
- cache.c cache_api.c cache_tagging.c cmpd_dset.c cross_read.c \
- dangle.c dsets.c dt_arith.c dtransform.c dtypes.c earray.c \
- enum.c err_compat.c error_test.c extend.c external.c farray.c \
- fheap.c fillval.c filter_fail.c flush1.c flush2.c freespace.c \
- gen_bad_ohdr.c gen_bogus.c gen_cross.c gen_deflate.c \
- gen_filespace.c gen_filters.c gen_new_array.c gen_new_fill.c \
- gen_new_group.c gen_new_mtime.c gen_new_super.c \
- gen_noencoder.c gen_nullspace.c gen_sizes_lheap.c \
- gen_specmetaread.c gen_udlinks.c getname.c gheap.c hyperslab.c \
- istore.c lheap.c links.c mf.c mount.c mtime.c ntypes.c \
- objcopy.c ohdr.c pool.c reserved.c set_extent.c \
- space_overflow.c stab.c tcheck_version.c $(testhdf5_SOURCES) \
- testmeta.c $(ttsafe_SOURCES) unlink.c vfd.c
-DIST_SOURCES = $(libh5test_la_SOURCES) app_ref.c big.c bittests.c \
+SOURCES = $(libh5test_la_SOURCES) accum.c app_ref.c big.c bittests.c \
btree2.c cache.c cache_api.c cache_tagging.c cmpd_dset.c \
cross_read.c dangle.c dsets.c dt_arith.c dtransform.c dtypes.c \
earray.c enum.c err_compat.c error_test.c extend.c external.c \
@@ -413,6 +403,21 @@ DIST_SOURCES = $(libh5test_la_SOURCES) app_ref.c big.c bittests.c \
objcopy.c ohdr.c pool.c reserved.c set_extent.c \
space_overflow.c stab.c tcheck_version.c $(testhdf5_SOURCES) \
testmeta.c $(ttsafe_SOURCES) unlink.c vfd.c
+DIST_SOURCES = $(libh5test_la_SOURCES) accum.c app_ref.c big.c \
+ bittests.c btree2.c cache.c cache_api.c cache_tagging.c \
+ cmpd_dset.c cross_read.c dangle.c dsets.c dt_arith.c \
+ dtransform.c dtypes.c earray.c enum.c err_compat.c \
+ error_test.c extend.c external.c farray.c fheap.c fillval.c \
+ filter_fail.c flush1.c flush2.c freespace.c gen_bad_ohdr.c \
+ gen_bogus.c gen_cross.c gen_deflate.c gen_filespace.c \
+ gen_filters.c gen_new_array.c gen_new_fill.c gen_new_group.c \
+ gen_new_mtime.c gen_new_super.c gen_noencoder.c \
+ gen_nullspace.c gen_sizes_lheap.c gen_specmetaread.c \
+ gen_udlinks.c getname.c gheap.c hyperslab.c istore.c lheap.c \
+ links.c mf.c mount.c mtime.c ntypes.c objcopy.c ohdr.c pool.c \
+ reserved.c set_extent.c space_overflow.c stab.c \
+ tcheck_version.c $(testhdf5_SOURCES) testmeta.c \
+ $(ttsafe_SOURCES) unlink.c vfd.c
ETAGS = etags
CTAGS = ctags
am__tty_colors = \
@@ -692,7 +697,7 @@ TRACE = perl $(top_srcdir)/bin/trace
# specifying a file prefix or low-level driver. Changing the file
# prefix or low-level driver with environment variables will influence
# the temporary file name in ways that the makefile is not aware of.
-CHECK_CLEANFILES = *.chkexe *.chklog *.clog cmpd_dset.h5 \
+CHECK_CLEANFILES = *.chkexe *.chklog *.clog accum.h5 cmpd_dset.h5 \
compact_dataset.h5 dataset.h5 dset_offset.h5 \
max_compact_dataset.h5 simple.h5 set_local.h5 random_chunks.h5 \
huge_chunks.h5 chunk_cache.h5 big_chunk.h5 chunk_expand.h5 \
@@ -730,7 +735,7 @@ SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT)
# the library yet. Move them to the end so that their failure do not block
# other current library code tests.
TEST_PROG = testhdf5 lheap ohdr stab gheap cache cache_api cache_tagging \
- pool hyperslab istore bittests dt_arith \
+ pool accum hyperslab istore bittests dt_arith \
dtypes dsets cmpd_dset filter_fail extend external objcopy links unlink \
big mtime fillval mount flush1 flush2 app_ref enum \
set_extent ttsafe \
@@ -861,6 +866,9 @@ clean-noinstPROGRAMS:
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
+accum$(EXEEXT): $(accum_OBJECTS) $(accum_DEPENDENCIES)
+ @rm -f accum$(EXEEXT)
+ $(LINK) $(accum_OBJECTS) $(accum_LDADD) $(LIBS)
app_ref$(EXEEXT): $(app_ref_OBJECTS) $(app_ref_DEPENDENCIES)
@rm -f app_ref$(EXEEXT)
$(LINK) $(app_ref_OBJECTS) $(app_ref_LDADD) $(LIBS)
@@ -1066,6 +1074,7 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/accum.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/app_ref.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/big.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bittests.Po@am__quote@
diff --git a/test/accum.c b/test/accum.c
new file mode 100644
index 0000000..91d30c4
--- /dev/null
+++ b/test/accum.c
@@ -0,0 +1,1809 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/* Programmer: Mike McGreevy
+ * October 7, 2010
+ */
+#include "h5test.h"
+
+#define H5F_PACKAGE
+#include "H5Fpkg.h"
+#include "H5FDprivate.h"
+#include "H5Iprivate.h"
+
+/* Filename */
+#define FILENAME "accum.h5"
+
+/* "big" I/O test values */
+#define BIG_BUF_SIZE (6 * 1024 * 1024)
+
+/* Random I/O test values */
+#define RANDOM_BUF_SIZE (1 * 1024 * 1024)
+#define MAX_RANDOM_SEGMENTS (5 * 1024)
+#define RAND_SEG_LEN (1024)
+#define RANDOM_BASE_OFF (1024 * 1024)
+
+/* Make file global to all tests */
+H5F_t * f = NULL;
+
+/* Function Prototypes */
+unsigned test_write_read(void);
+unsigned test_write_read_nonacc_front(void);
+unsigned test_write_read_nonacc_end(void);
+unsigned test_accum_overlap(void);
+unsigned test_accum_overlap_clean(void);
+unsigned test_accum_overlap_size(void);
+unsigned test_accum_non_overlap_size(void);
+unsigned test_accum_adjust(void);
+unsigned test_read_after(void);
+unsigned test_free(void);
+unsigned test_big(void);
+unsigned test_random_write(void);
+
+/* Helper Function Prototypes */
+void accum_printf(void);
+
+/* Private Test H5Faccum Function Wrappers */
+#define accum_write(a,s,b) H5F_block_write(f, H5FD_MEM_DEFAULT, (haddr_t)(a), (size_t)(s), H5AC_dxpl_id, (b))
+#define accum_read(a,s,b) H5F_block_read(f, H5FD_MEM_DEFAULT, (haddr_t)(a), (size_t)(s), H5AC_dxpl_id, (b))
+#define accum_free(a,s) H5F_accum_free(f, H5AC_dxpl_id, H5FD_MEM_DEFAULT, (haddr_t)(a), (hsize_t)(s))
+#define accum_flush() H5F_accum_flush(f, H5AC_dxpl_id)
+#define accum_reset() H5F_accum_reset(f, H5AC_dxpl_id, TRUE)
+
+/* ================= */
+/* Main Test Routine */
+/* ================= */
+
+
+/*-------------------------------------------------------------------------
+ * Function: main
+ *
+ * Purpose: Test the metadata accumulator code
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Mike McGreevy
+ * October 7, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+main(void)
+{
+ unsigned nerrors = 0; /* track errors */
+ hid_t fid = -1;
+
+ /* Test Setup */
+ puts("Testing the metadata accumulator");
+
+ /* Create a test file */
+ if((fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
+
+ /* Get H5F_t * to internal file structure */
+ if(NULL == (f = (H5F_t *)H5I_object(fid))) FAIL_STACK_ERROR
+
+ /* We'll be writing lots of garbage data, so extend the
+ file a ways. 10MB should do. */
+ if(H5FD_set_eoa(f->shared->lf, H5FD_MEM_DEFAULT, (haddr_t)(1024*1024*10)) < 0) FAIL_STACK_ERROR
+
+ /* Reset metadata accumulator for the file */
+ if(accum_reset() < 0) FAIL_STACK_ERROR
+
+ /* Test Functions */
+ nerrors += test_write_read();
+ nerrors += test_write_read_nonacc_front();
+ nerrors += test_write_read_nonacc_end();
+ nerrors += test_accum_overlap();
+ nerrors += test_accum_overlap_clean();
+ nerrors += test_accum_overlap_size();
+ nerrors += test_accum_non_overlap_size();
+ nerrors += test_accum_adjust();
+ nerrors += test_read_after();
+ nerrors += test_free();
+ nerrors += test_big();
+ nerrors += test_random_write();
+
+ /* End of test code, close and delete file */
+ if(H5Fclose(fid) < 0) TEST_ERROR
+ HDremove(FILENAME);
+
+ if(nerrors)
+ goto error;
+ puts("All metadata accumulator tests passed.");
+
+ return 0;
+
+error:
+ puts("*** TESTS FAILED ***");
+ return 1;
+} /* end main() */
+
+/* ============================= */
+/* Individual Unit Test Routines */
+/* ============================= */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_write_read
+ *
+ * Purpose: Simple test to write to then read from metadata accumulator.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Mike McGreevy
+ * October 7, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+test_write_read(void)
+{
+ int i = 0;
+ int *write_buf, *read_buf;
+
+ TESTING("simple write/read to/from metadata accumulator");
+
+ /* Allocate buffers */
+ write_buf = (int *)HDmalloc(1024 * sizeof(int));
+ HDassert(write_buf);
+ read_buf = (int *)HDcalloc(1024, sizeof(int));
+ HDassert(read_buf);
+
+ /* Fill buffer with data, zero out read buffer */
+ for(i = 0; i < 1024; i++)
+ write_buf[i] = i + 1;
+
+ /* Do a simple write/read/verify of data */
+ /* Write 1KB at Address 0 */
+ if(accum_write(0, 1024, write_buf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(0, 1024, read_buf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(write_buf, read_buf, 1024) != 0) TEST_ERROR;
+
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+ PASSED();
+
+ /* Release memory */
+ HDfree(write_buf);
+ HDfree(read_buf);
+
+ return 0;
+
+error:
+ /* Release memory */
+ HDfree(write_buf);
+ HDfree(read_buf);
+
+ return 1;
+} /* test_write_read */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_write_read_nonacc_front
+ *
+ * Purpose: Simple test to write to then read from before metadata accumulator.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Allen Byrne
+ * October 8, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+test_write_read_nonacc_front(void)
+{
+ int i = 0;
+ int *write_buf, *read_buf;
+
+ TESTING("simple write/read to/from before metadata accumulator");
+
+ /* Allocate buffers */
+ write_buf = (int *)HDmalloc(2048 * sizeof(int));
+ HDassert(write_buf);
+ read_buf = (int *)HDcalloc(2048, sizeof(int));
+ HDassert(read_buf);
+
+ /* Fill buffer with data, zero out read buffer */
+ for(i = 0; i < 2048; i++)
+ write_buf[i] = i + 1;
+
+ /* Do a simple write/read/verify of data */
+ /* Write 1KB at Address 0 */
+ if(accum_write(0, 1024, write_buf) < 0) FAIL_STACK_ERROR;
+ if(accum_flush() < 0) FAIL_STACK_ERROR;
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+ if(accum_write(1024, 1024, write_buf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(0, 1024, read_buf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(write_buf, read_buf, 1024) != 0) TEST_ERROR;
+
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+ PASSED();
+
+ /* Release memory */
+ HDfree(write_buf);
+ HDfree(read_buf);
+
+ return 0;
+
+error:
+ /* Release memory */
+ HDfree(write_buf);
+ HDfree(read_buf);
+
+ return 1;
+} /* test_write_read */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_write_read_nonacc_end
+ *
+ * Purpose: Simple test to write to then read from after metadata accumulator.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Allen Byrne
+ * October 8, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+test_write_read_nonacc_end(void)
+{
+ int i = 0;
+ int *write_buf, *read_buf;
+
+ TESTING("simple write/read to/from after metadata accumulator");
+
+ /* Allocate buffers */
+ write_buf = (int *)HDmalloc(2048 * sizeof(int));
+ HDassert(write_buf);
+ read_buf = (int *)HDcalloc(2048, sizeof(int));
+ HDassert(read_buf);
+
+ /* Fill buffer with data, zero out read buffer */
+ for(i = 0; i < 2048; i++)
+ write_buf[i] = i + 1;
+
+ /* Do a simple write/read/verify of data */
+ /* Write 1KB at Address 0 */
+ if(accum_write(1024, 1024, write_buf) < 0) FAIL_STACK_ERROR;
+ if(accum_flush() < 0) FAIL_STACK_ERROR;
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+ if(accum_write(0, 1024, write_buf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(1024, 1024, read_buf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(write_buf, read_buf, 1024) != 0) TEST_ERROR;
+
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+ PASSED();
+
+ /* Release memory */
+ HDfree(write_buf);
+ HDfree(read_buf);
+
+ return 0;
+
+error:
+ /* Release memory */
+ HDfree(write_buf);
+ HDfree(read_buf);
+
+ return 1;
+} /* test_write_read */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_free
+ *
+ * Purpose: Simple test to free metadata accumulator.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Raymond Lu
+ * October 8, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+test_free(void)
+{
+ int i = 0;
+ int32_t *wbuf = NULL;
+ int32_t *rbuf = NULL;
+ int32_t *expect = NULL;
+
+ TESTING("simple freeing metadata accumulator");
+
+ /* Write and free the whole accumulator. */
+ wbuf = (int32_t *)HDmalloc(256 * sizeof(int32_t));
+ HDassert(wbuf);
+ rbuf = (int32_t *)HDmalloc(256 * sizeof(int32_t));
+ HDassert(rbuf);
+ expect = (int32_t *)HDmalloc(256 * sizeof(int32_t));
+ HDassert(expect);
+
+ /* Fill buffer with data */
+ for(i = 0; i < 256; i++)
+ wbuf[i] = (int32_t)(i + 1);
+
+ if(accum_write(0, 256 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+
+ if(accum_free(0, 256 * sizeof(int32_t)) < 0) FAIL_STACK_ERROR;
+
+ /* Free an empty accumulator */
+ if(accum_free(0, 256 * 1024 * sizeof(int32_t)) < 0) FAIL_STACK_ERROR;
+
+ /* Write second quarter of the accumulator */
+ if(accum_write(64 * sizeof(int32_t), 64 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Free the second quarter of the accumulator, the requested area
+ * is bigger than the data region on the right side. */
+ if(accum_free(64 * sizeof(int32_t), 65 * sizeof(int32_t)) < 0) FAIL_STACK_ERROR;
+
+
+ /* Write half of the accumulator. */
+ if(accum_write(0, 128 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Free the first block of 4B */
+ if(accum_free(0, sizeof(int32_t)) < 0) FAIL_STACK_ERROR;
+
+ /* Check that the accumulator still contains the correct data */
+ if(accum_read(1 * sizeof(int32_t), 127 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf + 1, rbuf, 127 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Free the block of 4B at 127*4B */
+ if(accum_free(127 * sizeof(int32_t), sizeof(int32_t)) < 0) FAIL_STACK_ERROR;
+
+ /* Check that the accumulator still contains the correct data */
+ if(accum_read(1 * sizeof(int32_t), 126 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf + 1, rbuf, 126 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Free the block of 4B at 2*4B */
+ if(accum_free(2 * sizeof(int32_t), sizeof(int32_t)) < 0) FAIL_STACK_ERROR;
+
+ /* Check that the accumulator still contains the correct data */
+ if(accum_read(1 * sizeof(int32_t), 1 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf + 1, rbuf, 1 * sizeof(int32_t)) != 0) TEST_ERROR;
+ if(accum_read(3 * sizeof(int32_t), 124 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf + 3, rbuf, 124 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+
+ /* Test freeing section that overlaps the start of the accumulator and is
+ * entirely before dirty section */
+ if(accum_write(64 * sizeof(int32_t), 128 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ HDmemcpy(expect + 64, wbuf, 128 * sizeof(int32_t));
+ if(accum_flush() < 0) FAIL_STACK_ERROR;
+ if(accum_write(68 * sizeof(int32_t), 4 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ HDmemcpy(expect + 68, wbuf, 4 * sizeof(int32_t));
+ if(accum_free(62 * sizeof(int32_t), 4 * sizeof(int32_t)) < 0) FAIL_STACK_ERROR;
+
+ /* Check that the accumulator still contains the correct data */
+ if(accum_read(66 * sizeof(int32_t), 126 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(expect + 66, rbuf, 126 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+
+ /* Test freeing section that overlaps the start of the accumulator and
+ * completely contains dirty section */
+ if(accum_write(64 * sizeof(int32_t), 128 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ HDmemcpy(expect + 64, wbuf, 128 * sizeof(int32_t));
+ if(accum_flush() < 0) FAIL_STACK_ERROR;
+ if(accum_write(68 * sizeof(int32_t), 4 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ HDmemcpy(expect + 68, wbuf, 4 * sizeof(int32_t));
+ if(accum_free(62 * sizeof(int32_t), 16 * sizeof(int32_t)) < 0) FAIL_STACK_ERROR;
+
+ /* Check that the accumulator still contains the correct data */
+ if(accum_read(78 * sizeof(int32_t), 114 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(expect + 78, rbuf, 114 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+
+ /* Test freeing section completely contained in accumulator and is entirely
+ * before dirty section */
+ if(accum_write(64 * sizeof(int32_t), 128 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ HDmemcpy(expect + 64, wbuf, 128 * sizeof(int32_t));
+ if(accum_flush() < 0) FAIL_STACK_ERROR;
+ if(accum_write(72 * sizeof(int32_t), 4 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ HDmemcpy(expect + 72, wbuf, 4 * sizeof(int32_t));
+ if(accum_free(66 * sizeof(int32_t), 4 * sizeof(int32_t)) < 0) FAIL_STACK_ERROR;
+
+ /* Check that the accumulator still contains the correct data */
+ if(accum_read(70 * sizeof(int32_t), 122 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(expect + 70, rbuf, 122 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+
+ /* Test freeing section completely contained in accumulator, starts before
+ * dirty section, and ends in dirty section */
+ if(accum_write(64 * sizeof(int32_t), 128 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ HDmemcpy(expect + 64, wbuf, 128 * sizeof(int32_t));
+ if(accum_flush() < 0) FAIL_STACK_ERROR;
+ if(accum_write(72 * sizeof(int32_t), 4 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ HDmemcpy(expect + 72, wbuf, 4 * sizeof(int32_t));
+ if(accum_free(70 * sizeof(int32_t), 4 * sizeof(int32_t)) < 0) FAIL_STACK_ERROR;
+
+ /* Check that the accumulator still contains the correct data */
+ if(accum_read(74 * sizeof(int32_t), 118 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(expect + 74, rbuf, 118 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+
+ /* Test freeing section completely contained in accumulator and completely
+ * contains dirty section */
+ if(accum_write(64 * sizeof(int32_t), 128 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ HDmemcpy(expect + 64, wbuf, 128 * sizeof(int32_t));
+ if(accum_flush() < 0) FAIL_STACK_ERROR;
+ if(accum_write(72 * sizeof(int32_t), 4 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ HDmemcpy(expect + 72, wbuf, 4 * sizeof(int32_t));
+ if(accum_free(70 * sizeof(int32_t), 8 * sizeof(int32_t)) < 0) FAIL_STACK_ERROR;
+
+ /* Check that the accumulator still contains the correct data */
+ if(accum_read(78 * sizeof(int32_t), 114 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(expect + 78, rbuf, 114 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+
+ /* Test freeing section completely contained in accumulator, starts at start
+ * of dirty section, and ends in dirty section */
+ if(accum_write(64 * sizeof(int32_t), 128 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ HDmemcpy(expect + 64, wbuf, 128 * sizeof(int32_t));
+ if(accum_flush() < 0) FAIL_STACK_ERROR;
+ if(accum_write(72 * sizeof(int32_t), 8 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ HDmemcpy(expect + 72, wbuf, 8 * sizeof(int32_t));
+ if(accum_free(72 * sizeof(int32_t), 4 * sizeof(int32_t)) < 0) FAIL_STACK_ERROR;
+
+ /* Check that the accumulator still contains the correct data */
+ if(accum_read(76 * sizeof(int32_t), 116 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(expect + 76, rbuf, 116 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ HDfree(wbuf);
+ HDfree(rbuf);
+ HDfree(expect);
+
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+ PASSED();
+
+ return 0;
+
+error:
+ HDfree(wbuf);
+ HDfree(rbuf);
+ HDfree(expect);
+
+ return 1;
+} /* test_free */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_accum_overlap
+ *
+ * Purpose: This test will write a series of pieces of data
+ * to the accumulator with the goal of overlapping
+ * the writes in various different ways.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Mike McGreevy
+ * October 7, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+test_accum_overlap(void)
+{
+ int i = 0;
+ int32_t *wbuf, *rbuf;
+
+ TESTING("overlapping write to metadata accumulator");
+
+ /* Allocate buffers */
+ wbuf = (int32_t *)HDmalloc(4096 * sizeof(int32_t));
+ HDassert(wbuf);
+ rbuf = (int32_t *)HDcalloc(4096, sizeof(int32_t));
+ HDassert(rbuf);
+
+ /* Case 1: No metadata in accumulator */
+ /* Write 10 1's at address 40 */
+ /* @0:| 1111111111| */
+ /* Put some data in the accumulator initially */
+ for(i = 0; i < 10; i++)
+ wbuf[i] = 1;
+ if(accum_write(40, 10 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(40, 10 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 10 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Case 2: End of new piece aligns with start of accumulated data */
+ /* Write 5 2's at address 20 */
+ /* @0:| 222221111111111| */
+ for(i = 0; i < 5; i++)
+ wbuf[i] = 2;
+ if(accum_write(20, 5 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(20, 5 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 5 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Case 3: Start of new piece aligns with start of accumulated data */
+ /* Write 3 3's at address 20 */
+ /* @0:| 333221111111111| */
+ for(i = 0; i < 3; i++)
+ wbuf[i] = 3;
+ if(accum_write(20, 3 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(20, 3 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 3 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Case 4: New piece overlaps start of accumulated data */
+ /* Write 5 4's at address 8 */
+ /* @0:| 444443221111111111| */
+ for(i = 0; i < 5; i++)
+ wbuf[i] = 4;
+ if(accum_write(8, 5 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(8, 5 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 5 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Case 5: New piece completely within accumulated data */
+ /* Write 4 5's at address 48 */
+ /* @0:| 444443221155551111| */
+ for(i = 0; i < 4; i++)
+ wbuf[i] = 5;
+ if(accum_write(48, 4 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(48, 4 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 4 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Case 6: End of new piece aligns with end of accumulated data */
+ /* Write 3 6's at address 68 */
+ /* @0:| 444443221155551666| */
+ for(i = 0; i < 3; i++)
+ wbuf[i] = 6;
+ if(accum_write(68, 3 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(68, 3 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 3 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Case 7: New piece overlaps end of accumulated data */
+ /* Write 5 7's at address 76 */
+ /* @0:| 4444432211555516677777| */
+ for(i = 0; i < 5; i++)
+ wbuf[i] = 7;
+ if(accum_write(76, 5 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(76, 5 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 5 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Case 8: Start of new piece aligns with end of accumulated data */
+ /* Write 3 8's at address 96 */
+ /* @0:| 4444432211555516677777888| */
+ for(i = 0; i < 3; i++)
+ wbuf[i] = 8;
+ if(accum_write(96, 3 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(96, 3 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 3 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Set up expected data buffer and verify contents of
+ accumulator as constructed by cases 1-8, above */
+ for(i = 0; i < 5; i++)
+ wbuf[i] = 4;
+ for(i = 5; i < 6; i++)
+ wbuf[i] = 3;
+ for(i = 6; i < 8; i++)
+ wbuf[i] = 2;
+ for(i = 8; i < 10; i++)
+ wbuf[i] = 1;
+ for(i = 10; i < 14; i++)
+ wbuf[i] = 5;
+ for(i = 14; i < 15; i++)
+ wbuf[i] = 1;
+ for(i = 15; i < 17; i++)
+ wbuf[i] = 6;
+ for(i = 17; i < 22; i++)
+ wbuf[i] = 7;
+ for(i = 22; i < 25; i++)
+ wbuf[i] = 8;
+ if(accum_read(8, 25 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 25 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Case 9: New piece completely before accumulated data */
+ /* Write 1 9 at address 0 */
+ /* @0:|9 4444432211555516677777888| */
+ for(i = 0; i < 1; i++)
+ wbuf[i] = 9;
+ if(accum_write(0, 1 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(0, 1 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 1 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Case 10: New piece completely after accumulated data */
+ /* Write 4 3's at address 116 */
+ /* @0:|9 4444432211555516677777888 3333| */
+ for(i = 0; i < 4; i++)
+ wbuf[i] = 3;
+ if(accum_write(116, 4 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(116, 4 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 4 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Case 11: New piece completely overlaps accumulated data */
+ /* Write 6 4's at address 112 */
+ /* @0:|9 4444432211555516677777888 444444| */
+ for(i = 0; i < 6; i++)
+ wbuf[i] = 4;
+ if(accum_write(112, 6 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(112, 6 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 6 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+ PASSED();
+
+ /* Release memory */
+ HDfree(wbuf);
+ HDfree(rbuf);
+
+ return 0;
+
+error:
+ /* Release memory */
+ HDfree(wbuf);
+ HDfree(rbuf);
+
+ return 1;
+} /* test_accum_overlap */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_accum_overlap_clean
+ *
+ * Purpose: This test will write a series of pieces of data
+ * to the accumulator with the goal of overlapping
+ * the writes in various different ways, with clean
+ * areas in the accumulator.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Neil Fortner
+ * October 8, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+test_accum_overlap_clean(void)
+{
+ int i = 0;
+ int32_t *wbuf, *rbuf;
+
+ TESTING("overlapping write to partially clean metadata accumulator");
+
+ /* Allocate buffers */
+ wbuf = (int32_t *)HDmalloc(4096 * sizeof(int32_t));
+ HDassert(wbuf);
+ rbuf = (int32_t *)HDcalloc(4096, sizeof(int32_t));
+ HDassert(rbuf);
+
+ /* Case 1: No metadata in accumulator */
+ /* Write 10 1's at address 40 */
+ /* @0:| 1111111111| */
+ /* Put some data in the accumulator initially */
+ for(i = 0; i < 10; i++)
+ wbuf[i] = 1;
+ if(accum_write(40, 10 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(40, 10 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 10 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Case 2: End of new piece aligns with start of clean accumulated data */
+ /* Write 5 2's at address 20 */
+ /* @0:| 222221111111111| */
+ if(accum_flush() < 0) FAIL_STACK_ERROR;
+ for(i = 0; i < 5; i++)
+ wbuf[i] = 2;
+ if(accum_write(20, 5 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(20, 5 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 5 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Case 3: Start of new piece aligns with start of accumulated data,
+ * completely encloses dirty section of accumulator */
+ /* Write 6 3's at address 20 */
+ /* @0:| 333333111111111| */
+ for(i = 0; i < 6; i++)
+ wbuf[i] = 3;
+ if(accum_write(20, 6 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(20, 6 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 6 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Case 4: New piece completely within accumulated data, overlaps
+ * end of dirty section of accumulator */
+ /* Write 2 4's at address 40 */
+ /* @0:| 333334411111111| */
+ for(i = 0; i < 2; i++)
+ wbuf[i] = 4;
+ if(accum_write(40, 2 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(40, 2 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 2 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Case 5: New piece completely within accumulated data, completely
+ * after dirty section of accumulator */
+ /* Write 2 5's at address 52 */
+ /* @0:| 333334415511111| */
+ for(i = 0; i < 2; i++)
+ wbuf[i] = 5;
+ if(accum_write(52, 2 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(52, 2 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 2 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Case 6: New piece completely within clean accumulated data */
+ /* Write 3 6's at address 44 */
+ /* @0:| 333334666511111| */
+ if(accum_flush() < 0) FAIL_STACK_ERROR;
+ for(i = 0; i < 3; i++)
+ wbuf[i] = 6;
+ if(accum_write(44, 3 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(44, 3 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 3 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Case 7: New piece overlaps start of clean accumulated data */
+ /* Write 2 7's at address 16 */
+ /* @0:| 7733334666511111| */
+ if(accum_flush() < 0) FAIL_STACK_ERROR;
+ for(i = 0; i < 2; i++)
+ wbuf[i] = 7;
+ if(accum_write(16, 2 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(16, 2 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 2 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Case 8: New piece overlaps start of accumulated data, completely
+ * encloses dirty section of accumulator */
+ /* Write 4 8's at address 12 */
+ /* @0:| 88883334666511111| */
+ for(i = 0; i < 4; i++)
+ wbuf[i] = 8;
+ if(accum_write(12, 4 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(12, 4 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 4 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Case 9: Start of new piece aligns with end of clean accumulated data */
+ /* Write 3 9's at address 80 */
+ /* @0:| 88883334666511111999| */
+ if(accum_flush() < 0) FAIL_STACK_ERROR;
+ for(i = 0; i < 3; i++)
+ wbuf[i] = 9;
+ if(accum_write(80, 3 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(80, 3 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 3 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Case 10: New piece overlaps end of clean accumulated data */
+ /* Write 3 2's at address 88 */
+ /* @0:| 888833346665111119922| */
+ if(accum_flush() < 0) FAIL_STACK_ERROR;
+ for(i = 0; i < 2; i++)
+ wbuf[i] = 2;
+ if(accum_write(88, 2 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(88, 2 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 2 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Case 11: New piece overlaps end of accumulated data, completely encloses
+ * dirty section of accumulator */
+ /* Write 4 7's at address 84 */
+ /* @0:| 8888333466651111197777| */
+ for(i = 0; i < 4; i++)
+ wbuf[i] = 7;
+ if(accum_write(84, 4 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(84, 4 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 4 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Set up expected data buffer and verify contents of
+ accumulator as constructed by cases 1-11, above */
+ for(i = 0; i < 4; i++)
+ wbuf[i] = 8;
+ for(i = 4; i < 7; i++)
+ wbuf[i] = 3;
+ for(i = 7; i < 8; i++)
+ wbuf[i] = 4;
+ for(i = 8; i < 11; i++)
+ wbuf[i] = 6;
+ for(i = 11; i < 12; i++)
+ wbuf[i] = 5;
+ for(i = 12; i < 17; i++)
+ wbuf[i] = 1;
+ for(i = 17; i < 18; i++)
+ wbuf[i] = 9;
+ for(i = 18; i < 22; i++)
+ wbuf[i] = 7;
+ if(accum_read(12, 22 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 22 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+ PASSED();
+
+ /* Release memory */
+ HDfree(wbuf);
+ HDfree(rbuf);
+
+ return 0;
+
+error:
+ /* Release memory */
+ HDfree(wbuf);
+ HDfree(rbuf);
+
+ return 1;
+} /* test_accum_overlap_clean */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_accum_non_overlap_size
+ *
+ * Purpose: This test will write a series of pieces of data
+ * to the accumulator with the goal of not overlapping
+ * the writes with a data size larger then the accum size.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Allen Byrne
+ * October 8, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+test_accum_non_overlap_size(void)
+{
+ int i = 0;
+ int32_t *wbuf, *rbuf;
+
+ TESTING("non-overlapping write to accumulator larger then accum_size");
+
+ /* Allocate buffers */
+ wbuf = (int *)HDmalloc(4096 * sizeof(int32_t));
+ HDassert(wbuf);
+ rbuf = (int *)HDcalloc(4096, sizeof(int32_t));
+ HDassert(rbuf);
+
+ /* Case 1: No metadata in accumulator */
+ /* Write 10 1's at address 140 */
+ /* @0:| 1111111111| */
+ /* Put some data in the accumulator initially */
+ for(i = 0; i < 10; i++)
+ wbuf[i] = 1;
+ if(accum_write(140, 10 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(140, 10 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 10 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Case 9: New piece completely before accumulated data */
+ /* Write 20 9 at address 0 */
+ /* @0:|9 1111111111| */
+ for(i = 0; i < 20; i++)
+ wbuf[i] = 9;
+ if(accum_write(0, 20 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(0, 20 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 20 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+ PASSED();
+
+ /* Release memory */
+ HDfree(wbuf);
+ HDfree(rbuf);
+
+ return 0;
+
+error:
+ /* Release memory */
+ HDfree(wbuf);
+ HDfree(rbuf);
+
+ return 1;
+} /* test_accum_non_overlap_size */
+
+/*-------------------------------------------------------------------------
+ * Function: test_accum_overlap_size
+ *
+ * Purpose: This test will write a series of pieces of data
+ * to the accumulator with the goal of overlapping
+ * the writes with a data size completely overlapping
+ * the accumulator at both ends.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Allen Byrne
+ * October 8, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+test_accum_overlap_size(void)
+{
+ int i = 0;
+ int32_t *wbuf, *rbuf;
+
+ TESTING("overlapping write to accumulator larger then accum_size");
+
+ /* Allocate buffers */
+ wbuf = (int32_t *)HDmalloc(4096 * sizeof(int32_t));
+ HDassert(wbuf);
+ rbuf = (int32_t *)HDcalloc(4096, sizeof(int32_t));
+ HDassert(rbuf);
+
+ /* Case 1: No metadata in accumulator */
+ /* Write 10 1's at address 64 */
+ /* @0:| 1111111111| */
+ /* Put some data in the accumulator initially */
+ for(i = 0; i < 10; i++)
+ wbuf[i] = 1;
+ if(accum_write(64, 10 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(64, 10 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 10 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ /* Case 9: New piece completely before accumulated data */
+ /* Write 72 9 at address 60 */
+ /* @0:|9 1111111111| */
+ for(i = 0; i < 72; i++)
+ wbuf[i] = 9;
+ if(accum_write(60, 72 * sizeof(int32_t), wbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(60, 72 * sizeof(int32_t), rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 72 * sizeof(int32_t)) != 0) TEST_ERROR;
+
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+ PASSED();
+
+ /* Release memory */
+ HDfree(wbuf);
+ HDfree(rbuf);
+
+ return 0;
+
+error:
+ /* Release memory */
+ HDfree(wbuf);
+ HDfree(rbuf);
+
+ return 1;
+} /* test_accum_overlap_size */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_accum_adjust
+ *
+ * Purpose: This test examines the various ways the accumulator might
+ * adjust itself as a result of data appending or prepending
+ * to it.
+ *
+ * This test program covers all the code in H5F_accum_adjust,
+ * but NOT all possible paths through said code. It only covers
+ * six potential paths through the function. (Again, though, each
+ * piece of code within an if/else statement in H5F_accum_adjust is
+ * covered by one of the paths in this test function). Since there
+ * are a ridiculous number of total possible paths through this
+ * function due to its large number of embedded if/else statements,
+ * that's certainly a lot of different test cases to write by hand.
+ * (Though if someone comes across this code and has some free
+ * time, go for it).
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Mike McGreevy
+ * October 11, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+test_accum_adjust(void)
+{
+ int i = 0;
+ int s = 1048576; /* size of buffer */
+ int32_t *wbuf, *rbuf;
+
+ TESTING("accumulator adjustments after append/prepend of data");
+
+ /* Allocate buffers */
+ wbuf = (int32_t *)HDmalloc((size_t)s * sizeof(int32_t));
+ HDassert(wbuf);
+ rbuf = (int32_t *)HDcalloc((size_t)s, sizeof(int32_t));
+ HDassert(rbuf);
+
+ /* Fill up write buffer */
+ for(i = 0; i < s; i++)
+ wbuf[i] = i + 1;
+
+ /* ================================================================ */
+ /* CASE 1: Prepending small block to large, fully dirty accumulator */
+ /* ================================================================ */
+
+ /* Write data to the accumulator to fill it just under 1MB (max size),
+ * but not quite full. This will force the accumulator to, on subsequent
+ * writes, a) have to adjust since it's nearly full, and b) prevent
+ * an increase in size because it's already at it's maximum size */
+ if(accum_write((1024 * 1024), (1024 * 1024) - 1, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Write a small (1KB) block that prepends to the front of the accumulator. */
+ /* ==> Accumulator will need more buffer space */
+ /* ==> Accumulator will try to resize, but see that it's getting too big */
+ /* ==> Size of new block is less than half maximum size of accumulator */
+ /* ==> New block is being prepended to accumulator */
+ /* ==> Accumulator is dirty, it will be flushed. */
+ /* ==> Dirty region overlaps region to eliminate from accumulator */
+ if(accum_write((1024 * 1024) - 1024, 1024, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Read back and verify first write */
+ if(accum_read((1024 * 1024), (1024 * 1024) - 1, rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, (1024 * 1024) - 1) != 0) TEST_ERROR;
+
+ /* Read back and verify second write */
+ if(accum_read((1024 * 1024) - 1024, 1024, rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 1024) != 0) TEST_ERROR;
+
+ /* Reset accumulator for next case */
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+ /* ================================================================ */
+ /* Case 2: Prepending large block to large, fully dirty accumulator */
+ /* ================================================================ */
+
+ /* Write data to the accumulator to fill it just under 1MB (max size),
+ * but not quite full. This will force the accumulator to, on subsequent
+ * writes, a) have to adjust since it's nearly full, and b) prevent
+ * an increase in size because it's already at it's maximum size */
+ if(accum_write((1024 * 1024), (1024 * 1024) - 1, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Write a large (just under 1MB) block to the front of the accumulator. */
+ /* ==> Accumulator will need more buffer space */
+ /* ==> Accumulator will try to resize, but see that it's getting too big */
+ /* ==> Size of new block is larger than half maximum size of accumulator */
+ /* ==> New block is being prepended to accumulator */
+ /* ==> Accumulator is dirty, it will be flushed. */
+ /* ==> Dirty region overlaps region to eliminate from accumulator */
+ if(accum_write(5, (1024 * 1024) - 5, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Read back and verify both pieces of data */
+ if(accum_read(1048576, 1048575, rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 1048576) != 0) TEST_ERROR;
+
+ if(accum_read(5, 1048571, rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 1048571) != 0) TEST_ERROR;
+
+ /* Reset accumulator for next case */
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+ /* ========================================================= */
+ /* Case 3: Appending small block to large, clean accumulator */
+ /* ========================================================= */
+
+ /* Write data to the accumulator to fill it just under 1MB (max size),
+ * but not quite full. This will force the accumulator to, on subsequent
+ * writes, a) have to adjust since it's nearly full, and b) prevent
+ * an increase in size because it's already at it's maximum size */
+ if(accum_write(0, (1024 * 1024) - 1, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Flush the accumulator -- we want to test the case when
+ accumulator contains clean data */
+ if(accum_flush() < 0) FAIL_STACK_ERROR
+
+ /* Write a small (1KB) block to the end of the accumulator */
+ /* ==> Accumulator will need more buffer space */
+ /* ==> Accumulator will try to resize, but see that it's getting too big */
+ /* ==> Size of new block is larger than half maximum size of accumulator */
+ /* ==> New block being appended to accumulator */
+ /* ==> Accumulator is NOT dirty */
+ /* ==> Since we're appending, need to adjust location of accumulator */
+ if(accum_write((1024 * 1024) - 1, 1024, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Write a piece of metadata outside current accumulator to force write
+ to disk */
+ if(accum_write(0, 1, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Read in the piece we wrote to disk above, and then verify that
+ the data is as expected */
+ if(accum_read((1024 * 1024) - 1, 1024, rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 1024) != 0) TEST_ERROR;
+
+ /* Reset accumulator for next case */
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+ /* ==================================================================== */
+ /* Case 4: Appending small block to large, partially dirty accumulator, */
+ /* with existing dirty region NOT aligning with the new block */
+ /* ==================================================================== */
+
+ /* Write data to the accumulator to fill it just under 1MB (max size),
+ * but not quite full. This will force the accumulator to, on subsequent
+ * writes, a) have to adjust since it's nearly full, and b) prevent
+ * an increase in size because it's already at it's maximum size */
+ if(accum_write(0, (1024 * 1024) - 5, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Flush the accumulator to clean it */
+ if(accum_flush() < 0) FAIL_STACK_ERROR
+
+ /* write to part of the accumulator so just the start of it is dirty */
+ if(accum_write(0, 5, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Write a small (~340KB) piece of data to the other end of the accumulator */
+ /* ==> Accumulator will need more buffer space */
+ /* ==> Accumulator will try to resize, but see that it's getting too big */
+ /* ==> Size of new block is less than than half maximum size of accumulator */
+ /* ==> New block being appended to accumulator */
+ /* ==> We can slide the dirty region down, to accomodate the request */
+ /* ==> Max Buffer Size - (dirty offset + adjust size) >= 2 * size) */
+ /* ==> Need to adjust location of accumulator while appending */
+ /* ==> Accumulator will need to be reallocated */
+ if(accum_write(1048571, 349523, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Write a piece of metadata outside current accumulator to force write
+ to disk */
+ if(accum_write(1398900, 1, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Read in the piece we wrote to disk above, and then verify that
+ the data is as expected */
+ if(accum_read(1048571, 349523, rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 349523) != 0) TEST_ERROR;
+
+ /* Reset accumulator for next case */
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+ /* ==================================================================== */
+ /* Case 5: Appending small block to large, partially dirty accumulator, */
+ /* with existing dirty region aligning with new block */
+ /* ==================================================================== */
+
+ /* Write data to the accumulator to fill it just under max size (but not full) */
+ if(accum_write(0, (1024 * 1024) - 5, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Flush the accumulator to clean it */
+ if(accum_flush() < 0) FAIL_STACK_ERROR
+
+ /* write to part of the accumulator so it's dirty, but not entirely dirty */
+ /* (just the begging few bytes will be clean) */
+ if(accum_write(10, (1024 * 1024) - 15, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Write a small piece of data to the dirty end of the accumulator */
+ /* ==> Accumulator will need more buffer space */
+ /* ==> Accumulator will try to resize, but see that it's getting too big */
+ /* ==> Size of new block is less than than half maximum size of accumulator */
+ /* ==> New block being appended to accumulator */
+ /* ==> We can slide the dirty region down, to accomodate the request */
+ /* ==> Max Buffer Size - (dirty offset + adjust size) < 2 * size) */
+ /* ==> Need to adjust location of accumulator while appending */
+ if(accum_write((1024 * 1024) - 5, 10, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Write a piece of metadata outside current accumulator to force write
+ to disk */
+ if(accum_write(0, 1, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Read in the piece we wrote to disk above, and then verify that
+ the data is as expected */
+ if(accum_read((1024 * 1024) - 5, 10, rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 10) != 0) TEST_ERROR;
+
+ /* Reset accumulator for next case */
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+ /* ================================================================= */
+ /* Case 6: Appending small block to large, fully dirty accumulator */
+ /* ================================================================= */
+
+ /* Write data to the accumulator to fill it just under 1MB (max size),
+ * but not quite full. This will force the accumulator to, on subsequent
+ * writes, a) have to adjust since it's nearly full, and b) prevent
+ * an increase in size because it's already at it's maximum size */
+ if(accum_write(0, (1024 * 1024) - 5, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Write a small (~340KB) piece of data to the end of the accumulator */
+ /* ==> Accumulator will need more buffer space */
+ /* ==> Accumulator will try to resize, but see that it's getting too big */
+ /* ==> Size of new block is less than than half maximum size of accumulator */
+ /* ==> New block being appended to accumulator */
+ /* ==> We cannot slide dirty region down, it's all dirty */
+ /* ==> Dirty region overlaps region to eliminate from accumulator */
+ /* ==> Need to adjust location of accumulator while appending */
+ if(accum_write(1048571, 349523, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Write a piece of metadata outside current accumulator to force write
+ to disk */
+ if(accum_write(1398900, 1, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Read in the piece we wrote to disk above, and then verify that
+ the data is as expected */
+ if(accum_read(1048571, 349523, rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 349523) != 0) TEST_ERROR;
+
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+ PASSED();
+
+ /* Release memory */
+ HDfree(wbuf);
+ HDfree(rbuf);
+
+ return 0;
+
+error:
+ /* Release memory */
+ HDfree(wbuf);
+ HDfree(rbuf);
+
+ return 1;
+} /* test_accum_adjust */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_read_after
+ *
+ * Purpose: This test will verify the case when metadata is read partly
+ * from the accumulator and partly from disk. The test will
+ * write a block of data at address 512, force the data to be
+ * written to disk, write new data partially overlapping the
+ * original block from below, then read data at address 512.
+ * The data read should be partly new and partly original.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Larry Knox
+ * October 8, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+test_read_after(void)
+{
+ int i = 0;
+ int s = 128; /* size of buffer */
+ int32_t *wbuf, *rbuf;
+
+ TESTING("reading data from both accumulator and disk");
+
+ /* Allocate buffers */
+ wbuf = (int32_t *)HDmalloc((size_t)s * sizeof(int32_t));
+ HDassert(wbuf);
+ rbuf = (int32_t *)HDcalloc((size_t)s, sizeof(int32_t));
+ HDassert(rbuf);
+
+ /* Fill up write buffer with 1s */
+ for(i = 0; i < s; i++)
+ wbuf[i] = 1;
+
+ /* Write data to the accumulator to fill it. */
+ if(accum_write(512, 512, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Write a piece of metadata outside current accumulator to force write
+ to disk */
+ if(accum_write(0, 1, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Fill up write buffer with 2s */
+ for(i = 0; i < s; i++)
+ wbuf[i] = 2;
+
+ /* Write a block of 2s of the original size that will overlap the lower half
+ of the original block */
+ if(accum_write(256, 512, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Read 128 bytes at the original address, and then */
+ if(accum_read(512, 512, rbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Set the second half of wbuf back to 1s */
+ for(i = 64; i < s; i++)
+ wbuf[i] = 1;
+
+ /* Read in the piece we wrote to disk above, and then verify that
+ the data is as expected */
+ if(accum_read(512, 512, rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf, rbuf, 128) != 0) TEST_ERROR;
+
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+ PASSED();
+
+ /* Release memory */
+ HDfree(wbuf);
+ HDfree(rbuf);
+
+ return 0;
+
+error:
+ /* Release memory */
+ HDfree(wbuf);
+ HDfree(rbuf);
+
+ return 1;
+} /* end test_read_after */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_big
+ *
+ * Purpose: This test exercises writing large pieces of metadata to the
+ * file.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * October 12, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+test_big(void)
+{
+ uint8_t *wbuf, *wbuf2, *rbuf, *zbuf; /* Buffers for reading & writing, etc */
+ unsigned u; /* Local index variable */
+
+ /* Allocate space for the write & read buffers */
+ wbuf = (uint8_t *)HDmalloc(BIG_BUF_SIZE);
+ HDassert(wbuf);
+ wbuf2 = (uint8_t *)HDmalloc(BIG_BUF_SIZE);
+ HDassert(wbuf2);
+ rbuf = (uint8_t *)HDcalloc(BIG_BUF_SIZE + 1536, 1);
+ HDassert(rbuf);
+ zbuf = (uint8_t *)HDcalloc(BIG_BUF_SIZE + 1536, 1);
+ HDassert(zbuf);
+
+ /* Initialize write buffers */
+ for(u = 0; u < BIG_BUF_SIZE; u++) {
+ wbuf[u] = (uint8_t)u;
+ wbuf2[u] = (uint8_t)(u + 1);
+ } /* end for */
+
+ TESTING("large metadata I/O operations");
+
+ /* Write large data segment to file */
+ if(accum_write(0, BIG_BUF_SIZE, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Read entire segment back from file */
+ if(accum_read(0, BIG_BUF_SIZE, rbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Verify data read */
+ if(HDmemcmp(wbuf, rbuf, BIG_BUF_SIZE) != 0) TEST_ERROR;
+
+
+ /* Reset data in file back to zeros & reset the read buffer */
+ if(accum_write(0, BIG_BUF_SIZE, zbuf) < 0) FAIL_STACK_ERROR;
+ HDmemset(rbuf, 0, BIG_BUF_SIZE);
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+
+ /* Write small section to middle of accumulator */
+ if(accum_write(1024, 1024, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Read entire segment back from file */
+ /* (Read covers entire dirty region) */
+ if(accum_read(0, BIG_BUF_SIZE, rbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Verify data read */
+ if(HDmemcmp(zbuf, rbuf, 1024) != 0) TEST_ERROR;
+ if(HDmemcmp(wbuf, rbuf + 1024, 1024) != 0) TEST_ERROR;
+ if(HDmemcmp(zbuf, rbuf + 2048, (BIG_BUF_SIZE - 2048)) != 0) TEST_ERROR;
+
+
+ /* Reset data in file back to zeros & reset the read buffer */
+ if(accum_write(1024, 1024, zbuf) < 0) FAIL_STACK_ERROR;
+ HDmemset(rbuf, 0, BIG_BUF_SIZE);
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+
+ /* Write small section to overlap with end of "big" region */
+ if(accum_write(BIG_BUF_SIZE - 512, 1024, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Read entire segment back from file */
+ /* (Read covers bottom half of dirty region) */
+ if(accum_read(0, BIG_BUF_SIZE, rbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Verify data read */
+ if(HDmemcmp(zbuf, rbuf, (BIG_BUF_SIZE - 512)) != 0) TEST_ERROR;
+ if(HDmemcmp(wbuf, rbuf + (BIG_BUF_SIZE - 512), 512) != 0) TEST_ERROR;
+
+
+ /* Reset data in file back to zeros & reset the read buffer */
+ if(accum_write(BIG_BUF_SIZE - 512, 1024, zbuf) < 0) FAIL_STACK_ERROR;
+ HDmemset(rbuf, 0, BIG_BUF_SIZE);
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+
+ /* Write small section to overlap with beginning of "big" region */
+ if(accum_write(0, 1024, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Read entire segment back from file */
+ /* (Read covers bottom half of dirty region) */
+ if(accum_read(512, BIG_BUF_SIZE, rbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Verify data read */
+ if(HDmemcmp(wbuf + 512, rbuf, 512) != 0) TEST_ERROR;
+ if(HDmemcmp(zbuf, rbuf + 512, (BIG_BUF_SIZE - 512)) != 0) TEST_ERROR;
+
+
+ /* Reset data in file back to zeros & reset the read buffer */
+ if(accum_write(0, 1024, zbuf) < 0) FAIL_STACK_ERROR;
+ HDmemset(rbuf, 0, BIG_BUF_SIZE);
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+
+ /* Write small section to middle of accumulator */
+ /* (With write buffer #1) */
+ if(accum_write(1024, 1024, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Write entire segment to from file */
+ /* (With write buffer #2) */
+ /* (Write covers entire dirty region) */
+ if(accum_write(0, BIG_BUF_SIZE, wbuf2) < 0) FAIL_STACK_ERROR;
+
+ /* Read entire segment back from file */
+ if(accum_read(0, BIG_BUF_SIZE, rbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Verify data read */
+ if(HDmemcmp(wbuf2, rbuf, BIG_BUF_SIZE) != 0) TEST_ERROR;
+
+
+ /* Reset data in file back to zeros & reset the read buffer */
+ if(accum_write(0, BIG_BUF_SIZE, zbuf) < 0) FAIL_STACK_ERROR;
+ HDmemset(rbuf, 0, BIG_BUF_SIZE);
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+
+ /* Write small section to overlap with end of "big" region */
+ /* (With write buffer #1) */
+ if(accum_write(BIG_BUF_SIZE - 512, 1024, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Write entire segment to from file */
+ /* (With write buffer #2) */
+ /* (Read covers bottom half of dirty region) */
+ if(accum_write(0, BIG_BUF_SIZE, wbuf2) < 0) FAIL_STACK_ERROR;
+
+ /* Read both segments back from file */
+ if(accum_read(0, BIG_BUF_SIZE + 512, rbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Verify data read */
+ if(HDmemcmp(wbuf2, rbuf, BIG_BUF_SIZE) != 0) TEST_ERROR;
+ if(HDmemcmp(wbuf + 512, rbuf + BIG_BUF_SIZE, 512) != 0) TEST_ERROR;
+
+
+ /* Reset data in file back to zeros & reset the read buffer */
+ if(accum_write(0, BIG_BUF_SIZE + 512, zbuf) < 0) FAIL_STACK_ERROR;
+ HDmemset(rbuf, 0, BIG_BUF_SIZE + 512);
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+
+ /* Write small section to be past "big" region */
+ /* (With write buffer #1) */
+ if(accum_write(BIG_BUF_SIZE + 512, 1024, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Read section before "big" region */
+ /* (To enlarge accumulator, to it will intersect with big write) */
+ if(accum_read(BIG_BUF_SIZE - 512, 1024, rbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Write entire segment to from file */
+ /* (With write buffer #2) */
+ /* (Doesn't overlap with small section) */
+ if(accum_write(0, BIG_BUF_SIZE, wbuf2) < 0) FAIL_STACK_ERROR;
+
+ /* Read both segments & gap back from file */
+ if(accum_read(0, BIG_BUF_SIZE + 1024, rbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Verify data read */
+ if(HDmemcmp(wbuf2, rbuf, BIG_BUF_SIZE) != 0) TEST_ERROR;
+ if(HDmemcmp(zbuf, rbuf + BIG_BUF_SIZE, 512) != 0) TEST_ERROR;
+ if(HDmemcmp(wbuf, rbuf + BIG_BUF_SIZE + 512, 512) != 0) TEST_ERROR;
+
+
+ /* Reset data in file back to zeros & reset the read buffer */
+ if(accum_write(0, BIG_BUF_SIZE + 1536, zbuf) < 0) FAIL_STACK_ERROR;
+ HDmemset(rbuf, 0, BIG_BUF_SIZE + 1024);
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+
+ /* Write small section to be past "big" region */
+ /* (With write buffer #1) */
+ if(accum_write(BIG_BUF_SIZE + 512, 1024, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Read section before "big" region */
+ /* (To enlarge accumulator, so it will intersect with big write) */
+ if(accum_read(BIG_BUF_SIZE - 512, 1024, rbuf) < 0) FAIL_STACK_ERROR;
+ if(accum_read(BIG_BUF_SIZE + 1536, 1024, rbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Write entire segment to from file */
+ /* (With write buffer #2) */
+ /* (Overwriting dirty region, but not invalidating entire accumulator) */
+ if(accum_write(1536, BIG_BUF_SIZE, wbuf2) < 0) FAIL_STACK_ERROR;
+
+ /* Read both segments & gap back from file */
+ if(accum_read(0, BIG_BUF_SIZE + 1536, rbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Verify data read */
+ if(HDmemcmp(zbuf, rbuf, 1536) != 0) TEST_ERROR;
+ if(HDmemcmp(wbuf2, rbuf + 1536, BIG_BUF_SIZE) != 0) TEST_ERROR;
+
+
+ /* Reset data in file back to zeros & reset the read buffer */
+ if(accum_write(1536, BIG_BUF_SIZE, zbuf) < 0) FAIL_STACK_ERROR;
+ HDmemset(rbuf, 0, BIG_BUF_SIZE + 1536);
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+
+ /* Write small section before "big" region */
+ /* (With write buffer #1) */
+ if(accum_write(1024, 1024, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Read section before "big" region */
+ /* (To enlarge accumulator, so it will intersect with big write) */
+ if(accum_read(0, 1024, rbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Write entire segment to from file */
+ /* (With write buffer #2) */
+ /* (Overwriting dirty region, but not invalidating entire accumulator) */
+ if(accum_write(512, BIG_BUF_SIZE, wbuf2) < 0) FAIL_STACK_ERROR;
+
+ /* Read both segments & gap back from file */
+ if(accum_read(0, BIG_BUF_SIZE + 512, rbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Verify data read */
+ if(HDmemcmp(zbuf, rbuf, 512) != 0) TEST_ERROR;
+ if(HDmemcmp(wbuf2, rbuf + 512, BIG_BUF_SIZE) != 0) TEST_ERROR;
+
+
+ /* Reset data in file back to zeros & reset the read buffer */
+ if(accum_write(512, BIG_BUF_SIZE, zbuf) < 0) FAIL_STACK_ERROR;
+ HDmemset(rbuf, 0, BIG_BUF_SIZE + 512);
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+
+ /* Write small section before "big" region */
+ /* (With write buffer #1) */
+ if(accum_write(0, 1024, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Read section before "big" region */
+ /* (To enlarge accumulator, so it will intersect with big write) */
+ if(accum_read(1024, 1024, rbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Write entire segment to from file */
+ /* (With write buffer #2) */
+ /* (Avoiding dirty region, and not invalidating entire accumulator) */
+ if(accum_write(1536, BIG_BUF_SIZE, wbuf2) < 0) FAIL_STACK_ERROR;
+
+ /* Read both segments & gap back from file */
+ if(accum_read(0, BIG_BUF_SIZE + 1536, rbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Verify data read */
+ if(HDmemcmp(wbuf, rbuf, 1024) != 0) TEST_ERROR;
+ if(HDmemcmp(zbuf, rbuf + 1024, 512) != 0) TEST_ERROR;
+ if(HDmemcmp(wbuf2, rbuf + 1536, BIG_BUF_SIZE) != 0) TEST_ERROR;
+
+
+ /* Reset data in file back to zeros & reset the read buffer */
+ if(accum_write(0, BIG_BUF_SIZE + 1536, zbuf) < 0) FAIL_STACK_ERROR;
+ HDmemset(rbuf, 0, BIG_BUF_SIZE + 1536);
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+
+ /* Write small section before "big" region */
+ /* (With write buffer #1) */
+ if(accum_write(0, 1024, wbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Read section before "big" region */
+ /* (To enlarge accumulator, so it will intersect with big write) */
+ if(accum_read(1024, 1024, rbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Write entire segment to from file */
+ /* (With write buffer #2) */
+ /* (Partially overwriting dirty region, and not invalidating entire accumulator) */
+ if(accum_write(512, BIG_BUF_SIZE, wbuf2) < 0) FAIL_STACK_ERROR;
+
+ /* Read both segments back from file */
+ if(accum_read(0, BIG_BUF_SIZE + 512, rbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Verify data read */
+ if(HDmemcmp(wbuf, rbuf, 512) != 0) TEST_ERROR;
+ if(HDmemcmp(wbuf2, rbuf + 512, BIG_BUF_SIZE) != 0) TEST_ERROR;
+
+
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+ PASSED();
+
+ /* Release memory */
+ HDfree(wbuf);
+ HDfree(wbuf2);
+ HDfree(rbuf);
+ HDfree(zbuf);
+
+ return 0;
+
+error:
+ HDfree(wbuf);
+ HDfree(wbuf2);
+ HDfree(rbuf);
+ HDfree(zbuf);
+
+ return 1;
+} /* end test_random_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_random_write
+ *
+ * Purpose: This test writes random pieces of data to the file and
+ * then reads it all back.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * October 11, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+test_random_write(void)
+{
+ uint8_t *wbuf, *rbuf; /* Buffers for reading & writing */
+ unsigned long seed = 0; /* Random # seed */
+ size_t *off; /* Offset of buffer segments to write */
+ size_t *len; /* Size of buffer segments to write */
+ size_t cur_off; /* Current offset */
+ size_t nsegments; /* Number of segments to write */
+ size_t swap; /* Position to swap with */
+ unsigned u; /* Local index variable */
+
+ /* Allocate space for the write & read buffers */
+ wbuf = (uint8_t *)malloc(RANDOM_BUF_SIZE);
+ HDassert(wbuf);
+ rbuf = (uint8_t *)calloc(RANDOM_BUF_SIZE, 1);
+ HDassert(rbuf);
+
+ /* Initialize write buffer */
+ for(u = 0; u < RANDOM_BUF_SIZE; u++)
+ wbuf[u] = (uint8_t)u;
+
+ TESTING("random writes to accumulator");
+
+ /* Choose random # seed */
+ seed = (unsigned long)HDtime(NULL);
+#ifdef QAK
+/* seed = (unsigned long)1155438845; */
+HDfprintf(stderr, "Random # seed was: %lu\n", seed);
+#endif /* QAK */
+ HDsrandom(seed);
+
+ /* Allocate space for the segment length buffer */
+ off = (size_t *)malloc(MAX_RANDOM_SEGMENTS * sizeof(size_t));
+ HDassert(off);
+ len = (size_t *)malloc(MAX_RANDOM_SEGMENTS * sizeof(size_t));
+ HDassert(len);
+
+ /* Randomly choose lengths of segments */
+ cur_off = 0;
+ for(u = 0; u < MAX_RANDOM_SEGMENTS; ) {
+ size_t length = 0; /* Length of current segment */
+
+ /* Choose random length of segment, allowing for variance */
+ do {
+ length += (size_t)(HDrandom() % RAND_SEG_LEN) + 1;
+ } while((HDrandom() & 256) >= 128); /* end while */
+
+ /* Check for going off end of buffer */
+ if((cur_off + length) > RANDOM_BUF_SIZE)
+ length = RANDOM_BUF_SIZE - cur_off;
+
+ /* Set offset & length of segment */
+ off[u] = cur_off;
+ len[u] = length;
+
+ /* Advance array offset */
+ u++;
+
+ /* Advance current offset */
+ cur_off += length;
+
+ /* If we've used up entire buffer before hitting limit of segments, get out */
+ if(cur_off >= RANDOM_BUF_SIZE)
+ break;
+ } /* end for */
+ nsegments = u;
+
+ /* Increase length of last segment, if it doesn't reach end of buffer */
+ if(nsegments < MAX_RANDOM_SEGMENTS)
+ len[nsegments - 1] = RANDOM_BUF_SIZE - off[nsegments - 1];
+
+ /* Shuffle order of segments, to randomize positions to write */
+ for(u = 0; u < nsegments; u++) {
+ size_t tmp; /* Temporary holder for offset & length values */
+
+ /* Choose value within next few elements to to swap with */
+ swap = ((size_t)HDrandom() % 8) + u;
+ if(swap >= nsegments)
+ swap = nsegments - 1;
+
+ /* Swap values */
+ tmp = off[u]; off[u] = off[swap]; off[swap] = tmp;
+ tmp = len[u]; len[u] = len[swap]; len[swap] = tmp;
+ } /* end for */
+
+ /* Write data segments to file */
+ for(u = 0; u < nsegments; u++) {
+ if(accum_write(RANDOM_BASE_OFF + off[u], len[u], wbuf + off[u]) < 0) FAIL_STACK_ERROR;
+
+ /* Verify individual reads */
+ if(accum_read(RANDOM_BASE_OFF + off[u], len[u], rbuf) < 0) FAIL_STACK_ERROR;
+ if(HDmemcmp(wbuf + off[u], rbuf, len[u]) != 0) TEST_ERROR;
+ } /* end for */
+
+ /* Read entire region back from file */
+ if(accum_read(RANDOM_BASE_OFF, RANDOM_BUF_SIZE, rbuf) < 0) FAIL_STACK_ERROR;
+
+ /* Verify data read back in */
+ if(HDmemcmp(wbuf, rbuf, RANDOM_BUF_SIZE) != 0) TEST_ERROR;
+
+ if(accum_reset() < 0) FAIL_STACK_ERROR;
+
+ PASSED();
+
+ /* Release memory */
+ HDfree(wbuf);
+ HDfree(rbuf);
+ HDfree(off);
+ HDfree(len);
+
+ return 0;
+
+error:
+ /* Release memory */
+ HDfree(wbuf);
+ HDfree(rbuf);
+ HDfree(off);
+ HDfree(len);
+
+ HDfprintf(stderr, "Random # seed was: %lu\n", seed);
+ return 1;
+} /* end test_random_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: accum_printf
+ *
+ * Purpose: Debug function to print some stats about the accumulator
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Mike McGreevy
+ * October 7, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+accum_printf(void)
+{
+ H5F_meta_accum_t * accum = &f->shared->accum;
+
+ printf("\n");
+ printf("Current contents of accumulator:\n");
+ if (accum->alloc_size == 0) {
+ printf("=====================================================\n");
+ printf(" No accumulator allocated.\n");
+ printf("=====================================================\n");
+ } else {
+ printf("=====================================================\n");
+ printf(" accumulator allocated size == %lu\n", (unsigned long)accum->alloc_size);
+ printf(" accumulated data size == %lu\n", (unsigned long)accum->size);
+ printf(" accumulator dirty? == %d\n", accum->dirty);
+ printf("=====================================================\n");
+ printf(" start of accumulated data, loc = %llu\n", accum->loc);
+ if (accum->dirty) printf(" start of dirty region, loc = %llu\n", accum->loc + accum->dirty_off);
+ if (accum->dirty) printf(" end of dirty region, loc = %llu\n", accum->loc + accum->dirty_off + accum->dirty_len);
+ printf(" end of accumulated data, loc = %llu\n", accum->loc + accum->size);
+ printf(" end of accumulator allocation, loc = %llu\n", accum->loc + accum->alloc_size);
+ printf("=====================================================\n");
+ }
+ printf("\n\n");
+} /* accum_printf() */
+