summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2009-06-18 17:49:17 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2009-06-18 17:49:17 (GMT)
commitb1b2c88b2c759bd02b8e24e0f3c43d30b6681a40 (patch)
tree852a37416b5c585274d38b492f4cb92b53465ac3
parentb6cfe32b73a7fd3e4c9ace7bcec1e27156db67d3 (diff)
downloadhdf5-b1b2c88b2c759bd02b8e24e0f3c43d30b6681a40.zip
hdf5-b1b2c88b2c759bd02b8e24e0f3c43d30b6681a40.tar.gz
hdf5-b1b2c88b2c759bd02b8e24e0f3c43d30b6681a40.tar.bz2
[svn-r17084] Description:
Bring r17038-17039,17045,17062 from trunk to 1.8 branch: Switch fractal heap direct & indirect blocks to use temp. space alloc. Improvements to metadata accumulator 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/C++ & FORTRAN, w/threadsafe, in debug mode Linux/64-amd64 2.6 (smirom) 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, in production mode Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN, in production mode Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in debug mode Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in production mode Mac OS X/32 10.5.7 (amazon) in debug mode Mac OS X/32 10.5.7 (amazon) w/C++ & FORTRAN, w/threadsafe, in production mode
-rw-r--r--src/H5Faccum.c222
-rw-r--r--src/H5HFcache.c170
-rw-r--r--src/H5HFdblock.c40
-rw-r--r--src/H5HFiblock.c32
4 files changed, 350 insertions, 114 deletions
diff --git a/src/H5Faccum.c b/src/H5Faccum.c
index 05f6910..9529e0c 100644
--- a/src/H5Faccum.c
+++ b/src/H5Faccum.c
@@ -40,6 +40,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* File access */
#include "H5FDprivate.h" /* File drivers */
+#include "H5Vprivate.h" /* Vectors and arrays */
/****************/
@@ -49,12 +50,19 @@
/* Metadata accumulator controls */
#define H5F_ACCUM_THROTTLE 8
#define H5F_ACCUM_THRESHOLD 2048
+#define H5F_ACCUM_MAX_SIZE (1024 *1024) /* Max. accum. buf size (max. I/Os will be 1/2 this size) */
/******************/
/* Local Typedefs */
/******************/
+/* Enumerated type to indicate how data will be added to accumulator */
+typedef enum {
+ H5F_ACCUM_PREPEND, /* Data will be prepended to accumulator */
+ H5F_ACCUM_APPEND /* Data will be appended to accumulator */
+} H5F_accum_adjust_t;
+
/********************/
/* Package Typedefs */
@@ -112,7 +120,8 @@ 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) {
+ if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && type != H5FD_MEM_DRAW
+ && size < H5F_ACCUM_MAX_SIZE) {
/* Current read overlaps with metadata accumulator */
if(H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size)) {
unsigned char *read_buf = (unsigned char *)buf; /* Pointer to the buffer being read in */
@@ -195,12 +204,17 @@ H5F_accum_read(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
/* Cache the new piece of metadata */
/* Check if we need to resize 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 */
- if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, size)))
+ 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 = size;
+ f->shared->accum.alloc_size = new_size;
} /* end if */
else {
/* Check if we should shrink the accumulator buffer */
@@ -246,6 +260,111 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5F_accum_adjust
+ *
+ * Purpose: Adjust accumulator size, if necessary
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jun 11 2009
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F_accum_adjust(H5F_meta_accum_t *accum, H5FD_t *lf, hid_t dxpl_id,
+ H5F_accum_adjust_t adjust, size_t size)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5F_accum_adjust)
+
+ HDassert(accum);
+ HDassert(lf);
+ HDassert(size > 0);
+ HDassert(size <= H5F_ACCUM_MAX_SIZE);
+
+ /* Check if we need more buffer space */
+ if((size + accum->size) > 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 + accum->size) - 1)));
+
+ /* Check for accumulator getting too big */
+ if(new_size > H5F_ACCUM_MAX_SIZE) {
+ size_t shrink_size; /* Amount to shrink accumulator by */
+ size_t remnant_size; /* Amount left in accumulator */
+
+ /* Cap the accumulator's growth, leaving some room */
+
+ /* Determine the amounts to work with */
+ if(size > (H5F_ACCUM_MAX_SIZE / 2)) {
+ new_size = H5F_ACCUM_MAX_SIZE;
+ shrink_size = accum->size;
+ 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;
+ } /* 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")
+ } /* 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")
+
+ /* 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;
+ } /* end if */
+
+ /* Trim the accumulator's use of its buffer */
+ accum->size = remnant_size;
+ } /* end if */
+
+ /* Check for accumulator needing to be reallocated */
+ if(new_size > accum->alloc_size) {
+ unsigned char *new_buf; /* New buffer to hold the accumulated metadata */
+
+ /* 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")
+
+ /* Update accumulator info */
+ accum->buf = new_buf;
+ accum->alloc_size = new_size;
+#ifdef H5_CLEAR_MEMORY
+HDmemset(accum->buf + accum->size, 0, (accum->alloc_size - (accum->size + size)));
+#endif /* H5_CLEAR_MEMORY */
+ } /* end if */
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_accum_adjust() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5F_accum_write
*
* Purpose: Attempts to read some data from the metadata accumulator for
@@ -273,23 +392,15 @@ 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) {
+ if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && type != H5FD_MEM_DRAW
+ && size < H5F_ACCUM_MAX_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 more buffer space */
- if((size + f->shared->accum.size) > f->shared->accum.alloc_size) {
- /* Adjust the buffer size, by doubling it */
- f->shared->accum.alloc_size = MAX(f->shared->accum.alloc_size * 2, size + f->shared->accum.size);
-
- /* 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_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-#ifdef H5_CLEAR_MEMORY
-HDmemset(f->shared->accum.buf + f->shared->accum.size, 0, (f->shared->accum.alloc_size - (f->shared->accum.size + size)));
-#endif /* H5_CLEAR_MEMORY */
- } /* end if */
+ /* 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);
@@ -306,18 +417,9 @@ HDmemset(f->shared->accum.buf + f->shared->accum.size, 0, (f->shared->accum.allo
} /* 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 more buffer space */
- if((size + f->shared->accum.size) > f->shared->accum.alloc_size) {
- /* Adjust the buffer size, by doubling it */
- f->shared->accum.alloc_size = MAX(f->shared->accum.alloc_size * 2, size + f->shared->accum.size);
-
- /* 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_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-#ifdef H5_CLEAR_MEMORY
-HDmemset(f->shared->accum.buf + f->shared->accum.size + size, 0, (f->shared->accum.alloc_size - (f->shared->accum.size + size)));
-#endif /* H5_CLEAR_MEMORY */
- } /* end if */
+ /* 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 end */
HDmemcpy(f->shared->accum.buf + f->shared->accum.size, buf, size);
@@ -330,7 +432,7 @@ HDmemset(f->shared->accum.buf + f->shared->accum.size + size, 0, (f->shared->acc
} /* 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 new_size; /* New size of the accumulator buffer */
+ 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)) {
@@ -344,21 +446,12 @@ HDmemset(f->shared->accum.buf + f->shared->accum.size + size, 0, (f->shared->acc
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 new accumulator size, based on the amount of overlap */
- H5_ASSIGN_OVERFLOW(new_size, (f->shared->accum.loc - addr) + 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, (f->shared->accum.loc - addr), hsize_t, size_t);
- /* Check if we need more buffer space */
- if(new_size > f->shared->accum.alloc_size) {
- /* Adjust the buffer size, by doubling it */
- f->shared->accum.alloc_size = MAX(f->shared->accum.alloc_size + 2, new_size);
-
- /* 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_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-#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 */
- } /* end if */
+ /* 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);
@@ -371,34 +464,25 @@ HDmemset(f->shared->accum.buf + f->shared->accum.size, 0, (f->shared->accum.allo
/* Set the new size & location of the metadata accumulator */
f->shared->accum.loc = addr;
- f->shared->accum.size = new_size;
+ f->shared->accum.size += add_size;
/* Mark it as written to */
f->shared->accum.dirty = TRUE;
} /* 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)) {
- /* Calculate the new accumulator size, based on the amount of overlap */
- H5_ASSIGN_OVERFLOW(new_size, (addr - f->shared->accum.loc) + size, hsize_t, size_t);
-
- /* Check if we need more buffer space */
- if(new_size > f->shared->accum.alloc_size) {
- /* Adjust the buffer size, by doubling it */
- f->shared->accum.alloc_size = MAX(f->shared->accum.alloc_size * 2, new_size);
+ /* 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);
- /* 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_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-#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 */
- } /* end if */
+ /* 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 + (addr - f->shared->accum.loc), buf, size);
- /* Set the new size & location of the metadata accumulator */
- f->shared->accum.size = new_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;
@@ -421,12 +505,17 @@ HDmemset(f->shared->accum.buf + f->shared->accum.size, 0, (f->shared->accum.allo
/* Cache the new piece of metadata */
/* Check if we need to resize 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 */
- if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, size)))
+ 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 = size;
+ f->shared->accum.alloc_size = new_size;
#ifdef H5_CLEAR_MEMORY
{
size_t clear_size = MAX(f->shared->accum.size, size);
@@ -462,12 +551,17 @@ HDmemset(f->shared->accum.buf + clear_size, 0, (f->shared->accum.alloc_size - cl
else {
/* 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)));
+
/* Reallocate the metadata accumulator buffer */
- if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, size)))
+ 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 = size;
+ f->shared->accum.alloc_size = new_size;
} /* end if */
/* Update the metadata accumulator information */
diff --git a/src/H5HFcache.c b/src/H5HFcache.c
index 96ffe2d..f4c70c7 100644
--- a/src/H5HFcache.c
+++ b/src/H5HFcache.c
@@ -358,7 +358,7 @@ HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr);
H5O_pline_t *pline; /* Pipeline information from the header on disk */
/* Compute the offset of the filter info in the header */
- filter_info_off = p - buf;
+ filter_info_off = (size_t)(p - buf);
/* Compute the size of the extra filter information */
filter_info_size = hdr->sizeof_size /* Size of size for filtered root direct block */
@@ -1053,6 +1053,57 @@ HDfprintf(stderr, "%s: iblock->filt_ents[%Zu] = {%Zu, %x}\n", FUNC, u, iblock->f
HDassert(max_child == iblock->max_child);
#endif /* NDEBUG */
+ /* Check for needing to re-allocate indirect block from 'temp.' to 'normal' file space */
+ if(H5F_IS_TMP_ADDR(f, addr)) {
+#ifdef QAK
+HDfprintf(stderr, "%s: Re-allocating indirect block in temporary space - addr = %a\n", FUNC, addr);
+#endif /* QAK */
+ /* Sanity check */
+ HDassert(H5F_addr_eq(iblock->addr, addr));
+
+ /* Allocate 'normal' space for the new indirect block on disk */
+ if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, (hsize_t)iblock->size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap indirect block")
+
+ /* Sanity check */
+ HDassert(!H5F_addr_eq(iblock->addr, addr));
+
+ /* Let the metadata cache know the block moved */
+ if(H5AC_rename(f, H5AC_FHEAP_IBLOCK, iblock->addr, addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRENAME, FAIL, "unable to move indirect block")
+
+ /* Update the internal address for the block */
+ iblock->addr = addr;
+
+ /* Check for root indirect block */
+ if(NULL == iblock->parent) {
+ /* Update information about indirect block's location */
+ hdr->man_dtable.table_addr = addr;
+
+ /* Mark that heap header was modified */
+ if(H5HF_hdr_dirty(hdr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
+ } /* end if */
+ else {
+ H5HF_indirect_t *par_iblock; /* Parent indirect block */
+ unsigned par_entry; /* Entry in parent indirect block */
+
+ /* Get parent information */
+ par_iblock = iblock->parent;
+ par_entry = iblock->par_entry;
+
+ /* Update information about indirect block's location */
+ par_iblock->ents[par_entry].addr = addr;
+
+ /* Mark that parent was modified */
+ if(H5HF_iblock_dirty(par_iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
+ } /* end if */
+ } /* end if */
+
+ /* Indirect block must be in 'normal' file space now */
+ HDassert(!H5F_IS_TMP_ADDR(f, addr));
+
/* Write the indirect block */
if(H5F_block_write(f, H5FD_MEM_FHEAP_IBLOCK, addr, iblock->size, dxpl_id, buf) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTFLUSH, FAIL, "unable to save fractal heap indirect block to disk")
@@ -1109,10 +1160,14 @@ HDfprintf(stderr, "%s: Destroying indirect block\n", FUNC);
/* Check for freeing file space for indirect block */
if(iblock->cache_info.free_file_space_on_destroy) {
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_FHEAP_IBLOCK, H5AC_dxpl_id, iblock->cache_info.addr, (hsize_t)iblock->size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block")
+ /* Check if the indirect block is NOT currently allocated in temp. file space */
+ /* (temp. file space does not need to be freed) */
+ if(!H5F_IS_TMP_ADDR(f, iblock->cache_info.addr)) {
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_FHEAP_IBLOCK, H5AC_dxpl_id, iblock->cache_info.addr, (hsize_t)iblock->size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block")
+ } /* end if */
} /* end if */
/* Set the shared heap header's file context for this operation */
@@ -1127,11 +1182,11 @@ HDfprintf(stderr, "%s: Destroying indirect block\n", FUNC);
/* Release entry tables */
if(iblock->ents)
- H5FL_SEQ_FREE(H5HF_indirect_ent_t, iblock->ents);
+ (void)H5FL_SEQ_FREE(H5HF_indirect_ent_t, iblock->ents);
if(iblock->filt_ents)
- H5FL_SEQ_FREE(H5HF_indirect_filt_ent_t, iblock->filt_ents);
+ (void)H5FL_SEQ_FREE(H5HF_indirect_filt_ent_t, iblock->filt_ents);
if(iblock->child_iblocks)
- H5FL_SEQ_FREE(H5HF_indirect_ptr_t, iblock->child_iblocks);
+ (void)H5FL_SEQ_FREE(H5HF_indirect_ptr_t, iblock->child_iblocks);
/* Free fractal heap indirect block info */
(void)H5FL_FREE(H5HF_indirect_t, iblock);
@@ -1434,6 +1489,7 @@ H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
if(dblock->cache_info.is_dirty) {
H5HF_hdr_t *hdr; /* Shared fractal heap information */
+ hbool_t at_tmp_addr = H5F_IS_TMP_ADDR(f, addr); /* Flag to indicate direct block is at temporary address */
void *write_buf; /* Pointer to buffer to write out */
size_t write_size; /* Size of buffer to write out */
uint8_t *p; /* Pointer into raw data buffer */
@@ -1523,13 +1579,17 @@ HDfprintf(stderr, "%s: hdr->man_dtable.table_addr = %a, addr = %a\n", FUNC, hdr-
} /* end if */
/* Check if we need to re-size the block on disk */
- if(hdr->pline_root_direct_size != write_size) {
+ if(hdr->pline_root_direct_size != write_size || at_tmp_addr) {
#ifdef QAK
HDfprintf(stderr, "%s: Need to re-allocate root direct block!\n", FUNC);
#endif /* QAK */
- /* Release direct block's current disk space */
- if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, addr, (hsize_t)hdr->pline_root_direct_size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
+ /* Check if the direct block is NOT currently allocated in temp. file space */
+ /* (temp. file space does not need to be freed) */
+ if(!at_tmp_addr) {
+ /* Release direct block's current disk space */
+ if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, addr, (hsize_t)hdr->pline_root_direct_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
+ } /* end if */
/* Allocate space for the compressed direct block */
if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)write_size)))
@@ -1577,13 +1637,17 @@ HDfprintf(stderr, "%s: par_iblock->ents[%u].addr = %a, addr = %a\n", FUNC, par_e
} /* end if */
/* Check if we need to re-size the block on disk */
- if(par_iblock->filt_ents[par_entry].size != write_size) {
+ if(par_iblock->filt_ents[par_entry].size != write_size || at_tmp_addr) {
#ifdef QAK
HDfprintf(stderr, "%s: Need to re-allocate non-root direct block!\n", FUNC);
#endif /* QAK */
- /* Release direct block's current disk space */
- if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, addr, (hsize_t)par_iblock->filt_ents[par_entry].size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
+ /* Check if the direct block is NOT currently allocated in temp. file space */
+ /* (temp. file space does not need to be freed) */
+ if(!at_tmp_addr) {
+ /* Release direct block's current disk space */
+ if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, addr, (hsize_t)par_iblock->filt_ents[par_entry].size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
+ } /* end if */
/* Allocate space for the compressed direct block */
if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)write_size)))
@@ -1611,8 +1675,70 @@ HDfprintf(stderr, "%s: Need to re-allocate non-root direct block!\n", FUNC);
else {
write_buf = dblock->blk;
write_size = dblock->size;
+
+ /* Check for needing to re-allocate direct block from 'temp.' to 'normal' file space */
+ if(at_tmp_addr) {
+#ifdef QAK
+HDfprintf(stderr, "%s: Re-allocating direct block in temporary space - addr = %a, write_size = %Zu\n", FUNC, addr, write_size);
+#endif /* QAK */
+ /* Check for root direct block */
+ if(NULL == dblock->parent) {
+ /* Sanity check */
+ HDassert(H5F_addr_eq(hdr->man_dtable.table_addr, addr));
+
+ /* Allocate 'normal' space for the direct block */
+ if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)write_size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
+
+ /* Sanity check */
+ HDassert(!H5F_addr_eq(hdr->man_dtable.table_addr, addr));
+
+ /* Let the metadata cache know the block moved */
+ if(H5AC_rename(f, H5AC_FHEAP_DBLOCK, hdr->man_dtable.table_addr, addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRENAME, FAIL, "unable to move direct block")
+
+ /* Update information about direct block's location */
+ hdr->man_dtable.table_addr = addr;
+
+ /* Mark that heap header was modified */
+ if(H5HF_hdr_dirty(hdr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
+ } /* end if */
+ else {
+ H5HF_indirect_t *par_iblock; /* Parent indirect block */
+ unsigned par_entry; /* Entry in parent indirect block */
+
+ /* Get parent information */
+ par_iblock = dblock->parent;
+ par_entry = dblock->par_entry;
+
+ /* Sanity check */
+ HDassert(H5F_addr_eq(par_iblock->ents[par_entry].addr, addr));
+
+ /* Allocate 'normal' space for the direct block */
+ if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)write_size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
+
+ /* Sanity check */
+ HDassert(!H5F_addr_eq(par_iblock->ents[par_entry].addr, addr));
+
+ /* Let the metadata cache know the block moved */
+ if(H5AC_rename(f, H5AC_FHEAP_DBLOCK, par_iblock->ents[par_entry].addr, addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRENAME, FAIL, "unable to move direct block")
+
+ /* Update information about direct block's location */
+ par_iblock->ents[par_entry].addr = addr;
+
+ /* Mark that parent was modified */
+ if(H5HF_iblock_dirty(par_iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
+ } /* end else */
+ } /* end if */
} /* end else */
+ /* Direct block must be in 'normal' file space now */
+ HDassert(!H5F_IS_TMP_ADDR(f, addr));
+
/* Write the direct block */
#ifdef QAK
HDfprintf(stderr, "%s: addr = %a, write_size = %Zu\n", FUNC, addr, write_size);
@@ -1672,10 +1798,14 @@ HDfprintf(stderr, "%s: Destroying direct block, dblock = %p\n", FUNC, dblock);
/* Sanity check */
HDassert(dblock->file_size > 0);
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, H5AC_dxpl_id, dblock->cache_info.addr, dblock->file_size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
+ /* Check if the direct block is NOT currently allocated in temp. file space */
+ /* (temp. file space does not need to be freed) */
+ if(!H5F_IS_TMP_ADDR(f, dblock->cache_info.addr)) {
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, H5AC_dxpl_id, dblock->cache_info.addr, dblock->file_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
+ } /* end if */
} /* end if */
/* Set the shared heap header's file context for this operation */
diff --git a/src/H5HFdblock.c b/src/H5HFdblock.c
index a4ce8b2..77b1e33 100644
--- a/src/H5HFdblock.c
+++ b/src/H5HFdblock.c
@@ -149,8 +149,8 @@ H5HF_man_dblock_create(hid_t dxpl_id, H5HF_hdr_t *hdr, H5HF_indirect_t *par_iblo
HDmemset(dblock->blk, 0, dblock->size);
#endif /* H5_CLEAR_MEMORY */
- /* Allocate space for the direct block on disk */
- if(HADDR_UNDEF == (dblock_addr = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)dblock->size)))
+ /* Allocate [temporary] space for the direct block on disk */
+ if(HADDR_UNDEF == (dblock_addr = H5MF_alloc_tmp(hdr->f, (hsize_t)dblock->size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
#ifdef QAK
HDfprintf(stderr, "%s: direct block address = %a\n", FUNC, dblock_addr);
@@ -696,22 +696,26 @@ HDfprintf(stderr, "%s: Done expunging direct block from cache\n", FUNC);
#endif /* QAK */
} /* end if */
- /* Release direct block's disk space */
- /* (XXX: Under the best of circumstances, this block's space in the file
- * would be freed in the H5AC_expunge_entry() call above (and the
- * H5AC__FREE_FILE_SPACE_FLAG used there), but since the direct
- * block structure might have a different size on disk than in
- * the heap's 'abstract' address space, we would need to set the
- * "file_size" field for the direct block structure. In order to
- * do that, we'd have to protect/unprotect the direct block and
- * that would add a bunch of unnecessary overhead to the process,
- * so we just release the file space here, directly. When the
- * revised metadata cache is operating, it will "know" the file
- * size of each entry in the cache and we can the the
- * H5AC_expunge_entry() method. -QAK)
- */
- if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, dblock_addr, dblock_size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
+ /* Check if the direct block is NOT currently allocated in temp. file space */
+ /* (temp. file space does not need to be freed) */
+ if(!H5F_IS_TMP_ADDR(f, dblock_addr)) {
+ /* Release direct block's disk space */
+ /* (XXX: Under the best of circumstances, this block's space in the file
+ * would be freed in the H5AC_expunge_entry() call above (and the
+ * H5AC__FREE_FILE_SPACE_FLAG used there), but since the direct
+ * block structure might have a different size on disk than in
+ * the heap's 'abstract' address space, we would need to set the
+ * "file_size" field for the direct block structure. In order to
+ * do that, we'd have to protect/unprotect the direct block and
+ * that would add a bunch of unnecessary overhead to the process,
+ * so we just release the file space here, directly. When the
+ * revised metadata cache is operating, it will "know" the file
+ * size of each entry in the cache and we can the the
+ * H5AC_expunge_entry() method. -QAK)
+ */
+ if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, dblock_addr, dblock_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5HFiblock.c b/src/H5HFiblock.c
index a01a5be..2c79403 100644
--- a/src/H5HFiblock.c
+++ b/src/H5HFiblock.c
@@ -578,6 +578,9 @@ HDfprintf(stderr, "%s: iblock->nrows = %u, iblock->max_rows = %u\n", FUNC, ibloc
HDfprintf(stderr, "%s: new_next_entry = %u\n", FUNC, new_next_entry);
#endif /* QAK */
+ /* Check if the indirect block is NOT currently allocated in temp. file space */
+ /* (temp. file space does not need to be freed) */
+ if(!H5F_IS_TMP_ADDR(hdr->f, iblock->addr)) {
/* Currently, the old block data is "thrown away" after the space is reallocated,
* to avoid data copy in H5MF_realloc() call by just free'ing the space and
* allocating new space.
@@ -587,16 +590,17 @@ HDfprintf(stderr, "%s: new_next_entry = %u\n", FUNC, new_next_entry);
*
* QAK - 3/14/2006
*/
- /* Free previous indirect block disk space */
- if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, iblock->addr, (hsize_t)iblock->size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block file space")
+ /* Free previous indirect block disk space */
+ if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, iblock->addr, (hsize_t)iblock->size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block file space")
+ } /* end if */
/* Compute size of buffer needed for new indirect block */
iblock->nrows = new_nrows;
iblock->size = H5HF_MAN_INDIRECT_SIZE(hdr, iblock);
- /* Allocate space for the new indirect block on disk */
- if(HADDR_UNDEF == (new_addr = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, (hsize_t)iblock->size)))
+ /* Allocate [temporary] space for the new indirect block on disk */
+ if(HADDR_UNDEF == (new_addr = H5MF_alloc_tmp(hdr->f, (hsize_t)iblock->size)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap indirect block")
#ifdef QAK
HDfprintf(stderr, "%s: Check 1.0 - iblock->addr = %a, new_addr = %a\n", FUNC, iblock->addr, new_addr);
@@ -739,6 +743,9 @@ HDfprintf(stderr, "%s: new_nrows = %u\n", FUNC, new_nrows);
HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows);
#endif /* QAK */
+ /* Check if the indirect block is NOT currently allocated in temp. file space */
+ /* (temp. file space does not need to be freed) */
+ if(!H5F_IS_TMP_ADDR(hdr->f, iblock->addr)) {
/* Currently, the old block data is "thrown away" after the space is reallocated,
* to avoid data copy in H5MF_realloc() call by just free'ing the space and
* allocating new space.
@@ -748,9 +755,10 @@ HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows);
*
* QAK - 6/12/2006
*/
- /* Free previous indirect block disk space */
- if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, iblock->addr, (hsize_t)iblock->size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block file space")
+ /* Free previous indirect block disk space */
+ if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, iblock->addr, (hsize_t)iblock->size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block file space")
+ } /* end if */
/* Compute free space in rows to delete */
acc_dblock_free = 0;
@@ -762,8 +770,8 @@ HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows);
iblock->nrows = new_nrows;
iblock->size = H5HF_MAN_INDIRECT_SIZE(hdr, iblock);
- /* Allocate space for the new indirect block on disk */
- if(HADDR_UNDEF == (new_addr = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, (hsize_t)iblock->size)))
+ /* Allocate [temporary] space for the new indirect block on disk */
+ if(HADDR_UNDEF == (new_addr = H5MF_alloc_tmp(hdr->f, (hsize_t)iblock->size)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap indirect block")
#ifdef QAK
HDfprintf(stderr, "%s: new_addr = %a\n", FUNC, new_addr);
@@ -1078,8 +1086,8 @@ HDfprintf(stderr, "%s: dir_rows = %u\n", FUNC, dir_rows);
else
iblock->child_iblocks = NULL;
- /* Allocate space for the indirect block on disk */
- if(HADDR_UNDEF == (*addr_p = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, (hsize_t)iblock->size)))
+ /* Allocate [temporary] space for the indirect block on disk */
+ if(HADDR_UNDEF == (*addr_p = H5MF_alloc_tmp(hdr->f, (hsize_t)iblock->size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap indirect block")
iblock->addr = *addr_p;