summaryrefslogtreecommitdiffstats
path: root/src/H5HFcache.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2006-03-04 22:56:44 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2006-03-04 22:56:44 (GMT)
commitdfbf976509bea0b4d598716d0dd73be494efacdd (patch)
tree891886081cf2ed280788eb2a33c609c55dfe2391 /src/H5HFcache.c
parent0e708b387c78f5a286ab82eda55214fddf6c2127 (diff)
downloadhdf5-dfbf976509bea0b4d598716d0dd73be494efacdd.zip
hdf5-dfbf976509bea0b4d598716d0dd73be494efacdd.tar.gz
hdf5-dfbf976509bea0b4d598716d0dd73be494efacdd.tar.bz2
[svn-r12004] Purpose:
New feature & code cleanup Description: Update fractal heap to be able to insert objects into a direct block hanging off the header. Extract "octal dump" code into separate routine so that both the local heaps & fractal heaps can use it. Other code cleanups & support to get this far. Platforms tested: FreeBSD 4.11 (sleipnir) Linux 2.4
Diffstat (limited to 'src/H5HFcache.c')
-rw-r--r--src/H5HFcache.c557
1 files changed, 534 insertions, 23 deletions
diff --git a/src/H5HFcache.c b/src/H5HFcache.c
index c20d05d..735037b 100644
--- a/src/H5HFcache.c
+++ b/src/H5HFcache.c
@@ -35,13 +35,19 @@
#include "H5private.h" /* Generic Functions */
#include "H5HFpkg.h" /* Fractal heaps */
#include "H5Eprivate.h" /* Error handling */
+#include "H5Vprivate.h" /* Vectors and arrays */
/****************/
/* Local Macros */
/****************/
/* Fractal heap format version #'s */
-#define H5HF_HDR_VERSION 0 /* Header */
+#define H5HF_HDR_VERSION 0 /* Header */
+#define H5HF_DBLOCK_VERSION 0 /* Direct block */
+
+/* Size of free space description in an absolute managed direct block */
+#define H5HF_MAN_ABS_FREE_NODE_SIZE(d) (2 * (d)->blk_off_size)
+
/******************/
/* Local Typedefs */
@@ -56,12 +62,20 @@ static H5HF_t *H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const
static herr_t H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_t *fh);
static herr_t H5HF_cache_hdr_clear(H5F_t *f, H5HF_t *fh, hbool_t destroy);
static herr_t H5HF_cache_hdr_size(const H5F_t *f, const H5HF_t *fh, size_t *size_ptr);
+static H5HF_direct_t *H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, void *udata);
+static herr_t H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_direct_t *dblock);
+static herr_t H5HF_cache_dblock_clear(H5F_t *f, H5HF_direct_t *dblock, hbool_t destroy);
+static herr_t H5HF_cache_dblock_size(const H5F_t *f, const H5HF_direct_t *dblock, size_t *size_ptr);
+
+/* Local encode/decode routines */
+static herr_t H5HF_dtable_encode(H5F_t *f, uint8_t **pp, const H5HF_dtable_param_t *dt_param);
+static herr_t H5HF_dtable_decode(H5F_t *f, const uint8_t **pp, H5HF_dtable_param_t *dt_param);
/*********************/
/* Package Variables */
/*********************/
-/* H5HF inherits cache-like properties from H5AC */
+/* H5HF header inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_FHEAP_HDR[1] = {{
H5AC_FHEAP_HDR_ID,
(H5AC_load_func_t)H5HF_cache_hdr_load,
@@ -71,6 +85,16 @@ const H5AC_class_t H5AC_FHEAP_HDR[1] = {{
(H5AC_size_func_t)H5HF_cache_hdr_size,
}};
+/* H5HF direct block inherits cache-like properties from H5AC */
+const H5AC_class_t H5AC_FHEAP_DBLOCK[1] = {{
+ H5AC_FHEAP_DBLOCK_ID,
+ (H5AC_load_func_t)H5HF_cache_dblock_load,
+ (H5AC_flush_func_t)H5HF_cache_dblock_flush,
+ (H5AC_dest_func_t)H5HF_cache_dblock_dest,
+ (H5AC_clear_func_t)H5HF_cache_dblock_clear,
+ (H5AC_size_func_t)H5HF_cache_dblock_size,
+}};
+
/*****************************/
/* Library Private Variables */
/*****************************/
@@ -80,9 +104,112 @@ const H5AC_class_t H5AC_FHEAP_HDR[1] = {{
/* Local Variables */
/*******************/
-/* Declare a free list to manage B-tree header data to/from disk */
+/* Declare a free list to manage heap header data to/from disk */
H5FL_BLK_DEFINE_STATIC(header_block);
+/* Declare a free list to manage heap direct block data to/from disk */
+H5FL_BLK_DEFINE(direct_block);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_dtable_decode
+ *
+ * Purpose: Decodes the metadata for a doubling table
+ *
+ * Return: Success: Pointer to a new fractal heap
+ *
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 27 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_dtable_decode(H5F_t *f, const uint8_t **pp, H5HF_dtable_param_t *dt_param)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_dtable_decode)
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(pp && *pp);
+ HDassert(dt_param);
+
+ /* Table width */
+ UINT16DECODE(*pp, dt_param->cparam.width);
+
+ /* Starting block size */
+ H5F_DECODE_LENGTH(f, *pp, dt_param->cparam.start_block_size);
+
+ /* Maximum direct block size */
+ H5F_DECODE_LENGTH(f, *pp, dt_param->cparam.max_direct_size);
+
+ /* Maximum heap size (as # of bits) */
+ UINT16DECODE(*pp, dt_param->cparam.max_index);
+
+ /* Starting # of rows in root indirect block */
+ UINT16DECODE(*pp, dt_param->cparam.start_root_rows);
+
+ /* Address of table */
+ H5F_addr_decode(f, pp, &(dt_param->table_addr));
+
+ /* Current # of rows in root indirect block */
+ UINT16DECODE(*pp, dt_param->curr_root_rows);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HF_dtable_decode() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_dtable_encode
+ *
+ * Purpose: Encodes the metadata for a doubling table
+ *
+ * Return: Success: Pointer to a new fractal heap
+ *
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 27 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_dtable_encode(H5F_t *f, uint8_t **pp, const H5HF_dtable_param_t *dt_param)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_dtable_encode)
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(pp && *pp);
+ HDassert(dt_param);
+
+ /* Table width */
+ UINT16ENCODE(*pp, dt_param->cparam.width);
+
+ /* Starting block size */
+ H5F_ENCODE_LENGTH(f, *pp, dt_param->cparam.start_block_size);
+
+ /* Maximum direct block size */
+ H5F_ENCODE_LENGTH(f, *pp, dt_param->cparam.max_direct_size);
+
+ /* Maximum heap size (as # of bits) */
+ UINT16ENCODE(*pp, dt_param->cparam.max_index);
+
+ /* Starting # of rows in root indirect block */
+ UINT16ENCODE(*pp, dt_param->cparam.start_root_rows);
+
+ /* Address of table */
+ H5F_addr_encode(f, pp, dt_param->table_addr);
+
+ /* Current # of rows in root indirect block */
+ UINT16ENCODE(*pp, dt_param->curr_root_rows);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HF_dtable_encode() */
/*-------------------------------------------------------------------------
@@ -104,10 +231,10 @@ static H5HF_t *
H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *udata1, void UNUSED *udata2)
{
H5HF_t *fh = NULL; /* Fractal heap info */
+ H5HF_shared_t *shared = NULL; /* Shared fractal heap information */
size_t size; /* Header size */
uint8_t *buf = NULL; /* Temporary buffer */
- uint8_t *p; /* Pointer into raw data buffer */
- H5HF_create_t cparam; /* Creation parameters for heap */
+ const uint8_t *p; /* Pointer into raw data buffer */
uint32_t metadata_chksum; /* Metadata checksum value */
H5HF_t *ret_value; /* Return value */
@@ -122,6 +249,11 @@ H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *ud
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
HDmemset(&fh->cache_info, 0, sizeof(H5AC_info_t));
+ /* Allocate & basic initialization for the shared info struct */
+ if(NULL == (shared = H5HF_shared_alloc(f)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate space for shared heap info")
+ shared->heap_addr = addr;
+
/* Compute the size of the fractal heap header on disk */
size = H5HF_HEADER_SIZE(f);
@@ -135,12 +267,12 @@ H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *ud
p = buf;
- /* magic number */
+ /* Magic number */
if(HDmemcmp(p, H5HF_HDR_MAGIC, H5HF_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong fractal heap header signature")
p += H5HF_SIZEOF_MAGIC;
- /* version */
+ /* Version */
if(*p++ != H5HF_HDR_VERSION)
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong fractal heap header version")
@@ -156,21 +288,29 @@ H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *ud
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect metadata checksum for fractal heap header")
/* Heap address mapping */
- cparam.addrmap = *p++;
+ shared->addrmap = *p++;
HDassert(H5HF_ABSOLUTE == 0);
- if(cparam.addrmap > H5HF_MAPPED)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect fractal heap type")
+ if(shared->addrmap > H5HF_MAPPED)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect fractal heap address mapping")
/* Min. size of standalone objects */
- UINT32DECODE(p, cparam.standalone_size);
+ UINT32DECODE(p, shared->standalone_size);
+
+ /* Length of fixed-length objects in heap */
+ UINT32DECODE(p, shared->fixed_len_size);
- /* Size of fixed-length objects in heap */
- UINT32DECODE(p, cparam.fixed_len_size);
+ /* Size of ref. count for objects in heap */
+ shared->ref_count_size = *p++;
+
+ /* Managed objects' doubling-table info */
+ if(H5HF_dtable_decode(shared->f, &p, &(shared->man_dtable_info)) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, NULL, "unable to encode managed obj. doubling table info")
- /* Initialize shared fractal heap info */
HDassert((size_t)(p - buf) == size);
- if(H5HF_shared_init(fh, &cparam) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't create shared fractal heap info")
+
+ /* Make shared heap info reference counted */
+ if(H5HF_shared_own(fh, shared) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't create ref-count wrapper for shared fractal heap info")
/* Set return value */
ret_value = fh;
@@ -201,6 +341,7 @@ done:
static herr_t
H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_t *fh)
{
+ H5HF_shared_t *shared; /* Shared fractal heap information */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5HF_cache_hdr_flush, FAIL)
@@ -210,17 +351,16 @@ H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5H
HDassert(H5F_addr_defined(addr));
HDassert(fh);
+ /* Get the pointer to the shared heap info */
+ shared = H5RC_GET_OBJ(fh->shared);
+ HDassert(shared);
+
if(fh->cache_info.is_dirty) {
- H5HF_shared_t *shared; /* Shared fractal heap information */
uint8_t *buf = NULL; /* Temporary raw data buffer */
uint8_t *p; /* Pointer into raw data buffer */
size_t size; /* Header size on disk */
- /* Get the pointer to the shared B-tree info */
- shared = H5RC_GET_OBJ(fh->shared);
- HDassert(shared);
-
- /* Compute the size of the B-tree header on disk */
+ /* Compute the size of the heap header on disk */
size = H5HF_HEADER_SIZE(f);
/* Allocate temporary buffer */
@@ -254,7 +394,14 @@ H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5H
/* Size of fixed-length objects in heap */
UINT32ENCODE(p, shared->fixed_len_size);
- /* Write the B-tree header. */
+ /* Size of ref. count for objects in heap */
+ *p++ = shared->ref_count_size;
+
+ /* Managed objects' doubling-table info */
+ if(H5HF_dtable_encode(shared->f, &p, &(shared->man_dtable_info)) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, FAIL, "unable to encode managed obj. doubling table info")
+
+ /* Write the heap header. */
HDassert((size_t)(p - buf) == size);
if(H5F_block_write(f, H5FD_MEM_FHEAP_HDR, addr, size, dxpl_id, buf) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTFLUSH, FAIL, "unable to save fractal heap header to disk")
@@ -375,3 +522,367 @@ H5HF_cache_hdr_size(const H5F_t *f, const H5HF_t UNUSED *fh, size_t *size_ptr)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5HF_cache_hdr_size() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_cache_dblock_load
+ *
+ * Purpose: Loads a fractal heap direct block from the disk.
+ *
+ * Return: Success: Pointer to a new fractal heap direct block
+ *
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 27 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5HF_direct_t *
+H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_size, void *_fh_shared)
+{
+ const size_t *size = (const size_t *)_size; /* Size of block */
+ H5RC_t *fh_shared = (H5RC_t *)_fh_shared; /* Shared heap information */
+ H5HF_shared_t *shared = NULL; /* Shared fractal heap information */
+ H5HF_direct_t *dblock = NULL; /* Direct block info */
+ uint8_t *buf = NULL; /* Temporary buffer */
+ const uint8_t *p; /* Pointer into raw data buffer */
+ haddr_t heap_addr; /* Address of heap header in the file */
+ uint32_t metadata_chksum; /* Metadata checksum value */
+ H5HF_direct_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5HF_cache_dblock_load, NULL)
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(fh_shared);
+
+ /* Allocate space for the fractal heap direct block */
+ if(NULL == (dblock = H5FL_MALLOC(H5HF_direct_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ HDmemset(&dblock->cache_info, 0, sizeof(H5AC_info_t));
+
+ /* Share common heap information */
+ dblock->shared = fh_shared;
+ H5RC_INC(dblock->shared);
+
+ /* Get the pointer to the shared heap info */
+ shared = H5RC_GET_OBJ(dblock->shared);
+ HDassert(shared);
+
+ /* Set block's internal information */
+ dblock->size = *size;
+ dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dblock->size);
+ dblock->free_list = NULL;
+
+ /* Allocate block buffer */
+/* XXX: Change to using free-list factories */
+ if((buf = H5FL_BLK_MALLOC(direct_block, (size_t)dblock->size)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* Read header from disk */
+ if(H5F_block_read(f, H5FD_MEM_FHEAP_HDR, addr, (size_t)dblock->size, dxpl_id, buf) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "can't read fractal heap direct block")
+
+ p = buf;
+
+ /* Magic number */
+ if(HDmemcmp(p, H5HF_DBLOCK_MAGIC, H5HF_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong fractal heap direct block signature")
+ p += H5HF_SIZEOF_MAGIC;
+
+ /* Version */
+ if(*p++ != H5HF_DBLOCK_VERSION)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong fractal heap direct block version")
+
+ /* Metadata flags (unused, currently) */
+/* XXX: Plan out metadata flags (including "read-only duplicate" feature) */
+ if(*p++ != 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unknown metadata flag in fractal heap direct block")
+
+ /* Metadata checksum (unused, currently) */
+ UINT32DECODE(p, metadata_chksum);
+/* XXX: Verify checksum */
+ if(metadata_chksum != 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect metadata checksum for fractal heap direct block")
+
+ /* Address of heap that owns this block (skip) */
+ H5F_addr_decode(f, &p, &heap_addr);
+ if(H5F_addr_ne(heap_addr, shared->heap_addr))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect heap header address for direct block")
+
+ /* Offset of heap within the heap's address space */
+ UINT64DECODE_VAR(p, dblock->block_off, shared->heap_off_size);
+
+ /* Total free space in block */
+ UINT64DECODE_VAR(p, dblock->blk_free_space, dblock->blk_off_size);
+
+ /* Offset of free list head */
+ /* (Defer deserializing the whole free list until we actually need to modify it) */
+ UINT64DECODE_VAR(p, dblock->free_list_head, dblock->blk_off_size);
+
+ /* Keep pointer to block buffer */
+ dblock->blk = buf;
+
+ /* Set return value */
+ ret_value = dblock;
+
+done:
+ if(!ret_value && dblock)
+ (void)H5HF_cache_dblock_dest(f, dblock);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_cache_dblock_load() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_cache_dblock_flush
+ *
+ * Purpose: Flushes a dirty fractal heap direct block to disk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 27 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_direct_t *dblock)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5HF_cache_dblock_flush, FAIL)
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(dblock);
+
+ if(dblock->cache_info.is_dirty) {
+ H5HF_shared_t *shared; /* Shared fractal heap information */
+ uint8_t *p; /* Pointer into raw data buffer */
+
+ /* Get the pointer to the shared heap info */
+ shared = H5RC_GET_OBJ(dblock->shared);
+ HDassert(shared);
+
+ p = dblock->blk;
+
+ /* Magic number */
+ HDmemcpy(p, H5HF_DBLOCK_MAGIC, H5HF_SIZEOF_MAGIC);
+ p += H5HF_SIZEOF_MAGIC;
+
+ /* Version # */
+ *p++ = H5HF_DBLOCK_VERSION;
+
+ /* Metadata status flags */
+/* XXX: Set this? */
+ *p++ = 0;
+
+ /* Metadata checksum */
+/* XXX: Set this! (After all the metadata is in the buffer) */
+ HDmemset(p, 0, 4);
+ p += 4;
+
+ /* Address of heap header for heap which owns this block */
+ H5F_addr_encode(f, &p, shared->heap_addr);
+
+ /* Offset of block in heap */
+ UINT64ENCODE_VAR(p, dblock->block_off, shared->heap_off_size);
+
+ /* Check for (currently) unsupported address mapping */
+ if(shared->addrmap != H5HF_ABSOLUTE)
+ HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "encoding mapped direct blocks not supported currently")
+
+ /* Total free space in block */
+ UINT64ENCODE_VAR(p, dblock->blk_free_space, dblock->blk_off_size);
+
+ /* Offset of free list head */
+ UINT64ENCODE_VAR(p, dblock->free_list_head, dblock->blk_off_size);
+
+ /* Sanity check */
+ HDassert((size_t)(p - dblock->blk) == H5HF_MAN_ABS_DIRECT_OVERHEAD_DBLOCK(shared, dblock));
+
+ /* Check for dirty free list */
+ if(dblock->free_list && dblock->free_list->dirty) {
+ H5HF_direct_free_node_t *node; /* Pointer to free list node for block */
+
+ /* Loop over all free list blocks, updating their data */
+ node = dblock->free_list->first;
+ while(node) {
+ /* Find first node which has enough room to describe free space */
+ while(node && node->size < H5HF_MAN_ABS_FREE_NODE_SIZE(dblock))
+ node = node->next;
+
+ /* Check for free space node to encode */
+ if(node) {
+ H5HF_direct_free_node_t *next_node; /* Pointer to next free list node for block */
+
+ /* Probe ahead for next node that is large enough to encode free space description */
+ next_node = node->next;
+ while(next_node && next_node->size < H5HF_MAN_ABS_FREE_NODE_SIZE(dblock))
+ next_node = next_node->next;
+
+ /* Encode information for this node on free list */
+ p = dblock->blk + node->my_offset;
+ UINT64ENCODE_VAR(p, node->size, dblock->blk_off_size);
+ UINT64ENCODE_VAR(p, (next_node ? next_node->my_offset : 0), dblock->blk_off_size);
+
+ /* Advance to next node */
+ node = node->next;
+ } /* end if */
+
+ } /* end while */
+
+ /* Reset the free list dirty flag */
+ dblock->free_list->dirty = FALSE;
+ } /* end if */
+
+ /* Write the heap header. */
+ if(H5F_block_write(f, H5FD_MEM_FHEAP_HDR, addr, (size_t)dblock->size, dxpl_id, dblock->blk) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFLUSH, FAIL, "unable to save fractal heap direct block to disk")
+
+ dblock->cache_info.is_dirty = FALSE;
+ } /* end if */
+
+ if(destroy)
+ if(H5HF_cache_dblock_dest(f, dblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap direct block")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HF_cache_dblock_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_cache_dblock_dest
+ *
+ * Purpose: Destroys a fractal heap direct block in memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 27 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+herr_t
+H5HF_cache_dblock_dest(H5F_t UNUSED *f, H5HF_direct_t *dblock)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_dblock_dest)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(dblock);
+
+ /* Decrement reference count on shared fractal heap info */
+ if(dblock->shared)
+ H5RC_DEC(dblock->shared);
+
+ /* Check for free list & free it, if necessary */
+ if(dblock->free_list) {
+ H5HF_direct_free_node_t *node; /* Pointer to free list node for block */
+
+ /* Walk through list, freeing the nodes */
+ node = dblock->free_list->first;
+ while(node) {
+ H5HF_direct_free_node_t *last_node; /* Pointer to last free list node for block */
+
+ /* Advance to next node */
+ last_node = node;
+ node = node->next;
+
+ /* Release the last node */
+ H5FL_FREE(H5HF_direct_free_node_t, last_node);
+ } /* end while */
+
+ /* Release the free list head */
+ H5FL_FREE(H5HF_direct_free_head_t, dblock->free_list);
+ } /* end if */
+
+ /* Free block's buffer */
+ H5FL_BLK_FREE(direct_block, dblock->blk);
+
+ /* Free fractal heap direct block info */
+ H5FL_FREE(H5HF_direct_t, dblock);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HF_cache_dblock_dest() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_cache_dblock_clear
+ *
+ * Purpose: Mark a fractal heap direct block in memory as non-dirty.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 27 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_cache_dblock_clear(H5F_t *f, H5HF_direct_t *dblock, hbool_t destroy)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_cache_dblock_clear)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(dblock);
+
+ /* Reset the free list dirty flag */
+ dblock->free_list->dirty = FALSE;
+
+ /* Reset the dirty flag. */
+ dblock->cache_info.is_dirty = FALSE;
+
+ if(destroy)
+ if(H5HF_cache_dblock_dest(f, dblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap direct block")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_cache_dblock_clear() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_cache_block_size
+ *
+ * Purpose: Compute the size in bytes of a fractal heap direct block
+ * on disk, and return it in *size_ptr. On failure,
+ * the value of *size_ptr is undefined.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Feb 24 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_cache_dblock_size(const H5F_t UNUSED *f, const H5HF_direct_t *dblock, size_t *size_ptr)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_dblock_size)
+
+ /* check arguments */
+ HDassert(dblock);
+ HDassert(size_ptr);
+
+ /* Set size value */
+ *size_ptr = dblock->size;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5HF_cache_dblock_size() */
+