summaryrefslogtreecommitdiffstats
path: root/src/H5HL.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5HL.c')
-rw-r--r--src/H5HL.c1288
1 files changed, 584 insertions, 704 deletions
diff --git a/src/H5HL.c b/src/H5HL.c
index 358816b..5c7c247 100644
--- a/src/H5HL.c
+++ b/src/H5HL.c
@@ -29,62 +29,81 @@
*
*-------------------------------------------------------------------------
*/
+
+/****************/
+/* Module Setup */
+/****************/
#define H5F_PACKAGE /* Suppress error about including H5Fpkg */
#define H5HL_PACKAGE /* Suppress error about including H5HLpkg */
+/***********/
+/* Headers */
+/***********/
#include "H5private.h" /* Generic Functions */
-#include "H5ACprivate.h" /* Metadata cache */
+#include "H5AC2private.h" /* Metadata cache */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* File access */
#include "H5FLprivate.h" /* Free lists */
#include "H5HLpkg.h" /* Local Heaps */
#include "H5MFprivate.h" /* File memory management */
-/* Private macros */
-#define H5HL_FREE_NULL 1 /*end of free list on disk */
-#define H5HL_MIN_HEAP 128 /* Minimum size to reduce heap buffer to */
+/****************/
+/* Local Macros */
+/****************/
+
+/* Minimum size to reduce heap buffer to */
+#define H5HL_MIN_HEAP 128
+
+/* Set the local heap size to speculatively read in */
+/* (needs to be more than the local heap prefix size to work at all and
+ * should be larger than the default local heap size to save the
+ * extra I/O operations) */
+#define H5HL_SPEC_READ_SIZE 512
+
-/*
- * Local heap collection version.
- */
-#define H5HL_VERSION 0
-/* Private typedefs */
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
-/* PRIVATE PROTOTYPES */
-static herr_t H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf);
static H5HL_free_t *H5HL_remove_free(H5HL_t *heap, H5HL_free_t *fl);
static herr_t H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap);
-/* Metadata cache callbacks */
-static H5HL_t *H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1,
- void *udata2);
-static herr_t H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr);
-static herr_t H5HL_dest(H5F_t *f, H5HL_t *heap);
-static herr_t H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy);
-static herr_t H5HL_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr);
-/*
- * H5HL inherits cache-like properties from H5AC
- */
-const H5AC_class_t H5AC_LHEAP[1] = {{
- H5AC_LHEAP_ID,
- (H5AC_load_func_t)H5HL_load,
- (H5AC_flush_func_t)H5HL_flush,
- (H5AC_dest_func_t)H5HL_dest,
- (H5AC_clear_func_t)H5HL_clear,
- (H5AC_size_func_t)H5HL_size,
-}};
+/*********************/
+/* Package Variables */
+/*********************/
/* Declare a free list to manage the H5HL_free_t struct */
-H5FL_DEFINE_STATIC(H5HL_free_t);
+H5FL_DEFINE(H5HL_free_t);
/* Declare a free list to manage the H5HL_t struct */
-H5FL_DEFINE_STATIC(H5HL_t);
+H5FL_DEFINE(H5HL_t);
/* Declare a PQ free list to manage the heap chunk information */
-H5FL_BLK_DEFINE_STATIC(heap_chunk);
+H5FL_BLK_DEFINE(lheap_chunk);
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
/*-------------------------------------------------------------------------
@@ -106,198 +125,190 @@ H5FL_BLK_DEFINE_STATIC(heap_chunk);
* matzke@llnl.gov
* Jul 16 1997
*
- * Modifications:
- *
- * Robb Matzke, 5 Aug 1997
- * Takes a flag that determines the type of heap that is
- * created.
- *
- * John Mainzer, 6/7/05
- * Removed code modifying the is_dirty field of the cache info.
- *
*-------------------------------------------------------------------------
*/
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);
+ FUNC_ENTER_NOAPI(H5HL_create, FAIL)
/* check arguments */
- assert(f);
- assert(addr_p);
+ HDassert(f);
+ HDassert(addr_p);
- if (size_hint && size_hint < H5HL_SIZEOF_FREE(f))
+ /* 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 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 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(heap_chunk,(sizeof_hdr + size_hint))))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
+ /* Allocate memory structure */
+ if(NULL == (heap = H5FL_CALLOC(H5HL_t)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed")
+ heap->prfx_size = H5HL_SIZEOF_HDR(f);
+
+ /* 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_NOSPACE, FAIL, "unable to allocate file memory")
+
+ /* 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->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");
+ if(size_hint) {
+ if(NULL == (heap->freelist = H5FL_MALLOC(H5HL_free_t)))
+ 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;
- } else {
+ } /* end if */
+ 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(H5AC2_set(f, dxpl_id, H5AC2_LHEAP_PRFX, heap->prfx_addr, (size_t)total_size, prfx, H5AC2__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");
- }
- }
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ if(ret_value < 0) {
+ 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)
+} /* end H5HL_create() */
/*-------------------------------------------------------------------------
- * Function: H5HL_load
- *
- * Purpose: Loads a heap from disk.
+ * Function: H5HL_dblk_realloc
*
- * Return: Success: Ptr to a local heap memory data structure.
+ * Purpose: Reallocate data block for heap
*
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jul 17 1997
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Modifications:
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Oct 12 2008
*
- * Quincey Koziol, 2002-7-180
- * Added dxpl parameter to allow more control over I/O from metadata
- * cache.
*-------------------------------------------------------------------------
*/
-static H5HL_t *
-H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1,
- void UNUSED * udata2)
+static herr_t
+H5HL_dblk_realloc(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t new_heap_size)
{
- uint8_t hdr[52];
- size_t sizeof_hdr; /* Cache H5HL header size for file */
- const uint8_t *p = NULL;
- H5HL_t *heap = NULL;
- H5HL_free_t *fl = NULL, *tail = NULL;
- size_t free_block = H5HL_FREE_NULL;
- H5HL_t *ret_value;
+ 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(H5HL_load, NULL)
+ FUNC_ENTER_NOAPI_NOINIT(H5HL_dblk_realloc)
/* check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(!udata1);
- HDassert(!udata2);
-
- /* Cache this for later */
- sizeof_hdr = H5HL_SIZEOF_HDR(f);
- HDassert(sizeof_hdr <= sizeof(hdr));
-
- /* Get the local heap's header */
- if(H5F_block_read(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read heap header")
- p = hdr;
-
- /* Check magic number */
- if(HDmemcmp(hdr, H5HL_MAGIC, (size_t)H5HL_SIZEOF_MAGIC))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap signature")
- p += H5HL_SIZEOF_MAGIC;
-
- /* Version */
- if(H5HL_VERSION != *p++)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong version number in global heap")
-
- /* Reserved */
- p += 3;
+ 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(H5AC2_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(H5AC2_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(H5AC2_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(H5AC2_set(f, dxpl_id, H5AC2_LHEAP_DBLK, new_addr, (size_t)new_heap_size, dblk, H5AC2__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(H5AC2_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")
- /* Allocate space in memory for the heap */
- if(NULL == (heap = H5FL_CALLOC(H5HL_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- /* heap data size */
- H5F_DECODE_LENGTH(f, p, heap->heap_alloc);
-
- /* free list head */
- H5F_DECODE_LENGTH(f, p, free_block);
- if(free_block != H5HL_FREE_NULL && free_block >= heap->heap_alloc)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list")
-
- /* data */
- H5F_addr_decode(f, &p, &(heap->addr));
- if(NULL == (heap->chunk = H5FL_BLK_CALLOC(heap_chunk, (sizeof_hdr + heap->heap_alloc))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- if(heap->heap_alloc &&
- H5F_block_read(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc, dxpl_id, heap->chunk + sizeof_hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to read heap data")
-
- /* Build free list */
- while(H5HL_FREE_NULL != free_block) {
- if(free_block >= heap->heap_alloc)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list")
- if(NULL == (fl = H5FL_MALLOC(H5HL_free_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- fl->offset = free_block;
- fl->prev = tail;
- fl->next = NULL;
- if(tail)
- tail->next = fl;
- tail = fl;
- if(!heap->freelist)
- heap->freelist = fl;
-
- p = heap->chunk + sizeof_hdr + free_block;
-
- H5F_DECODE_LENGTH(f, p, free_block);
- if(free_block == 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "free block size is zero?")
-
- H5F_DECODE_LENGTH(f, p, fl->size);
- if (fl->offset + fl->size > heap->heap_alloc)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list")
- } /* end while */
+ /* Relocate the heap data block in the cache */
+ if(H5AC2_rename(f, H5AC2_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 */
- /* Set return value */
- ret_value = heap;
+ /* Update heap info*/
+ heap->dblk_addr = new_addr;
+ heap->dblk_size = new_heap_size;
done:
- if(!ret_value && heap)
- if(H5HL_dest(f,heap) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy local heap collection")
-
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HL_load() */
+} /* end H5HL_dblk_realloc() */
/*-------------------------------------------------------------------------
@@ -334,9 +345,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)
@@ -344,8 +354,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
@@ -358,7 +366,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 */
@@ -373,7 +381,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
@@ -395,8 +403,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
@@ -406,12 +415,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 */
@@ -422,31 +432,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(heap_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);
- H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, (hsize_t)heap->heap_alloc);
- H5E_clear_stack(NULL); /* don't really care if the free failed */
-
- /* 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->image = H5FL_BLK_REALLOC(lheap_chunk, heap->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:
@@ -455,313 +450,95 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5HL_serialize
+ * Function: H5HL_protect
*
- * Purpose: Serialize the heap. This function will eliminate free
- * blocks at the tail of the heap and also split the block
- * if it needs to be split for the file. This is so that we
- * can serialize it correctly.
+ * Purpose: This function is a wrapper for the H5AC2_protect call.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: Non-NULL pointer to the local heap prefix.
+ * Failure: NULL
*
* Programmer: Bill Wendling
* wendling@ncsa.uiuc.edu
- * Sept. 16, 2003
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf)
-{
- H5HL_free_t *fl;
- uint8_t *p;
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_serialize)
-
- /* check args */
- assert(buf);
- assert(heap);
-
- /* serialize the header */
- p = buf;
- fl = heap->freelist;
- HDmemcpy(p, H5HL_MAGIC, (size_t)H5HL_SIZEOF_MAGIC);
- p += H5HL_SIZEOF_MAGIC;
- *p++ = H5HL_VERSION;
- *p++ = 0; /*reserved*/
- *p++ = 0; /*reserved*/
- *p++ = 0; /*reserved*/
- H5F_ENCODE_LENGTH(f, p, heap->heap_alloc);
- H5F_ENCODE_LENGTH(f, p, fl ? fl->offset : H5HL_FREE_NULL);
- H5F_addr_encode(f, &p, heap->addr);
-
- /* serialize the free list */
- for (; fl; fl = fl->next) {
- assert (fl->offset == H5HL_ALIGN (fl->offset));
- p = heap->chunk + H5HL_SIZEOF_HDR(f) + fl->offset;
-
- if (fl->next) {
- H5F_ENCODE_LENGTH(f, p, fl->next->offset);
- } else {
- H5F_ENCODE_LENGTH(f, p, H5HL_FREE_NULL);
- }
-
- H5F_ENCODE_LENGTH(f, p, fl->size);
- }
-
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HL_flush
- *
- * Purpose: Flushes a heap from memory to disk if it's dirty. Optionally
- * deletes the heap from memory.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jul 17 1997
- *
- * Modifications:
- * rky, 1998-08-28
- * Only p0 writes metadata to disk.
- *
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
- *
- * Quincey Koziol, 2002-7-180
- * Added dxpl parameter to allow more control over I/O from metadata
- * cache.
- *
- * Bill Wendling, 2003-09-16
- * Separated out the bit that serializes the heap.
- *
- * John Mainzer, 2005-08-10
- * Removed call to H5HL_minimize_heap_space(). It does disk space
- * allocation, which can cause problems if done at flush time.
- * Instead, disk space allocation/deallocation is now done at
- * insert/remove time.
- *
- * John Mainzer, 2006-08-21
- * Added the flags_ptr parameter. This parameter exists to
- * allow the flush routine to report to the cache if the
- * entry is resized or renamed as a result of the flush.
- * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry.
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5HL_flush, FAIL);
-
- /* check arguments */
- HDassert( f );
- HDassert( H5F_addr_defined(addr) );
- HDassert( heap );
-
- if (heap->cache_info.is_dirty) {
- haddr_t hdr_end_addr;
- size_t sizeof_hdr = H5HL_SIZEOF_HDR(f); /* cache H5HL header size for file */
-
- /* Write the header */
- if (H5HL_serialize(f, heap, heap->chunk) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTSERIALIZE, FAIL, "unable to serialize local heap")
-
- /* Copy buffer to disk */
- hdr_end_addr = addr + (hsize_t)sizeof_hdr;
-
- if (H5F_addr_eq(heap->addr, hdr_end_addr)) {
- /* The header and data are contiguous */
- if (H5F_block_write(f, H5FD_MEM_LHEAP, addr, (sizeof_hdr + heap->heap_alloc),
- dxpl_id, heap->chunk) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header and data to file")
- } else {
- if (H5F_block_write(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, heap->chunk) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header to file")
-
- if (H5F_block_write(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc,
- dxpl_id, heap->chunk + sizeof_hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap data to file")
- }
-
- heap->cache_info.is_dirty = FALSE;
- }
-
- /* Should we destroy the memory version? */
- if (destroy) {
- if (H5HL_dest(f,heap) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection")
- }
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HL_dest
- *
- * Purpose: Destroys a heap in memory.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Jan 15 2003
- *
- * Modifications:
+ * Sept. 17, 2003
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HL_dest(H5F_t UNUSED *f, H5HL_t *heap)
+H5HL_t *
+H5HL_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5AC2_protect_t rw)
{
- H5HL_free_t *fl;
+ 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 = H5AC2__NO_FLAGS_SET; /* Cache flags for unprotecting prefix entry */
+ unsigned dblk_cache_flags = H5AC2__NO_FLAGS_SET; /* Cache flags for unprotecting data block entry */
+ H5HL_t *ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_dest);
+ FUNC_ENTER_NOAPI(H5HL_protect, NULL)
/* check arguments */
- assert(heap);
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
- /* Verify that node is clean */
- assert (heap->cache_info.is_dirty==FALSE);
+ /* Construct the user data for protect callback */
+ prfx_udata.made_attempt = FALSE;
+ prfx_udata.f = f;
+ prfx_udata.loaded = FALSE;
+ prfx_udata.free_block = 0;
+
+ /* Protect the local heap prefix */
+ if(NULL == (prfx = (H5HL_prfx_t *)H5AC2_protect(f, dxpl_id, H5AC2_LHEAP_PRFX, addr, H5HL_SPEC_READ_SIZE, &prfx_udata, rw)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, 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 |= H5AC2__PIN_ENTRY_FLAG;
+ } /* end if */
+ else {
+ H5HL_cache_dblk_ud_t dblk_udata; /* User data for protecting local heap data block */
- if(heap->chunk)
- heap->chunk = H5FL_BLK_FREE(heap_chunk,heap->chunk);
- while (heap->freelist) {
- fl = heap->freelist;
- heap->freelist = fl->next;
- H5FL_FREE(H5HL_free_t,fl);
- }
- H5FL_FREE(H5HL_t,heap);
+ /* Construct the user data for protect callback */
+ dblk_udata.f = f;
+ 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;
- FUNC_LEAVE_NOAPI(SUCCEED);
-} /* end H5HL_dest() */
+ /* Protect the local heap data block */
+ if(NULL == (dblk = (H5HL_dblk_t *)H5AC2_protect(f, dxpl_id, H5AC2_LHEAP_DBLK, heap->dblk_addr, heap->dblk_size, &dblk_udata, rw)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to load heap data block")
-
-/*-------------------------------------------------------------------------
- * Function: H5HL_clear
- *
- * Purpose: Mark a local heap in memory as non-dirty.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 20 2003
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy)
-{
- herr_t ret_value = SUCCEED;
+ /* Pin the prefix, if the data block was loaded from file */
+ if(dblk_udata.loaded)
+ prfx_cache_flags |= H5AC2__PIN_ENTRY_FLAG;
- FUNC_ENTER_NOAPI_NOINIT(H5HL_clear);
-
- /* check arguments */
- assert(heap);
+ /* Set the flag for pinning the data block when unprotecting it */
+ dblk_cache_flags |= H5AC2__PIN_ENTRY_FLAG;
+ } /* end if */
+ } /* end if */
- /* Mark heap as clean */
- heap->cache_info.is_dirty = FALSE;
+ /* Increment # of times heap is protected */
+ heap->prots++;
- if (destroy)
- if (H5HL_dest(f, heap) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection");
+ /* Set return value */
+ ret_value = heap;
done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5HL_clear() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HL_size
- *
- * Purpose: Compute the size in bytes of the specified instance of
- * H5HL_t on disk, and return it in *len_ptr. On failure,
- * the value of *len_ptr is undefined.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: John Mainzer
- * 5/13/04
- *
- * Modifications:
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HL_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_size);
-
- /* check arguments */
- HDassert(f);
- HDassert(heap);
- HDassert(size_ptr);
-
- *size_ptr = H5HL_SIZEOF_HDR(f) + heap->heap_alloc;
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5HL_size() */
-
-
-/*-------------------------------------------------------------------------
- * 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.
- * Failure: NULL
- *
- * Programmer: Bill Wendling
- * wendling@ncsa.uiuc.edu
- * Sept. 17, 2003
- *
- *-------------------------------------------------------------------------
- */
-H5HL_t *
-H5HL_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5AC_protect_t rw)
-{
- H5HL_t *ret_value;
-
- FUNC_ENTER_NOAPI(H5HL_protect, NULL)
-
- /* check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Release the prefix from the cache, now pinned */
+ if(prfx && H5AC2_unprotect(f, dxpl_id, H5AC2_LHEAP_PRFX, heap->prfx_addr, (size_t)0, prfx, prfx_cache_flags) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release local heap prefix")
- if(NULL == (ret_value = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, rw)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to load heap")
+ /* Release the data block from the cache, now pinned */
+ if(dblk && H5AC2_unprotect(f, dxpl_id, H5AC2_LHEAP_DBLK, heap->dblk_addr, (size_t)0, dblk, dblk_cache_flags) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release local heap data block")
-done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HL_protect() */
@@ -779,23 +556,23 @@ done:
* wendling@ncsa.uiuc.edu
* Sept. 17, 2003
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
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
* valid heap pointer. So, this can remain "FUNC_ENTER_NOAPI_NOINIT"
*/
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_offset_into)
- assert(f);
- assert(heap);
- assert(offset < heap->heap_alloc);
- FUNC_LEAVE_NOAPI(heap->chunk + H5HL_SIZEOF_HDR(f) + offset)
-}
+
+ /* Sanity check */
+ HDassert(heap);
+ HDassert(offset < heap->dblk_size);
+
+ FUNC_LEAVE_NOAPI(heap->image + offset)
+} /* end H5HL_offset_into() */
/*-------------------------------------------------------------------------
@@ -813,19 +590,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;
+ herr_t ret_value = SUCCEED; /* Return value */
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(H5AC2_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(H5AC2_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)
@@ -844,22 +638,66 @@ done:
* matzke@llnl.gov
* Jul 17 1997
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static H5HL_free_t *
H5HL_remove_free(H5HL_t *heap, H5HL_free_t *fl)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_remove_free);
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_remove_free)
- if (fl->prev) fl->prev->next = fl->next;
- if (fl->next) fl->next->prev = fl->prev;
+ if(fl->prev)
+ fl->prev->next = fl->next;
+ if(fl->next)
+ fl->next->prev = fl->prev;
- if (!fl->prev) heap->freelist = fl->next;
+ if(!fl->prev)
+ heap->freelist = fl->next;
- FUNC_LEAVE_NOAPI(H5FL_FREE(H5HL_free_t,fl));
-}
+ FUNC_LEAVE_NOAPI(H5FL_FREE(H5HL_free_t, fl))
+} /* end H5HL_remove_free() */
+
+
+/*-------------------------------------------------------------------------
+ * 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(H5AC2_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(H5AC2_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() */
/*-------------------------------------------------------------------------
@@ -884,10 +722,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);
@@ -901,11 +738,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,
@@ -949,12 +783,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 can_extend; /* Whether the local heap's data segment on disk can be 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
@@ -962,85 +797,50 @@ 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);
/* Check if current heap is extendible */
- can_extend = H5MF_can_extend(f, H5FD_MEM_LHEAP, heap->addr, (hsize_t)(heap->heap_alloc), (hsize_t)need_more);
+ can_extend = H5MF_can_extend(f, H5FD_MEM_LHEAP, heap->dblk_addr, (hsize_t)(heap->dblk_size), (hsize_t)need_more);
if(can_extend < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "unable to check whether heap can be extended")
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "unable to check whether heap can be extended")
- /* extend the current heap if we can... */
+ /* Check if we can extend heap in file */
if(can_extend == TRUE) {
- if(H5MF_extend(f, H5FD_MEM_LHEAP, heap->addr, (hsize_t)(heap->heap_alloc), (hsize_t)need_more) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "can't extend heap on disk")
+ /* Extend file space allocation */
+ if(H5MF_extend(f, H5FD_MEM_LHEAP, heap->dblk_addr, (hsize_t)(heap->dblk_size), (hsize_t)need_more) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "can't extend heap on disk")
+
+ /* Check for prefix & data block contiguous */
+ if(heap->single_cache_obj) {
+ /* Resize prefix+data block */
+ if(H5AC2_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(H5AC2_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 */
- haddr_t new_addr;
-
- /* The new allocation may fail -- to avoid the possiblity of
- * file corruption, allocate the new heap first, and then
- * deallocate the old.
- */
-
- /* allocate new disk space for the heap */
- if((new_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")
-
- /* Release old space on disk */
- H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->addr, (hsize_t)heap->heap_alloc);
- H5E_clear_stack(NULL); /* don't really care if the free failed */
-
- heap->addr = new_addr;
+ /* 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 else */
/* 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.
*/
@@ -1065,17 +865,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_RESOURCE, H5E_NOSPACE, 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) {
@@ -1090,24 +891,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(heap_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->image = H5FL_BLK_REALLOC(lheap_chunk, heap->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->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->image + offset, buf, buf_size);
/* Set return value */
ret_value = offset;
@@ -1147,7 +944,7 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
H5HL_free_t *fl = NULL;
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5HL_remove, FAIL);
+ FUNC_ENTER_NOAPI(H5HL_remove, FAIL)
/* check arguments */
HDassert(f);
@@ -1157,8 +954,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
@@ -1166,7 +963,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")
/*
@@ -1181,18 +978,18 @@ 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")
}
@@ -1200,8 +997,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_RESOURCE, H5E_CANTFREE, FAIL, "heap size minimization failed")
}
@@ -1209,28 +1006,28 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
} 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")
- }
+ } /* 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")
- }
+ } /* end if */
HGOTO_DONE(SUCCEED);
- }
+ } /* end if */
fl = fl->next;
} /* end while */
@@ -1264,14 +1061,14 @@ 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")
} /* end if */
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HL_remove() */
@@ -1286,67 +1083,91 @@ done:
* koziol@ncsa.uiuc.edu
* Mar 22 2003
*
- * Modifications:
- *
- * John Mainzer - 6/17/05
- * Modified function to use the new dirtied parmeter of
- * H5AC_unprotect(), which allows management of the is_dirty
- * field of the cache info to be moved into the cache code.
- *
*-------------------------------------------------------------------------
*/
herr_t
H5HL_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr)
{
- H5HL_t *heap = NULL;
- size_t sizeof_hdr; /* Cache H5HL header size for file */
- 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_dblk_t *dblk = NULL; /* Local heap data block */
+ H5HL_t *heap; /* Heap data structure */
+ unsigned cache_flags = H5AC2__NO_FLAGS_SET; /* Cache flags for unprotecting entries */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5HL_delete, FAIL);
+ FUNC_ENTER_NOAPI(H5HL_delete, FAIL)
/* check arguments */
- assert(f);
- assert(H5F_addr_defined(addr));
-
- /* Cache this for later */
- sizeof_hdr= H5HL_SIZEOF_HDR(f);
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
- /* Get heap pointer */
- if (NULL == (heap = 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.made_attempt = FALSE;
+ prfx_udata.f = f;
+ prfx_udata.loaded = FALSE;
+ prfx_udata.free_block = 0;
+
+ /* Protect the local heap prefix */
+ if(NULL == (prfx = (H5HL_prfx_t *)H5AC2_protect(f, dxpl_id, H5AC2_LHEAP_PRFX, addr, H5HL_SPEC_READ_SIZE, &prfx_udata, H5AC2_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, 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.f = f;
+ 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 *)H5AC2_protect(f, dxpl_id, H5AC2_LHEAP_DBLK, heap->dblk_addr, heap->dblk_size, &dblk_udata, H5AC2_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap data block")
+
+ /* Pin the prefix, if the data block was loaded from file */
+ if(dblk_udata.loaded) {
+ if(H5AC2_pin_protected_entry(prfx) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPIN, FAIL, "unable to pin local heap prefix")
+ } /* end if */
+ } /* end if */
/* Check if the heap is contiguous on disk */
- assert(!H5F_addr_overflow(addr,sizeof_hdr));
- if(H5F_addr_eq(heap->addr,addr+sizeof_hdr)) {
+ if(heap->single_cache_obj) {
/* Free the contiguous local heap in one call */
- H5_CHECK_OVERFLOW(sizeof_hdr+heap->heap_alloc,size_t,hsize_t);
- if (H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, addr, (hsize_t)(sizeof_hdr+heap->heap_alloc))<0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free contiguous local heap");
+ 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 header */
- H5_CHECK_OVERFLOW(sizeof_hdr,size_t,hsize_t);
- if (H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, addr, (hsize_t)sizeof_hdr)<0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap header");
-
- /* Free the local heap's data */
- H5_CHECK_OVERFLOW(heap->heap_alloc,size_t,hsize_t);
- if (H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->addr, (hsize_t)heap->heap_alloc)<0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap data");
+ /* 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 */
- /* Release the local heap metadata from the cache */
- if (H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, H5AC__DIRTIED_FLAG | H5C__DELETED_FLAG)<0) {
- heap = NULL;
- HGOTO_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release local heap");
- }
- heap = NULL;
+ /* Set the flags for releasing the prefix and data block */
+ cache_flags |= H5AC2__DIRTIED_FLAG | H5AC2__DELETED_FLAG;
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");
+ /* Release the data block from the cache, now deleted */
+ if(dblk && H5AC2_unprotect(f, dxpl_id, H5AC2_LHEAP_DBLK, heap->dblk_addr, (size_t)0, 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 && H5AC2_unprotect(f, dxpl_id, H5AC2_LHEAP_PRFX, heap->prfx_addr, (size_t)0, prfx, cache_flags) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release local heap prefix")
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HL_delete() */
@@ -1366,8 +1187,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)
@@ -1376,16 +1199,25 @@ 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 = 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.made_attempt = FALSE;
+ prfx_udata.f = f;
+ prfx_udata.loaded = FALSE;
+ prfx_udata.free_block = 0;
+
+ /* Protect the local heap prefix */
+ if(NULL == (prfx = (H5HL_prfx_t *)H5AC2_protect(f, dxpl_id, H5AC2_LHEAP_PRFX, addr, H5HL_SPEC_READ_SIZE, &prfx_udata, H5AC2_READ)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, 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 && H5AC2_unprotect(f, dxpl_id, H5AC2_LHEAP_PRFX, heap->prfx_addr, (size_t)0, prfx, H5AC2__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() */
@@ -1407,9 +1239,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)
@@ -1418,21 +1251,68 @@ 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 = 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.made_attempt = FALSE;
+ prfx_udata.f = f;
+ prfx_udata.loaded = FALSE;
+ prfx_udata.free_block = 0;
- /* 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")
+ /* Protect the local heap prefix */
+ if(NULL == (prfx = (H5HL_prfx_t *)H5AC2_protect(f, dxpl_id, H5AC2_LHEAP_PRFX, addr, H5HL_SPEC_READ_SIZE, &prfx_udata, H5AC2_READ)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap prefix")
+
+ /* 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 && H5AC2_unprotect(f, dxpl_id, H5AC2_LHEAP_PRFX, heap->prfx_addr, (size_t)0, prfx, H5AC2__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() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_dest
+ *
+ * Purpose: Destroys a heap in memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Jan 15 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HL_dest(H5HL_t *heap)
+{
+ FUNC_ENTER_NOAPI_NOFUNC(H5HL_dest)
+
+ /* check arguments */
+ HDassert(heap);
+
+ /* Verify that node is unused */
+ HDassert(heap->prots == 0);
+ HDassert(heap->rc == 0);
+ HDassert(heap->prfx == NULL);
+ HDassert(heap->dblk == NULL);
+
+ if(heap->image)
+ heap->image = H5FL_BLK_FREE(lheap_chunk, heap->image);
+ while(heap->freelist) {
+ H5HL_free_t *fl;
+
+ fl = heap->freelist;
+ heap->freelist = fl->next;
+ H5FL_FREE(H5HL_free_t, fl);
+ } /* end while */
+ H5FL_FREE(H5HL_t, heap);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HL_dest() */
+