summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2010-08-17 13:08:34 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2010-08-17 13:08:34 (GMT)
commitee251b8395c98300e2c3b43fbddc7fe4461e6086 (patch)
treeb00bf669d1691592059897a78164999d46ca8b2b /src
parent771a850c58b88ffd4f8519573f175dcd0b90a65f (diff)
downloadhdf5-ee251b8395c98300e2c3b43fbddc7fe4461e6086.zip
hdf5-ee251b8395c98300e2c3b43fbddc7fe4461e6086.tar.gz
hdf5-ee251b8395c98300e2c3b43fbddc7fe4461e6086.tar.bz2
[svn-r19247] Description:
Bring r19246 from Coverity branch to trunk: Improve metadata "accumulator" for files to track the dirty region within the accumulator data. This allows the accumulator to drop clean data and reduces the number of I/O operations when it is dirtied. This is progress toward Bz#1142 - speeding up the fheap test (which it doesn't help much, actually, but it does help other aspects of file I/O). Tested on: FreeBSD/32 6.3 (duty) in debug mode FreeBSD/64 6.3 (liberty) w/C++ & FORTRAN, in debug mode Linux/32 2.6 (jam) w/PGI compilers, w/default API=1.8.x, w/C++ & FORTRAN, w/threadsafe, in debug mode Linux/64-amd64 2.6 (amani) w/Intel compilers, w/default API=1.6.x, w/C++ & FORTRAN, in production mode Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN, w/szip filter, w/threadsafe, in production mode Linux/PPC 2.6 (heiwa) w/C++ & FORTRAN, w/threadsafe, in debug mode Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN, in production mode Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in debug mode Mac OS X/32 10.6.4 (amazon) in debug mode Mac OS X/32 10.6.4 (amazon) w/C++ & FORTRAN, w/threadsafe, in production mode Mac OS X/32 10.6.4 (amazon) w/parallel, in debug mode
Diffstat (limited to 'src')
-rw-r--r--src/H5Faccum.c285
-rw-r--r--src/H5Fpkg.h2
2 files changed, 234 insertions, 53 deletions
diff --git a/src/H5Faccum.c b/src/H5Faccum.c
index 426a639..c170671 100644
--- a/src/H5Faccum.c
+++ b/src/H5Faccum.c
@@ -143,13 +143,18 @@ H5F_accum_read(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
- new_addr);
/* Check if we need more buffer space */
- if(new_size > f->shared->accum.size) {
- /* Adjust the buffer size, by doubling it */
- f->shared->accum.alloc_size = MAX(f->shared->accum.alloc_size * 2, new_size);
+ 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, f->shared->accum.alloc_size)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate 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));
#endif /* H5_CLEAR_MEMORY */
@@ -163,6 +168,10 @@ HDmemset(f->shared->accum.buf + f->shared->accum.size, 0, (f->shared->accum.allo
/* 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;
+
/* 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")
@@ -228,6 +237,7 @@ H5F_accum_adjust(H5F_meta_accum_t *accum, H5FD_t *lf, hid_t dxpl_id,
HDassert(accum);
HDassert(lf);
+ HDassert(H5F_ACCUM_APPEND == adjust || H5F_ACCUM_PREPEND == adjust);
HDassert(size > 0);
HDassert(size <= H5F_ACCUM_MAX_SIZE);
@@ -252,36 +262,65 @@ H5F_accum_adjust(H5F_meta_accum_t *accum, H5FD_t *lf, hid_t dxpl_id,
remnant_size = 0;
} /* end if */
else {
- new_size = (H5F_ACCUM_MAX_SIZE / 2);
- shrink_size = (H5F_ACCUM_MAX_SIZE / 2);
- remnant_size = accum->size - shrink_size;
+ if(H5F_ACCUM_PREPEND == adjust) {
+ new_size = (H5F_ACCUM_MAX_SIZE / 2);
+ shrink_size = (H5F_ACCUM_MAX_SIZE / 2);
+ remnant_size = accum->size - shrink_size;
+ } /* end if */
+ else {
+ size_t adjust_size = size + accum->dirty_len;
+
+ /* Check if we can slide the dirty region down, to accommodate the request */
+ if(accum->dirty && (adjust_size <= H5F_ACCUM_MAX_SIZE)) {
+ if((ssize_t)(H5F_ACCUM_MAX_SIZE - (accum->dirty_off + adjust_size)) >= (ssize_t)(2 * size))
+ shrink_size = accum->dirty_off / 2;
+ else
+ shrink_size = accum->dirty_off;
+ remnant_size = accum->size - shrink_size;
+ new_size = remnant_size + size;
+ } /* end if */
+ else {
+ new_size = (H5F_ACCUM_MAX_SIZE / 2);
+ shrink_size = (H5F_ACCUM_MAX_SIZE / 2);
+ remnant_size = accum->size - shrink_size;
+ } /* end else */
+ } /* end else */
} /* end else */
/* Check if we need to flush accumulator data to file */
if(accum->dirty) {
/* Check whether to accumulator will be prepended or appended */
if(H5F_ACCUM_PREPEND == adjust) {
- /* Write out upper part of the existing metadata accumulator, with dispatch to driver */
- if(H5FD_write(lf, dxpl_id, H5FD_MEM_DEFAULT, (accum->loc + remnant_size), shrink_size, (accum->buf + remnant_size)) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
+ /* Check if the dirty region overlaps the region to eliminate from the accumulator */
+ if((accum->size - shrink_size) < (accum->dirty_off + accum->dirty_len)) {
+ /* Write out the dirty region from the metadata accumulator, with dispatch to driver */
+ if(H5FD_write(lf, dxpl_id, H5FD_MEM_DEFAULT, (accum->loc + accum->dirty_off), accum->dirty_len, (accum->buf + accum->dirty_off)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "file write failed")
+
+ /* Reset accumulator dirty flag */
+ accum->dirty = FALSE;
+ } /* end if */
} /* end if */
else {
- /* Sanity check */
- HDassert(H5F_ACCUM_APPEND == adjust);
-
- /* Write out lower part of the existing metadata accumulator, with dispatch to driver */
- if(H5FD_write(lf, dxpl_id, H5FD_MEM_DEFAULT, accum->loc, shrink_size, accum->buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
+ /* Check if the dirty region overlaps the region to eliminate from the accumulator */
+ if(shrink_size > accum->dirty_off) {
+ /* Write out the dirty region from the metadata accumulator, with dispatch to driver */
+ if(H5FD_write(lf, dxpl_id, H5FD_MEM_DEFAULT, (accum->loc + accum->dirty_off), accum->dirty_len, (accum->buf + accum->dirty_off)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "file write failed")
+
+ /* Reset accumulator dirty flag */
+ accum->dirty = FALSE;
+ } /* end if */
/* Move remnant of accumulator down */
HDmemmove(accum->buf, (accum->buf + shrink_size), remnant_size);
/* Adjust accumulator's location */
accum->loc += shrink_size;
- } /* end else */
- /* Reset accumulator dirty flag (in case of error) */
- accum->dirty = FALSE;
+ /* Adjust dirty region tracking info */
+ accum->dirty_off -= shrink_size;
+ } /* end else */
} /* end if */
/* Trim the accumulator's use of its buffer */
@@ -294,7 +333,7 @@ H5F_accum_adjust(H5F_meta_accum_t *accum, H5FD_t *lf, hid_t dxpl_id,
/* Reallocate the metadata accumulator buffer */
if(NULL == (new_buf = H5FL_BLK_REALLOC(meta_accum, accum->buf, new_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate metadata accumulator buffer")
/* Update accumulator info */
accum->buf = new_buf;
@@ -361,8 +400,15 @@ H5F_accum_write(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
f->shared->accum.loc = addr;
f->shared->accum.size += size;
- /* Mark it as written to */
- f->shared->accum.dirty = TRUE;
+ /* 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)) {
@@ -373,11 +419,18 @@ H5F_accum_write(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
/* 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)
+ 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 */
+
/* Set the new size of the metadata accumulator */
f->shared->accum.size += size;
-
- /* Mark it as written to */
- f->shared->accum.dirty = TRUE;
} /* 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)) {
@@ -385,11 +438,33 @@ H5F_accum_write(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
/* 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)) {
- /* Copy the new metadata to the proper location within the accumulator */
- HDmemcpy(f->shared->accum.buf + (addr - f->shared->accum.loc), buf, size);
+ size_t dirty_off = (size_t)(addr - f->shared->accum.loc);
- /* Mark it as written to */
- f->shared->accum.dirty = TRUE;
+ /* 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)) {
@@ -415,11 +490,26 @@ H5F_accum_write(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
f->shared->accum.loc = addr;
f->shared->accum.size += add_size;
- /* Mark it as written to */
- f->shared->accum.dirty = TRUE;
+ /* Adjust the dirty region and mark accumulator dirty */
+ if(f->shared->accum.dirty) {
+ size_t curr_dirty_end = old_offset + 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_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 */
/* 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);
+
/* 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);
@@ -428,24 +518,43 @@ H5F_accum_write(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
HGOTO_ERROR(H5E_IO, H5E_CANTRESIZE, FAIL, "can't adjust metadata accumulator")
/* Copy the new metadata to the end */
- HDmemcpy(f->shared->accum.buf + (addr - f->shared->accum.loc), buf, size);
+ HDmemcpy(f->shared->accum.buf + dirty_off, buf, size);
/* Set the new size of the metadata accumulator */
f->shared->accum.size += add_size;
- /* Mark it as written to */
- f->shared->accum.dirty = TRUE;
+ /* 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_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 {
/* Check if we need more buffer space */
- if(size > f->shared->accum.size) {
- /* Adjust the buffer size, by doubling it */
- f->shared->accum.alloc_size = MAX(f->shared->accum.alloc_size * 2, size);
+ 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, f->shared->accum.alloc_size)))
+ 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 */
@@ -458,7 +567,9 @@ HDmemset(f->shared->accum.buf + size, 0, (f->shared->accum.alloc_size - size));
f->shared->accum.loc = addr;
f->shared->accum.size = size;
- /* Mark it as written to */
+ /* 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 */
@@ -466,7 +577,7 @@ HDmemset(f->shared->accum.buf + size, 0, (f->shared->accum.alloc_size - size));
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.size, f->shared->accum.buf) < 0)
+ 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 */
@@ -512,10 +623,14 @@ HDmemset(f->shared->accum.buf + clear_size, 0, (f->shared->accum.alloc_size - cl
/* Update the metadata accumulator information */
f->shared->accum.loc = addr;
f->shared->accum.size = size;
- f->shared->accum.dirty = TRUE;
/* 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 */
/* No metadata in the accumulator, grab this piece and keep it */
@@ -538,10 +653,14 @@ HDmemset(f->shared->accum.buf + clear_size, 0, (f->shared->accum.alloc_size - cl
/* Update the metadata accumulator information */
f->shared->accum.loc = addr;
f->shared->accum.size = size;
- f->shared->accum.dirty = TRUE;
/* 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 */
/* Indicate success */
@@ -610,25 +729,84 @@ H5F_accum_free(H5F_t *f, hid_t dxpl_id, H5FD_mem_t UNUSED type, haddr_t addr,
/* Adjust the accumulator information */
f->shared->accum.loc += overlap_size;
f->shared->accum.size = new_accum_size;
+
+ /* Adjust the dirty region and possibly mark accumulator clean */
+ if(f->shared->accum.dirty) {
+ /* Check if block freed is entirely before dirty region */
+ if(overlap_size < f->shared->accum.dirty_off)
+ f->shared->accum.dirty_off -= overlap_size;
+ else {
+ /* Check if block freed ends within dirty region */
+ if(overlap_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) - overlap_size;
+ f->shared->accum.dirty_off = 0;
+ } /* end if */
+ /* Block freed encompasses dirty region */
+ else
+ f->shared->accum.dirty = FALSE;
+ } /* end else */
+ } /* end if */
} /* end else */
} /* end if */
/* Block to free must start within the accumulator */
else {
+ haddr_t dirty_end = f->shared->accum.loc + f->shared->accum.dirty_off + f->shared->accum.dirty_len;
+ haddr_t dirty_start = f->shared->accum.loc + f->shared->accum.dirty_off;
+
/* Calculate the size of the overlap with the accumulator */
H5_ASSIGN_OVERFLOW(overlap_size, (f->shared->accum.loc + f->shared->accum.size) - addr, haddr_t, size_t);
- /* Block to free is in the middle of the accumulator */
- if(H5F_addr_lt((addr + size), f->shared->accum.loc + f->shared->accum.size)) {
+ /* Check if block to free begins before end of dirty region */
+ if(f->shared->accum.dirty && H5F_addr_lt(addr, dirty_end)) {
haddr_t tail_addr;
- size_t tail_size;
- /* Calculate the address & size of the tail to write */
+ /* Calculate the address of the tail to write */
tail_addr = addr + size;
- H5_ASSIGN_OVERFLOW(tail_size, (f->shared->accum.loc + f->shared->accum.size) - tail_addr, haddr_t, size_t);
- /* Write out the part of the accumulator after the block to free */
- if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, tail_addr, tail_size, f->shared->accum.buf + (tail_addr - f->shared->accum.loc)) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
+ /* Check if there's dirty data after the block to free */
+ if(H5F_addr_lt(tail_addr, dirty_end)) {
+ /* Check if the dirty region falls entirely after block to free */
+ if(tail_addr < dirty_start) {
+ /* Write out the dirty region of the accumulator */
+ if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, dirty_start, 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 dirty flag */
+ f->shared->accum.dirty = FALSE;
+ } /* end if */
+ /* Dirty region overlaps block to free */
+ else {
+ size_t tail_size;
+ size_t write_size;
+
+ /* Calculate the size of the tail to write */
+ H5_ASSIGN_OVERFLOW(tail_size, dirty_end - tail_addr, haddr_t, size_t);
+ write_size = (size_t)(dirty_end - tail_addr);
+
+ /* Write out the dirty part of the accumulator after the block to free */
+ if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, tail_addr, write_size, f->shared->accum.buf + (tail_addr - f->shared->accum.loc)) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
+
+ /* Check if block to free falls within dirty region */
+ if(addr == dirty_start)
+ /* Reset dirty flag */
+ f->shared->accum.dirty = FALSE;
+ else
+ /* Truncate dirty region */
+ f->shared->accum.dirty_len = (size_t)(addr - dirty_start);
+ } /* end else */
+ } /* end if */
+ else {
+ /* Check if entire dirty region is in block to free */
+ if(addr < dirty_start)
+ /* Reset dirty flag */
+ f->shared->accum.dirty = FALSE;
+ /* Block to free truncates dirty region */
+ else {
+ /* Truncate dirty region */
+ f->shared->accum.dirty_len = (size_t)(addr - dirty_start);
+ } /* end else */
+ } /* end else */
} /* end if */
/* Adjust the accumulator information */
@@ -665,9 +843,9 @@ H5F_accum_flush(H5F_t *f, hid_t dxpl_id)
HDassert(f->shared);
/* Check if we need to flush out the metadata accumulator */
- if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && f->shared->accum.dirty && f->shared->accum.size > 0) {
+ if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && f->shared->accum.dirty) {
/* Flush the metadata contents */
- if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, f->shared->accum.loc, f->shared->accum.size, f->shared->accum.buf) < 0)
+ 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 the dirty flag */
@@ -719,6 +897,7 @@ H5F_accum_reset(H5F_t *f, hid_t dxpl_id)
f->shared->accum.alloc_size = f->shared->accum.size = 0;
f->shared->accum.loc = HADDR_UNDEF;
f->shared->accum.dirty = FALSE;
+ f->shared->accum.dirty_len = 0;
} /* end if */
done:
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index 0f5616f..d264d04 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -142,6 +142,8 @@ typedef struct H5F_meta_accum_t {
haddr_t loc; /* File location (offset) of the accumulated metadata */
size_t size; /* Size of the accumulated metadata buffer used (in bytes) */
size_t alloc_size; /* Size of the accumulated metadata buffer allocated (in bytes) */
+ size_t dirty_off; /* Offset of the dirty region in the accumulator buffer */
+ size_t dirty_len; /* Length of the dirty region in the accumulator buffer */
hbool_t dirty; /* Flag to indicate that the accumulated metadata is dirty */
} H5F_meta_accum_t;