summaryrefslogtreecommitdiffstats
path: root/src/H5HL.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5HL.c')
-rw-r--r--src/H5HL.c736
1 files changed, 493 insertions, 243 deletions
diff --git a/src/H5HL.c b/src/H5HL.c
index a69eb16..f7c1f22 100644
--- a/src/H5HL.c
+++ b/src/H5HL.c
@@ -72,6 +72,12 @@ static herr_t H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap);
/* Package Variables */
/*********************/
+/* Declare a free list to manage the H5HL_free_t struct */
+H5FL_DEFINE(H5HL_free_t);
+
+/* Declare a PQ free list to manage the heap chunk information */
+H5FL_BLK_DEFINE(lheap_chunk);
+
/*****************************/
/* Library Private Variables */
@@ -82,15 +88,6 @@ static herr_t H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap);
/* Local Variables */
/*******************/
-/* 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);
-
/*-------------------------------------------------------------------------
@@ -117,10 +114,10 @@ H5FL_BLK_DEFINE(lheap_chunk);
herr_t
H5HL_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, haddr_t *addr_p/*out*/)
{
- H5HL_t *heap = NULL;
- hsize_t total_size; /*total heap size on disk */
- size_t sizeof_hdr; /* Cache H5HL header size for file */
- herr_t ret_value = SUCCEED;
+ H5HL_t *heap = NULL; /* Heap created */
+ H5HL_prfx_t *prfx = NULL; /* Heap prefix */
+ hsize_t total_size; /* Total heap size on disk */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5HL_create, FAIL)
@@ -128,30 +125,32 @@ H5HL_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, haddr_t *addr_p/*out*/)
HDassert(f);
HDassert(addr_p);
+ /* Adjust size hint as necessary */
if(size_hint && size_hint < H5HL_SIZEOF_FREE(f))
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)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate file memory")
+ /* 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_RESOURCE, H5E_NOSPACE, 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_RESOURCE, H5E_NOSPACE, 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) {
if(NULL == (heap->freelist = H5FL_MALLOC(H5HL_free_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed")
heap->freelist->offset = 0;
heap->freelist->size = size_hint;
heap->freelist->prev = heap->freelist->next = NULL;
@@ -159,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;
- /* 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")
+ /* 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_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 collection")
+ 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)
@@ -177,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(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(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(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(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
@@ -194,9 +312,8 @@ 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;
- herr_t ret_value = SUCCEED;
+ 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)
@@ -204,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
@@ -218,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 */
@@ -233,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
@@ -255,8 +370,9 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap)
/* Truncate the free block */
last_fl->size = H5HL_ALIGN(new_heap_size - last_fl->offset);
new_heap_size = last_fl->offset + last_fl->size;
- assert(last_fl->size >= H5HL_SIZEOF_FREE(f));
- } else {
+ HDassert(last_fl->size >= H5HL_SIZEOF_FREE(f));
+ } /* end if */
+ else {
/*
* Set the size of the memory buffer to the start
* of the free list
@@ -266,12 +382,13 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap)
/* Eliminate the free block from the list */
last_fl = H5HL_remove_free(heap, last_fl);
} /* end else */
- } else {
+ } /* end if */
+ else {
/* Truncate the free block */
last_fl->size = H5HL_ALIGN(new_heap_size - last_fl->offset);
new_heap_size = last_fl->offset + last_fl->size;
- assert(last_fl->size >= H5HL_SIZEOF_FREE(f));
- assert(last_fl->size == H5HL_ALIGN(last_fl->size));
+ HDassert(last_fl->size >= H5HL_SIZEOF_FREE(f));
+ HDassert(last_fl->size == H5HL_ALIGN(last_fl->size));
} /* end else */
} /* end if */
} /* end if */
@@ -282,31 +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 */
- heap->chunk = H5FL_BLK_REALLOC(lheap_chunk, heap->chunk, (sizeof_hdr + new_heap_size));
- if(!heap->chunk)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 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)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate file space for heap")
-
- /* Update heap info*/
- heap->addr = new_addr;
- heap->heap_alloc = 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")
+
+ /* 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")
} /* end if */
done:
@@ -317,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
@@ -348,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)
@@ -356,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_CANTLOAD, 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() */
@@ -380,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
@@ -388,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() */
@@ -411,19 +557,36 @@ 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(H5HL_t *heap)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5HL_unprotect, FAIL)
/* 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) != SUCCEED)
- HGOTO_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release object header")
+ /* 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(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(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)
@@ -462,13 +625,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(H5HL_t *heap)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HL_dirty)
+
+ /* check arguments */
+ 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(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(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: (size_t)(-1)
+ * Failure: UFAIL
*
* Programmer: Robb Matzke
* matzke@llnl.gov
@@ -483,10 +688,9 @@ 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, (size_t)(-1))
+ FUNC_ENTER_NOAPI(H5HL_insert, UFAIL)
/* check arguments */
HDassert(f);
@@ -500,11 +704,8 @@ 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)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, (size_t)(-1), "unable to mark heap as dirty")
-
- /* Cache this for later */
- sizeof_hdr = H5HL_SIZEOF_HDR(f);
+ if(H5HL_dirty(heap) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, UFAIL, "unable to mark heap as dirty")
/*
* In order to keep the free list descriptors aligned on word boundaries,
@@ -548,12 +749,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
@@ -561,72 +763,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;
-#if 0 /* JRM */ /* delete this once we are convinced that the general
- * fix will do the job.
- */
-/*
- * XXX: This is a _total_ hack, a real kludge. :-/ The metadata cache currently
- * responds very poorly when an object is inserted into the cache (or
- * resized) that is larger than the current cache size. It waits through
- * an entire 'epoch' of cache operations to resize the cache larger (getting
- * _very_ poor performance), instead of immediately accommodating the large
- * object by increasing the cache size.
- *
- * So, what we are doing here is to look at the current cache size, check
- * if the new local heap will overwhelm the cache and, if so, resize the
- * cache to be large enough to hold the new local heap block along with
- * leaving room for other objects in the cache.
- *
- * John will be working on a fix inside the cache itself, so this special
- * case code here can be removed when he's finished. - QAK, 2007/12/21
- */
-{
- H5AC_cache_config_t mdc_config;
-
- /* Retrieve the current cache information */
- mdc_config.version = H5AC__CURR_CACHE_CONFIG_VERSION;
- if(H5AC_get_cache_auto_resize_config(f->shared->cache, &mdc_config) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (size_t)-1, "H5AC_get_cache_auto_resize_config() failed.")
-
- /* Check if the current cache will get blown out by adding this heap
- * block and resize it if so.
- */
- if((2 * new_heap_alloc) >= mdc_config.initial_size) {
- mdc_config.set_initial_size = TRUE;
- mdc_config.initial_size = 2 * new_heap_alloc;
-
- if(H5AC_set_cache_auto_resize_config(f->shared->cache, &mdc_config) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (size_t)-1, "H5AC_set_cache_auto_resize_config() failed.")
- } /* end if */
-}
-#endif /* JRM */
- 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, (size_t)(-1), "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, (size_t)(-1), "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_RESOURCE, H5E_NOSPACE, (size_t)(-1), "unable to allocate file space for heap")
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, UFAIL, "error trying to extend 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(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(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.
*/
@@ -651,17 +827,18 @@ 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_RESOURCE, H5E_NOSPACE, (size_t)(-1), "memory allocation failed")
- fl->offset = heap->heap_alloc + need_size;
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, UFAIL, "memory allocation failed")
+ 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));
fl->prev = NULL;
fl->next = heap->freelist;
- if (heap->freelist) heap->freelist->prev = fl;
+ if(heap->freelist)
+ heap->freelist->prev = fl;
heap->freelist = fl;
#ifdef H5HL_DEBUG
} else if (H5DEBUG(HL) && need_more > need_size) {
@@ -676,24 +853,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;
- heap->chunk = H5FL_BLK_REALLOC(lheap_chunk, heap->chunk, (sizeof_hdr + heap->heap_alloc));
- if(NULL == heap->chunk)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "memory allocation failed")
+ 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);
+ /* Copy the data into the heap */
+ HDmemcpy(heap->dblk_image + offset, buf, buf_size);
/* Set return value */
ret_value = offset;
@@ -743,8 +916,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
@@ -752,7 +925,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(heap) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to mark heap as dirty")
/*
@@ -767,56 +940,56 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
if((offset + size) == fl->offset) {
fl->offset = offset;
fl->size += size;
- HDassert(fl->offset==H5HL_ALIGN (fl->offset));
- HDassert(fl->size==H5HL_ALIGN (fl->size));
+ HDassert(fl->offset == H5HL_ALIGN(fl->offset));
+ HDassert(fl->size == H5HL_ALIGN(fl->size));
fl2 = fl->next;
while(fl2) {
if((fl2->offset + fl2->size) == fl->offset) {
fl->offset = fl2->offset;
fl->size += fl2->size;
- HDassert(fl->offset == H5HL_ALIGN (fl->offset));
- HDassert(fl->size == H5HL_ALIGN (fl->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_RESOURCE, H5E_CANTFREE, FAIL, "heap size minimization failed")
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "heap size minimization failed")
}
HGOTO_DONE(SUCCEED);
}
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_RESOURCE, H5E_CANTFREE, FAIL, "heap size minimization failed")
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "heap size minimization failed")
}
HGOTO_DONE(SUCCEED);
} else if(fl->offset + fl->size == offset) {
fl->size += size;
fl2 = fl->next;
- HDassert(fl->size==H5HL_ALIGN (fl->size));
+ HDassert(fl->size == H5HL_ALIGN(fl->size));
while(fl2) {
if(fl->offset + fl->size == fl2->offset) {
fl->size += fl2->size;
- HDassert(fl->size==H5HL_ALIGN (fl->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_RESOURCE, H5E_CANTFREE, FAIL, "heap size minimization failed")
- }
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "heap size minimization failed")
+ } /* end if */
HGOTO_DONE(SUCCEED);
- }
+ } /* end if */
fl2 = fl2->next;
- }
- if(((fl->offset + fl->size) == heap->heap_alloc) &&
- ((2 * fl->size) > heap->heap_alloc)) {
+ } /* end while */
+ 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_RESOURCE, H5E_CANTFREE, FAIL, "heap size minimization failed")
- }
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "heap size minimization failed")
+ } /* end if */
HGOTO_DONE(SUCCEED);
- }
+ } /* end if */
fl = fl->next;
} /* end while */
@@ -839,7 +1012,7 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
* Add an entry to the free list.
*/
if(NULL == (fl = H5FL_MALLOC(H5HL_free_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed")
fl->offset = offset;
fl->size = size;
HDassert(fl->offset == H5HL_ALIGN(fl->offset));
@@ -850,10 +1023,10 @@ 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_RESOURCE, H5E_CANTFREE, FAIL, "heap size minimization failed")
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "heap size minimization failed")
} /* end if */
done:
@@ -877,9 +1050,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)
@@ -887,16 +1063,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_CANTLOAD, 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(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_PROTECT, 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() */
@@ -918,8 +1149,10 @@ 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 */
- herr_t ret_value = SUCCEED; /* Return value */
+ 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)
@@ -928,16 +1161,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_CANTLOAD, 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_PROTECT, 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() */
@@ -959,9 +1202,10 @@ 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;
- herr_t ret_value = SUCCEED; /* Return value */
+ 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)
@@ -970,20 +1214,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_CANTLOAD, 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_CANTLOAD, 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_PROTECT, 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() */