summaryrefslogtreecommitdiffstats
path: root/src/H5Faccum.c
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 /src/H5Faccum.c
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
Diffstat (limited to 'src/H5Faccum.c')
-rw-r--r--src/H5Faccum.c721
1 files changed, 426 insertions, 295 deletions
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) {