summaryrefslogtreecommitdiffstats
path: root/src/H5HL.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5HL.c')
-rw-r--r--src/H5HL.c625
1 files changed, 398 insertions, 227 deletions
diff --git a/src/H5HL.c b/src/H5HL.c
index 40350ce..3813efe 100644
--- a/src/H5HL.c
+++ b/src/H5HL.c
@@ -28,7 +28,11 @@
*
*-------------------------------------------------------------------------
*/
-#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+#define H5F_PACKAGE /* Suppress error about including H5Fpkg */
+
+/* Pablo information */
+/* (Put before include files to avoid problems with inline functions) */
+#define PABLO_MASK H5HL_mask
#include "H5private.h" /* Generic Functions */
#include "H5ACprivate.h" /* Metadata cache */
@@ -39,9 +43,6 @@
#include "H5MFprivate.h" /* File memory management */
#include "H5MMprivate.h" /* Memory management */
-/* Pablo information */
-#define PABLO_MASK H5HL_mask
-
/* Private macros */
#define H5HL_FREE_NULL 1 /*end of free list on disk */
#define H5HL_MIN_HEAP 256 /* Minimum size to reduce heap buffer to */
@@ -65,7 +66,7 @@ typedef struct H5HL_free_t {
struct H5HL_free_t *next; /*next entry in free list */
} H5HL_free_t;
-typedef struct H5HL_t {
+struct H5HL_t {
H5AC_info_t cache_info; /* Information for H5AC cache functions, _must_ be */
/* first field in structure */
haddr_t addr; /*address of data */
@@ -74,7 +75,7 @@ typedef struct H5HL_t {
size_t disk_resrv; /*data bytes "reserved" on disk */
uint8_t *chunk; /*the chunk, including header */
H5HL_free_t *freelist; /*the free list */
-} H5HL_t;
+};
/* PRIVATE PROTOTYPES */
#ifdef NOT_YET
@@ -83,7 +84,10 @@ static void *H5HL_read(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset, siz
static herr_t H5HL_write(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset, size_t size,
const void *buf);
#endif /* NOT_YET */
-static H5HL_free_t * H5HL_remove_free(H5HL_t *heap, H5HL_free_t *fl);
+
+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,
@@ -275,7 +279,7 @@ H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1,
/* 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->disk_alloc);
heap->mem_alloc = heap->disk_alloc;
@@ -328,6 +332,219 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5HL_minimize_heap_space
+ *
+ * Purpose: Go through the heap's freelist and determine if we can
+ * eliminate the free blocks at the tail of the buffer.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Bill Wendling
+ * wendling@ncsa.uiuc.edu
+ * Sept. 16, 2003
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap)
+{
+ herr_t ret_value = SUCCEED;
+ size_t sizeof_hdr;
+
+ FUNC_ENTER_NOAPI(H5HL_minimize_heap_space, FAIL)
+
+ /* check args */
+ assert(f);
+ assert(heap);
+
+ sizeof_hdr = H5HL_SIZEOF_HDR(f); /* cache H5HL header size for file */
+
+ /*
+ * When the heap is being flushed to disk, release the file space reserved
+ * for it.
+ */
+ H5MF_free_reserved(f, (hsize_t)heap->disk_resrv);
+ heap->disk_resrv = 0;
+
+ /*
+ * 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
+ * buffer out.
+ */
+ if (heap->freelist) {
+ H5HL_free_t *tmp_fl;
+ H5HL_free_t *last_fl = NULL;
+
+ /* 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->mem_alloc) {
+ last_fl = tmp_fl;
+ break;
+ }
+
+ /*
+ * Found free block at the end of the buffer, decide what to do
+ * about it
+ */
+ if (last_fl) {
+ size_t new_mem_size = heap->mem_alloc; /* New size of memory buffer */
+
+ /*
+ * If the last free block's size is more than half the memory
+ * buffer size (and the memory buffer is larger than the
+ * minimum size), reduce or eliminate it.
+ */
+ if (last_fl->size >= (heap->mem_alloc / 2) && heap->mem_alloc > H5HL_MIN_HEAP) {
+ /*
+ * Reduce size of buffer until it's too small or would
+ * eliminate the free block
+ */
+ while (new_mem_size > H5HL_MIN_HEAP &&
+ new_mem_size >= (last_fl->offset + H5HL_SIZEOF_FREE(f)))
+ new_mem_size /= 2;
+
+ /*
+ * Check if reducing the memory buffer size would
+ * eliminate the free list
+ */
+ if (new_mem_size < (last_fl->offset + H5HL_SIZEOF_FREE(f))) {
+ /* Check if this is the only block on the free list */
+ if (last_fl->prev == NULL && last_fl->next == NULL) {
+ /* Double the new memory size */
+ new_mem_size *= 2;
+
+ /* Truncate the free block */
+ last_fl->size = H5HL_ALIGN(new_mem_size - last_fl->offset);
+ new_mem_size = last_fl->offset + last_fl->size;
+ assert(last_fl->size >= H5HL_SIZEOF_FREE(f));
+ } else {
+ /*
+ * Set the size of the memory buffer to the start
+ * of the free list
+ */
+ new_mem_size = last_fl->offset;
+
+ /* Eliminate the free block from the list */
+ last_fl = H5HL_remove_free(heap, last_fl);
+ }
+ } else {
+ /* Truncate the free block */
+ last_fl->size = H5HL_ALIGN(new_mem_size - last_fl->offset);
+ new_mem_size = last_fl->offset + last_fl->size;
+ assert(last_fl->size >= H5HL_SIZEOF_FREE(f));
+ assert(last_fl->size == H5HL_ALIGN(last_fl->size));
+ }
+
+ /* Resize the memory buffer and reserved space in file */
+ if (new_mem_size != heap->mem_alloc) {
+
+ heap->mem_alloc = new_mem_size;
+ heap->chunk = H5FL_BLK_REALLOC(heap_chunk, heap->chunk, (sizeof_hdr + new_mem_size));
+
+ if (!heap->chunk)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ }
+ }
+ }
+ }
+
+ /*
+ * If the heap grew larger or smaller than disk storage then move the
+ * data segment of the heap to another contiguous block of disk
+ * storage.
+ */
+ if (heap->mem_alloc != heap->disk_alloc) {
+ haddr_t old_addr = heap->addr, new_addr;
+
+ /* Release old space on disk */
+ H5_CHECK_OVERFLOW(heap->disk_alloc, size_t, hsize_t);
+ H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, (hsize_t)heap->disk_alloc);
+ H5E_clear(); /* don't really care if the free failed */
+
+ /* Allocate new space on disk */
+ H5_CHECK_OVERFLOW(heap->mem_alloc, size_t, hsize_t);
+
+ if (HADDR_UNDEF == (new_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)heap->mem_alloc)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate file space for heap")
+
+ heap->addr = new_addr;
+
+ /* Set new size of block on disk */
+ heap->disk_alloc = heap->mem_alloc;
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_serialize
+ *
+ * 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.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * 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, 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->mem_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
@@ -340,25 +557,24 @@ done:
* Jul 17 1997
*
* Modifications:
- * rky, 1998-08-28
- * Only p0 writes metadata to disk.
+ * rky, 1998-08-28
+ * Only p0 writes metadata to disk.
*
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
+ * 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.
*-------------------------------------------------------------------------
*/
static herr_t
H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap)
{
- uint8_t *p;
- H5HL_free_t *fl;
- haddr_t hdr_end_addr;
- size_t sizeof_hdr; /* Cache H5HL header size for file */
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5HL_flush, FAIL);
@@ -368,176 +584,45 @@ H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap)
assert(heap);
if (heap->cache_info.dirty) {
- /* Cache this for later */
- sizeof_hdr= H5HL_SIZEOF_HDR(f);
+ haddr_t hdr_end_addr;
+ size_t sizeof_hdr = H5HL_SIZEOF_HDR(f); /* cache H5HL header size for file */
- /*
- * Since the file is being flushed to disk, release the file space reserved
- * for it.
- */
- H5MF_free_reserved(f, heap->disk_resrv);
- heap->disk_resrv = 0;
-
- /*
- * 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
- * buffer out.
- */
- if(heap->freelist) {
- H5HL_free_t *tmp_fl=heap->freelist;
- H5HL_free_t *last_fl=NULL;
-
- /* Search for a free block at the end of the buffer */
- while(tmp_fl!=NULL) {
- /* Check if the end of this free block is at the end of the buffer */
- if(tmp_fl->offset + tmp_fl->size == heap->mem_alloc) {
- last_fl=tmp_fl;
- break;
- } /* end if */
- tmp_fl=tmp_fl->next;
- } /* end while */
-
- /* Found free block at the end of the buffer, decide what to do about it */
- if(last_fl) {
- size_t new_mem_size=heap->mem_alloc; /* New size of memory buffer */
-
- /*
- *If the last free block's size is more than half the memory
- * buffer size (and the memory buffer is larger than the minimum
- * size), reduce or eliminate it.
- */
- if(last_fl->size>=(heap->mem_alloc/2) && heap->mem_alloc>H5HL_MIN_HEAP) {
- /* Reduce size of buffer until it's too small or would eliminate the free block */
- while(new_mem_size>H5HL_MIN_HEAP &&
- new_mem_size>=(last_fl->offset+H5HL_SIZEOF_FREE(f)))
- new_mem_size /= 2;
-
- /* Check if reducing the memory buffer size would eliminate the free list */
- if(new_mem_size<(last_fl->offset+H5HL_SIZEOF_FREE(f))) {
- /* Check if this is the only block on the free list */
- if(last_fl->prev==NULL && last_fl->next==NULL) {
- /* Double the new memory size */
- new_mem_size *=2;
-
- /* Truncate the free block */
- last_fl->size=H5HL_ALIGN(new_mem_size-last_fl->offset);
- new_mem_size=last_fl->offset+last_fl->size;
- assert(last_fl->size>=H5HL_SIZEOF_FREE(f));
- } /* end if */
- else {
- /* Set the size of the memory buffer to the start of the free list */
- new_mem_size=last_fl->offset;
-
- /* Eliminate the free block from the list */
- last_fl = H5HL_remove_free(heap, last_fl);
- } /* end else */
- } /* end if */
- else {
- /* Truncate the free block */
- last_fl->size=H5HL_ALIGN(new_mem_size-last_fl->offset);
- new_mem_size=last_fl->offset+last_fl->size;
- assert(last_fl->size>=H5HL_SIZEOF_FREE(f));
- assert(last_fl->size==H5HL_ALIGN(last_fl->size));
- } /* end else */
-
- /* Resize the memory buffer */
- if(new_mem_size!=heap->mem_alloc) {
- heap->mem_alloc=new_mem_size;
- heap->chunk = H5FL_BLK_REALLOC(heap_chunk,heap->chunk,
- (sizeof_hdr + new_mem_size));
- if (NULL==heap->chunk)
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
- } /* end if */
- } /* end if */
- } /* end if */
- } /* end if */
-
- /*
- * If the heap grew larger or smaller than disk storage then move the
- * data segment of the heap to another contiguous block of
- * disk storage.
- */
- if (heap->mem_alloc != heap->disk_alloc) {
- haddr_t old_addr = heap->addr, new_addr;
-
- /* Release old space on disk */
- H5_CHECK_OVERFLOW(heap->disk_alloc,size_t,hsize_t);
- H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, (hsize_t)heap->disk_alloc);
- H5E_clear(); /*don't really care if the free failed */
-
- /* Allocate new space on disk */
- H5_CHECK_OVERFLOW(heap->mem_alloc,size_t,hsize_t);
- if (HADDR_UNDEF==(new_addr=H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id,
- (hsize_t)heap->mem_alloc)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate file space for heap");
- heap->addr = new_addr;
-
- /* Set new size of block on disk */
- heap->disk_alloc = heap->mem_alloc;
- }
+ /* Minimize the heap space size if possible */
+ if (H5HL_minimize_heap_space(f, dxpl_id, heap) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to minimize local heap space")
- /*
- * Write the header.
- */
- p = heap->chunk;
- fl=heap->freelist;
- HDmemcpy(p, H5HL_MAGIC, 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->mem_alloc);
- H5F_ENCODE_LENGTH(f, p, fl ? fl->offset : H5HL_FREE_NULL);
- H5F_addr_encode(f, &p, heap->addr);
-
- /*
- * Write the free list.
- */
- while (fl) {
- assert (fl->offset == H5HL_ALIGN (fl->offset));
- p = heap->chunk + sizeof_hdr + 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);
- fl = fl->next;
- }
+ /* Write the header */
+ if (H5HL_serialize(f, heap, heap->chunk) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_WRITEERROR, FAIL, "unable to serialize local heap")
- /*
- * Copy buffer to disk.
- */
+ /* 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->disk_alloc),
+ if (H5F_block_write(f, H5FD_MEM_LHEAP, addr, (sizeof_hdr + heap->disk_alloc),
dxpl_id, heap->chunk) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header and data to file");
+ 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, 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->disk_alloc,
dxpl_id, heap->chunk + sizeof_hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap data to file");
+ HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap data to file")
}
- heap->cache_info.dirty = 0;
+ heap->cache_info.dirty = FALSE;
}
- /*
- * Should we destroy the memory version?
- */
+ /* 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");
+ 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);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -567,7 +652,7 @@ H5HL_dest(H5F_t UNUSED *f, H5HL_t *heap)
assert(heap);
/* Verify that node is clean */
- assert (heap->cache_info.dirty==0);
+ assert (heap->cache_info.dirty==FALSE);
if(heap->chunk)
heap->chunk = H5FL_BLK_FREE(heap_chunk,heap->chunk);
@@ -606,7 +691,7 @@ H5HL_clear(H5HL_t *heap)
assert(heap);
/* Mark heap as clean */
- heap->cache_info.dirty = 0;
+ heap->cache_info.dirty = FALSE;
FUNC_LEAVE_NOAPI(SUCCEED);
} /* end H5HL_clear() */
@@ -652,8 +737,9 @@ H5HL_read(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset, size_t size, voi
assert(f);
assert (H5F_addr_defined(addr));
- if (NULL == (heap = H5AC_find(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL)))
+ if (NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to load heap");
+
assert(offset < heap->mem_alloc);
assert(offset + size <= heap->mem_alloc);
@@ -665,60 +751,128 @@ H5HL_read(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset, size_t size, voi
ret_value=buf;
done:
+ if (heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, FALSE) != SUCCEED)
+ HDONE_ERROR(H5E_HEAP, H5E_PROTECT, NULL, "unable to release object header");
+
FUNC_LEAVE_NOAPI(ret_value);
}
#endif /* NOT_YET */
/*-------------------------------------------------------------------------
- * Function: H5HL_peek
+ * 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
*
- * Purpose: This function is a more efficient version of H5HL_read.
- * Instead of copying a heap object into a caller-supplied
- * buffer, this function returns a pointer directly into the
- * cache where the heap is being held. Thus, the return pointer
- * is valid only until the next call to the cache.
+ * Modifications:
*
- * The address of the heap is ADDR in file F. OFFSET is the
- * byte offset of the object from the beginning of the heap and
- * may include an offset into the interior of the object.
+ *-------------------------------------------------------------------------
+ */
+const H5HL_t *
+H5HL_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr)
+{
+ H5HL_t *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI(H5HL_protect, NULL);
+
+ /* check arguments */
+ assert(f);
+ assert(H5F_addr_defined(addr));
+
+ if (NULL == (ret_value = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to load heap");
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_offset_into
*
- * 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: Called directly after the call to H5HL_protect so that
+ * a pointer to the object in the heap can be got.
*
- * Failure: NULL
+ * Return: Success: Valid pointer.
+ * Failure: NULL
*
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jul 16 1997
+ * Programmer: Bill Wendling
+ * wendling@ncsa.uiuc.edu
+ * Sept. 17, 2003
*
* Modifications:
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
+ *
*-------------------------------------------------------------------------
*/
-const void *
-H5HL_peek(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset)
+void *
+H5HL_offset_into(H5F_t *f, const H5HL_t *heap, size_t offset)
{
- H5HL_t *heap;
- const void *ret_value;
+ /*
+ * 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->mem_alloc);
+ FUNC_LEAVE_NOAPI(heap->chunk + H5HL_SIZEOF_HDR(f) + offset)
+}
- FUNC_ENTER_NOAPI(H5HL_peek, NULL);
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_unprotect
+ *
+ * Purpose: Unprotect the data retrieved by the H5HL_protect call.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Bill Wendling
+ * wendling@ncsa.uiuc.edu
+ * Sept. 17, 2003
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HL_unprotect(H5F_t *f, hid_t dxpl_id, const H5HL_t *heap, haddr_t addr)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5HL_unprotect, FAIL);
/* check arguments */
assert(f);
+ assert(heap);
assert(H5F_addr_defined(addr));
- if (NULL == (heap = H5AC_find(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to load heap");
- assert(offset < heap->mem_alloc);
-
- /* Set return value */
- ret_value = heap->chunk + H5HL_SIZEOF_HDR(f) + offset;
+ if (H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, (void *)heap, FALSE) != SUCCEED)
+ HGOTO_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release object header");
done:
FUNC_LEAVE_NOAPI(ret_value);
@@ -781,7 +935,7 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t buf_size, const void *
size_t offset = 0;
size_t need_size, old_size, need_more;
hbool_t found;
- size_t disk_resrv; /* Amount of additional space to reserve in file */
+ size_t disk_resrv; /* Amount of additional space to reserve in file */
size_t sizeof_hdr; /* Cache H5HL header size for file */
size_t ret_value; /* Return value */
@@ -792,12 +946,14 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t buf_size, const void *
assert(H5F_addr_defined(addr));
assert(buf_size > 0);
assert(buf);
+
if (0==(f->intent & H5F_ACC_RDWR))
HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, (size_t)(-1), "no write intent on file");
- if (NULL == (heap = H5AC_find(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, (size_t)(-1), "unable to load heap");
- heap->cache_info.dirty += 1;
+ if (NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL)))
+ HGOTO_ERROR(H5E_HEAP, H5E_PROTECT, (size_t)(-1), "unable to load heap");
+
+ heap->cache_info.dirty=TRUE;
/* Cache this for later */
sizeof_hdr= H5HL_SIZEOF_HDR(f);
@@ -845,6 +1001,19 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t buf_size, const void *
if (found==FALSE) {
need_more = MAX3(need_size, heap->mem_alloc, H5HL_SIZEOF_FREE(f));
+ /* Reserve space in the file to hold the increased heap size
+ */
+ if( heap->disk_resrv == heap->mem_alloc)
+ disk_resrv = need_more;
+ else
+ disk_resrv = heap->mem_alloc + need_more - heap->disk_resrv;
+
+ if( H5MF_reserve(f, (hsize_t)disk_resrv) < 0 )
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "unable to reserve space in file");
+
+ /* Update heap's record of how much space it has reserved */
+ heap->disk_resrv += disk_resrv;
+
if (max_fl && max_fl->offset + max_fl->size == heap->mem_alloc) {
/*
* Increase the size of the maximum free block.
@@ -890,18 +1059,6 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t buf_size, const void *
}
}
- /* Reserve space in file to hold the increased heap size */
- if( heap->disk_resrv == heap->mem_alloc)
- disk_resrv = need_more;
- else
- disk_resrv = heap->mem_alloc + need_more - heap->disk_resrv;
-
- if( H5MF_reserve(f, disk_resrv) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t) (-1), "unable to reserve space for heap");
-
- /* Update heap's record of how much space it has reserved */
- heap->disk_resrv += disk_resrv;
-
#ifdef H5HL_DEBUG
if (H5DEBUG(HL)) {
fprintf(H5DEBUG(HL),
@@ -929,6 +1086,9 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t buf_size, const void *
ret_value=offset;
done:
+ if (heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, FALSE) != SUCCEED)
+ HDONE_ERROR(H5E_HEAP, H5E_PROTECT, (size_t)(-1), "unable to release object header");
+
FUNC_LEAVE_NOAPI(ret_value);
}
@@ -969,18 +1129,23 @@ H5HL_write(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset, size_t size, co
assert(H5F_addr_defined(addr));
assert(buf);
assert (offset==H5HL_ALIGN (offset));
+
if (0==(f->intent & H5F_ACC_RDWR))
HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file");
- if (NULL == (heap = H5AC_find(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap");
+ if (NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL)))
+ HGOTO_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to load heap");
+
assert(offset < heap->mem_alloc);
assert(offset + size <= heap->mem_alloc);
- heap->cache_info.dirty += 1;
+ heap->cache_info.dirty=TRUE;
HDmemcpy(heap->chunk + H5HL_SIZEOF_HDR(f) + offset, buf, size);
done:
+ if (heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, FALSE) != SUCCEED && ret_value != FAIL)
+ HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release object header");
+
FUNC_LEAVE_NOAPI(ret_value);
}
#endif /* NOT_YET */
@@ -1027,17 +1192,20 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset, size_t size)
assert(H5F_addr_defined(addr));
assert(size > 0);
assert (offset==H5HL_ALIGN (offset));
+
if (0==(f->intent & H5F_ACC_RDWR))
HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file");
size = H5HL_ALIGN (size);
- if (NULL == (heap = H5AC_find(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap");
+
+ if (NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL)))
+ HGOTO_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to load heap");
+
assert(offset < heap->mem_alloc);
assert(offset + size <= heap->mem_alloc);
- fl = heap->freelist;
- heap->cache_info.dirty += 1;
+ fl = heap->freelist;
+ heap->cache_info.dirty=TRUE;
/*
* Check if this chunk can be prepended or appended to an already
@@ -1112,6 +1280,9 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset, size_t size)
heap->freelist = fl;
done:
+ if (heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, FALSE) != SUCCEED)
+ HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release object header");
+
FUNC_LEAVE_NOAPI(ret_value);
}