summaryrefslogtreecommitdiffstats
path: root/src/H5HFcache.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2015-06-18 00:58:49 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2015-06-18 00:58:49 (GMT)
commitf30ab55f41296667eab0b273132ffc20c4323717 (patch)
tree2fd6a85b7c15e3505e308e21b41e67297cc58508 /src/H5HFcache.c
parent6e9e9e0dd200979642de8d2a2bce2f66f9728237 (diff)
downloadhdf5-f30ab55f41296667eab0b273132ffc20c4323717.zip
hdf5-f30ab55f41296667eab0b273132ffc20c4323717.tar.gz
hdf5-f30ab55f41296667eab0b273132ffc20c4323717.tar.bz2
[svn-r27237] Description:
Merge v3 metadata cache changes to trunk. Yay! :-) Tested on: MacOSX/64 10.10.3 (amazon) w/serial & parallel Linux/32 2.6.x (jam) w/serial & parallel (daily tested on branch)
Diffstat (limited to 'src/H5HFcache.c')
-rw-r--r--src/H5HFcache.c2422
1 files changed, 1431 insertions, 991 deletions
diff --git a/src/H5HFcache.c b/src/H5HFcache.c
index 07e5b36..ec8d9a6 100644
--- a/src/H5HFcache.c
+++ b/src/H5HFcache.c
@@ -53,12 +53,6 @@
#define H5HF_DBLOCK_VERSION 0 /* Direct block */
#define H5HF_IBLOCK_VERSION 0 /* Indirect block */
-/* Size of stack buffer for serialized headers */
-#define H5HF_HDR_BUF_SIZE 512
-
-/* Size of stack buffer for serialized indirect blocks */
-#define H5HF_IBLOCK_BUF_SIZE 4096
-
/******************/
/* Local Typedefs */
@@ -79,24 +73,48 @@ static herr_t H5HF__dtable_encode(H5F_t *f, uint8_t **pp, const H5HF_dtable_t *d
static herr_t H5HF__dtable_decode(H5F_t *f, const uint8_t **pp, H5HF_dtable_t *dtable);
/* Metadata cache (H5AC) callbacks */
-static H5HF_hdr_t *H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_hdr_t *hdr, unsigned H5_ATTR_UNUSED * flags_ptr);
-static herr_t H5HF_cache_hdr_dest(H5F_t *f, H5HF_hdr_t *hdr);
-static herr_t H5HF_cache_hdr_clear(H5F_t *f, H5HF_hdr_t *hdr, hbool_t destroy);
-static herr_t H5HF_cache_hdr_size(const H5F_t *f, const H5HF_hdr_t *hdr, size_t *size_ptr);
-static H5HF_indirect_t *H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5HF_cache_iblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_indirect_t *iblock, unsigned H5_ATTR_UNUSED * flags_ptr);
-static herr_t H5HF_cache_iblock_dest(H5F_t *f, H5HF_indirect_t *iblock);
-static herr_t H5HF_cache_iblock_clear(H5F_t *f, H5HF_indirect_t *iblock, hbool_t destroy);
-static herr_t H5HF_cache_iblock_notify(H5C_notify_action_t action, H5HF_indirect_t *iblock);
-static herr_t H5HF_cache_iblock_size(const H5F_t *f, const H5HF_indirect_t *iblock, size_t *size_ptr);
-static H5HF_direct_t *H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, 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, unsigned H5_ATTR_UNUSED * flags_ptr);
-static herr_t H5HF_cache_dblock_dest(H5F_t *f, 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_notify(H5C_notify_action_t action, H5HF_direct_t *dblock);
-static herr_t H5HF_cache_dblock_size(const H5F_t *f, const H5HF_direct_t *dblock, size_t *size_ptr);
-
+static herr_t H5HF__cache_hdr_get_load_size(const void *udata, size_t *image_len);
+static void *H5HF__cache_hdr_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5HF__cache_hdr_image_len(const void *thing, size_t *image_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static herr_t H5HF__cache_hdr_pre_serialize(const H5F_t *f, hid_t dxpl_id,
+ void *thing, haddr_t addr, size_t len, size_t compressed_len,
+ haddr_t *new_addr, size_t *new_len, size_t *new_compressed_len,
+ unsigned *flags);
+static herr_t H5HF__cache_hdr_serialize(const H5F_t *f, void *image,
+ size_t len, void *thing);
+static herr_t H5HF__cache_hdr_free_icr(void *thing);
+
+static herr_t H5HF__cache_iblock_get_load_size(const void *udata, size_t *image_len);
+static void *H5HF__cache_iblock_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5HF__cache_iblock_image_len(const void *thing,
+ size_t *image_len, hbool_t *compressed_ptr,
+ size_t *compressed_image_len_ptr);
+static herr_t H5HF__cache_iblock_pre_serialize(const H5F_t *f, hid_t dxpl_id,
+ void *thing, haddr_t addr, size_t len, size_t compressed_len,
+ haddr_t *new_addr, size_t *new_len, size_t *new_compressed_len,
+ unsigned *flags);
+static herr_t H5HF__cache_iblock_serialize(const H5F_t *f, void *image,
+ size_t len, void *thing);
+static herr_t H5HF__cache_iblock_notify(H5C_notify_action_t action, void *thing);
+static herr_t H5HF__cache_iblock_free_icr(void *thing);
+
+static herr_t H5HF__cache_dblock_get_load_size(const void *udata, size_t *image_len);
+static void *H5HF__cache_dblock_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5HF__cache_dblock_image_len(const void *thing,
+ size_t *image_len, hbool_t *compressed_ptr,
+ size_t *compressed_image_len_ptr);
+static herr_t H5HF__cache_dblock_pre_serialize(const H5F_t *f, hid_t dxpl_id,
+ void *thing, haddr_t addr, size_t len, size_t compressed_len,
+ haddr_t *new_addr, size_t *new_len, size_t *new_compressed_len,
+ unsigned *flags);
+static herr_t H5HF__cache_dblock_serialize(const H5F_t *f, void *image,
+ size_t len, void *thing);
+static herr_t H5HF__cache_dblock_notify(H5C_notify_action_t action, void *thing);
+static herr_t H5HF__cache_dblock_free_icr(void *thing);
/* Debugging Function Prototypes */
#ifndef NDEBUG
@@ -117,35 +135,53 @@ static herr_t H5HF__cache_verify_descendant_iblocks_clean(H5F_t *f, hid_t dxpl_i
/* 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,
- (H5AC_flush_func_t)H5HF_cache_hdr_flush,
- (H5AC_dest_func_t)H5HF_cache_hdr_dest,
- (H5AC_clear_func_t)H5HF_cache_hdr_clear,
- (H5AC_notify_func_t)NULL,
- (H5AC_size_func_t)H5HF_cache_hdr_size,
+ H5AC_FHEAP_HDR_ID, /* Metadata client ID */
+ "fractal heap header", /* Metadata client name (for debugging) */
+ H5FD_MEM_FHEAP_HDR, /* File space memory type for client */
+ H5AC__CLASS_SPECULATIVE_LOAD_FLAG, /* Client class behavior flags */
+ H5HF__cache_hdr_get_load_size, /* 'get_load_size' callback */
+ H5HF__cache_hdr_deserialize, /* 'deserialize' callback */
+ H5HF__cache_hdr_image_len, /* 'image_len' callback */
+ H5HF__cache_hdr_pre_serialize, /* 'pre_serialize' callback */
+ H5HF__cache_hdr_serialize, /* 'serialize' callback */
+ NULL, /* 'notify' callback */
+ H5HF__cache_hdr_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
/* H5HF indirect block inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_FHEAP_IBLOCK[1] = {{
- H5AC_FHEAP_IBLOCK_ID,
- (H5AC_load_func_t)H5HF_cache_iblock_load,
- (H5AC_flush_func_t)H5HF_cache_iblock_flush,
- (H5AC_dest_func_t)H5HF_cache_iblock_dest,
- (H5AC_clear_func_t)H5HF_cache_iblock_clear,
- (H5AC_notify_func_t)H5HF_cache_iblock_notify,
- (H5AC_size_func_t)H5HF_cache_iblock_size,
+ H5AC_FHEAP_IBLOCK_ID, /* Metadata client ID */
+ "fractal heap indirect block", /* Metadata client name (for debugging) */
+ H5FD_MEM_FHEAP_IBLOCK, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5HF__cache_iblock_get_load_size, /* 'get_load_size' callback */
+ H5HF__cache_iblock_deserialize, /* 'deserialize' callback */
+ H5HF__cache_iblock_image_len, /* 'image_len' callback */
+ H5HF__cache_iblock_pre_serialize, /* 'pre_serialize' callback */
+ H5HF__cache_iblock_serialize, /* 'serialize' callback */
+ H5HF__cache_iblock_notify, /* 'notify' callback */
+ H5HF__cache_iblock_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
/* 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_notify_func_t)H5HF_cache_dblock_notify,
- (H5AC_size_func_t)H5HF_cache_dblock_size,
+ H5AC_FHEAP_DBLOCK_ID, /* Metadata client ID */
+ "fractal heap direct block", /* Metadata client name (for debugging) */
+ H5FD_MEM_FHEAP_DBLOCK, /* File space memory type for client */
+ H5C__CLASS_COMPRESSED_FLAG, /* Client class behavior flags */
+ H5HF__cache_dblock_get_load_size, /* 'get_load_size' callback */
+ H5HF__cache_dblock_deserialize, /* 'deserialize' callback */
+ H5HF__cache_dblock_image_len, /* 'image_len' callback */
+ H5HF__cache_dblock_pre_serialize, /* 'pre_serialize' callback */
+ H5HF__cache_dblock_serialize, /* 'serialize' callback */
+ H5HF__cache_dblock_notify, /* 'notify' callback */
+ H5HF__cache_dblock_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
@@ -268,119 +304,191 @@ H5HF__dtable_encode(H5F_t *f, uint8_t **pp, const H5HF_dtable_t *dtable)
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_hdr_load
+ * Function: H5HF__cache_hdr_get_load_size()
*
- * Purpose: Loads a fractal heap header from the disk.
+ * Purpose: Determine the size of the fractal heap header on disk,
+ * and set *image_len to this value.
*
- * Return: Success: Pointer to a new fractal heap
+ * This code is based on the old H5HF_cache_hdr_load() routine
+ * that was used with the version 2 metadata cache. Note the
+ * use of a dummy header to compute the on disk size of the header.
+ *
+ * Note also that the value returned by this function presumes that
+ * there is no I/O filtering data in the header. If there is, the
+ * size reported will be too small, and H5C_load_entry()
+ * will have to make two tries to load the fractal heap header.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF__cache_hdr_get_load_size(const void *_udata, size_t *image_len)
+{
+ const H5HF_hdr_cache_ud_t *udata = (const H5HF_hdr_cache_ud_t *)_udata; /* pointer to user data */
+ H5HF_hdr_t dummy_hdr; /* dummy header -- to compute size */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity checks */
+ HDassert(udata);
+ HDassert(image_len);
+
+ /* Set the internal parameters for the heap */
+ dummy_hdr.f = udata->f;
+ dummy_hdr.sizeof_size = H5F_SIZEOF_SIZE(udata->f);
+ dummy_hdr.sizeof_addr = H5F_SIZEOF_ADDR(udata->f);
+
+ /* Compute the 'base' size of the fractal heap header on disk */
+ *image_len = (size_t)H5HF_HEADER_SIZE(&dummy_hdr);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HF__cache_hdr_get_load_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF__cache_hdr_deserialize
+ *
+ * Purpose: Given a buffer containing an on disk image of a fractal heap
+ * header block, allocate an instance of H5HF_hdr_t, load the contents
+ * of the buffer into into the new instance of H5HF_hdr_t, and then
+ * return a pointer to the new instance.
+ *
+ * Since H5HF__cache_hdr_get_load_size() reports header on disk size
+ * base on the assumption that the header contains no I/O filtering
+ * data, it is possible that the provided image will be too small.
+ *
+ * In this case, we DO NOT flag an error when this is discovered.
+ * Instead, we make note of the correct image size, and report
+ * success.
+ *
+ * Since H5HF__cache_hdr_image_len() callback is defined,
+ * H5C_load_entry() will call H5HF__cache_hdr_image_len() and
+ * obtain the correct image length.
+ *
+ * Since the H5AC__CLASS_SPECULATIVE_LOAD_FLAG is set,
+ * H5C_load_entry() will load an image of the correct size, and
+ * then call this function again to deserialize it. Before doing
+ * so, it will also call H5HF__cache_hdr_free_icr() to discard the
+ * result of the first deserialize call.
+ *
+ * Note that the v2 B-tree and free space manager associated
+ * with the fractal heap (roots stored in the huge_bt2 and fspace
+ * fields respectively) are not loaded at this time. As best I can
+ * tell from reviewing the code, they are loaded or created when
+ * they are accessed.
+ *
+ * Return: Success: Pointer to in core representation
* Failure: NULL
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 24 2006
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static H5HF_hdr_t *
-H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
+static void *
+H5HF__cache_hdr_deserialize(const void *_image, size_t len, void *_udata,
+ hbool_t H5_ATTR_UNUSED *dirty)
{
- H5HF_hdr_t *hdr = NULL; /* Fractal heap info */
- H5HF_hdr_cache_ud_t *udata = (H5HF_hdr_cache_ud_t *)_udata;
- size_t size; /* Header size */
- H5WB_t *wb = NULL; /* Wrapped buffer for header data */
- uint8_t hdr_buf[H5HF_HDR_BUF_SIZE]; /* Buffer for header */
- uint8_t *buf; /* Pointer to header buffer */
- const uint8_t *p; /* Pointer into raw data buffer */
+ H5HF_hdr_t *hdr = NULL; /* Fractal heap info */
+ H5HF_hdr_cache_ud_t *udata = (H5HF_hdr_cache_ud_t *)_udata; /* User data for callback */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into into supplied image */
+ size_t size; /* Header size */
uint32_t stored_chksum; /* Stored metadata checksum value */
uint32_t computed_chksum; /* Computed metadata checksum value */
uint8_t heap_flags; /* Status flags for heap */
- H5HF_hdr_t *ret_value; /* Return value */
+ void * ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Sanity checks */
+ HDassert(image);
+ HDassert(len > 0);
HDassert(udata);
+ HDassert(dirty);
/* Allocate space for the fractal heap data structure */
if(NULL == (hdr = H5HF_hdr_alloc(udata->f)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- /* Wrap the local buffer for serialized header info */
- if(NULL == (wb = H5WB_wrap(hdr_buf, sizeof(hdr_buf))))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't wrap buffer")
-
/* Compute the 'base' size of the fractal heap header on disk */
size = (size_t)H5HF_HEADER_SIZE(hdr);
- /* Get a pointer to a buffer that's large enough for serialized header */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
- HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "can't get actual buffer")
-
- /* Read header from disk */
- if(H5F_block_read(f, H5FD_MEM_FHEAP_HDR, addr, size, dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "can't read fractal heap header")
-
- /* Get temporary pointer to serialized header */
- p = buf;
+ /* the size we have just calculated presumes that there is no I/O
+ * filter information in the header. If there is no filter information,
+ * the deserialize operation should succeed.
+ *
+ * If there is filter information, the first attempt to deserialize
+ * the header will reveal this. In this case, we will be unable to
+ * deserialize the header as the supplied image will be too small.
+ * However, we will make note of the correct size and report success
+ * anyway.
+ *
+ * When H5C_load_entry() calls H5HF__cache_hdr_image_len(), we will report
+ * the correct size. Since the H5C__CLASS_SPECULATIVE_LOAD_FLAG is set,
+ * this will prompt H5C_load_entry() to load the correct size image,
+ * discard the result of the first attempt at deserialization, and
+ * call this routine a second time to deserialize the correct size
+ * buffer.
+ */
+ HDassert(size <= len);
/* Magic number */
- if(HDmemcmp(p, H5HF_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong fractal heap header signature")
- p += H5_SIZEOF_MAGIC;
+ if(HDmemcmp(image, H5HF_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "wrong fractal heap header signature")
+ image += H5_SIZEOF_MAGIC;
/* Version */
- if(*p++ != H5HF_HDR_VERSION)
+ if(*image++ != H5HF_HDR_VERSION)
HGOTO_ERROR(H5E_HEAP, H5E_VERSION, NULL, "wrong fractal heap header version")
/* General heap information */
- UINT16DECODE(p, hdr->id_len); /* Heap ID length */
- UINT16DECODE(p, hdr->filter_len); /* I/O filters' encoded length */
+ UINT16DECODE(image, hdr->id_len); /* Heap ID length */
+ UINT16DECODE(image, hdr->filter_len); /* I/O filters' encoded length */
/* Heap status flags */
/* (bit 0: "huge" object IDs have wrapped) */
/* (bit 1: checksum direct blocks) */
- heap_flags = *p++;
+ heap_flags = *image++;
hdr->huge_ids_wrapped = heap_flags & H5HF_HDR_FLAGS_HUGE_ID_WRAPPED;
hdr->checksum_dblocks = heap_flags & H5HF_HDR_FLAGS_CHECKSUM_DBLOCKS;
/* "Huge" object information */
- UINT32DECODE(p, hdr->max_man_size); /* Max. size of "managed" objects */
- H5F_DECODE_LENGTH(udata->f, p, hdr->huge_next_id); /* Next ID to use for "huge" object */
- H5F_addr_decode(udata->f, &p, &hdr->huge_bt2_addr); /* Address of "huge" object tracker B-tree */
+ UINT32DECODE(image, hdr->max_man_size); /* Max. size of "managed" objects */
+ H5F_DECODE_LENGTH(udata->f, image, hdr->huge_next_id); /* Next ID to use for "huge" object */
+ H5F_addr_decode(udata->f, &image, &hdr->huge_bt2_addr); /* Address of "huge" object tracker B-tree */
/* "Managed" object free space information */
- H5F_DECODE_LENGTH(udata->f, p, hdr->total_man_free); /* Internal free space in managed direct blocks */
- H5F_addr_decode(udata->f, &p, &hdr->fs_addr); /* Address of free section header */
+ H5F_DECODE_LENGTH(udata->f, image, hdr->total_man_free); /* Internal free space in managed direct blocks */
+ H5F_addr_decode(udata->f, &image, &hdr->fs_addr); /* Address of free section header */
/* Heap statistics */
- H5F_DECODE_LENGTH(udata->f, p, hdr->man_size);
- H5F_DECODE_LENGTH(udata->f, p, hdr->man_alloc_size);
- H5F_DECODE_LENGTH(udata->f, p, hdr->man_iter_off);
- H5F_DECODE_LENGTH(udata->f, p, hdr->man_nobjs);
- H5F_DECODE_LENGTH(udata->f, p, hdr->huge_size);
- H5F_DECODE_LENGTH(udata->f, p, hdr->huge_nobjs);
- H5F_DECODE_LENGTH(udata->f, p, hdr->tiny_size);
- H5F_DECODE_LENGTH(udata->f, p, hdr->tiny_nobjs);
+ H5F_DECODE_LENGTH(udata->f, image, hdr->man_size);
+ H5F_DECODE_LENGTH(udata->f, image, hdr->man_alloc_size);
+ H5F_DECODE_LENGTH(udata->f, image, hdr->man_iter_off);
+ H5F_DECODE_LENGTH(udata->f, image, hdr->man_nobjs);
+ H5F_DECODE_LENGTH(udata->f, image, hdr->huge_size);
+ H5F_DECODE_LENGTH(udata->f, image, hdr->huge_nobjs);
+ H5F_DECODE_LENGTH(udata->f, image, hdr->tiny_size);
+ H5F_DECODE_LENGTH(udata->f, image, hdr->tiny_nobjs);
/* Managed objects' doubling-table info */
- if(H5HF__dtable_decode(hdr->f, &p, &(hdr->man_dtable)) < 0)
+ if(H5HF__dtable_decode(hdr->f, &image, &(hdr->man_dtable)) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, NULL, "unable to encode managed obj. doubling table info")
/* Sanity check */
/* (allow for checksum not decoded yet) */
- HDassert((size_t)(p - (const uint8_t *)buf) == (size - H5HF_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) == (size - H5HF_SIZEOF_CHKSUM));
/* Check for I/O filter information to decode */
if(hdr->filter_len > 0) {
- size_t filter_info_off; /* Offset in header of filter information */
size_t filter_info_size; /* Size of filter information */
H5O_pline_t *pline; /* Pipeline information from the header on disk */
- /* Compute the offset of the filter info in the header */
- filter_info_off = (size_t)(p - (const uint8_t *)buf);
-
/* Compute the size of the extra filter information */
filter_info_size = (size_t)(hdr->sizeof_size /* Size of size for filtered root direct block */
+ (unsigned)4 /* Size of filter mask for filtered root direct block */
@@ -389,28 +497,27 @@ H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
/* Compute the heap header's size */
hdr->heap_size = size + filter_info_size;
- /* Re-size current buffer */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, hdr->heap_size)))
- HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "can't get actual buffer")
-
- /* Read in I/O filter information */
- /* (and the checksum) */
- if(H5F_block_read(f, H5FD_MEM_FHEAP_HDR, (addr + filter_info_off), (filter_info_size + H5HF_SIZEOF_CHKSUM), dxpl_id, (buf + filter_info_off)) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "can't read fractal heap header's I/O pipeline filter info")
+ if(size == len)
+ /* we were supplied with too small a buffer -- goto done
+ * and let H5C_load_entry() retry with a larger buffer
+ */
+ HGOTO_DONE((void *)hdr)
- /* Point at correct offset in header for the filter information */
- p = buf + filter_info_off;
+ else
+ if((size + filter_info_size) != len)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "bad image len")
/* Decode the size of a filtered root direct block */
- H5F_DECODE_LENGTH(udata->f, p, hdr->pline_root_direct_size);
+ H5F_DECODE_LENGTH(udata->f, image, hdr->pline_root_direct_size);
/* Decode the filter mask for a filtered root direct block */
- UINT32DECODE(p, hdr->pline_root_direct_filter_mask);
+ UINT32DECODE(image, hdr->pline_root_direct_filter_mask);
/* Decode I/O filter information */
- if(NULL == (pline = (H5O_pline_t *)H5O_msg_decode(hdr->f, udata->dxpl_id, NULL, H5O_PLINE_ID, p)))
+ if(NULL == (pline = (H5O_pline_t *)H5O_msg_decode(hdr->f, udata->dxpl_id, NULL, H5O_PLINE_ID, image)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTDECODE, NULL, "can't decode I/O pipeline filters")
- p += hdr->filter_len;
+
+ image += hdr->filter_len;
/* Copy the information into the header's I/O pipeline structure */
if(NULL == H5O_msg_copy(H5O_PLINE_ID, pline, &(hdr->pline)))
@@ -425,13 +532,13 @@ H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
/* Compute checksum on entire header */
/* (including the filter information, if present) */
- computed_chksum = H5_checksum_metadata(buf, (size_t)(p - (const uint8_t *)buf), 0);
+ computed_chksum = H5_checksum_metadata(_image, (size_t)(image - (const uint8_t *)_image), 0);
/* Metadata checksum */
- UINT32DECODE(p, stored_chksum);
+ UINT32DECODE(image, stored_chksum);
/* Sanity check */
- HDassert((size_t)(p - (const uint8_t *)buf) == hdr->heap_size);
+ HDassert((size_t)(image - (const uint8_t *)_image) == hdr->heap_size);
/* Verify checksum */
if(stored_chksum != computed_chksum)
@@ -442,291 +549,324 @@ H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, NULL, "can't finish initializing shared fractal heap header")
/* Set return value */
- ret_value = hdr;
+ ret_value = (void *)hdr;
done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CLOSEERROR, NULL, "can't close wrapped buffer")
if(!ret_value && hdr)
if(H5HF_hdr_free(hdr) < 0)
HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, NULL, "unable to release fractal heap header")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_cache_hdr_load() */ /*lint !e818 Can't make udata a pointer to const */
+} /* end H5HF__cache_hdr_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_hdr_flush
+ * Function: H5HF__cache_hdr_image_len
*
- * Purpose: Flushes a dirty fractal heap header to disk.
+ * Purpose: Return the actual size of the fractal heap header on
+ * disk image.
*
- * Return: Non-negative on success/Negative on failure
+ * If the header contains filter information, this size will be
+ * larger than the value returned by H5HF__cache_hdr_get_load_size().
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 24 2006
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_hdr_t *hdr, unsigned H5_ATTR_UNUSED * flags_ptr)
+static herr_t
+H5HF__cache_hdr_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- H5WB_t *wb = NULL; /* Wrapped buffer for header data */
- uint8_t hdr_buf[H5HF_HDR_BUF_SIZE]; /* Buffer for header */
- herr_t ret_value = SUCCEED; /* Return value */
+ const H5HF_hdr_t *hdr = (const H5HF_hdr_t *)_thing; /* Fractal heap info */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR
- /* check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Sanity checks */
HDassert(hdr);
+ HDassert(hdr->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(hdr->cache_info.type == H5AC_FHEAP_HDR);
+ HDassert(image_len);
- if(hdr->cache_info.is_dirty) {
- uint8_t *buf; /* Temporary raw data buffer */
- uint8_t *p; /* Pointer into raw data buffer */
- size_t size; /* Header size on disk */
- uint8_t heap_flags; /* Status flags for heap */
- uint32_t metadata_chksum; /* Computed metadata checksum value */
-
-#ifndef NDEBUG
-{
- /* Verify that flush dependencies are working correctly. Do this
- * by verifying that either:
- *
- * 1) the header has a root iblock, and that the root iblock and all
- * of its children are clean, or
- *
- * 2) The header has a root dblock, which is clean, or
- *
- * 3) The heap is empty, and thus the header has neither a root
- * iblock no a root dblock. In this case, the flush ordering
- * constraint is met by default.
- *
- * Do this with a call to H5HF__cache_verify_hdr_descendants_clean().
- */
- hbool_t descendants_clean = TRUE;
+ *image_len = hdr->heap_size;
- if(H5HF__cache_verify_hdr_descendants_clean(f, dxpl_id, hdr, &descendants_clean) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "can't verify hdr descendants clean.")
- HDassert(descendants_clean);
-}
-#endif /* NDEBUG */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HF__cache_hdr_image_len() */
- /* Set the shared heap header's file context for this operation */
- hdr->f = f;
-
- /* Wrap the local buffer for serialized header info */
- if(NULL == (wb = H5WB_wrap(hdr_buf, sizeof(hdr_buf))))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't wrap buffer")
-
- /* Compute the size of the heap header on disk */
- size = hdr->heap_size;
-
- /* Get a pointer to a buffer that's large enough for serialized header */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
- HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "can't get actual buffer")
-
- /* Get temporary pointer to serialized header */
- p = buf;
-
- /* Magic number */
- HDmemcpy(p, H5HF_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
-
- /* Version # */
- *p++ = H5HF_HDR_VERSION;
-
- /* General heap information */
- UINT16ENCODE(p, hdr->id_len); /* Heap ID length */
- UINT16ENCODE(p, hdr->filter_len); /* I/O filters' encoded length */
-
- /* Heap status flags */
- /* (bit 0: "huge" object IDs have wrapped) */
- /* (bit 1: checksum direct blocks) */
- heap_flags = 0;
- heap_flags = (uint8_t)(heap_flags | (hdr->huge_ids_wrapped ? H5HF_HDR_FLAGS_HUGE_ID_WRAPPED : 0));
- heap_flags = (uint8_t)(heap_flags | (hdr->checksum_dblocks ? H5HF_HDR_FLAGS_CHECKSUM_DBLOCKS : 0));
- *p++ = heap_flags;
-
- /* "Huge" object information */
- UINT32ENCODE(p, hdr->max_man_size); /* Max. size of "managed" objects */
- H5F_ENCODE_LENGTH(f, p, hdr->huge_next_id); /* Next ID to use for "huge" object */
- H5F_addr_encode(f, &p, hdr->huge_bt2_addr); /* Address of "huge" object tracker B-tree */
-
- /* "Managed" object free space information */
- H5F_ENCODE_LENGTH(f, p, hdr->total_man_free); /* Internal free space in managed direct blocks */
- H5F_addr_encode(f, &p, hdr->fs_addr); /* Address of free section header */
-
- /* Heap statistics */
- H5F_ENCODE_LENGTH(f, p, hdr->man_size);
- H5F_ENCODE_LENGTH(f, p, hdr->man_alloc_size);
- H5F_ENCODE_LENGTH(f, p, hdr->man_iter_off);
- H5F_ENCODE_LENGTH(f, p, hdr->man_nobjs);
- H5F_ENCODE_LENGTH(f, p, hdr->huge_size);
- H5F_ENCODE_LENGTH(f, p, hdr->huge_nobjs);
- H5F_ENCODE_LENGTH(f, p, hdr->tiny_size);
- H5F_ENCODE_LENGTH(f, p, hdr->tiny_nobjs);
-
- /* Managed objects' doubling-table info */
- if(H5HF__dtable_encode(hdr->f, &p, &(hdr->man_dtable)) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, FAIL, "unable to encode managed obj. doubling table info")
-
- /* Check for I/O filter information to encode */
- if(hdr->filter_len > 0) {
- /* Encode the size of a filtered root direct block */
- H5F_ENCODE_LENGTH(f, p, hdr->pline_root_direct_size);
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF__cache_hdr_pre_serialize
+ *
+ * Purpose: As best I can tell, fractal heap header blocks are always
+ * allocated in real file space. Thus this routine simply verifies
+ * this, verifies that the len parameter contains the expected
+ * value, and returns an error if either of these checks fail.
+ *
+ * When compiled in debug mode, the function also verifies that all
+ * indirect and direct blocks that are children of the header are
+ * either clean, or not in the metadata cache.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF__cache_hdr_pre_serialize(const H5F_t *f, hid_t dxpl_id, void *_thing,
+ haddr_t addr, size_t len, size_t H5_ATTR_UNUSED compressed_len,
+ haddr_t H5_ATTR_UNUSED *new_addr, size_t H5_ATTR_UNUSED *new_len,
+ size_t H5_ATTR_UNUSED *new_compressed_len, unsigned *flags)
+{
+ H5HF_hdr_t *hdr = (H5HF_hdr_t *)_thing; /* Fractal heap info */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Encode the filter mask for a filtered root direct block */
- UINT32ENCODE(p, hdr->pline_root_direct_filter_mask);
+ FUNC_ENTER_STATIC
- /* Encode I/O filter information */
- if(H5O_msg_encode(hdr->f, H5O_PLINE_ID, FALSE, p, &(hdr->pline)) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, FAIL, "can't encode I/O pipeline fiters")
- p += hdr->filter_len;
- } /* end if */
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(hdr);
+ HDassert(hdr->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(hdr->cache_info.type == H5AC_FHEAP_HDR);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(addr == hdr->heap_addr);
+ HDassert(new_addr);
+ HDassert(new_len);
+ HDassert(flags);
- /* Compute metadata checksum */
- metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
+#ifndef NDEBUG
+{
+ hbool_t descendants_clean = TRUE;
- /* Metadata checksum */
- UINT32ENCODE(p, metadata_chksum);
+ /* Verify that flush dependencies are working correctly. Do this
+ * by verifying that either:
+ *
+ * 1) the header has a root iblock, and that the root iblock and all
+ * of its children are clean, or
+ *
+ * 2) The header has a root dblock, which is clean, or
+ *
+ * 3) The heap is empty, and thus the header has neither a root
+ * iblock no a root dblock. In this case, the flush ordering
+ * constraint is met by default.
+ *
+ * Do this with a call to H5HF__cache_verify_hdr_descendants_clean().
+ */
+ if(H5HF__cache_verify_hdr_descendants_clean((H5F_t *)f, dxpl_id, hdr, &descendants_clean) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "can't verify hdr descendants clean.")
+ HDassert(descendants_clean);
+}
+#endif /* NDEBUG */
- /* 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")
+ if(H5F_IS_TMP_ADDR(f, addr))
+ HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "addr in temporary space?!?.");
- hdr->cache_info.is_dirty = FALSE;
- } /* end if */
+ if(len != hdr->heap_size)
+ HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "unexpected image len.");
- if(destroy)
- if(H5HF_cache_hdr_dest(f, hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap header")
+ *flags = 0;
done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer")
-
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HF_cache_hdr_flush() */
+} /* end H5HF__cache_hdr_pre_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_hdr_dest
+ * Function: H5HF__cache_hdr_serialize
*
- * Purpose: Destroys a fractal heap header in memory.
+ * Purpose: Construct the on disk image of the header, and place it in
+ * the buffer pointed to by image. Return SUCCEED on success,
+ * and FAIL on failure.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 24 2006
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_hdr_dest(H5F_t *f, H5HF_hdr_t *hdr)
+static herr_t
+H5HF__cache_hdr_serialize(const H5F_t *f, void *_image, size_t len,
+ void *_thing)
{
+ H5HF_hdr_t *hdr = (H5HF_hdr_t *)_thing; /* Fractal heap info */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ uint8_t heap_flags; /* Status flags for heap */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /*
- * Check arguments.
- */
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(image);
HDassert(hdr);
- HDassert(hdr->rc == 0);
+ HDassert(hdr->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(hdr->cache_info.type == H5AC_FHEAP_HDR);
+ HDassert(len == hdr->heap_size);
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!hdr->cache_info.free_file_space_on_destroy || H5F_addr_defined(hdr->cache_info.addr));
+ /* Set the shared heap header's file context for this operation */
+ hdr->f = f;
+
+ /* Magic number */
+ HDmemcpy(image, H5HF_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
- /* Check for freeing file space for heap header */
- if(hdr->cache_info.free_file_space_on_destroy) {
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_FHEAP_HDR, H5AC_dxpl_id, hdr->cache_info.addr, (hsize_t)hdr->heap_size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap header")
+ /* Version # */
+ *image++ = H5HF_HDR_VERSION;
+
+ /* General heap information */
+ UINT16ENCODE(image, hdr->id_len); /* Heap ID length */
+ UINT16ENCODE(image, hdr->filter_len); /* I/O filters' encoded length */
+
+ /* Heap status flags */
+ /* (bit 0: "huge" object IDs have wrapped) */
+ /* (bit 1: checksum direct blocks) */
+ heap_flags = 0;
+ heap_flags = (uint8_t)(heap_flags | (hdr->huge_ids_wrapped ? H5HF_HDR_FLAGS_HUGE_ID_WRAPPED : 0));
+ heap_flags = (uint8_t)(heap_flags | (hdr->checksum_dblocks ? H5HF_HDR_FLAGS_CHECKSUM_DBLOCKS : 0));
+ *image++ = heap_flags;
+
+ /* "Huge" object information */
+ UINT32ENCODE(image, hdr->max_man_size); /* Max. size of "managed" objects */
+ H5F_ENCODE_LENGTH(f, image, hdr->huge_next_id); /* Next ID to use for "huge" object */
+ H5F_addr_encode(f, &image, hdr->huge_bt2_addr); /* Address of "huge" object tracker B-tree */
+
+ /* "Managed" object free space information */
+ H5F_ENCODE_LENGTH(f, image, hdr->total_man_free); /* Internal free space in managed direct blocks */
+ H5F_addr_encode(f, &image, hdr->fs_addr); /* Address of free section header */
+
+ /* Heap statistics */
+ H5F_ENCODE_LENGTH(f, image, hdr->man_size);
+ H5F_ENCODE_LENGTH(f, image, hdr->man_alloc_size);
+ H5F_ENCODE_LENGTH(f, image, hdr->man_iter_off);
+ H5F_ENCODE_LENGTH(f, image, hdr->man_nobjs);
+ H5F_ENCODE_LENGTH(f, image, hdr->huge_size);
+ H5F_ENCODE_LENGTH(f, image, hdr->huge_nobjs);
+ H5F_ENCODE_LENGTH(f, image, hdr->tiny_size);
+ H5F_ENCODE_LENGTH(f, image, hdr->tiny_nobjs);
+
+ /* Managed objects' doubling-table info */
+ if(H5HF__dtable_encode(hdr->f, &image, &(hdr->man_dtable)) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, FAIL, "unable to encode managed obj. doubling table info")
+
+ /* Check for I/O filter information to encode */
+ if(hdr->filter_len > 0) {
+ /* Encode the size of a filtered root direct block */
+ H5F_ENCODE_LENGTH(f, image, hdr->pline_root_direct_size);
+
+ /* Encode the filter mask for a filtered root direct block */
+ UINT32ENCODE(image, hdr->pline_root_direct_filter_mask);
+
+ /* Encode I/O filter information */
+ if(H5O_msg_encode(hdr->f, H5O_PLINE_ID, FALSE, image, &(hdr->pline)) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, FAIL, "can't encode I/O pipeline fiters")
+ image += hdr->filter_len;
} /* end if */
- /* Free the shared info itself */
- if(H5HF_hdr_free(hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "unable to release fractal heap header")
+ /* Compute metadata checksum */
+ metadata_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
+
+ /* Metadata checksum */
+ UINT32ENCODE(image, metadata_chksum);
+
+ /* sanity check */
+ HDassert((size_t)(image - (uint8_t *)_image) == len);
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_cache_hdr_dest() */
+} /* end H5HF__cache_hdr_serialize() */
+
+/***************************************/
+/* no H5HF__cache_hdr_notify() function */
+/***************************************/
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_hdr_clear
+ * Function: H5HF__cache_hdr_free_icr
*
- * Purpose: Mark a fractal heap header in memory as non-dirty.
+ * Purpose: Free the in core representation of the fractal heap header.
*
- * Return: Non-negative on success/Negative on failure
+ * This routine frees just the header itself, not the
+ * associated version 2 B-Tree, the associated Free Space Manager,
+ * nor the indirect/direct block tree that is rooted in the header.
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 24 2006
+ * This routine also does not free the file space that may
+ * be allocated to the header.
+ *
+ * Note: The metadata cache sets the object's cache_info.magic to
+ * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
+ * callback (checked in assert).
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_hdr_clear(H5F_t *f, H5HF_hdr_t *hdr, hbool_t destroy)
+static herr_t
+H5HF__cache_hdr_free_icr(void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5HF_hdr_t *hdr = (H5HF_hdr_t *)_thing; /* Fractal heap info */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /*
- * Check arguments.
- */
+ /* Sanity checks */
HDassert(hdr);
+ HDassert(hdr->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(hdr->cache_info.type == H5AC_FHEAP_HDR);
+ HDassert(hdr->rc == 0);
- /* Reset the dirty flag. */
- hdr->cache_info.is_dirty = FALSE;
-
- if(destroy)
- if(H5HF_cache_hdr_dest(f, hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap header")
+ if(H5HF_hdr_free(hdr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "unable to release fractal heap header")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_cache_hdr_clear() */
+} /* end H5HF__cache_hdr_free_icr() */
+
+/***********************************************************/
+/* metadata cache callback definitions for indirect blocks */
+/***********************************************************/
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_hdr_size
+ * Function: H5HF__cache_iblock_get_load_size()
*
- * Purpose: Compute the size in bytes of a fractal heap header
- * on disk, and return it in *size_ptr. On failure,
- * the value of *size_ptr is undefined.
+ * Purpose: Compute the size of the on disk image of the indirect
+ * block, and place this value in *image_len.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 24 2006
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_hdr_size(const H5F_t H5_ATTR_UNUSED *f, const H5HF_hdr_t *hdr, size_t *size_ptr)
+static herr_t
+H5HF__cache_iblock_get_load_size(const void *_udata, size_t *image_len)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ const H5HF_iblock_cache_ud_t *udata = (const H5HF_iblock_cache_ud_t *)_udata; /* User data for callback */
- /* Check arguments */
- HDassert(f);
- HDassert(hdr);
- HDassert(size_ptr);
+ FUNC_ENTER_STATIC_NOERR
- /* Set size value */
- *size_ptr = hdr->heap_size;
+ /* Sanity checks */
+ HDassert(udata);
+ HDassert(image_len);
+
+ *image_len = (size_t)H5HF_MAN_INDIRECT_SIZE(udata->par_info->hdr, *udata->nrows);
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5HF_cache_hdr_size() */
+} /* end H5HF__cache_iblock_get_load_size() */
/***********************************************************/
/* metadata cache callback definitions for indirect blocks */
@@ -734,53 +874,55 @@ H5HF_cache_hdr_size(const H5F_t H5_ATTR_UNUSED *f, const H5HF_hdr_t *hdr, size_t
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_iblock_load
+ * Function: H5HF__cache_iblock_deserialize
*
- * Purpose: Loads a fractal heap indirect block from the disk.
+ * Purpose: Given a buffer containing the on disk image of the indirect
+ * block, allocate an instance of H5HF_indirect_t, load the data
+ * in the buffer into this new instance, and return a pointer to
+ * it.
*
- * Return: Success: Pointer to a new fractal heap indirect block
+ * As best I can tell, the size of the indirect block image is fully
+ * know before the image is loaded, so this function should succeed
+ * unless the image is corrupt or memory allocation fails.
*
+ * Return: Success: Pointer to in core representation
* Failure: NULL
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 27 2006
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static H5HF_indirect_t *
-H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
+static void *
+H5HF__cache_iblock_deserialize(const void *_image, size_t len, void *_udata,
+ hbool_t H5_ATTR_UNUSED *dirty)
{
H5HF_hdr_t *hdr; /* Shared fractal heap information */
- H5HF_iblock_cache_ud_t *udata = (H5HF_iblock_cache_ud_t *)_udata; /* user data for callback */
- H5HF_indirect_t *iblock = NULL; /* Indirect block info */
- H5WB_t *wb = NULL; /* Wrapped buffer for indirect block data */
- uint8_t iblock_buf[H5HF_IBLOCK_BUF_SIZE]; /* Buffer for indirect block */
- uint8_t *buf; /* Temporary buffer */
- const uint8_t *p; /* Pointer into raw data buffer */
+ H5HF_iblock_cache_ud_t *udata = (H5HF_iblock_cache_ud_t *)_udata; /* User data for callback */
+ H5HF_indirect_t *iblock = NULL; /* Indirect block info */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
haddr_t heap_addr; /* Address of heap header in the file */
uint32_t stored_chksum; /* Stored metadata checksum value */
uint32_t computed_chksum; /* Computed metadata checksum value */
unsigned u; /* Local index variable */
- H5HF_indirect_t *ret_value; /* Return value */
+ void * ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Sanity checks */
+ HDassert(image);
HDassert(udata);
-
- /* Allocate space for the fractal heap indirect block */
- if(NULL == (iblock = H5FL_CALLOC(H5HF_indirect_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- /* Get the pointer to the shared heap header */
+ HDassert(dirty);
hdr = udata->par_info->hdr;
+ HDassert(hdr->f);
/* Set the shared heap header's file context for this operation */
hdr->f = udata->f;
+ /* Allocate space for the fractal heap indirect block */
+ if(NULL == (iblock = H5FL_CALLOC(H5HF_indirect_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
/* Share common heap information */
iblock->hdr = hdr;
if(H5HF_hdr_incr(hdr) < 0)
@@ -791,35 +933,23 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
iblock->nrows = *udata->nrows;
iblock->nchildren = 0;
- /* Wrap the local buffer for serialized indirect block */
- if(NULL == (wb = H5WB_wrap(iblock_buf, sizeof(iblock_buf))))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't wrap buffer")
-
/* Compute size of indirect block */
iblock->size = H5HF_MAN_INDIRECT_SIZE(hdr, iblock->nrows);
- /* Get a pointer to a buffer that's large enough for serialized indirect block */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, iblock->size)))
- HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "can't get actual buffer")
-
- /* Read indirect block from disk */
- if(H5F_block_read(f, H5FD_MEM_FHEAP_IBLOCK, addr, iblock->size, dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "can't read fractal heap indirect block")
-
- /* Get temporary pointer to serialized indirect block */
- p = buf;
+ /* sanity check */
+ HDassert(iblock->size == len);
/* Magic number */
- if(HDmemcmp(p, H5HF_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong fractal heap indirect block signature")
- p += H5_SIZEOF_MAGIC;
+ if(HDmemcmp(image, H5HF_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "wrong fractal heap indirect block signature")
+ image += H5_SIZEOF_MAGIC;
/* Version */
- if(*p++ != H5HF_IBLOCK_VERSION)
+ if(*image++ != H5HF_IBLOCK_VERSION)
HGOTO_ERROR(H5E_HEAP, H5E_VERSION, NULL, "wrong fractal heap direct block version")
/* Address of heap that owns this block */
- H5F_addr_decode(udata->f, &p, &heap_addr);
+ H5F_addr_decode(udata->f, &image, &heap_addr);
if(H5F_addr_ne(heap_addr, hdr->heap_addr))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect heap header address for direct block")
@@ -844,7 +974,7 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
} /* end else */
/* Offset of heap within the heap's address space */
- UINT64DECODE_VAR(p, iblock->block_off, hdr->heap_off_size);
+ UINT64DECODE_VAR(image, iblock->block_off, hdr->heap_off_size);
/* Allocate & decode child block entry tables */
HDassert(iblock->nrows > 0);
@@ -866,7 +996,7 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
for(u = 0; u < (iblock->nrows * hdr->man_dtable.cparam.width); u++) {
/* Decode child block address */
- H5F_addr_decode(udata->f, &p, &(iblock->ents[u].addr));
+ H5F_addr_decode(udata->f, &image, &(iblock->ents[u].addr));
/* Check for heap with I/O filters */
if(hdr->filter_len > 0) {
@@ -876,7 +1006,7 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
/* Decode extra information for direct blocks */
if(u < (hdr->man_dtable.max_direct_rows * hdr->man_dtable.cparam.width)) {
/* Size of filtered direct block */
- H5F_DECODE_LENGTH(udata->f, p, iblock->filt_ents[u].size);
+ H5F_DECODE_LENGTH(udata->f, image, iblock->filt_ents[u].size);
/* Sanity check */
/* (either both the address & size are defined or both are
@@ -886,7 +1016,7 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
|| (!H5F_addr_defined(iblock->ents[u].addr) && iblock->filt_ents[u].size == 0));
/* I/O filter mask for filtered direct block */
- UINT32DECODE(p, iblock->filt_ents[u].filter_mask);
+ UINT32DECODE(image, iblock->filt_ents[u].filter_mask);
} /* end if */
} /* end if */
@@ -901,13 +1031,13 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
HDassert(iblock->nchildren); /* indirect blocks w/no children should have been deleted */
/* Compute checksum on indirect block */
- computed_chksum = H5_checksum_metadata(buf, (size_t)(p - (const uint8_t *)buf), 0);
+ computed_chksum = H5_checksum_metadata((const uint8_t *)_image, (size_t)(image - (const uint8_t *)_image), 0);
/* Metadata checksum */
- UINT32DECODE(p, stored_chksum);
+ UINT32DECODE(image, stored_chksum);
/* Sanity check */
- HDassert((size_t)(p - (const uint8_t *)buf) == iblock->size);
+ HDassert((size_t)(image - (const uint8_t *)_image) == iblock->size);
/* Verify checksum */
if(stored_chksum != computed_chksum)
@@ -915,7 +1045,7 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
/* Check if we have any indirect block children */
if(iblock->nrows > hdr->man_dtable.max_direct_rows) {
- unsigned indir_rows; /* Number of indirect rows in this indirect block */
+ unsigned indir_rows;/* Number of indirect rows in this indirect block */
/* Compute the number of indirect rows for this indirect block */
indir_rows = iblock->nrows - hdr->man_dtable.max_direct_rows;
@@ -928,343 +1058,323 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
iblock->child_iblocks = NULL;
/* Set return value */
- ret_value = iblock;
+ ret_value = (void *)iblock;
done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CLOSEERROR, NULL, "can't close wrapped buffer")
if(!ret_value && iblock)
if(H5HF_man_iblock_dest(iblock) < 0)
HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy fractal heap indirect block")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_cache_iblock_load() */
+} /* end H5HF__cache_iblock_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_iblock_flush
+ * Function: H5HF__cache_iblock_image_len
*
- * Purpose: Flushes a dirty fractal heap indirect block to disk.
+ * Purpose: Return the size of the on disk image of the iblock.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 6 2006
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_iblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_indirect_t *iblock, unsigned H5_ATTR_UNUSED * flags_ptr)
+static herr_t
+H5HF__cache_iblock_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- H5WB_t *wb = NULL; /* Wrapped buffer for indirect block data */
- uint8_t iblock_buf[H5HF_IBLOCK_BUF_SIZE]; /* Buffer for indirect block */
- herr_t ret_value = SUCCEED; /* Return value */
+ const H5HF_indirect_t *iblock = (const H5HF_indirect_t *)_thing; /* Indirect block info */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR
- /* check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Sanity checks */
HDassert(iblock);
+ HDassert(iblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(iblock->cache_info.type == H5AC_FHEAP_IBLOCK);
+ HDassert(image_len);
- if(iblock->cache_info.is_dirty) {
- H5HF_hdr_t *hdr; /* Shared fractal heap information */
- uint8_t *buf; /* Temporary buffer */
- uint8_t *p; /* Pointer into raw data buffer */
-#ifndef NDEBUG
- unsigned nchildren = 0; /* Track # of children */
- unsigned max_child = 0; /* Track max. child entry used */
-#endif /* NDEBUG */
- uint32_t metadata_chksum; /* Computed metadata checksum value */
- size_t u; /* Local index variable */
-
-#ifndef NDEBUG
-{
- /* Verify that flush dependencies are working correctly. Do this
- * by verifying that all children of this iblock are clean.
- */
- hbool_t descendants_clean = TRUE;
- unsigned iblock_status;
-
- if(H5AC_get_entry_status(f, iblock->addr, &iblock_status) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get iblock status")
-
- /* since the current iblock is the guest of honor in a flush, we know
- * that it is locked into the cache for the duration of the call. Hence
- * there is no need to check to see if it is pinned or protected, or to
- * protect it if it is not.
- */
- if(H5HF__cache_verify_iblock_descendants_clean(f, dxpl_id, iblock, &iblock_status, &descendants_clean) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "can't verify descendants clean.")
-
- HDassert(descendants_clean);
-}
-#endif /* NDEBUG */
-
- /* Get the pointer to the shared heap header */
- hdr = iblock->hdr;
-
- /* Set the shared heap header's file context for this operation */
- hdr->f = f;
-
- /* Wrap the local buffer for serialized indirect block */
- if(NULL == (wb = H5WB_wrap(iblock_buf, sizeof(iblock_buf))))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't wrap buffer")
-
- /* Get a pointer to a buffer that's large enough for serialized indirect block */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, iblock->size)))
- HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "can't get actual buffer")
-
- /* Get temporary pointer to buffer for serialized indirect block */
- p = buf;
-
- /* Magic number */
- HDmemcpy(p, H5HF_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
-
- /* Version # */
- *p++ = H5HF_IBLOCK_VERSION;
-
- /* Address of heap header for heap which owns this block */
- H5F_addr_encode(f, &p, hdr->heap_addr);
-
- /* Offset of block in heap */
- UINT64ENCODE_VAR(p, iblock->block_off, hdr->heap_off_size);
-
- /* Encode indirect block-specific fields */
- for(u = 0; u < (iblock->nrows * hdr->man_dtable.cparam.width); u++) {
- /* Encode child block address */
- H5F_addr_encode(f, &p, iblock->ents[u].addr);
+ *image_len = iblock->size;
- /* Check for heap with I/O filters */
- if(hdr->filter_len > 0) {
- /* Sanity check */
- HDassert(iblock->filt_ents);
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HF__cache_iblock_image_len() */
- /* Encode extra information for direct blocks */
- if(u < (hdr->man_dtable.max_direct_rows * hdr->man_dtable.cparam.width)) {
- /* Sanity check */
- /* (either both the address & size are defined or both are
- * not defined)
- */
- HDassert((H5F_addr_defined(iblock->ents[u].addr) && iblock->filt_ents[u].size)
- || (!H5F_addr_defined(iblock->ents[u].addr) && iblock->filt_ents[u].size == 0));
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF__cache_iblock_pre_serialize
+ *
+ * Purpose: The primary objective of this function is to determine if the
+ * indirect block is currently allocated in temporary file space,
+ * and if so, to move it to real file space before the entry is
+ * serialized.
+ *
+ * In debug compiles, this function also verifies that all children
+ * of this indirect block are either clean or are not in cache.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF__cache_iblock_pre_serialize(const H5F_t *f, hid_t dxpl_id, void *_thing,
+ haddr_t addr, size_t H5_ATTR_UNUSED len, size_t H5_ATTR_UNUSED compressed_len,
+ haddr_t *new_addr, size_t H5_ATTR_UNUSED *new_len,
+ size_t H5_ATTR_UNUSED *new_compressed_len, unsigned *flags)
+{
+ H5HF_hdr_t *hdr; /* Shared fractal heap information */
+ H5HF_indirect_t *iblock = (H5HF_indirect_t *)_thing; /* Indirect block info */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Size of filtered direct block */
- H5F_ENCODE_LENGTH(f, p, iblock->filt_ents[u].size);
+ FUNC_ENTER_STATIC
- /* I/O filter mask for filtered direct block */
- UINT32ENCODE(p, iblock->filt_ents[u].filter_mask);
- } /* end if */
- } /* end if */
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(iblock);
+ HDassert(iblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(iblock->cache_info.type == H5AC_FHEAP_IBLOCK);
+ HDassert(iblock->cache_info.size == iblock->size);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(H5F_addr_eq(iblock->addr, addr));
+ HDassert(new_addr);
+ HDassert(new_len);
+ HDassert(flags);
+ hdr = iblock->hdr;
+ HDassert(hdr);
+ HDassert(hdr->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(hdr->cache_info.type == H5AC_FHEAP_HDR);
#ifndef NDEBUG
- /* Count child blocks */
- if(H5F_addr_defined(iblock->ents[u].addr)) {
- nchildren++;
- if(u > max_child)
- max_child = u;
- } /* end if */
-#endif /* NDEBUG */
- } /* end for */
-
- /* Compute checksum */
- metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
+{
+ hbool_t descendants_clean = TRUE;
+ unsigned iblock_status = 0;
- /* Metadata checksum */
- UINT32ENCODE(p, metadata_chksum);
+ /* verify that flush dependencies are working correctly. Do this
+ * by verifying that all children of this iblock are clean.
+ */
+ if(H5AC_get_entry_status(f, iblock->addr, &iblock_status) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get iblock status")
- /* Sanity check */
- HDassert((size_t)(p - buf) == iblock->size);
-#ifndef NDEBUG
- HDassert(nchildren == iblock->nchildren);
- HDassert(max_child == iblock->max_child);
+ /* since the current iblock is the guest of honor in a flush, we know
+ * that it is locked into the cache for the duration of the call. Hence
+ * there is no need to check to see if it is pinned or protected, or to
+ * protect it if it is not.
+ */
+ if(H5HF__cache_verify_iblock_descendants_clean((H5F_t *)f, dxpl_id, iblock, &iblock_status, &descendants_clean) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "can't verify descendants clean.")
+ HDassert(descendants_clean);
+}
#endif /* NDEBUG */
- /* Check for needing to re-allocate indirect block from 'temp.' to 'normal' file space */
- if(H5F_IS_TMP_ADDR(f, addr)) {
- /* Sanity check */
- HDassert(H5F_addr_eq(iblock->addr, addr));
+ /* Check to see if we must re-allocate the iblock from temporary to
+ * normal (AKA real) file space.
+ */
+ if(H5F_IS_TMP_ADDR(f, addr)) {
+ haddr_t iblock_addr;
- /* Allocate 'normal' space for the new indirect block on disk */
- if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, (hsize_t)iblock->size)))
- HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap indirect block")
+ /* Allocate 'normal' space for the new indirect block on disk */
+ if(HADDR_UNDEF == (iblock_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, (hsize_t)iblock->size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap indirect block")
- /* Sanity check */
- HDassert(!H5F_addr_eq(iblock->addr, addr));
+ /* Sanity check */
+ HDassert(!H5F_addr_eq(iblock->addr, iblock_addr));
- /* Let the metadata cache know the block moved */
- if(H5AC_move_entry(f, H5AC_FHEAP_IBLOCK, iblock->addr, addr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move indirect block")
+ /* Let the metadata cache know the block moved */
+ if(H5AC_move_entry((H5F_t *)f, H5AC_FHEAP_IBLOCK, iblock->addr, iblock_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move indirect block")
- /* Update the internal address for the block */
- iblock->addr = addr;
+ /* Update the internal address for the block */
+ iblock->addr = iblock_addr;
- /* Check for root indirect block */
- if(NULL == iblock->parent) {
- /* Update information about indirect block's location */
- hdr->man_dtable.table_addr = addr;
+ /* Check for root indirect block */
+ if(NULL == iblock->parent) {
+ /* Update information about indirect block's location */
+ hdr->man_dtable.table_addr = iblock_addr;
- /* Mark that heap header was modified */
- if(H5HF_hdr_dirty(hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
- } /* end if */
- else {
- H5HF_indirect_t *par_iblock; /* Parent indirect block */
- unsigned par_entry; /* Entry in parent indirect block */
+ /* Mark that heap header was modified */
+ if(H5HF_hdr_dirty(hdr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
+ } /* end if */
+ else {
+ H5HF_indirect_t *par_iblock; /* Parent indirect block */
+ unsigned par_entry; /* Entry in parent indirect block */
- /* Get parent information */
- par_iblock = iblock->parent;
- par_entry = iblock->par_entry;
+ /* Get parent information */
+ par_iblock = iblock->parent;
+ par_entry = iblock->par_entry;
- /* Update information about indirect block's location */
- par_iblock->ents[par_entry].addr = addr;
+ /* Update information about indirect block's location */
+ par_iblock->ents[par_entry].addr = iblock_addr;
- /* Mark that parent was modified */
- if(H5HF_iblock_dirty(par_iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
- } /* end if */
+ /* Mark that parent was modified */
+ if(H5HF_iblock_dirty(par_iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
} /* end if */
- /* Indirect block must be in 'normal' file space now */
- HDassert(!H5F_IS_TMP_ADDR(f, addr));
-
- /* Write the indirect block */
- if(H5F_block_write(f, H5FD_MEM_FHEAP_IBLOCK, addr, iblock->size, dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFLUSH, FAIL, "unable to save fractal heap indirect block to disk")
-
- /* Reset dirty flags */
- iblock->cache_info.is_dirty = FALSE;
+ *new_addr = iblock_addr;
+ *flags = H5C__SERIALIZE_MOVED_FLAG;
} /* end if */
-
- if(destroy)
- if(H5HF_cache_iblock_dest(f, iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap indirect block")
+ else
+ *flags = 0;
done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer")
-
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HF_cache_iblock_flush() */
+} /* end H5HF__cache_iblock_pre_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_iblock_dest
+ * Function: H5HF__cache_iblock_serialize
*
- * Purpose: Destroys a fractal heap indirect block in memory.
+ * Purpose: Given a pointer to an iblock, and a pointer to a buffer of
+ * the appropriate size, write the contents of the iblock to the
+ * buffer in format appropriate for writing to disk.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 6 2006
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_iblock_dest(H5F_t *f, H5HF_indirect_t *iblock)
+static herr_t
+H5HF__cache_iblock_serialize(const H5F_t *f, void *_image, size_t len,
+ void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5HF_hdr_t *hdr; /* Shared fractal heap information */
+ H5HF_indirect_t *iblock = (H5HF_indirect_t *)_thing; /* Indirect block info */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+#ifndef NDEBUG
+ unsigned nchildren = 0; /* Track # of children */
+ size_t max_child = 0; /* Track max. child entry used */
+#endif /* NDEBUG */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+ size_t u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR
- /*
- * Check arguments.
- */
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(image);
HDassert(iblock);
- HDassert(iblock->rc == 0);
- HDassert(iblock->hdr);
+ HDassert(iblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(iblock->cache_info.type == H5AC_FHEAP_IBLOCK);
+ HDassert(iblock->cache_info.size == iblock->size);
+ HDassert(len == iblock->size);
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!iblock->cache_info.free_file_space_on_destroy || H5F_addr_defined(iblock->cache_info.addr));
-
- /* Check for freeing file space for indirect block */
- if(iblock->cache_info.free_file_space_on_destroy) {
- /* Check if the indirect block is NOT currently allocated in temp. file space */
- /* (temp. file space does not need to be freed) */
- if(!H5F_IS_TMP_ADDR(f, iblock->cache_info.addr)) {
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_FHEAP_IBLOCK, H5AC_dxpl_id, iblock->cache_info.addr, (hsize_t)iblock->size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block")
- } /* end if */
- } /* end if */
+ /* Indirect block must be in 'normal' file space */
+ HDassert(!H5F_IS_TMP_ADDR(f, iblock->addr));
+ HDassert(H5F_addr_eq(iblock->addr, iblock->cache_info.addr));
- /* Destroy fractal heap indirect block */
- if(H5HF_man_iblock_dest(iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap indirect block")
+ /* Get the pointer to the shared heap header */
+ hdr = iblock->hdr;
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_cache_iblock_dest() */
+ /* Set the shared heap header's file context for this operation */
+ hdr->f = f;
-
-/*-------------------------------------------------------------------------
- * Function: H5HF_cache_iblock_clear
- *
- * Purpose: Mark a fractal heap indirect block in memory as non-dirty.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 6 2006
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HF_cache_iblock_clear(H5F_t *f, H5HF_indirect_t *iblock, hbool_t destroy)
-{
- herr_t ret_value = SUCCEED; /* Return value */
+ /* Magic number */
+ HDmemcpy(image, H5HF_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
- FUNC_ENTER_NOAPI_NOINIT
+ /* Version # */
+ *image++ = H5HF_IBLOCK_VERSION;
- /*
- * Check arguments.
- */
- HDassert(iblock);
+ /* Address of heap header for heap which owns this block */
+ H5F_addr_encode(f, &image, hdr->heap_addr);
- /* Reset the dirty flag. */
- iblock->cache_info.is_dirty = FALSE;
+ /* Offset of block in heap */
+ UINT64ENCODE_VAR(image, iblock->block_off, hdr->heap_off_size);
- if(destroy)
- if(H5HF_cache_iblock_dest(f, iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap indirect block")
+ /* Encode indirect block-specific fields */
+ for(u = 0; u < (iblock->nrows * hdr->man_dtable.cparam.width); u++) {
+ /* Encode child block address */
+ H5F_addr_encode(f, &image, iblock->ents[u].addr);
+
+ /* Check for heap with I/O filters */
+ if(hdr->filter_len > 0) {
+ /* Sanity check */
+ HDassert(iblock->filt_ents);
+
+ /* Encode extra information for direct blocks */
+ if(u < (hdr->man_dtable.max_direct_rows * hdr->man_dtable.cparam.width)) {
+ /* Sanity check */
+ /* (either both the address & size are defined or both are
+ * not defined)
+ */
+ HDassert((H5F_addr_defined(iblock->ents[u].addr) && iblock->filt_ents[u].size)
+ || (!H5F_addr_defined(iblock->ents[u].addr) && iblock->filt_ents[u].size == 0));
+
+ /* Size of filtered direct block */
+ H5F_ENCODE_LENGTH(f, image, iblock->filt_ents[u].size);
+
+ /* I/O filter mask for filtered direct block */
+ UINT32ENCODE(image, iblock->filt_ents[u].filter_mask);
+ } /* end if */
+ } /* end if */
+
+#ifndef NDEBUG
+ /* Count child blocks */
+ if(H5F_addr_defined(iblock->ents[u].addr)) {
+ nchildren++;
+ if(u > max_child)
+ max_child = u;
+ } /* end if */
+#endif /* NDEBUG */
+ } /* end for */
+
+ /* Compute checksum */
+ metadata_chksum = H5_checksum_metadata((uint8_t *)_image, (size_t)(image - (uint8_t *)_image), 0);
+
+ /* Metadata checksum */
+ UINT32ENCODE(image, metadata_chksum);
+
+ /* Sanity checks */
+ HDassert((size_t)(image - (uint8_t *)_image) == iblock->size);
+#ifndef NDEBUG
+ HDassert(nchildren == iblock->nchildren);
+ HDassert(max_child == iblock->max_child);
+#endif /* NDEBUG */
-done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_cache_iblock_clear() */
+} /* end H5HF__cache_iblock_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_iblock_notify
+ * Function: H5HF__cache_iblock_notify
*
- * Purpose: Setup / takedown flush dependencies as indirect blocks
+ * Purpose: This function is used to create and destroy flush dependency
+ * relationships between iblocks and their parents as indirect blocks
* are loaded / inserted and evicted from the metadata cache.
*
- * Return: Non-negative on success/Negative on failure
+ * In general, the parent will be another iblock, but it may be the
+ * header if the iblock in question is the root iblock.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
* Programmer: John Mainzer
- * 5/17/14
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_iblock_notify(H5C_notify_action_t action, H5HF_indirect_t *iblock)
+static herr_t
+H5HF__cache_iblock_notify(H5C_notify_action_t action, void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5HF_indirect_t *iblock = (H5HF_indirect_t *)_thing; /* Indirect block info */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /*
- * Check arguments.
- */
+ /* Sanity checks */
HDassert(iblock);
HDassert(iblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(iblock->cache_info.type == H5AC_FHEAP_IBLOCK);
HDassert(iblock->hdr);
if(action == H5AC_NOTIFY_ACTION_BEFORE_EVICT)
@@ -1309,6 +1419,7 @@ H5HF_cache_iblock_notify(H5C_notify_action_t action, H5HF_indirect_t *iblock)
switch(action) {
case H5AC_NOTIFY_ACTION_AFTER_INSERT:
+ case H5AC_NOTIFY_ACTION_AFTER_LOAD:
if(iblock->parent) { /* this is a child iblock */
/* create flush dependency with parent iblock */
if(H5AC_create_flush_dependency(iblock->parent, iblock) < 0)
@@ -1321,6 +1432,10 @@ H5HF_cache_iblock_notify(H5C_notify_action_t action, H5HF_indirect_t *iblock)
} /* end else */
break;
+ case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
+ /* do nothing */
+ break;
+
case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
if(iblock->fd_parent) { /* this is a child iblock */
/* destroy flush dependency with parent iblock */
@@ -1341,38 +1456,104 @@ H5HF_cache_iblock_notify(H5C_notify_action_t action, H5HF_indirect_t *iblock)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_cache_iblock_notify() */
+} /* end H5HF__cache_iblock_notify() */
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_iblock_size
+ * Function: H5HF__cache_iblock_free_icr
*
- * Purpose: Compute the size in bytes of a fractal heap indirect block
- * on disk, and return it in *size_ptr. On failure,
- * the value of *size_ptr is undefined.
+ * Purpose: Unlink the supplied instance of H5HF_indirect_t from the
+ * fractal heap and free its memory.
*
- * Return: Non-negative on success/Negative on failure
+ * Note: The metadata cache sets the object's cache_info.magic to
+ * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
+ * callback (checked in assert).
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 6 2006
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_iblock_size(const H5F_t H5_ATTR_UNUSED *f, const H5HF_indirect_t *iblock, size_t *size_ptr)
+static herr_t
+H5HF__cache_iblock_free_icr(void *thing)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ H5HF_indirect_t *iblock = (H5HF_indirect_t *)thing; /* Fractal heap indirect block to free */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Check arguments */
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
HDassert(iblock);
- HDassert(size_ptr);
+ HDassert(iblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(iblock->cache_info.type == H5AC_FHEAP_IBLOCK);
+ HDassert(iblock->rc == 0);
+ HDassert(iblock->hdr);
+
+ /* Destroy fractal heap indirect block */
+ if(H5HF_man_iblock_dest(iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap indirect block")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF__cache_iblock_free_icr() */
+
+/*********************************************************/
+/* metadata cache callback definitions for direct blocks */
+/*********************************************************/
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF__cache_dblock_get_load_size()
+ *
+ * Purpose: Determine the size of the direct block on disk image, and
+ * return it in *image_len.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF__cache_dblock_get_load_size(const void *_udata, size_t *image_len)
+{
+ const H5HF_dblock_cache_ud_t *udata = (const H5HF_dblock_cache_ud_t *)_udata; /* User data for callback */
+ const H5HF_parent_t *par_info; /* Pointer to parent information */
+ const H5HF_hdr_t *hdr; /* Shared fractal heap information */
+ size_t size;
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity checks */
+ HDassert(udata);
+ HDassert(image_len);
+ par_info = (const H5HF_parent_t *)(&(udata->par_info));
+ HDassert(par_info);
+ hdr = par_info->hdr;
+ HDassert(hdr);
+ HDassert(hdr->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(hdr->cache_info.type == H5AC_FHEAP_HDR);
+
+ /* Check for I/O filters on this heap */
+ if(hdr->filter_len > 0) {
+ /* Check for root direct block */
+ if(par_info->iblock == NULL)
+ size = hdr->pline_root_direct_size;
+ else
+ size = par_info->iblock->filt_ents[par_info->entry].size;
+ } /* end if */
+ else
+ size = udata->dblock_size;
- /* Set size value */
- *size_ptr = iblock->size;
+ *image_len = size;
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5HF_cache_iblock_size() */
+} /* end H5HF__cache_dblock_get_load_size() */
/*********************************************************/
/* metadata cache callback definitions for direct blocks */
@@ -1380,49 +1561,55 @@ H5HF_cache_iblock_size(const H5F_t H5_ATTR_UNUSED *f, const H5HF_indirect_t *ibl
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_dblock_load
+ * Function: H5HF__cache_dblock_deserialize
*
- * Purpose: Loads a fractal heap direct block from the disk.
+ * Purpose: Given a buffer containing the on disk image of a direct
+ * block, allocate an instance of H5HF_direct_t, load the data
+ * in the buffer into this new instance, and return a pointer to
+ * it.
*
- * Return: Success: Pointer to a new fractal heap direct block
+ * As best I can tell, the size of the direct block image is fully
+ * know before the image is loaded, so this function should succeed
+ * unless the image is corrupt or memory allocation fails.
*
+ * Return: Success: Pointer to in core representation
* Failure: NULL
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 27 2006
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static H5HF_direct_t *
-H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
+static void *
+H5HF__cache_dblock_deserialize(const void *_image, size_t len, void *_udata,
+ hbool_t H5_ATTR_UNUSED *dirty)
{
H5HF_hdr_t *hdr; /* Shared fractal heap information */
H5HF_dblock_cache_ud_t *udata = (H5HF_dblock_cache_ud_t *)_udata; /* User data for callback */
H5HF_parent_t *par_info; /* Pointer to parent information */
- H5HF_direct_t *dblock = NULL; /* Direct block info */
- const uint8_t *p; /* Pointer into raw data buffer */
+ H5HF_direct_t *dblock = NULL; /* Direct block info */
+ const uint8_t *image; /* Pointer into raw data buffer */
haddr_t heap_addr; /* Address of heap header in the file */
- H5HF_direct_t *ret_value; /* Return value */
+ void * ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(udata != NULL);
- HDassert(udata->f != NULL);
- HDassert(udata->dblock_size > 0);
+ /* Sanity checks */
+ HDassert(_image);
+ HDassert(udata);
+ par_info = (H5HF_parent_t *)(&(udata->par_info));
+ HDassert(par_info);
+ hdr = par_info->hdr;
+ HDassert(hdr);
+ HDassert(hdr->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(hdr->cache_info.type == H5AC_FHEAP_HDR);
+ HDassert(dirty);
/* 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));
- /* Get the pointer to the shared heap header */
- par_info = (H5HF_parent_t *)(&(udata->par_info));
- hdr = par_info->hdr;
-
/* Set the shared heap header's file context for this operation */
hdr->f = udata->f;
@@ -1435,6 +1622,10 @@ H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
dblock->size = udata->dblock_size;
dblock->file_size = 0;
+ /* initialize fields used in serialization */
+ dblock->write_buf = NULL;
+ dblock->write_size = 0;
+
/* Allocate block buffer */
/* XXX: Change to using free-list factories */
if(NULL == (dblock->blk = H5FL_BLK_MALLOC(direct_block, (size_t)dblock->size)))
@@ -1449,28 +1640,21 @@ H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
unsigned filter_mask; /* Excluded filters for direct block */
/* Check for root direct block */
- if(par_info->iblock == NULL) {
- /* Sanity check */
- HDassert(H5F_addr_eq(hdr->man_dtable.table_addr, addr));
-
+ if(par_info->iblock == NULL)
/* Set up parameters to read filtered direct block */
read_size = hdr->pline_root_direct_size;
- } /* end if */
- else {
- /* Sanity check */
- HDassert(H5F_addr_eq(par_info->iblock->ents[par_info->entry].addr, addr));
-
+ else
/* Set up parameters to read filtered direct block */
read_size = par_info->iblock->filt_ents[par_info->entry].size;
- } /* end else */
+ HDassert(len == read_size);
- /* Allocate buffer to perform I/O filtering on */
+ /* Allocate buffer to perform I/O filtering on and copy image into
+ * it. Must do this as H5Z_pipeline() may re-sized the buffer
+ * provided to it.
+ */
if(NULL == (read_buf = H5MM_malloc(read_size)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "memory allocation failed for pipeline buffer")
-
- /* Read filtered direct block from disk */
- if(H5F_block_read(f, H5FD_MEM_FHEAP_DBLOCK, addr, read_size, dxpl_id, read_buf) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "can't read fractal heap direct block")
+ HDmemcpy(read_buf, _image, len);
/* Push direct block data through I/O filter pipeline */
nbytes = read_size;
@@ -1488,25 +1672,25 @@ H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
H5MM_xfree(read_buf);
} /* end if */
else {
- /* Read direct block from disk */
- if(H5F_block_read(f, H5FD_MEM_FHEAP_DBLOCK, addr, dblock->size, dxpl_id, dblock->blk) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "can't read fractal heap direct block")
+ /* copy image to dblock->blk */
+ HDassert(dblock->size == len);
+ HDmemcpy(dblock->blk, _image, dblock->size);
} /* end else */
/* Start decoding direct block */
- p = dblock->blk;
+ image = dblock->blk;
/* Magic number */
- if(HDmemcmp(p, H5HF_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong fractal heap direct block signature")
- p += H5_SIZEOF_MAGIC;
+ if(HDmemcmp(image, H5HF_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "wrong fractal heap direct block signature")
+ image += H5_SIZEOF_MAGIC;
/* Version */
- if(*p++ != H5HF_DBLOCK_VERSION)
+ if(*image++ != H5HF_DBLOCK_VERSION)
HGOTO_ERROR(H5E_HEAP, H5E_VERSION, NULL, "wrong fractal heap direct block version")
/* Address of heap that owns this block (just for file integrity checks) */
- H5F_addr_decode(udata->f, &p, &heap_addr);
+ H5F_addr_decode(udata->f, &image, &heap_addr);
if(H5F_addr_ne(heap_addr, hdr->heap_addr))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect heap header address for direct block")
@@ -1521,7 +1705,7 @@ H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
} /* end if */
/* Offset of heap within the heap's address space */
- UINT64DECODE_VAR(p, dblock->block_off, hdr->heap_off_size);
+ UINT64DECODE_VAR(image, dblock->block_off, hdr->heap_off_size);
/* Decode checksum on direct block, if requested */
if(hdr->checksum_dblocks) {
@@ -1529,11 +1713,11 @@ H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
uint32_t computed_chksum; /* Computed metadata checksum value */
/* Metadata checksum */
- UINT32DECODE(p, stored_chksum);
+ UINT32DECODE(image, stored_chksum);
/* Reset checksum field, for computing the checksum */
/* (Casting away const OK - QAK) */
- HDmemset((uint8_t *)p - H5HF_SIZEOF_CHKSUM, 0, (size_t)H5HF_SIZEOF_CHKSUM);
+ HDmemset((uint8_t *)image - H5HF_SIZEOF_CHKSUM, 0, (size_t)H5HF_SIZEOF_CHKSUM);
/* Compute checksum on entire direct block */
computed_chksum = H5_checksum_metadata(dblock->blk, dblock->size, 0);
@@ -1544,10 +1728,10 @@ H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
} /* end if */
/* Sanity check */
- HDassert((size_t)(p - dblock->blk) == (size_t)H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr));
+ HDassert((size_t)(image - dblock->blk) == (size_t)H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr));
/* Set return value */
- ret_value = dblock;
+ ret_value = (void *)dblock;
done:
if(!ret_value && dblock)
@@ -1555,402 +1739,646 @@ done:
HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy fractal heap direct block")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_cache_dblock_load() */
+} /* end H5HF__cache_dblock_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_dblock_flush
+ * Function: H5HF__cache_dblock_image_len
*
- * Purpose: Flushes a dirty fractal heap direct block to disk.
+ * Purpose: Report the actual size of the direct block image on disk.
+ * Note that this value will probably be incorrect if compression
+ * is enabled and the entry is dirty.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 27 2006
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_direct_t *dblock, unsigned H5_ATTR_UNUSED * flags_ptr)
+static herr_t
+H5HF__cache_dblock_image_len(const void *_thing, size_t *image_len, hbool_t *compressed_ptr, size_t *compressed_image_len_ptr)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ const H5HF_direct_t *dblock = (const H5HF_direct_t *)_thing; /* Direct block info */
+ const H5HF_indirect_t *par_iblock; /* Parent iblock */
+ const H5HF_hdr_t *hdr; /* Shared fractal heap information */
+ hbool_t compressed;
+ size_t size;
+ size_t compressed_size;
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR
- /* check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ /* Sanity checks */
HDassert(dblock);
+ HDassert(dblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(dblock->cache_info.type == H5AC_FHEAP_DBLOCK);
+ HDassert(image_len);
+ HDassert(compressed_ptr);
+ HDassert(compressed_image_len_ptr);
- if(dblock->cache_info.is_dirty) {
- H5HF_hdr_t *hdr; /* Shared fractal heap information */
- hbool_t at_tmp_addr = H5F_IS_TMP_ADDR(f, addr); /* Flag to indicate direct block is at temporary address */
- void *write_buf; /* Pointer to buffer to write out */
- size_t write_size; /* Size of buffer to write out */
- uint8_t *p; /* Pointer into raw data buffer */
+ /* Set up convenience variables */
+ hdr = dblock->hdr;
+ par_iblock = dblock->parent;
- /* Get the pointer to the shared heap header */
- hdr = dblock->hdr;
+ /* Check for I/O filters on this heap */
+ if(hdr->filter_len > 0) {
- /* Set the shared heap header's file context for this operation */
- hdr->f = f;
+ /* Filters are enabled, so set compressed to TRUE, and set
+ * size equal to the uncompressed size of the direct block.
+ * If the data is available, set compressed_size to the compressed
+ * size of the direct block -- otherwise set it equal to the
+ * uncompressed size.
+ *
+ * We have three possible scenarios here.
+ *
+ * First, the block may never have been flushed. In this
+ * case, both dblock->file_size and the size stored in the
+ * parent (either the header or the parent iblock) will all
+ * be zero. In this case, return the uncompressed size
+ * stored in dblock->size as the compressed size.
+ *
+ * Second, the block may have just been serialized, in which
+ * case, dblock->file_size should be zero, and the correct
+ * on disk size should be stored in the parent (again, either
+ * the header or the parent iblock as case may be).
+ *
+ * Third, we may be in the process of discarding this
+ * dblock without writing it. In this case, dblock->file_size
+ * should be non-zero and have the correct size. Note that
+ * in this case, the direct block will have been detached,
+ * and thus looking up the parent will likely return incorrect
+ * data.
+ */
+ size = dblock->size;
+ compressed = TRUE;
+ compressed_size = dblock->size; /* will overwrite if compressed
+ * size is available.
+ */
+
+ if(dblock->file_size != 0)
+ compressed_size = dblock->file_size;
+ else {
+ if(par_iblock) {
+ unsigned par_entry; /* Entry in parent indirect block */
- HDassert(dblock->blk);
- p = dblock->blk;
+ par_entry = dblock->par_entry;
+ compressed_size = par_iblock->filt_ents[par_entry].size;
- /* Magic number */
- HDmemcpy(p, H5HF_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
+ } /* end if */
+ else {
+ compressed_size = hdr->pline_root_direct_size;
+ }
- /* Version # */
- *p++ = H5HF_DBLOCK_VERSION;
+ if(compressed_size == 0)
+ compressed_size = dblock->size;
- /* Address of heap header for heap which owns this block */
- H5F_addr_encode(f, &p, hdr->heap_addr);
+ } /* end else */
+ } /* end if */
+ else {
+ size = dblock->size;
+ compressed = FALSE;
+ compressed_size = 0; /* a convenient, invalid value */
+ }
- /* Offset of block in heap */
- UINT64ENCODE_VAR(p, dblock->block_off, hdr->heap_off_size);
+ HDassert(size > 0);
- /* Metadata checksum */
- if(hdr->checksum_dblocks) {
- uint32_t metadata_chksum; /* Computed metadata checksum value */
+ *image_len = size;
+ *compressed_ptr = compressed;
+ *compressed_image_len_ptr = compressed_size;
- /* Clear the checksum field, to compute the checksum */
- HDmemset(p, 0, (size_t)H5HF_SIZEOF_CHKSUM);
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HF__cache_dblock_image_len() */
- /* Compute checksum on entire direct block */
- metadata_chksum = H5_checksum_metadata(dblock->blk, dblock->size, 0);
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF__cache_dblock_pre_serialize
+ *
+ * Purpose: In principle, the purpose of this function is to determine
+ * the size and location of the disk image of the target direct
+ * block. In this case, the uncompressed size of the block is
+ * fixed, but sined the H5C__CLASS_COMPRESSED_FLAG is set,
+ * we may need to compute and report the compressed size.
+ *
+ * This is a bit sticky in the case of a direct block when I/O
+ * filters are enabled, as the size of the compressed version
+ * of the on disk image is not known until the direct block has
+ * been run through the filters. Further, the location of the
+ * on disk image may change if the compressed size of the image
+ * changes as well.
+ *
+ * To complicate matters further, the direct block may have been
+ * initially allocated in temporary (AKA imaginary) file space.
+ * In this case, we must relocate the direct block's on disk
+ * image to real file space regardless of whether it has changed
+ * size.
+ *
+ * One simplifying factor is the direct block's "blk" field,
+ * which contains a pointer to a buffer which (with the exception
+ * of a small header) contains the on disk image in uncompressed
+ * form.
+ *
+ * To square this particular circle, this function does
+ * everything the serialize function usually does, with the
+ * exception of copying the image into the image buffer provided
+ * to the serialize function by the metadata cache. The data to
+ * copy is provided to the serialize function in a buffer pointed
+ * to by the write_buf field.
+ *
+ * If I/O filters are enabled, on exit,
+ * H5HF__cache_dblock_pre_serialize() sets the write_buf field to
+ * point to a buffer containing the filtered image of the direct
+ * block. The serialize function should free this block, and set
+ * the write_buf field to NULL after copying it into the image
+ * buffer provided by the metadata cache.
+ *
+ * If I/O filters are not enabled, this function prepares
+ * the buffer pointed to by the blk field for copying to the
+ * image buffer provided by the metadata cache, and sets the
+ * write_buf field equal to the blk field. In this case, the
+ * serialize function should simply set the write_buf field to
+ * NULL after copying the direct block image into the image
+ * buffer.
+ *
+ * In both of the above cases, the length of the buffer pointed
+ * to by write_buf is provided in the write_len field. This
+ * field must contain 0 on entry to this function, and should
+ * be set back to 0 at the end of the serialize function.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF__cache_dblock_pre_serialize(const H5F_t *f, hid_t dxpl_id, void *_thing,
+ haddr_t addr, size_t len, size_t compressed_len, haddr_t *new_addr,
+ size_t H5_ATTR_UNUSED *new_len, size_t *new_compressed_len, unsigned *flags)
+{
+ hbool_t at_tmp_addr; /* Flag to indicate direct block is */
+ /* at temporary address */
+ haddr_t dblock_addr;
+ H5HF_hdr_t *hdr; /* Shared fractal heap information */
+ H5HF_direct_t *dblock = (H5HF_direct_t *)_thing; /* Direct block info */
+ H5HF_indirect_t *par_iblock; /* Parent indirect block */
+ unsigned par_entry; /* Entry in parent indirect block */
+ void *write_buf; /* Pointer to buffer to write out */
+ size_t write_size; /* Size of buffer to write out */
+ uint8_t *image; /* Pointer into raw data buffer */
+ unsigned dblock_flags = 0;
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Metadata checksum */
- UINT32ENCODE(p, metadata_chksum);
- } /* end if */
+ FUNC_ENTER_STATIC
- /* Sanity check */
- HDassert((size_t)(p - dblock->blk) == (size_t)H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr));
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(dblock);
+ HDassert(dblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(dblock->cache_info.type == H5AC_FHEAP_DBLOCK);
+ HDassert(dblock->write_buf == NULL);
+ HDassert(dblock->write_size == 0);
+ HDassert(dblock->cache_info.size == len);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(len == dblock->size);
+ HDassert(new_addr);
+ HDassert(new_compressed_len);
+ HDassert(flags);
- /* Check for I/O filters on this heap */
- if(hdr->filter_len > 0) {
- H5Z_cb_t filter_cb = {NULL, NULL}; /* Filter callback structure */
- size_t nbytes; /* Number of bytes used */
- unsigned filter_mask = 0; /* Filter mask for block */
+ /* Set up local variables */
+ hdr = dblock->hdr;
+ dblock_addr = addr; /* will update dblock_addr if we move the block */
- /* Allocate buffer to perform I/O filtering on */
- write_size = dblock->size;
- if(NULL == (write_buf = H5MM_malloc(write_size)))
- HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "memory allocation failed for pipeline buffer")
- HDmemcpy(write_buf, dblock->blk, write_size);
+ /* dblock->size must match dblock->cache_info.size */
+ HDassert(dblock->cache_info.size == dblock->size);
- /* Push direct block data through I/O filter pipeline */
- nbytes = write_size;
- if(H5Z_pipeline(&(hdr->pline), 0, &filter_mask, H5Z_ENABLE_EDC, filter_cb, &nbytes, &write_size, &write_buf) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "output pipeline failed")
+ /* Set the shared heap header's file context for this operation */
+ hdr->f = (H5F_t *)f;
- /* Use the compressed number of bytes as the size to write */
- write_size = nbytes;
+ HDassert(hdr);
+ HDassert(hdr->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(hdr->cache_info.type == H5AC_FHEAP_HDR);
- /* Check for root direct block */
- if(dblock->parent == NULL) {
- hbool_t hdr_changed = FALSE; /* Whether the header information changed */
+ if(dblock->parent) {
+ /* this is the common case, in which the direct block is the child
+ * of an indirect block. Set up the convenience variables we will
+ * need if the address and/or compressed size of the on disk image
+ * of the direct block changes, and do some sanity checking in
+ * passing.
+ */
+ par_iblock = dblock->parent;
+ par_entry = dblock->par_entry;
- /* Sanity check */
- HDassert(H5F_addr_eq(hdr->man_dtable.table_addr, addr));
- HDassert(hdr->pline_root_direct_size > 0);
+ HDassert(par_iblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(par_iblock->cache_info.type == H5AC_FHEAP_IBLOCK);
+ HDassert(H5F_addr_eq(par_iblock->ents[par_entry].addr, addr));
+ } /* end if */
+ else {
+ /* the direct block is a root direct block -- just set par_iblock
+ * to NULL, as the field will not be used.
+ */
+ par_iblock = NULL;
+ } /* end else */
- /* Check if the filter mask changed */
- if(hdr->pline_root_direct_filter_mask != filter_mask) {
- hdr->pline_root_direct_filter_mask = filter_mask;
- hdr_changed = TRUE;
- } /* end if */
+ at_tmp_addr = H5F_IS_TMP_ADDR(f, addr);
- /* Check if we need to re-size the block on disk */
- if(hdr->pline_root_direct_size != write_size || at_tmp_addr) {
- /* Check if the direct block is NOT currently allocated in temp. file space */
- /* (temp. file space does not need to be freed) */
- if(!at_tmp_addr) {
- /* Release direct block's current disk space */
- if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, addr, (hsize_t)hdr->pline_root_direct_size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
- } /* end if */
+ /* Begin by preping the direct block to be written to disk. Do
+ * this by writing the correct magic number, the dblock version,
+ * the address of the header, the offset of the block in the heap,
+ * and the checksum at the beginning of the block.
+ */
- /* Allocate space for the compressed direct block */
- if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)write_size)))
- HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
+ HDassert(dblock->blk);
+ image = dblock->blk;
- /* Let the metadata cache know, if the block moved */
- if(!H5F_addr_eq(hdr->man_dtable.table_addr, addr))
- if(H5AC_move_entry(f, H5AC_FHEAP_DBLOCK, hdr->man_dtable.table_addr, addr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move direct block")
+ /* Magic number */
+ HDmemcpy(image, H5HF_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
- /* Update information about compressed direct block's location & size */
- hdr->man_dtable.table_addr = addr;
- hdr->pline_root_direct_size = write_size;
+ /* Version # */
+ *image++ = H5HF_DBLOCK_VERSION;
- /* Note that heap header was modified */
- hdr_changed = TRUE;
- } /* end if */
+ /* Address of heap header for heap which owns this block */
+ H5F_addr_encode(f, &image, hdr->heap_addr);
- /* Check if heap header was modified */
- if(hdr_changed)
- if(H5HF_hdr_dirty(hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
- } /* end if */
- else {
- hbool_t par_changed = FALSE; /* Whether the parent's information changed */
- H5HF_indirect_t *par_iblock; /* Parent indirect block */
- unsigned par_entry; /* Entry in parent indirect block */
+ /* Offset of block in heap */
+ UINT64ENCODE_VAR(image, dblock->block_off, hdr->heap_off_size);
- /* Get parent information */
- par_iblock = dblock->parent;
- par_entry = dblock->par_entry;
+ /* Metadata checksum */
+ if(hdr->checksum_dblocks) {
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
- /* Sanity check */
- HDassert(H5F_addr_eq(par_iblock->ents[par_entry].addr, addr));
- HDassert(par_iblock->filt_ents[par_entry].size > 0);
+ /* Clear the checksum field, to compute the checksum */
+ HDmemset(image, 0, (size_t)H5HF_SIZEOF_CHKSUM);
- /* Check if the filter mask changed */
- if(par_iblock->filt_ents[par_entry].filter_mask != filter_mask) {
- par_iblock->filt_ents[par_entry].filter_mask = filter_mask;
- par_changed = TRUE;
- } /* end if */
+ /* Compute checksum on entire direct block */
+ metadata_chksum = H5_checksum_metadata(dblock->blk, dblock->size, 0);
- /* Check if we need to re-size the block on disk */
- if(par_iblock->filt_ents[par_entry].size != write_size || at_tmp_addr) {
- /* Check if the direct block is NOT currently allocated in temp. file space */
- /* (temp. file space does not need to be freed) */
- if(!at_tmp_addr) {
- /* Release direct block's current disk space */
- if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, addr, (hsize_t)par_iblock->filt_ents[par_entry].size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
- } /* end if */
+ /* Metadata checksum */
+ UINT32ENCODE(image, metadata_chksum);
+ } /* end if */
- /* Allocate space for the compressed direct block */
- if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)write_size)))
- HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
+ /* at this point, dblock->blk should point to an uncompressed image of
+ * the direct block. If I/O filters are not enabled, this image should
+ * be ready to hand off to the metadata cache.
+ */
- /* Let the metadata cache know, if the block moved */
- if(!H5F_addr_eq(par_iblock->ents[par_entry].addr, addr))
- if(H5AC_move_entry(f, H5AC_FHEAP_DBLOCK, par_iblock->ents[par_entry].addr, addr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move direct block")
+ /* Sanity check */
+ HDassert((size_t)(image - dblock->blk) == (size_t)H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr));
- /* Update information about compressed direct block's location & size */
- par_iblock->ents[par_entry].addr = addr;
- par_iblock->filt_ents[par_entry].size = write_size;
+ /* If I/O filters are enabled on this heap, we must run the direct block
+ * image through the filters to obtain the image that we will hand off
+ * to the metadata cache.
+ */
- /* Note that parent was modified */
- par_changed = TRUE;
- } /* end if */
+ /* Check for I/O filters on this heap */
+ if(hdr->filter_len > 0) {
+ H5Z_cb_t filter_cb = {NULL, NULL}; /* Filter callback structure */
+ size_t nbytes; /* Number of bytes used */
+ unsigned filter_mask = 0; /* Filter mask for block */
- /* Check if parent was modified */
- if(par_changed)
- if(H5HF_iblock_dirty(par_iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
- } /* end else */
- } /* end if */
- else {
- write_buf = dblock->blk;
- write_size = dblock->size;
+ /* Allocate buffer to perform I/O filtering on */
+ write_size = dblock->size;
- /* Check for needing to re-allocate direct block from 'temp.' to 'normal' file space */
- if(at_tmp_addr) {
- /* Check for root direct block */
- if(NULL == dblock->parent) {
- /* Sanity check */
- HDassert(H5F_addr_eq(hdr->man_dtable.table_addr, addr));
+ if(NULL == (write_buf = H5MM_malloc(write_size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "memory allocation failed for pipeline buffer")
+ HDmemcpy(write_buf, dblock->blk, write_size);
- /* Allocate 'normal' space for the direct block */
- if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)write_size)))
- HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
+ /* Push direct block data through I/O filter pipeline */
+ nbytes = write_size;
+ if(H5Z_pipeline(&(hdr->pline), 0, &filter_mask, H5Z_ENABLE_EDC, filter_cb, &nbytes, &write_size, &write_buf) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "output pipeline failed")
+
+ /* Use the compressed number of bytes as the size to write */
+ write_size = nbytes;
+
+ /* If the size and/or location of the on disk image of the
+ * direct block changes, we must touch up its parent to reflect
+ * these changes. Do this differently depending on whether the
+ * direct block's parent is an indirect block or (rarely) the
+ * fractal heap header. In this case, the direct block is known
+ * as a root direct block.
+ */
- /* Sanity check */
- HDassert(!H5F_addr_eq(hdr->man_dtable.table_addr, addr));
+ /* Check for root direct block */
+ if(dblock->parent == NULL) {
+ hbool_t hdr_changed = FALSE; /* Whether the header info changed */
- /* Let the metadata cache know the block moved */
- if(H5AC_move_entry(f, H5AC_FHEAP_DBLOCK, hdr->man_dtable.table_addr, addr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move direct block")
+ /* Sanity check */
+ HDassert(H5F_addr_eq(hdr->man_dtable.table_addr, addr));
+ HDassert(hdr->pline_root_direct_size > 0);
- /* Update information about direct block's location */
- hdr->man_dtable.table_addr = addr;
+ /* Check if the filter mask changed */
+ if(hdr->pline_root_direct_filter_mask != filter_mask) {
+ hdr->pline_root_direct_filter_mask = filter_mask;
+ hdr_changed = TRUE;
+ } /* end if */
+
+ /* verify that the cache's last record of the compressed
+ * size matches the heap's last record. This value will
+ * likely change shortly.
+ */
+ HDassert(compressed_len == hdr->pline_root_direct_size);
- /* Mark that heap header was modified */
- if(H5HF_hdr_dirty(hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
+ /* Check if we need to re-size the block on disk */
+ if(hdr->pline_root_direct_size != write_size || at_tmp_addr) {
+ /* Check if the direct block is NOT currently allocated
+ * in temp. file space
+ *
+ * (temp. file space does not need to be freed)
+ */
+ if(!at_tmp_addr) {
+ /* Release direct block's current disk space */
+ if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, addr, (hsize_t)hdr->pline_root_direct_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
} /* end if */
- else {
- H5HF_indirect_t *par_iblock; /* Parent indirect block */
- unsigned par_entry; /* Entry in parent indirect block */
- /* Get parent information */
- par_iblock = dblock->parent;
- par_entry = dblock->par_entry;
+ /* Allocate space for the compressed direct block */
+ if(HADDR_UNDEF == (dblock_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)write_size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
- /* Sanity check */
- HDassert(H5F_addr_eq(par_iblock->ents[par_entry].addr, addr));
+ /* Let the metadata cache know, if the block moved */
+ if(!H5F_addr_eq(hdr->man_dtable.table_addr, dblock_addr))
+ if(H5AC_move_entry((H5F_t *)f, H5AC_FHEAP_DBLOCK, hdr->man_dtable.table_addr, dblock_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move direct block")
- /* Allocate 'normal' space for the direct block */
- if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)write_size)))
- HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
+ /* Update information about compressed direct block's
+ * location & size
+ */
+ HDassert(hdr->man_dtable.table_addr == addr);
+ HDassert(hdr->pline_root_direct_size == compressed_len);
+ hdr->man_dtable.table_addr = dblock_addr;
+ hdr->pline_root_direct_size = write_size;
- /* Sanity check */
- HDassert(!H5F_addr_eq(par_iblock->ents[par_entry].addr, addr));
+ /* Note that heap header was modified */
+ hdr_changed = TRUE;
+ } /* end if */
+
+ /* Check if heap header was modified */
+ if(hdr_changed)
+ if(H5HF_hdr_dirty(hdr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
+ } /* end if */
+ else { /* the direct block's parent is an indirect block */
+ hbool_t par_changed = FALSE; /* Whether the parent's infochanged */
- /* Let the metadata cache know the block moved */
- if(H5AC_move_entry(f, H5AC_FHEAP_DBLOCK, par_iblock->ents[par_entry].addr, addr) < 0)
+ /* Sanity check */
+ HDassert(par_iblock);
+ HDassert(par_iblock->filt_ents[par_entry].size > 0);
+
+ /* Check if the filter mask changed */
+ if(par_iblock->filt_ents[par_entry].filter_mask != filter_mask) {
+ par_iblock->filt_ents[par_entry].filter_mask = filter_mask;
+ par_changed = TRUE;
+ } /* end if */
+
+ /* verify that the cache's last record of the compressed
+ * size matches the heap's last record. This value will
+ * likely change shortly.
+ */
+ HDassert(compressed_len == par_iblock->filt_ents[par_entry].size);
+
+ /* Check if we need to re-size the block on disk */
+ if(par_iblock->filt_ents[par_entry].size != write_size || at_tmp_addr) {
+ /* Check if the direct block is NOT currently allocated
+ * in temp. file space
+ *
+ * (temp. file space does not need to be freed)
+ */
+ if(!at_tmp_addr) {
+ /* Release direct block's current disk space */
+ if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, addr, (hsize_t)par_iblock->filt_ents[par_entry].size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
+ } /* end if */
+
+ /* Allocate space for the compressed direct block */
+ if(HADDR_UNDEF == (dblock_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)write_size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
+
+ /* Let the metadata cache know, if the block moved */
+ if(!H5F_addr_eq(par_iblock->ents[par_entry].addr, dblock_addr))
+ if(H5AC_move_entry((H5F_t *)f, H5AC_FHEAP_DBLOCK, par_iblock->ents[par_entry].addr, dblock_addr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move direct block")
- /* Update information about direct block's location */
- par_iblock->ents[par_entry].addr = addr;
+ /* Update information about compressed direct block's
+ * location & size
+ */
+ HDassert(par_iblock->ents[par_entry].addr == addr);
+ HDassert(par_iblock->filt_ents[par_entry].size == compressed_len);
+ par_iblock->ents[par_entry].addr = dblock_addr;
+ par_iblock->filt_ents[par_entry].size = write_size;
- /* Mark that parent was modified */
- if(H5HF_iblock_dirty(par_iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
- } /* end else */
+ /* Note that parent was modified */
+ par_changed = TRUE;
} /* end if */
+
+ /* Check if parent was modified */
+ if(par_changed)
+ if(H5HF_iblock_dirty(par_iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
} /* end else */
+ } /* end if */
+ else {
+ /* I/O filters are not enabled -- thus all we need to do is check to
+ * see if the direct block is in temporary (AKA imaginary) file
+ * space, and move it to real file space if it is.
+ *
+ * As in the I/O filters case above, we will have to touch up the
+ * direct blocks parent if the direct block is relocated.
+ *
+ * Recall that temporary file space need not be freed, which
+ * simplifies matters slightly.
+ */
+ write_buf = dblock->blk;
+ write_size = dblock->size;
- /* Direct block must be in 'normal' file space now */
- HDassert(!H5F_IS_TMP_ADDR(f, addr));
+ /* Check to see if we must re-allocate direct block from 'temp.'
+ * to 'normal' file space
+ */
+ if(at_tmp_addr) {
+ /* Check for root direct block */
+ if(NULL == dblock->parent) {
+ /* Sanity check */
+ HDassert(H5F_addr_eq(hdr->man_dtable.table_addr, addr));
- /* Write the direct block */
- if(H5F_block_write(f, H5FD_MEM_FHEAP_DBLOCK, addr, write_size, dxpl_id, write_buf) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFLUSH, FAIL, "unable to save fractal heap direct block to disk")
+ /* Allocate 'normal' space for the direct block */
+ if(HADDR_UNDEF == (dblock_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)write_size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
- /* Release the write buffer, if it was allocated */
- if(write_buf != dblock->blk)
- H5MM_xfree(write_buf);
+ /* Sanity check */
+ HDassert(!H5F_addr_eq(hdr->man_dtable.table_addr, dblock_addr));
- dblock->cache_info.is_dirty = FALSE;
- } /* end if */
+ /* Let the metadata cache know the block moved */
+ if(H5AC_move_entry((H5F_t *)f, H5AC_FHEAP_DBLOCK, hdr->man_dtable.table_addr, dblock_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move direct block")
- if(destroy)
- if(H5HF_cache_dblock_dest(f, dblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap direct block")
+ /* Update information about direct block's location */
+ hdr->man_dtable.table_addr = dblock_addr;
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HF_cache_dblock_flush() */
+ /* Mark that heap header was modified */
+ if(H5HF_hdr_dirty(hdr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
+ } /* end if */
+ else { /* the direct block's parent is an indirect block */
+ /* Sanity check */
+ HDassert(par_iblock);
+ HDassert(H5F_addr_eq(par_iblock->ents[par_entry].addr, addr));
-
-/*-------------------------------------------------------------------------
- * 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
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HF_cache_dblock_dest(H5F_t *f, H5HF_direct_t *dblock)
-{
- herr_t ret_value = SUCCEED; /* Return value */
+ /* Allocate 'normal' space for the direct block */
+ if(HADDR_UNDEF == (dblock_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)write_size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
- FUNC_ENTER_NOAPI_NOINIT
+ /* Sanity check */
+ HDassert(!H5F_addr_eq(par_iblock->ents[par_entry].addr, dblock_addr));
- /*
- * Check arguments.
- */
- HDassert(dblock);
+ /* Let the metadata cache know the block moved */
+ if(H5AC_move_entry((H5F_t *)f, H5AC_FHEAP_DBLOCK, par_iblock->ents[par_entry].addr, dblock_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move direct block")
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!dblock->cache_info.free_file_space_on_destroy || H5F_addr_defined(dblock->cache_info.addr));
+ /* Update information about direct block's location */
+ par_iblock->ents[par_entry].addr = dblock_addr;
- /* Check for freeing file space for direct block */
- if(dblock->cache_info.free_file_space_on_destroy) {
- /* Sanity check */
- HDassert(dblock->file_size > 0);
-
- /* Check if the direct block is NOT currently allocated in temp. file space */
- /* (temp. file space does not need to be freed) */
- if(!H5F_IS_TMP_ADDR(f, dblock->cache_info.addr)) {
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, H5AC_dxpl_id, dblock->cache_info.addr, dblock->file_size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
+ /* Mark that parent was modified */
+ if(H5HF_iblock_dirty(par_iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
+ } /* end else */
} /* end if */
+ } /* end else */
+
+ /* At this point, write_buf points to a buffer containing the image
+ * of the direct block that is ready to copy into the image buffer,
+ * and write_size contains the length of this buffer.
+ *
+ * Also, if image size or address has changed, the direct block's
+ * parent has been modified to reflect the change.
+ *
+ * Now, make note of the pointer and length of the above buffer for
+ * use by the serialize function.
+ */
+ dblock->write_buf = (uint8_t *)write_buf;
+ dblock->write_size = write_size;
+
+ /* finally, pass data back to the metadata cache as appropriate */
+ if(!H5F_addr_eq(addr, dblock_addr)) {
+ dblock_flags |= H5C__SERIALIZE_MOVED_FLAG;
+ *new_addr = dblock_addr;
} /* end if */
- /* Destroy fractal heap direct block */
- if(H5HF_man_dblock_dest(dblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap direct block")
+ if((hdr->filter_len > 0) && (compressed_len != write_size)) {
+ dblock_flags |= H5C__SERIALIZE_COMPRESSED_FLAG;
+ *new_compressed_len = write_size;
+ } /* end if */
+
+ *flags = dblock_flags;
+
+ /* final sanity check */
+ HDassert(dblock->write_buf);
+ HDassert(dblock->write_size > 0);
done:
+ /* discard the write buf if we have an error */
+ if(write_buf && (write_buf != dblock->blk) && (dblock->write_buf == NULL))
+ H5MM_xfree(write_buf);
+
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_cache_dblock_dest() */
+} /* end H5HF__cache_dblock_pre_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_dblock_clear
+ * Function: H5HF__cache_dblock_serialize
*
- * Purpose: Mark a fractal heap direct block in memory as non-dirty.
+ * Purpose: In principle, this function is supposed to construct the on
+ * disk image of the direct block, and place that image in the
+ * image buffer provided by the metadata cache.
*
- * Return: Non-negative on success/Negative on failure
+ * However, since there are cases in which the pre_serialize
+ * function has to construct the on disk image to determine its size
+ * and address, this function simply copies the image prepared by
+ * the pre-serialize function into the supplied image buffer, and
+ * discards a buffer if necessary.
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 27 2006
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_dblock_clear(H5F_t *f, H5HF_direct_t *dblock, hbool_t destroy)
+static herr_t
+H5HF__cache_dblock_serialize(const H5F_t *f, void *image, size_t len,
+ void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5HF_direct_t *dblock = (H5HF_direct_t *)_thing; /* Direct block info */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_NOERR
- /*
- * Check arguments.
- */
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(image);
+ HDassert(len > 0);
HDassert(dblock);
+ HDassert(dblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(dblock->cache_info.type == H5AC_FHEAP_DBLOCK);
+ HDassert((dblock->blk != dblock->write_buf) || (dblock->cache_info.size == dblock->size));
+ HDassert(dblock->write_buf);
+ HDassert(dblock->write_size > 0);
+ HDassert((dblock->blk != dblock->write_buf) || (dblock->write_size == dblock->size));
+ HDassert(dblock->write_size == len);
+
+ /* Copy the image from *(dblock->write_buf) to *image */
+ HDmemcpy(image, dblock->write_buf, dblock->write_size);
+
+ /* Free *(dblock->write_buf) if it was allocated by the
+ * pre-serialize function
+ */
+ if(dblock->write_buf != dblock->blk)
+ H5MM_xfree(dblock->write_buf);
- /* 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")
+ /* Reset the write_buf and write_size fields */
+ dblock->write_buf = NULL;
+ dblock->write_size = 0;
-done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_cache_dblock_clear() */
+} /* end H5HF__cache_dblock_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_dblock_notify
+ * Function: H5HF__cache_dblock_notify
*
* Purpose: Setup / takedown flush dependencies as direct blocks
* are loaded / inserted and evicted from the metadata cache.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
* Programmer: John Mainzer
- * 5/17/14
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_dblock_notify(H5C_notify_action_t action, H5HF_direct_t *dblock)
+static herr_t
+H5HF__cache_dblock_notify(H5C_notify_action_t action, void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5HF_direct_t *dblock = (H5HF_direct_t *)_thing; /* Fractal heap direct block */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /*
- * Check arguments.
- */
+ /* Sanity checks */
HDassert(dblock);
HDassert(dblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(dblock->cache_info.type == H5AC_FHEAP_DBLOCK);
HDassert(dblock->hdr);
HDassert((dblock->fd_parent) ||
((dblock->hdr->man_dtable.curr_root_rows == 0) && (dblock->block_off == (hsize_t)0)));
switch(action) {
case H5AC_NOTIFY_ACTION_AFTER_INSERT:
+ case H5AC_NOTIFY_ACTION_AFTER_LOAD:
HDassert(dblock->parent == dblock->fd_parent);
if(dblock->parent) { /* this is a leaf dblock */
/* create flush dependency with parent iblock */
@@ -1964,6 +2392,10 @@ H5HF_cache_dblock_notify(H5C_notify_action_t action, H5HF_direct_t *dblock)
} /* end else */
break;
+ case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
+ /* do nothing */
+ break;
+
case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
HDassert((dblock->parent == dblock->fd_parent) ||
((NULL == dblock->parent) && (dblock->fd_parent)));
@@ -1986,39 +2418,47 @@ H5HF_cache_dblock_notify(H5C_notify_action_t action, H5HF_direct_t *dblock)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_cache_dblock_notify() */
+} /* end H5HF__cache_dblock_notify() */
/*-------------------------------------------------------------------------
- * Function: H5HF_cache_dblock_size
+ * Function: H5HF__cache_dblock_free_icr
*
- * 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.
+ * Purpose: Free the in core memory allocated to the supplied direct
+ * block.
*
- * Return: Non-negative on success/Negative on failure
+ * Note: The metadata cache sets the object's cache_info.magic to
+ * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
+ * callback (checked in assert).
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Feb 24 2006
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5HF_cache_dblock_size(const H5F_t H5_ATTR_UNUSED *f, const H5HF_direct_t *dblock, size_t *size_ptr)
+static herr_t
+H5HF__cache_dblock_free_icr(void *_thing)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ H5HF_direct_t *dblock = (H5HF_direct_t *)_thing; /* Fractal heap direct block */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* check arguments */
- HDassert(dblock);
- HDassert(size_ptr);
+ FUNC_ENTER_STATIC
- /* Set size value */
- *size_ptr = dblock->size;
+ /* Sanity checks */
+ HDassert(dblock);
+ HDassert(dblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(dblock->cache_info.type == H5AC_FHEAP_DBLOCK);
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5HF_cache_dblock_size() */
+ /* Destroy fractal heap direct block */
+ if(H5HF_man_dblock_dest(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_free_icr() */
/*------------------------------------------------------------------------
@@ -2144,7 +2584,7 @@ H5HF__cache_verify_hdr_descendants_clean(H5F_t *f, hid_t dxpl_id,
* in this case, since we know that the entry is in cache,
* we can pass NULL udata.
*/
- if(NULL == (root_iblock = (H5HF_indirect_t *)H5AC_protect(f, dxpl_id, H5AC_FHEAP_IBLOCK, root_iblock_addr, NULL, H5AC_READ)))
+ if(NULL == (root_iblock = (H5HF_indirect_t *)H5AC_protect(f, dxpl_id, H5AC_FHEAP_IBLOCK, root_iblock_addr, NULL, H5C__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "H5AC_protect() faild.")
unprotect_root_iblock = TRUE;
} /* end if */
@@ -2205,7 +2645,7 @@ H5HF__cache_verify_hdr_descendants_clean(H5F_t *f, hid_t dxpl_id,
* in this case, since we know that the entry is in cache,
* we can pass NULL udata.
*/
- if(NULL == (iblock = (H5HF_indirect_t *)H5AC_protect(f, dxpl_id, H5AC_FHEAP_IBLOCK, root_iblock_addr, NULL, H5AC_READ)))
+ if(NULL == (iblock = (H5HF_indirect_t *)H5AC_protect(f, dxpl_id, H5AC_FHEAP_IBLOCK, root_iblock_addr, NULL, H5C__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "H5AC_protect() faild.")
unprotect_root_iblock = TRUE;
HDassert(iblock == root_iblock);
@@ -2595,7 +3035,7 @@ H5HF__cache_verify_descendant_iblocks_clean(H5F_t *f, hid_t dxpl_id,
/* in this case, since we know that the */
/* entry is in cache, we can pass NULL udata */
- if(NULL == (child_iblock = (H5HF_indirect_t *) H5AC_protect(f, dxpl_id, H5AC_FHEAP_IBLOCK, child_iblock_addr, NULL, H5AC_READ)))
+ if(NULL == (child_iblock = (H5HF_indirect_t *) H5AC_protect(f, dxpl_id, H5AC_FHEAP_IBLOCK, child_iblock_addr, NULL, H5C__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "H5AC_protect() faild.")
unprotect_child_iblock = TRUE;
} /* end if */