summaryrefslogtreecommitdiffstats
path: root/src/H5HL.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2010-01-07 22:45:21 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2010-01-07 22:45:21 (GMT)
commit86d40d2265865e2c601204ca50f9528543b96caa (patch)
tree99aa552b4f9e58ed0a7738e8162494b1b1714441 /src/H5HL.c
parent27c3c4fc9ab24b04e289a5ae07f3c5b791584eb8 (diff)
downloadhdf5-86d40d2265865e2c601204ca50f9528543b96caa.zip
hdf5-86d40d2265865e2c601204ca50f9528543b96caa.tar.gz
hdf5-86d40d2265865e2c601204ca50f9528543b96caa.tar.bz2
[svn-r18072] Description:
Bring r18071 from metadata journaling merge branch: Refactor local heap routines with changes from metadata journaling branch, along with other misc. changes as the changes on the metadata journaling branch are being converged with the current state of the trunk. 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, 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.6.2 (amazon) in debug mode Mac OS X/32 10.6.2 (amazon) w/C++ & FORTRAN, w/threadsafe, in production mode
Diffstat (limited to 'src/H5HL.c')
-rw-r--r--src/H5HL.c591
1 files changed, 441 insertions, 150 deletions
diff --git a/src/H5HL.c b/src/H5HL.c
index 5951509..aa187ad 100644
--- a/src/H5HL.c
+++ b/src/H5HL.c
@@ -75,9 +75,6 @@ static herr_t H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap);
/* Declare a free list to manage the H5HL_free_t struct */
H5FL_DEFINE(H5HL_free_t);
-/* Declare a free list to manage the H5HL_t struct */
-H5FL_DEFINE(H5HL_t);
-
/* Declare a PQ free list to manage the heap chunk information */
H5FL_BLK_DEFINE(lheap_chunk);
@@ -118,8 +115,8 @@ herr_t
H5HL_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, haddr_t *addr_p/*out*/)
{
H5HL_t *heap = NULL; /* Heap created */
+ H5HL_prfx_t *prfx = NULL; /* Heap prefix */
hsize_t total_size; /* Total heap size on disk */
- size_t sizeof_hdr; /* Cache H5HL header size for file */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5HL_create, FAIL)
@@ -133,21 +130,22 @@ H5HL_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, haddr_t *addr_p/*out*/)
size_hint = H5HL_SIZEOF_FREE(f);
size_hint = H5HL_ALIGN(size_hint);
- /* Cache this for later */
- sizeof_hdr = H5HL_SIZEOF_HDR(f);
+ /* Allocate memory structure */
+ if(NULL == (heap = H5HL_new(H5F_SIZEOF_SIZE(f), H5F_SIZEOF_ADDR(f), H5HL_SIZEOF_HDR(f))))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed")
- /* Allocate file version */
- total_size = sizeof_hdr + size_hint;
- if(HADDR_UNDEF == (*addr_p = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, total_size)))
+ /* Allocate file space */
+ total_size = heap->prfx_size + size_hint;
+ if(HADDR_UNDEF == (heap->prfx_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, total_size)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "unable to allocate file memory")
- /* allocate memory version */
- if(NULL == (heap = H5FL_CALLOC(H5HL_t)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed")
- heap->addr = *addr_p + (hsize_t)sizeof_hdr;
- heap->heap_alloc = size_hint;
- if(NULL == (heap->chunk = H5FL_BLK_CALLOC(lheap_chunk, (sizeof_hdr + size_hint))))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed")
+ /* Initialize info */
+ heap->single_cache_obj = TRUE;
+ heap->dblk_addr = heap->prfx_addr + (hsize_t)heap->prfx_size;
+ heap->dblk_size = size_hint;
+ if(size_hint)
+ if(NULL == (heap->dblk_image = H5FL_BLK_CALLOC(lheap_chunk, size_hint)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed")
/* free list */
if(size_hint) {
@@ -160,17 +158,32 @@ H5HL_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, haddr_t *addr_p/*out*/)
else
heap->freelist = NULL;
+ /* Allocate the heap prefix */
+ if(NULL == (prfx = H5HL_prfx_new(heap)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed")
+
/* Add to cache */
- if(H5AC_set(f, dxpl_id, H5AC_LHEAP, *addr_p, heap, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to cache heap")
+ if(H5AC_set(f, dxpl_id, H5AC_LHEAP_PRFX, heap->prfx_addr, prfx, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to cache local heap prefix")
+
+ /* Set address to return */
+ *addr_p = heap->prfx_addr;
done:
if(ret_value < 0) {
- if(H5F_addr_defined(*addr_p))
- H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, *addr_p, total_size);
- if(heap)
- if(H5HL_dest(f, heap) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap")
+ if(prfx) {
+ if(H5HL_prfx_dest(prfx) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap prefix")
+ } /* end if */
+ else {
+ if(heap) {
+ if(H5F_addr_defined(heap->prfx_addr))
+ if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->prfx_addr, total_size) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "can't release heap data?")
+ if(H5HL_dest(heap) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap")
+ } /* end if */
+ } /* end else */
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -178,6 +191,110 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5HL_dblk_realloc
+ *
+ * Purpose: Reallocate data block for heap
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Oct 12 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HL_dblk_realloc(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t new_heap_size)
+{
+ H5HL_dblk_t *dblk; /* Local heap data block */
+ haddr_t old_addr; /* Old location of heap data block */
+ haddr_t new_addr; /* New location of heap data block */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HL_dblk_realloc)
+
+ /* check arguments */
+ HDassert(heap);
+ HDassert(new_heap_size > 0);
+
+ /* Release old space on disk */
+ old_addr = heap->dblk_addr;
+ H5_CHECK_OVERFLOW(heap->dblk_size, size_t, hsize_t);
+ if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, (hsize_t)heap->dblk_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "can't release old heap data?")
+
+ /* Allocate new space on disk */
+ H5_CHECK_OVERFLOW(new_heap_size, size_t, hsize_t);
+ if(HADDR_UNDEF == (new_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)new_heap_size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "unable to allocate file space for heap")
+
+ /* Check if heap data block actually moved in the file */
+ if(H5F_addr_eq(old_addr, new_addr)) {
+ /* Check if heap data block is contiguous w/prefix */
+ if(heap->single_cache_obj) {
+ /* Sanity check */
+ HDassert(H5F_addr_eq(heap->prfx_addr + heap->prfx_size, heap->dblk_addr));
+ HDassert(heap->prfx);
+
+ /* Resize the heap prefix in the cache */
+ if(H5AC_resize_pinned_entry(f, heap->prfx, (size_t)(heap->prfx_size + new_heap_size)) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "unable to resize heap in cache")
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(H5F_addr_ne(heap->prfx_addr + heap->prfx_size, heap->dblk_addr));
+ HDassert(heap->dblk);
+
+ /* Resize the heap data block in the cache */
+ if(H5AC_resize_pinned_entry(f, heap->dblk, (size_t)new_heap_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "unable to resize heap in cache")
+ } /* end else */
+ } /* end if */
+ else {
+ /* Check if heap data block was contiguous w/prefix previously */
+ if(heap->single_cache_obj) {
+ /* Create new heap data block */
+ if(NULL == (dblk = H5HL_dblk_new(heap)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "unable to allocate local heap data block")
+
+ /* Resize current heap prefix */
+ heap->prfx_size = H5HL_SIZEOF_HDR(f);
+ if(H5AC_resize_pinned_entry(f, heap->prfx, (size_t)heap->prfx_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "unable to resize heap prefix in cache")
+
+ /* Insert data block into cache (pinned) */
+ if(H5AC_set(f, dxpl_id, H5AC_LHEAP_DBLK, new_addr, dblk, H5AC__PIN_ENTRY_FLAG) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to cache local heap data block")
+ dblk = NULL;
+
+ /* Reset 'single cache object' flag */
+ heap->single_cache_obj = FALSE;
+ } /* end if */
+ else {
+ /* Resize the heap data block in the cache */
+ /* (ignore [unlikely] case where heap data block ends up
+ * contiguous w/heap prefix again.
+ */
+ if(H5AC_resize_pinned_entry(f, heap->dblk, (size_t)new_heap_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "unable to resize heap data block in cache")
+
+ /* Relocate the heap data block in the cache */
+ if(H5AC_rename(f, H5AC_LHEAP_DBLK, old_addr, new_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRENAME, FAIL, "unable to move heap data block in cache")
+ } /* end else */
+ } /* end else */
+
+ /* Update heap info*/
+ heap->dblk_addr = new_addr;
+ heap->dblk_size = new_heap_size;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_dblk_realloc() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HL_minimize_heap_space
*
* Purpose: Go through the heap's freelist and determine if we can
@@ -195,8 +312,7 @@ done:
static herr_t
H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap)
{
- size_t new_heap_size = heap->heap_alloc; /* New size of heap */
- size_t sizeof_hdr;
+ size_t new_heap_size = heap->dblk_size; /* New size of heap */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5HL_minimize_heap_space, FAIL)
@@ -205,8 +321,6 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap)
HDassert(f);
HDassert(heap);
- sizeof_hdr = H5HL_SIZEOF_HDR(f); /* cache H5HL header size for file */
-
/*
* Check to see if we can reduce the size of the heap in memory by
* eliminating free blocks at the tail of the buffer before flushing the
@@ -219,7 +333,7 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap)
/* Search for a free block at the end of the buffer */
for(tmp_fl = heap->freelist; tmp_fl; tmp_fl = tmp_fl->next)
/* Check if the end of this free block is at the end of the buffer */
- if(tmp_fl->offset + tmp_fl->size == heap->heap_alloc) {
+ if(tmp_fl->offset + tmp_fl->size == heap->dblk_size) {
last_fl = tmp_fl;
break;
} /* end if */
@@ -234,7 +348,7 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap)
* buffer size (and the memory buffer is larger than the
* minimum size), reduce or eliminate it.
*/
- if(last_fl->size >= (heap->heap_alloc / 2) && heap->heap_alloc > H5HL_MIN_HEAP) {
+ if(last_fl->size >= (heap->dblk_size / 2) && heap->dblk_size > H5HL_MIN_HEAP) {
/*
* Reduce size of buffer until it's too small or would
* eliminate the free block
@@ -285,30 +399,16 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap)
* data segment of the heap to another contiguous block of disk
* storage.
*/
- if(new_heap_size != heap->heap_alloc) {
- haddr_t old_addr = heap->addr,
- new_addr;
-
- HDassert(new_heap_size < heap->heap_alloc);
+ if(new_heap_size != heap->dblk_size) {
+ HDassert(new_heap_size < heap->dblk_size);
/* Resize the memory buffer */
- if(NULL == (heap->chunk = H5FL_BLK_REALLOC(lheap_chunk, heap->chunk, (sizeof_hdr + new_heap_size))))
+ if(NULL == (heap->dblk_image = H5FL_BLK_REALLOC(lheap_chunk, heap->dblk_image, new_heap_size)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed")
- /* Release old space on disk */
- /* (Should be safe to free old heap space first, since it's shrinking -QAK) */
- H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t);
- if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, (hsize_t)heap->heap_alloc) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap")
-
- /* Allocate new space on disk */
- H5_CHECK_OVERFLOW(new_heap_size, size_t, hsize_t);
- if(HADDR_UNDEF == (new_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)new_heap_size)))
+ /* Reallocate data block in file */
+ if(H5HL_dblk_realloc(f, dxpl_id, heap, new_heap_size) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "reallocating data block failed")
-
- /* Update heap info*/
- heap->addr = new_addr;
- heap->heap_alloc = new_heap_size;
} /* end if */
done:
@@ -319,26 +419,9 @@ done:
/*-------------------------------------------------------------------------
* Function: H5HL_protect
*
- * Purpose: This function is a wrapper for the H5AC_protect call. The
- * old H5HL_peek call (which this once was) wasn't "safe"
- * for FPHDF5. (It'd get a read lock on an object but once
- * it got that object, it'd release it keeping the old
- * pointer value, which is no longer valid. This won't work
- * since the pointer into some metdata block can become
- * invalid.)
- *
- * N.B.: This function is always called in conjunction with
- * the H5HL_offset_into function. The return from that
- * function is the proper pointer to the heap's object. This
- * is done so that the return from this function can be sent
- * to H5HL_unprotect.
- *
- * Return: Success: Ptr to the object. The pointer points to a
- * chunk of memory large enough to hold the
- * object from the specified offset (usually the
- * beginning of the object) to the end of the
- * object. Do not attempt to read past the end
- * of the object.
+ * Purpose: This function is a wrapper for the H5AC_protect call.
+ *
+ * Return: Success: Non-NULL pointer to the local heap prefix.
* Failure: NULL
*
* Programmer: Bill Wendling
@@ -350,7 +433,13 @@ done:
H5HL_t *
H5HL_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5AC_protect_t rw)
{
- H5HL_t *ret_value;
+ H5HL_cache_prfx_ud_t prfx_udata; /* User data for protecting local heap prefix */
+ H5HL_prfx_t *prfx = NULL; /* Local heap prefix */
+ H5HL_dblk_t *dblk = NULL; /* Local heap data block */
+ H5HL_t *heap; /* Heap data structure */
+ unsigned prfx_cache_flags = H5AC__NO_FLAGS_SET; /* Cache flags for unprotecting prefix entry */
+ unsigned dblk_cache_flags = H5AC__NO_FLAGS_SET; /* Cache flags for unprotecting data block entry */
+ H5HL_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5HL_protect, NULL)
@@ -358,10 +447,65 @@ H5HL_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5AC_protect_t rw)
HDassert(f);
HDassert(H5F_addr_defined(addr));
- if(NULL == (ret_value = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, rw)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to load heap")
+ /* Construct the user data for protect callback */
+ prfx_udata.sizeof_size = H5F_SIZEOF_SIZE(f);
+ prfx_udata.sizeof_addr = H5F_SIZEOF_ADDR(f);
+ prfx_udata.sizeof_prfx = H5HL_SIZEOF_HDR(f);
+ prfx_udata.loaded = FALSE;
+ prfx_udata.free_block = H5HL_FREE_NULL;
+
+ /* Protect the local heap prefix */
+ if(NULL == (prfx = (H5HL_prfx_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_PRFX, addr, NULL, &prfx_udata, rw)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to load heap prefix")
+
+ /* Get the pointer to the heap */
+ heap = prfx->heap;
+
+ /* Check if the heap is already pinned in memory */
+ /* (for re-entrant situation) */
+ if(heap->prots == 0) {
+ /* Check if heap has separate data block */
+ if(heap->single_cache_obj) {
+ /* Set the flag for pinning the prefix when unprotecting it */
+ prfx_cache_flags |= H5AC__PIN_ENTRY_FLAG;
+ } /* end if */
+ else {
+ H5HL_cache_dblk_ud_t dblk_udata; /* User data for protecting local heap data block */
+
+ /* Construct the user data for protect callback */
+ dblk_udata.heap = heap;
+ dblk_udata.free_block = prfx_udata.loaded ? prfx_udata.free_block :
+ (heap->freelist ? heap->freelist->offset : H5HL_FREE_NULL);
+ dblk_udata.loaded = FALSE;
+
+ /* Protect the local heap data block */
+ if(NULL == (dblk = (H5HL_dblk_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_DBLK, heap->dblk_addr, NULL, &dblk_udata, rw)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to load heap data block")
+
+ /* Pin the prefix, if the data block was loaded from file */
+ if(dblk_udata.loaded)
+ prfx_cache_flags |= H5AC__PIN_ENTRY_FLAG;
+
+ /* Set the flag for pinning the data block when unprotecting it */
+ dblk_cache_flags |= H5AC__PIN_ENTRY_FLAG;
+ } /* end if */
+ } /* end if */
+
+ /* Increment # of times heap is protected */
+ heap->prots++;
+
+ /* Set return value */
+ ret_value = heap;
done:
+ /* Release the prefix from the cache, now pinned */
+ if(prfx && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP_PRFX, heap->prfx_addr, prfx, prfx_cache_flags) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release local heap prefix")
+
+ /* Release the data block from the cache, now pinned */
+ if(dblk && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP_DBLK, heap->dblk_addr, dblk, dblk_cache_flags) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release local heap data block")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HL_protect() */
@@ -382,7 +526,7 @@ done:
*-------------------------------------------------------------------------
*/
void *
-H5HL_offset_into(H5F_t *f, const H5HL_t *heap, size_t offset)
+H5HL_offset_into(const H5HL_t *heap, size_t offset)
{
/*
* We need to have called some other function before this to get a
@@ -390,11 +534,11 @@ H5HL_offset_into(H5F_t *f, const H5HL_t *heap, size_t offset)
*/
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_offset_into)
- HDassert(f);
+ /* Sanity check */
HDassert(heap);
- HDassert(offset < heap->heap_alloc);
+ HDassert(offset < heap->dblk_size);
- FUNC_LEAVE_NOAPI(heap->chunk + H5HL_SIZEOF_HDR(f) + offset)
+ FUNC_LEAVE_NOAPI(heap->dblk_image + offset)
} /* end H5HL_offset_into() */
@@ -413,7 +557,7 @@ H5HL_offset_into(H5F_t *f, const H5HL_t *heap, size_t offset)
*-------------------------------------------------------------------------
*/
herr_t
-H5HL_unprotect(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, haddr_t addr)
+H5HL_unprotect(H5F_t *f, H5HL_t *heap)
{
herr_t ret_value = SUCCEED;
@@ -422,10 +566,28 @@ H5HL_unprotect(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, haddr_t addr)
/* check arguments */
HDassert(f);
HDassert(heap);
- HDassert(H5F_addr_defined(addr));
- if(H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, (void *)heap, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap")
+ /* Decrement # of times heap is protected */
+ heap->prots--;
+
+ /* Check for last unprotection of heap */
+ if(heap->prots == 0) {
+ /* Check for separate heap data block */
+ if(heap->single_cache_obj) {
+ /* Mark local heap prefix as evictable again */
+ if(H5AC_unpin_entry(f, heap->prfx) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPIN, FAIL, "unable to unpin local heap data block")
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(heap->dblk);
+
+ /* Mark local heap data block as evictable again */
+ /* (data block still pins prefix) */
+ if(H5AC_unpin_entry(f, heap->dblk) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPIN, FAIL, "unable to unpin local heap data block")
+ } /* end else */
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -464,12 +626,55 @@ H5HL_remove_free(H5HL_t *heap, H5HL_free_t *fl)
/*-------------------------------------------------------------------------
+ * Function: H5HL_dirty
+ *
+ * Purpose: Mark heap as dirty
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Oct 12 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HL_dirty(H5F_t *f, H5HL_t *heap)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HL_dirty)
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(heap);
+ HDassert(heap->prfx);
+
+ /* Mark heap data block as dirty, if there is one */
+ if(!heap->single_cache_obj) {
+ /* Sanity check */
+ HDassert(heap->dblk);
+
+ if(H5AC_mark_pinned_or_protected_entry_dirty(f, heap->dblk) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to mark heap data block as dirty")
+ } /* end if */
+
+ /* Mark heap prefix as dirty */
+ if(H5AC_mark_pinned_or_protected_entry_dirty(f, heap->prfx) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to mark heap prefix as dirty")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_dirty() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HL_insert
*
* Purpose: Inserts a new item into the heap.
*
* Return: Success: Offset of new item within heap.
- *
* Failure: UFAIL
*
* Programmer: Robb Matzke
@@ -485,7 +690,6 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void *
size_t offset = 0;
size_t need_size;
hbool_t found;
- size_t sizeof_hdr; /* Cache H5HL header size for file */
size_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5HL_insert, UFAIL)
@@ -502,12 +706,9 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void *
* so we just accept that an extra flush of the heap info could occur
* if an error occurs -QAK)
*/
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, heap) < 0)
+ if(H5HL_dirty(f, heap) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, UFAIL, "unable to mark heap as dirty")
- /* Cache this for later */
- sizeof_hdr = H5HL_SIZEOF_HDR(f);
-
/*
* In order to keep the free list descriptors aligned on word boundaries,
* whatever that might mean, we round the size up to the next multiple of
@@ -550,12 +751,13 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void *
*/
if(found == FALSE) {
size_t need_more; /* How much more space we need */
- size_t new_heap_alloc; /* Final size of space allocated for heap */
+ size_t new_dblk_size; /* Final size of space allocated for heap data block */
+ size_t old_dblk_size; /* Previous size of space allocated for heap data block */
htri_t extended; /* Whether the local heap's data segment on disk was extended */
/* At least double the heap's size, making certain there's enough room
* for the new object */
- need_more = MAX(need_size, heap->heap_alloc);
+ need_more = MAX(need_size, heap->dblk_size);
/* If there is no last free block or it's not at the end of the heap,
* and the amount of space to allocate is not big enough to include at
@@ -563,33 +765,46 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void *
* space requested to just the amount of space needed. (Generally
* speaking, this only occurs when the heap is small -QAK)
*/
- if(!(last_fl && last_fl->offset + last_fl->size == heap->heap_alloc)
+ if(!(last_fl && last_fl->offset + last_fl->size == heap->dblk_size)
&& (need_more < (need_size + H5HL_SIZEOF_FREE(f))))
need_more = need_size;
- new_heap_alloc = heap->heap_alloc + need_more;
- HDassert(heap->heap_alloc < new_heap_alloc);
- H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t);
- H5_CHECK_OVERFLOW(new_heap_alloc, size_t, hsize_t);
+ new_dblk_size = heap->dblk_size + need_more;
+ HDassert(heap->dblk_size < new_dblk_size);
+ old_dblk_size = heap->dblk_size;
+ H5_CHECK_OVERFLOW(heap->dblk_size, size_t, hsize_t);
+ H5_CHECK_OVERFLOW(new_dblk_size, size_t, hsize_t);
/* Extend current heap if possible */
- extended = H5MF_try_extend(f, dxpl_id, H5FD_MEM_LHEAP, heap->addr, (hsize_t)(heap->heap_alloc), (hsize_t)need_more);
+ extended = H5MF_try_extend(f, dxpl_id, H5FD_MEM_LHEAP, heap->dblk_addr, (hsize_t)(heap->dblk_size), (hsize_t)need_more);
if(extended < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, UFAIL, "error trying to extend heap")
- /* If we couldn't extend the heap, release old chunk and allocate a new one */
- if(extended == FALSE) {
- /* Release old space on disk */
- if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->addr, (hsize_t)heap->heap_alloc) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, UFAIL, "unable to free local heap")
-
- /* allocate new disk space for the heap */
- if((heap->addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)new_heap_alloc)) == HADDR_UNDEF)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, UFAIL, "unable to allocate file space for heap")
+ /* Check if we extended the heap data block in file */
+ if(extended == TRUE) {
+ /* Check for prefix & data block contiguous */
+ if(heap->single_cache_obj) {
+ /* Resize prefix+data block */
+ if(H5AC_resize_pinned_entry(f, heap->prfx, (size_t)(heap->prfx_size + new_dblk_size)) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, UFAIL, "unable to resize heap prefix in cache")
+ } /* end if */
+ else {
+ /* Resize 'standalone' data block */
+ if(H5AC_resize_pinned_entry(f, heap->dblk, (size_t)new_dblk_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, UFAIL, "unable to resize heap data block in cache")
+ } /* end else */
+
+ /* Note new size */
+ heap->dblk_size = new_dblk_size;
+ } /* end if */
+ else { /* ...if we can't, allocate a new chunk & release the old */
+ /* Reallocate data block in file */
+ if(H5HL_dblk_realloc(f, dxpl_id, heap, new_dblk_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, UFAIL, "reallocating data block failed")
} /* end if */
/* If the last free list in the heap is at the end of the heap, extend it */
- if(last_fl && last_fl->offset + last_fl->size == heap->heap_alloc) {
+ if(last_fl && last_fl->offset + last_fl->size == old_dblk_size) {
/*
* Increase the size of the last free block.
*/
@@ -614,11 +829,11 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void *
* Create a new free list element large enough that we can
* take some space out of it right away.
*/
- offset = heap->heap_alloc;
+ offset = old_dblk_size;
if(need_more - need_size >= H5HL_SIZEOF_FREE(f)) {
if(NULL == (fl = H5FL_MALLOC(H5HL_free_t)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, UFAIL, "memory allocation failed")
- fl->offset = heap->heap_alloc + need_size;
+ fl->offset = old_dblk_size + need_size;
fl->size = need_more - need_size;
HDassert(fl->offset == H5HL_ALIGN(fl->offset));
HDassert(fl->size == H5HL_ALIGN(fl->size));
@@ -640,21 +855,20 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void *
if (H5DEBUG(HL)) {
fprintf(H5DEBUG(HL),
"H5HL: resize mem buf from %lu to %lu bytes\n",
- (unsigned long)(heap->heap_alloc),
- (unsigned long)(heap->heap_alloc + need_more));
+ (unsigned long)(old_dblk_size),
+ (unsigned long)(old_dblk_size + need_more));
}
#endif
- heap->heap_alloc = new_heap_alloc;
- if(NULL == (heap->chunk = H5FL_BLK_REALLOC(lheap_chunk, heap->chunk, (sizeof_hdr + heap->heap_alloc))))
+ if(NULL == (heap->dblk_image = H5FL_BLK_REALLOC(lheap_chunk, heap->dblk_image, heap->dblk_size)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, UFAIL, "memory allocation failed")
/* Clear new section so junk doesn't appear in the file */
/* (Avoid clearing section which will be overwritten with newly inserted data) */
- HDmemset(heap->chunk + sizeof_hdr + offset + buf_size, 0, (new_heap_alloc - (offset + buf_size)));
+ HDmemset(heap->dblk_image + offset + buf_size, 0, (new_dblk_size - (offset + buf_size)));
} /* end if */
/* Copy the data into the heap */
- HDmemcpy(heap->chunk + sizeof_hdr + offset, buf, buf_size);
+ HDmemcpy(heap->dblk_image + offset, buf, buf_size);
/* Set return value */
ret_value = offset;
@@ -704,8 +918,8 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
size = H5HL_ALIGN(size);
- HDassert(offset < heap->heap_alloc);
- HDassert(offset + size <= heap->heap_alloc);
+ HDassert(offset < heap->dblk_size);
+ HDassert(offset + size <= heap->dblk_size);
/* Mark heap as dirty in cache */
/* (A bit early in the process, but it's difficult to determine in the
@@ -713,7 +927,7 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
* so we just accept that an extra flush of the heap info could occur
* if an error occurs -QAK)
*/
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, heap) < 0)
+ if(H5HL_dirty(f, heap) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to mark heap as dirty")
/*
@@ -738,8 +952,8 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
HDassert(fl->offset == H5HL_ALIGN(fl->offset));
HDassert(fl->size == H5HL_ALIGN(fl->size));
fl2 = H5HL_remove_free(heap, fl2);
- if(((fl->offset + fl->size) == heap->heap_alloc ) &&
- ((2 * fl->size) > heap->heap_alloc )) {
+ if(((fl->offset + fl->size) == heap->dblk_size) &&
+ ((2 * fl->size) > heap->dblk_size)) {
if(H5HL_minimize_heap_space(f, dxpl_id, heap) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "heap size minimization failed")
}
@@ -747,8 +961,8 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
}
fl2 = fl2->next;
}
- if(((fl->offset + fl->size) == heap->heap_alloc) &&
- ((2 * fl->size) > heap->heap_alloc)) {
+ if(((fl->offset + fl->size) == heap->dblk_size) &&
+ ((2 * fl->size) > heap->dblk_size)) {
if(H5HL_minimize_heap_space(f, dxpl_id, heap) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "heap size minimization failed")
}
@@ -762,8 +976,8 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
fl->size += fl2->size;
HDassert(fl->size == H5HL_ALIGN(fl->size));
fl2 = H5HL_remove_free(heap, fl2);
- if(((fl->offset + fl->size) == heap->heap_alloc) &&
- ((2 * fl->size) > heap->heap_alloc)) {
+ if(((fl->offset + fl->size) == heap->dblk_size) &&
+ ((2 * fl->size) > heap->dblk_size)) {
if(H5HL_minimize_heap_space(f, dxpl_id, heap) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "heap size minimization failed")
} /* end if */
@@ -771,8 +985,8 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
} /* end if */
fl2 = fl2->next;
} /* end while */
- if(((fl->offset + fl->size) == heap->heap_alloc) &&
- ((2 * fl->size) > heap->heap_alloc)) {
+ if(((fl->offset + fl->size) == heap->dblk_size) &&
+ ((2 * fl->size) > heap->dblk_size)) {
if(H5HL_minimize_heap_space(f, dxpl_id, heap) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "heap size minimization failed")
} /* end if */
@@ -811,8 +1025,8 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
heap->freelist->prev = fl;
heap->freelist = fl;
- if(((fl->offset + fl->size) == heap->heap_alloc) &&
- ((2 * fl->size) > heap->heap_alloc)) {
+ if(((fl->offset + fl->size) == heap->dblk_size) &&
+ ((2 * fl->size) > heap->dblk_size)) {
if(H5HL_minimize_heap_space(f, dxpl_id, heap) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "heap size minimization failed")
} /* end if */
@@ -838,9 +1052,12 @@ done:
herr_t
H5HL_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr)
{
- H5HL_t *heap = NULL; /* Local heap to delete */
+ H5HL_t *heap; /* Local heap to delete */
+ H5HL_cache_prfx_ud_t prfx_udata; /* User data for protecting local heap prefix */
+ H5HL_prfx_t *prfx = NULL; /* Local heap prefix */
+ H5HL_dblk_t *dblk = NULL; /* Local heap data block */
unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting heap */
- herr_t ret_value = SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5HL_delete, FAIL)
@@ -848,16 +1065,71 @@ H5HL_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr)
HDassert(f);
HDassert(H5F_addr_defined(addr));
- /* Get heap pointer */
- if(NULL == (heap = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap")
+ /* Construct the user data for protect callback */
+ prfx_udata.sizeof_size = H5F_SIZEOF_SIZE(f);
+ prfx_udata.sizeof_addr = H5F_SIZEOF_ADDR(f);
+ prfx_udata.sizeof_prfx = H5HL_SIZEOF_HDR(f);
+ prfx_udata.loaded = FALSE;
+ prfx_udata.free_block = H5HL_FREE_NULL;
+
+ /* Protect the local heap prefix */
+ if(NULL == (prfx = (H5HL_prfx_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_PRFX, addr, NULL, &prfx_udata, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap prefix")
+
+ /* Get the pointer to the heap */
+ heap = prfx->heap;
+
+ /* Check if heap has separate data block */
+ if(!heap->single_cache_obj) {
+ H5HL_cache_dblk_ud_t dblk_udata; /* User data for protecting local heap data block */
+
+ /* Construct the user data for protect callback */
+ dblk_udata.heap = heap;
+ dblk_udata.free_block = prfx_udata.loaded ? prfx_udata.free_block :
+ (heap->freelist ? heap->freelist->offset : H5HL_FREE_NULL);
+ dblk_udata.loaded = FALSE;
+
+ /* Protect the local heap data block */
+ if(NULL == (dblk = (H5HL_dblk_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_DBLK, heap->dblk_addr, NULL, &dblk_udata, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap data block")
+
+ /* Pin the prefix, if the data block was loaded from file */
+ if(dblk_udata.loaded) {
+ if(H5AC_pin_protected_entry(f, prfx) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPIN, FAIL, "unable to pin local heap prefix")
+ } /* end if */
+ } /* end if */
- /* Set the cache flags to delete the heap & free its file space */
+ /* Check if the heap is contiguous on disk */
+ if(heap->single_cache_obj) {
+ /* Free the contiguous local heap in one call */
+ H5_CHECK_OVERFLOW(heap->prfx_size + heap->dblk_size, size_t, hsize_t);
+ if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, addr, (hsize_t)(heap->prfx_size + heap->dblk_size)) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free contiguous local heap")
+ } /* end if */
+ else {
+ /* Free the local heap's prefix */
+ H5_CHECK_OVERFLOW(heap->prfx_size, size_t, hsize_t);
+ if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->prfx_addr, (hsize_t)heap->prfx_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap header")
+
+ /* Free the local heap's data block */
+ H5_CHECK_OVERFLOW(heap->dblk_size, size_t, hsize_t);
+ if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->dblk_addr, (hsize_t)heap->dblk_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap data")
+ } /* end else */
+
+ /* Set the flags for releasing the prefix and data block */
cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
done:
- if(heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, cache_flags) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap")
+ /* Release the data block from the cache, now deleted */
+ if(dblk && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP_DBLK, heap->dblk_addr, dblk, cache_flags) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap data block")
+
+ /* Release the prefix from the cache, now deleted */
+ if(prfx && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP_PRFX, heap->prfx_addr, prfx, cache_flags) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap prefix")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HL_delete() */
@@ -879,7 +1151,9 @@ done:
herr_t
H5HL_get_size(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t *size)
{
- H5HL_t *heap = NULL; /* Heap to query */
+ H5HL_cache_prfx_ud_t prfx_udata; /* User data for protecting local heap prefix */
+ H5HL_prfx_t *prfx = NULL; /* Local heap prefix */
+ H5HL_t *heap; /* Heap data structure */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5HL_get_size, FAIL)
@@ -889,16 +1163,26 @@ H5HL_get_size(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t *size)
HDassert(H5F_addr_defined(addr));
HDassert(size);
- /* Get heap pointer */
- if(NULL == (heap = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap")
+ /* Construct the user data for protect callback */
+ prfx_udata.sizeof_size = H5F_SIZEOF_SIZE(f);
+ prfx_udata.sizeof_addr = H5F_SIZEOF_ADDR(f);
+ prfx_udata.sizeof_prfx = H5HL_SIZEOF_HDR(f);
+ prfx_udata.loaded = FALSE;
+ prfx_udata.free_block = H5HL_FREE_NULL;
+
+ /* Protect the local heap prefix */
+ if(NULL == (prfx = (H5HL_prfx_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_PRFX, addr, NULL, &prfx_udata, H5AC_READ)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap prefix")
+
+ /* Get the pointer to the heap */
+ heap = prfx->heap;
/* Set the size to return */
- *size = heap->heap_alloc;
+ *size = heap->dblk_size;
done:
- if(heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap")
+ if(prfx && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP_PRFX, heap->prfx_addr, prfx, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap prefix")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HL_get_size() */
@@ -920,8 +1204,9 @@ done:
herr_t
H5HL_heapsize(H5F_t *f, hid_t dxpl_id, haddr_t addr, hsize_t *heap_size)
{
- H5HL_t *heap = NULL; /* Heap to query */
- size_t local_heap_size = 0;
+ H5HL_cache_prfx_ud_t prfx_udata; /* User data for protecting local heap prefix */
+ H5HL_prfx_t *prfx = NULL; /* Local heap prefix */
+ H5HL_t *heap; /* Heap data structure */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5HL_heapsize, FAIL)
@@ -931,20 +1216,26 @@ H5HL_heapsize(H5F_t *f, hid_t dxpl_id, haddr_t addr, hsize_t *heap_size)
HDassert(H5F_addr_defined(addr));
HDassert(heap_size);
- /* Get heap pointer */
- if(NULL == (heap = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap")
+ /* Construct the user data for protect callback */
+ prfx_udata.sizeof_size = H5F_SIZEOF_SIZE(f);
+ prfx_udata.sizeof_addr = H5F_SIZEOF_ADDR(f);
+ prfx_udata.sizeof_prfx = H5HL_SIZEOF_HDR(f);
+ prfx_udata.loaded = FALSE;
+ prfx_udata.free_block = H5HL_FREE_NULL;
+
+ /* Protect the local heap prefix */
+ if(NULL == (prfx = (H5HL_prfx_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP_PRFX, addr, NULL, &prfx_udata, H5AC_READ)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load heap prefix")
- /* Get the total size of the local heap */
- if(H5HL_size(f, heap, &local_heap_size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to compute size of local heap")
+ /* Get the pointer to the heap */
+ heap = prfx->heap;
/* Accumulate the size of the local heap */
- *heap_size += (hsize_t)local_heap_size;
+ *heap_size += (hsize_t)(heap->prfx_size + heap->dblk_size);
done:
- if(heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap")
+ if(prfx && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP_PRFX, heap->prfx_addr, prfx, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap prefix")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HL_heapsize() */