#include "H5HFmodule.h"
#include "H5private.h"
#include "H5ACprivate.h"
#include "H5Eprivate.h"
#include "H5HFpkg.h"
#include "H5MFprivate.h"
#include "H5MMprivate.h"
#include "H5VMprivate.h"
#include "H5WBprivate.h"
#define H5HF_HDR_VERSION 0
#define H5HF_DBLOCK_VERSION 0
#define H5HF_IBLOCK_VERSION 0
static herr_t H5HF__hdr_prefix_decode(H5HF_hdr_t *hdr, const uint8_t **image_ref);
static herr_t H5HF__dtable_encode(H5F_t *f, uint8_t **pp, const H5HF_dtable_t *dtable);
static herr_t H5HF__dtable_decode(H5F_t *f, const uint8_t **pp, H5HF_dtable_t *dtable);
static herr_t H5HF__cache_hdr_get_initial_load_size(void *udata, size_t *image_len);
static herr_t H5HF__cache_hdr_get_final_load_size(const void *image_ptr,
size_t image_len, void *udata, size_t *actual_len);
static htri_t H5HF__cache_hdr_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
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);
static herr_t H5HF__cache_hdr_pre_serialize(H5F_t *f, void *thing, haddr_t addr,
size_t len, haddr_t *new_addr, size_t *new_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_initial_load_size(void *udata, size_t *image_len);
static htri_t H5HF__cache_iblock_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
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);
static herr_t H5HF__cache_iblock_pre_serialize(H5F_t *f, void *thing,
haddr_t addr, size_t len, haddr_t *new_addr, size_t *new_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(H5AC_notify_action_t action, void *thing);
static herr_t H5HF__cache_iblock_free_icr(void *thing);
static herr_t H5HF__cache_dblock_get_initial_load_size(void *udata, size_t *image_len);
static htri_t H5HF__cache_dblock_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
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);
static herr_t H5HF__cache_dblock_pre_serialize(H5F_t *f, void *thing, haddr_t addr,
size_t len, haddr_t *new_addr, size_t *new_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(H5AC_notify_action_t action, void *thing);
static herr_t H5HF__cache_dblock_free_icr(void *thing);
static herr_t H5HF__cache_dblock_fsf_size(const void *_thing, hsize_t *fsf_size);
#ifndef NDEBUG
static herr_t H5HF__cache_verify_hdr_descendants_clean(H5F_t *f, H5HF_hdr_t *hdr,
hbool_t *fd_clean, hbool_t *clean);
static herr_t H5HF__cache_verify_iblock_descendants_clean(H5F_t *f,
haddr_t fd_parent_addr, H5HF_indirect_t *iblock, unsigned *iblock_status,
hbool_t *fd_clean, hbool_t *clean);
static herr_t H5HF__cache_verify_iblocks_dblocks_clean(H5F_t *f,
haddr_t fd_parent_addr, H5HF_indirect_t *iblock, hbool_t *fd_clean,
hbool_t *clean, hbool_t *has_dblocks);
static herr_t H5HF__cache_verify_descendant_iblocks_clean(H5F_t *f,
haddr_t fd_parent_addr, H5HF_indirect_t *iblock,
hbool_t *fd_clean, hbool_t *clean, hbool_t *has_iblocks);
#endif
const H5AC_class_t H5AC_FHEAP_HDR[1] = {{
H5AC_FHEAP_HDR_ID,
"fractal heap header",
H5FD_MEM_FHEAP_HDR,
H5AC__CLASS_SPECULATIVE_LOAD_FLAG,
H5HF__cache_hdr_get_initial_load_size,
H5HF__cache_hdr_get_final_load_size,
H5HF__cache_hdr_verify_chksum,
H5HF__cache_hdr_deserialize,
H5HF__cache_hdr_image_len,
H5HF__cache_hdr_pre_serialize,
H5HF__cache_hdr_serialize,
NULL,
H5HF__cache_hdr_free_icr,
NULL,
}};
const H5AC_class_t H5AC_FHEAP_IBLOCK[1] = {{
H5AC_FHEAP_IBLOCK_ID,
"fractal heap indirect block",
H5FD_MEM_FHEAP_IBLOCK,
H5AC__CLASS_NO_FLAGS_SET,
H5HF__cache_iblock_get_initial_load_size,
NULL,
H5HF__cache_iblock_verify_chksum,
H5HF__cache_iblock_deserialize,
H5HF__cache_iblock_image_len,
H5HF__cache_iblock_pre_serialize,
H5HF__cache_iblock_serialize,
H5HF__cache_iblock_notify,
H5HF__cache_iblock_free_icr,
NULL,
}};
const H5AC_class_t H5AC_FHEAP_DBLOCK[1] = {{
H5AC_FHEAP_DBLOCK_ID,
"fractal heap direct block",
H5FD_MEM_FHEAP_DBLOCK,
H5AC__CLASS_NO_FLAGS_SET,
H5HF__cache_dblock_get_initial_load_size,
NULL,
H5HF__cache_dblock_verify_chksum,
H5HF__cache_dblock_deserialize,
H5HF__cache_dblock_image_len,
H5HF__cache_dblock_pre_serialize,
H5HF__cache_dblock_serialize,
H5HF__cache_dblock_notify,
H5HF__cache_dblock_free_icr,
H5HF__cache_dblock_fsf_size,
}};
H5FL_BLK_DEFINE(direct_block);
static herr_t
H5HF__hdr_prefix_decode(H5HF_hdr_t *hdr, const uint8_t **image_ref)
{
const uint8_t *image = *image_ref;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(hdr);
HDassert(image);
if(HDmemcmp(image, H5HF_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "wrong fractal heap header signature")
image += H5_SIZEOF_MAGIC;
if(*image++ != H5HF_HDR_VERSION)
HGOTO_ERROR(H5E_HEAP, H5E_VERSION, FAIL, "wrong fractal heap header version")
UINT16DECODE(image, hdr->id_len);
UINT16DECODE(image, hdr->filter_len);
*image_ref = image;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__dtable_decode(H5F_t *f, const uint8_t **pp, H5HF_dtable_t *dtable)
{
FUNC_ENTER_STATIC_NOERR
HDassert(f);
HDassert(pp && *pp);
HDassert(dtable);
UINT16DECODE(*pp, dtable->cparam.width);
H5F_DECODE_LENGTH(f, *pp, dtable->cparam.start_block_size);
H5F_DECODE_LENGTH(f, *pp, dtable->cparam.max_direct_size);
UINT16DECODE(*pp, dtable->cparam.max_index);
UINT16DECODE(*pp, dtable->cparam.start_root_rows);
H5F_addr_decode(f, pp, &(dtable->table_addr));
UINT16DECODE(*pp, dtable->curr_root_rows);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5HF__dtable_encode(H5F_t *f, uint8_t **pp, const H5HF_dtable_t *dtable)
{
FUNC_ENTER_STATIC_NOERR
HDassert(f);
HDassert(pp && *pp);
HDassert(dtable);
UINT16ENCODE(*pp, dtable->cparam.width);
H5F_ENCODE_LENGTH(f, *pp, dtable->cparam.start_block_size);
H5F_ENCODE_LENGTH(f, *pp, dtable->cparam.max_direct_size);
UINT16ENCODE(*pp, dtable->cparam.max_index);
UINT16ENCODE(*pp, dtable->cparam.start_root_rows);
H5F_addr_encode(f, pp, dtable->table_addr);
UINT16ENCODE(*pp, dtable->curr_root_rows);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5HF__cache_hdr_get_initial_load_size(void *_udata, size_t *image_len)
{
H5HF_hdr_cache_ud_t *udata = (H5HF_hdr_cache_ud_t *)_udata;
H5HF_hdr_t dummy_hdr;
FUNC_ENTER_STATIC_NOERR
HDassert(udata);
HDassert(image_len);
dummy_hdr.f = udata->f;
dummy_hdr.sizeof_size = H5F_SIZEOF_SIZE(udata->f);
dummy_hdr.sizeof_addr = H5F_SIZEOF_ADDR(udata->f);
*image_len = (size_t)H5HF_HEADER_SIZE(&dummy_hdr);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5HF__cache_hdr_get_final_load_size(const void *_image, size_t H5_ATTR_NDEBUG_UNUSED image_len,
void *_udata, size_t *actual_len)
{
H5HF_hdr_t hdr;
const uint8_t *image = (const uint8_t *)_image;
H5HF_hdr_cache_ud_t *udata = (H5HF_hdr_cache_ud_t *)_udata;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(image);
HDassert(udata);
HDassert(actual_len);
HDassert(*actual_len == image_len);
if(H5HF__hdr_prefix_decode(&hdr, &image) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDECODE, FAIL, "can't decode fractal heap header prefix")
if(hdr.filter_len > 0)
*actual_len += (size_t)(H5F_SIZEOF_SIZE(udata->f)
+ (unsigned)4
+ hdr.filter_len);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static htri_t
H5HF__cache_hdr_verify_chksum(const void *_image, size_t len, void H5_ATTR_UNUSED *_udata)
{
const uint8_t *image = (const uint8_t *)_image;
uint32_t stored_chksum;
uint32_t computed_chksum;
htri_t ret_value = TRUE;
FUNC_ENTER_STATIC_NOERR
HDassert(image);
H5F_get_checksums(image, len, &stored_chksum, &computed_chksum);
if(stored_chksum != computed_chksum)
ret_value = FALSE;
FUNC_LEAVE_NOAPI(ret_value)
}
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;
H5HF_hdr_cache_ud_t *udata = (H5HF_hdr_cache_ud_t *)_udata;
const uint8_t *image = (const uint8_t *)_image;
uint32_t stored_chksum;
uint8_t heap_flags;
void * ret_value = NULL;
FUNC_ENTER_STATIC
HDassert(image);
HDassert(len > 0);
HDassert(udata);
HDassert(dirty);
if(NULL == (hdr = H5HF_hdr_alloc(udata->f)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
if(H5HF__hdr_prefix_decode(hdr, &image) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDECODE, NULL, "can't decode fractal heap header prefix")
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;
UINT32DECODE(image, hdr->max_man_size);
H5F_DECODE_LENGTH(udata->f, image, hdr->huge_next_id);
H5F_addr_decode(udata->f, &image, &hdr->huge_bt2_addr);
H5F_DECODE_LENGTH(udata->f, image, hdr->total_man_free);
H5F_addr_decode(udata->f, &image, &hdr->fs_addr);
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);
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")
hdr->heap_size = (size_t)H5HF_HEADER_SIZE(hdr);
HDassert((size_t)(image - (const uint8_t *)_image) == (hdr->heap_size - H5HF_SIZEOF_CHKSUM));
if(hdr->filter_len > 0) {
H5O_pline_t *pline;
HDassert(len > hdr->heap_size);
hdr->heap_size += (size_t)(hdr->sizeof_size
+ (unsigned)4
+ hdr->filter_len);
H5F_DECODE_LENGTH(udata->f, image, hdr->pline_root_direct_size);
UINT32DECODE(image, hdr->pline_root_direct_filter_mask);
if(NULL == (pline = (H5O_pline_t *)H5O_msg_decode(hdr->f, NULL, H5O_PLINE_ID, len, image)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTDECODE, NULL, "can't decode I/O pipeline filters")
image += hdr->filter_len;
if(NULL == H5O_msg_copy(H5O_PLINE_ID, pline, &(hdr->pline)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTCOPY, NULL, "can't copy I/O filter pipeline")
H5O_msg_free(H5O_PLINE_ID, pline);
}
UINT32DECODE(image, stored_chksum);
HDassert((size_t)(image - (const uint8_t *)_image) == hdr->heap_size);
if(H5HF_hdr_finish_init(hdr) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, NULL, "can't finish initializing shared fractal heap header")
ret_value = (void *)hdr;
done:
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)
}
static herr_t
H5HF__cache_hdr_image_len(const void *_thing, size_t *image_len)
{
const H5HF_hdr_t *hdr = (const H5HF_hdr_t *)_thing;
FUNC_ENTER_STATIC_NOERR
HDassert(hdr);
HDassert(hdr->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(hdr->cache_info.type == H5AC_FHEAP_HDR);
HDassert(image_len);
*image_len = hdr->heap_size;
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5HF__cache_hdr_pre_serialize(H5F_t *f, void *_thing, haddr_t addr, size_t len,
haddr_t H5_ATTR_UNUSED *new_addr, size_t H5_ATTR_UNUSED *new_len,
unsigned *flags)
{
H5HF_hdr_t *hdr = (H5HF_hdr_t *)_thing;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
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);
#ifndef NDEBUG
{
hbool_t descendants_clean = TRUE;
hbool_t fd_children_clean = TRUE;
if(H5HF__cache_verify_hdr_descendants_clean((H5F_t *)f, hdr, &fd_children_clean, &descendants_clean) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "can't verify hdr descendants clean.")
HDassert(fd_children_clean);
}
#endif
if(H5F_IS_TMP_ADDR(f, addr))
HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "addr in temporary space?!?.");
if(len != hdr->heap_size)
HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "unexpected image len.");
*flags = 0;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__cache_hdr_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_NDEBUG_UNUSED len,
void *_thing)
{
H5HF_hdr_t *hdr = (H5HF_hdr_t *)_thing;
uint8_t *image = (uint8_t *)_image;
uint8_t heap_flags;
uint32_t metadata_chksum;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(f);
HDassert(image);
HDassert(hdr);
HDassert(hdr->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(hdr->cache_info.type == H5AC_FHEAP_HDR);
HDassert(len == hdr->heap_size);
hdr->f = f;
H5MM_memcpy(image, H5HF_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
image += H5_SIZEOF_MAGIC;
*image++ = H5HF_HDR_VERSION;
UINT16ENCODE(image, hdr->id_len);
UINT16ENCODE(image, hdr->filter_len);
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;
UINT32ENCODE(image, hdr->max_man_size);
H5F_ENCODE_LENGTH(f, image, hdr->huge_next_id);
H5F_addr_encode(f, &image, hdr->huge_bt2_addr);
H5F_ENCODE_LENGTH(f, image, hdr->total_man_free);
H5F_addr_encode(f, &image, hdr->fs_addr);
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);
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")
if(hdr->filter_len > 0) {
H5F_ENCODE_LENGTH(f, image, hdr->pline_root_direct_size);
UINT32ENCODE(image, hdr->pline_root_direct_filter_mask);
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;
}
metadata_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
UINT32ENCODE(image, metadata_chksum);
HDassert((size_t)(image - (uint8_t *)_image) == len);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__cache_hdr_free_icr(void *_thing)
{
H5HF_hdr_t *hdr = (H5HF_hdr_t *)_thing;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
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);
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)
}
static herr_t
H5HF__cache_iblock_get_initial_load_size(void *_udata, size_t *image_len)
{
H5HF_iblock_cache_ud_t *udata = (H5HF_iblock_cache_ud_t *)_udata;
FUNC_ENTER_STATIC_NOERR
HDassert(udata);
HDassert(udata->par_info);
HDassert(udata->par_info->hdr);
HDassert(image_len);
*image_len = (size_t)H5HF_MAN_INDIRECT_SIZE(udata->par_info->hdr, *udata->nrows);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static htri_t
H5HF__cache_iblock_verify_chksum(const void *_image, size_t len, void H5_ATTR_UNUSED *_udata)
{
const uint8_t *image = (const uint8_t *)_image;
uint32_t stored_chksum;
uint32_t computed_chksum;
htri_t ret_value = TRUE;
FUNC_ENTER_STATIC_NOERR
HDassert(image);
H5F_get_checksums(image, len, &stored_chksum, &computed_chksum);
if(stored_chksum != computed_chksum)
ret_value = FALSE;
FUNC_LEAVE_NOAPI(ret_value)
}
static void *
H5HF__cache_iblock_deserialize(const void *_image, size_t H5_ATTR_NDEBUG_UNUSED len,
void *_udata, hbool_t H5_ATTR_UNUSED *dirty)
{
H5HF_hdr_t *hdr;
H5HF_iblock_cache_ud_t *udata = (H5HF_iblock_cache_ud_t *)_udata;
H5HF_indirect_t *iblock = NULL;
const uint8_t *image = (const uint8_t *)_image;
haddr_t heap_addr;
uint32_t stored_chksum;
unsigned u;
void * ret_value = NULL;
FUNC_ENTER_STATIC
HDassert(image);
HDassert(udata);
HDassert(dirty);
hdr = udata->par_info->hdr;
HDassert(hdr->f);
hdr->f = udata->f;
if(NULL == (iblock = H5FL_CALLOC(H5HF_indirect_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
iblock->hdr = hdr;
if(H5HF_hdr_incr(hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared heap header")
iblock->rc = 0;
iblock->nrows = *udata->nrows;
iblock->nchildren = 0;
iblock->size = H5HF_MAN_INDIRECT_SIZE(hdr, iblock->nrows);
HDassert(iblock->size == len);
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;
if(*image++ != H5HF_IBLOCK_VERSION)
HGOTO_ERROR(H5E_HEAP, H5E_VERSION, NULL, "wrong fractal heap direct block version")
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")
iblock->parent = udata->par_info->iblock;
if(udata->par_info->iblock)
iblock->fd_parent = udata->par_info->iblock;
else
iblock->fd_parent = udata->par_info->hdr;
iblock->par_entry = udata->par_info->entry;
if(iblock->parent) {
if(H5HF_iblock_incr(iblock->parent) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block")
iblock->max_rows = iblock->nrows;
}
else {
iblock->max_rows = hdr->man_dtable.max_root_rows;
}
UINT64DECODE_VAR(image, iblock->block_off, hdr->heap_off_size);
HDassert(iblock->nrows > 0);
if(NULL == (iblock->ents = H5FL_SEQ_MALLOC(H5HF_indirect_ent_t, (size_t)(iblock->nrows * hdr->man_dtable.cparam.width))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for direct entries")
if(hdr->filter_len > 0) {
unsigned dir_rows;
dir_rows = MIN(iblock->nrows, hdr->man_dtable.max_direct_rows);
if(NULL == (iblock->filt_ents = H5FL_SEQ_MALLOC(H5HF_indirect_filt_ent_t, (size_t)(dir_rows * hdr->man_dtable.cparam.width))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for block entries")
}
else
iblock->filt_ents = NULL;
for(u = 0; u < (iblock->nrows * hdr->man_dtable.cparam.width); u++) {
H5F_addr_decode(udata->f, &image, &(iblock->ents[u].addr));
if(hdr->filter_len > 0) {
HDassert(iblock->filt_ents);
if(u < (hdr->man_dtable.max_direct_rows * hdr->man_dtable.cparam.width)) {
H5F_DECODE_LENGTH(udata->f, image, iblock->filt_ents[u].size);
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));
UINT32DECODE(image, iblock->filt_ents[u].filter_mask);
}
}
if(H5F_addr_defined(iblock->ents[u].addr)) {
iblock->nchildren++;
iblock->max_child = u;
}
}
HDassert(iblock->nchildren);
UINT32DECODE(image, stored_chksum);
HDassert((size_t)(image - (const uint8_t *)_image) == iblock->size);
if(iblock->nrows > hdr->man_dtable.max_direct_rows) {
unsigned indir_rows;
indir_rows = iblock->nrows - hdr->man_dtable.max_direct_rows;
if(NULL == (iblock->child_iblocks = H5FL_SEQ_CALLOC(H5HF_indirect_ptr_t, (size_t)(indir_rows * hdr->man_dtable.cparam.width))))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "memory allocation failed for block entries")
}
else
iblock->child_iblocks = NULL;
ret_value = (void *)iblock;
done:
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)
}
static herr_t
H5HF__cache_iblock_image_len(const void *_thing, size_t *image_len)
{
const H5HF_indirect_t *iblock = (const H5HF_indirect_t *)_thing;
FUNC_ENTER_STATIC_NOERR
HDassert(iblock);
HDassert(iblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(iblock->cache_info.type == H5AC_FHEAP_IBLOCK);
HDassert(image_len);
*image_len = iblock->size;
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5HF__cache_iblock_pre_serialize(H5F_t *f, void *_thing, haddr_t addr,
size_t H5_ATTR_UNUSED len, haddr_t *new_addr, size_t H5_ATTR_UNUSED *new_len,
unsigned *flags)
{
H5HF_hdr_t *hdr;
H5HF_indirect_t *iblock = (H5HF_indirect_t *)_thing;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
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
{
hbool_t descendants_clean = TRUE;
hbool_t fd_children_clean = TRUE;
unsigned iblock_status = 0;
if(H5AC_get_entry_status(f, iblock->addr, &iblock_status) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get iblock status")
if(H5HF__cache_verify_iblock_descendants_clean((H5F_t *)f, iblock->addr, iblock, &iblock_status, &fd_children_clean, &descendants_clean) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "can't verify descendants clean.")
HDassert(fd_children_clean);
}
#endif
if(H5F_IS_TMP_ADDR(f, addr)) {
haddr_t iblock_addr;
if(HADDR_UNDEF == (iblock_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FHEAP_IBLOCK, (hsize_t)iblock->size)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap indirect block")
HDassert(!H5F_addr_eq(iblock->addr, iblock_addr));
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")
iblock->addr = iblock_addr;
if(NULL == iblock->parent) {
hdr->man_dtable.table_addr = iblock_addr;
if(H5HF_hdr_dirty(hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
}
else {
H5HF_indirect_t *par_iblock;
unsigned par_entry;
par_iblock = iblock->parent;
par_entry = iblock->par_entry;
par_iblock->ents[par_entry].addr = iblock_addr;
if(H5HF_iblock_dirty(par_iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
}
*new_addr = iblock_addr;
*flags = H5AC__SERIALIZE_MOVED_FLAG;
}
else
*flags = 0;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__cache_iblock_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_NDEBUG_UNUSED len,
void *_thing)
{
H5HF_hdr_t *hdr;
H5HF_indirect_t *iblock = (H5HF_indirect_t *)_thing;
uint8_t *image = (uint8_t *)_image;
#ifndef NDEBUG
unsigned nchildren = 0;
size_t max_child = 0;
#endif
uint32_t metadata_chksum;
size_t u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC_NOERR
HDassert(f);
HDassert(image);
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(len == iblock->size);
HDassert(!H5F_IS_TMP_ADDR(f, iblock->addr));
HDassert(H5F_addr_eq(iblock->addr, iblock->cache_info.addr));
hdr = iblock->hdr;
hdr->f = f;
H5MM_memcpy(image, H5HF_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
image += H5_SIZEOF_MAGIC;
*image++ = H5HF_IBLOCK_VERSION;
H5F_addr_encode(f, &image, hdr->heap_addr);
UINT64ENCODE_VAR(image, iblock->block_off, hdr->heap_off_size);
for(u = 0; u < (iblock->nrows * hdr->man_dtable.cparam.width); u++) {
H5F_addr_encode(f, &image, iblock->ents[u].addr);
if(hdr->filter_len > 0) {
HDassert(iblock->filt_ents);
if(u < (hdr->man_dtable.max_direct_rows * hdr->man_dtable.cparam.width)) {
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));
H5F_ENCODE_LENGTH(f, image, iblock->filt_ents[u].size);
UINT32ENCODE(image, iblock->filt_ents[u].filter_mask);
}
}
#ifndef NDEBUG
if(H5F_addr_defined(iblock->ents[u].addr)) {
nchildren++;
if(u > max_child)
max_child = u;
}
#endif
}
metadata_chksum = H5_checksum_metadata((uint8_t *)_image, (size_t)(image - (uint8_t *)_image), 0);
UINT32ENCODE(image, metadata_chksum);
HDassert((size_t)(image - (uint8_t *)_image) == iblock->size);
#ifndef NDEBUG
HDassert(nchildren == iblock->nchildren);
HDassert(max_child == iblock->max_child);
#endif
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__cache_iblock_notify(H5AC_notify_action_t action, void *_thing)
{
H5HF_indirect_t *iblock = (H5HF_indirect_t *)_thing;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
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(iblock->parent == NULL) {
if((iblock->block_off == 0) && (iblock->hdr->root_iblock_flags & H5HF_ROOT_IBLOCK_PINNED))
HDassert(iblock->hdr->root_iblock == iblock);
}
else {
H5HF_indirect_t H5_ATTR_NDEBUG_UNUSED *par_iblock = iblock->parent;
unsigned H5_ATTR_NDEBUG_UNUSED indir_idx;
HDassert(par_iblock->child_iblocks);
HDassert(iblock->par_entry >= (iblock->hdr->man_dtable.max_direct_rows * iblock->hdr->man_dtable.cparam.width));
indir_idx = iblock->par_entry - (iblock->hdr->man_dtable.max_direct_rows * iblock->hdr->man_dtable.cparam.width);
HDassert((NULL == par_iblock->child_iblocks[indir_idx]) || (par_iblock->child_iblocks[indir_idx] == iblock));
}
switch(action) {
case H5AC_NOTIFY_ACTION_AFTER_INSERT:
case H5AC_NOTIFY_ACTION_AFTER_LOAD:
if(iblock->fd_parent)
if(H5AC_create_flush_dependency(iblock->fd_parent, iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
break;
case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
case H5AC_NOTIFY_ACTION_ENTRY_DIRTIED:
case H5AC_NOTIFY_ACTION_ENTRY_CLEANED:
case H5AC_NOTIFY_ACTION_CHILD_DIRTIED:
case H5AC_NOTIFY_ACTION_CHILD_CLEANED:
case H5AC_NOTIFY_ACTION_CHILD_UNSERIALIZED:
case H5AC_NOTIFY_ACTION_CHILD_SERIALIZED:
break;
case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
if(iblock->fd_parent) {
if(H5AC_destroy_flush_dependency(iblock->fd_parent, iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
iblock->fd_parent = NULL;
}
break;
default:
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unknown action from metadata cache")
break;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__cache_iblock_free_icr(void *thing)
{
H5HF_indirect_t *iblock = (H5HF_indirect_t *)thing;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(iblock);
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);
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)
}
static herr_t
H5HF__cache_dblock_get_initial_load_size(void *_udata, size_t *image_len)
{
const H5HF_dblock_cache_ud_t *udata = (const H5HF_dblock_cache_ud_t *)_udata;
const H5HF_parent_t *par_info;
const H5HF_hdr_t *hdr;
FUNC_ENTER_STATIC_NOERR
HDassert(udata);
HDassert(image_len);
par_info = (const H5HF_parent_t *)(&(udata->par_info));
HDassert(par_info);
hdr = par_info->hdr;
HDassert(hdr);
if(hdr->filter_len > 0) {
if(par_info->iblock == NULL)
*image_len = hdr->pline_root_direct_size;
else
*image_len = par_info->iblock->filt_ents[par_info->entry].size;
}
else
*image_len = udata->dblock_size;
FUNC_LEAVE_NOAPI(SUCCEED)
}
static htri_t
H5HF__cache_dblock_verify_chksum(const void *_image, size_t len, void *_udata)
{
const uint8_t *image = (const uint8_t *)_image;
H5HF_dblock_cache_ud_t *udata = (H5HF_dblock_cache_ud_t *)_udata;
void *read_buf = NULL;
H5HF_hdr_t *hdr;
H5HF_parent_t *par_info;
uint32_t stored_chksum;
uint32_t computed_chksum;
size_t chk_size;
uint8_t *chk_p;
htri_t ret_value = TRUE;
FUNC_ENTER_STATIC
HDassert(image);
HDassert(udata);
par_info = (H5HF_parent_t *)(&(udata->par_info));
HDassert(par_info);
hdr = par_info->hdr;
HDassert(hdr);
if(!(hdr->checksum_dblocks))
HGOTO_DONE(TRUE);
if(hdr->filter_len > 0) {
size_t nbytes;
unsigned filter_mask;
H5Z_cb_t filter_cb;
filter_cb.op_data = NULL;
filter_cb.func = NULL;
if(NULL == (read_buf = H5MM_malloc(len)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "memory allocation failed for pipeline buffer")
nbytes = len;
filter_mask = udata->filter_mask;
H5MM_memcpy(read_buf, image, len);
if(H5Z_pipeline(&(hdr->pline), H5Z_FLAG_REVERSE, &filter_mask, H5Z_ENABLE_EDC, filter_cb, &nbytes, &len, &read_buf) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTFILTER, FAIL, "output pipeline failed")
udata->decompressed = TRUE;
len = nbytes;
}
else
read_buf = (void *)image;
chk_size = (size_t)(H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr) - H5HF_SIZEOF_CHKSUM);
chk_p = (uint8_t *)read_buf + chk_size;
UINT32DECODE(chk_p, stored_chksum);
chk_p -= H5HF_SIZEOF_CHKSUM;
HDmemset(chk_p, 0, (size_t)H5HF_SIZEOF_CHKSUM);
computed_chksum = H5_checksum_metadata(read_buf, len, 0);
UINT32ENCODE(chk_p, stored_chksum)
if(stored_chksum != computed_chksum)
HGOTO_DONE(FALSE);
if(hdr->filter_len > 0) {
HDassert(udata->decompressed);
HDassert(len == udata->dblock_size);
if(NULL == (udata->dblk = H5FL_BLK_MALLOC(direct_block, (size_t)len)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
H5MM_memcpy(udata->dblk, read_buf, len);
}
done:
if(read_buf && read_buf != image)
H5MM_xfree(read_buf);
FUNC_LEAVE_NOAPI(ret_value)
}
static void *
H5HF__cache_dblock_deserialize(const void *_image, size_t len, void *_udata,
hbool_t H5_ATTR_UNUSED *dirty)
{
H5HF_hdr_t *hdr;
H5HF_dblock_cache_ud_t *udata = (H5HF_dblock_cache_ud_t *)_udata;
H5HF_parent_t *par_info;
H5HF_direct_t *dblock = NULL;
const uint8_t *image = (const uint8_t *)_image;
void *read_buf = NULL;
haddr_t heap_addr;
void * ret_value = NULL;
FUNC_ENTER_STATIC
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);
if(NULL == (dblock = H5FL_CALLOC(H5HF_direct_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
HDmemset(&dblock->cache_info, 0, sizeof(H5AC_info_t));
hdr->f = udata->f;
dblock->hdr = hdr;
if(H5HF_hdr_incr(hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared heap header")
dblock->size = udata->dblock_size;
if(hdr->filter_len > 0) {
if(udata->decompressed) {
HDassert(udata->dblk);
dblock->blk = udata->dblk;
udata->dblk = NULL;
}
else {
H5Z_cb_t filter_cb;
size_t nbytes;
unsigned filter_mask;
HDassert(udata->dblk == NULL);
filter_cb.op_data = NULL;
filter_cb.func = NULL;
if (NULL == (read_buf = H5MM_malloc(len)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "memory allocation failed for pipeline buffer")
H5MM_memcpy(read_buf, image, len);
nbytes = len;
filter_mask = udata->filter_mask;
if (H5Z_pipeline(&(hdr->pline), H5Z_FLAG_REVERSE, &filter_mask, H5Z_ENABLE_EDC, filter_cb, &nbytes, &len, &read_buf) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTFILTER, NULL, "output pipeline failed")
HDassert(nbytes == dblock->size);
H5MM_memcpy(dblock->blk, read_buf, dblock->size);
}
}
else {
HDassert(udata->dblk == NULL);
HDassert(!udata->decompressed);
if (NULL == (dblock->blk = H5FL_BLK_MALLOC(direct_block, (size_t)dblock->size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
HDassert(dblock->size == len);
H5MM_memcpy(dblock->blk, image, dblock->size);
}
image = dblock->blk;
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;
if(*image++ != H5HF_DBLOCK_VERSION)
HGOTO_ERROR(H5E_HEAP, H5E_VERSION, NULL, "wrong fractal heap direct block version")
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")
dblock->parent = par_info->iblock;
if(par_info->iblock)
dblock->fd_parent = par_info->iblock;
else
dblock->fd_parent = par_info->hdr;
dblock->par_entry = par_info->entry;
if(dblock->parent) {
if(H5HF_iblock_incr(dblock->parent) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block")
}
UINT64DECODE_VAR(image, dblock->block_off, hdr->heap_off_size);
if(hdr->checksum_dblocks) {
uint32_t stored_chksum;
UINT32DECODE(image, stored_chksum);
}
HDassert((size_t)(image - dblock->blk) == (size_t)H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr));
ret_value = (void *)dblock;
done:
if(read_buf)
H5MM_xfree(read_buf);
if(!ret_value && dblock)
if(H5HF_man_dblock_dest(dblock) < 0)
HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy fractal heap direct block")
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__cache_dblock_image_len(const void *_thing, size_t *image_len)
{
const H5HF_direct_t *dblock = (const H5HF_direct_t *)_thing;
const H5HF_hdr_t *hdr;
size_t size;
FUNC_ENTER_STATIC_NOERR
HDassert(dblock);
HDassert(dblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(dblock->cache_info.type == H5AC_FHEAP_DBLOCK);
HDassert(image_len);
hdr = dblock->hdr;
HDassert(hdr);
if(hdr->filter_len > 0) {
if(dblock->file_size != 0)
size = dblock->file_size;
else {
const H5HF_indirect_t *par_iblock = dblock->parent;
if(par_iblock)
size = par_iblock->filt_ents[dblock->par_entry].size;
else
size = hdr->pline_root_direct_size;
if(size == 0)
size = dblock->size;
}
}
else
size = dblock->size;
HDassert(size > 0);
*image_len = size;
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5HF__cache_dblock_pre_serialize(H5F_t *f, void *_thing,
haddr_t addr, size_t len, haddr_t *new_addr, size_t *new_len, unsigned *flags)
{
hbool_t at_tmp_addr;
haddr_t dblock_addr;
H5HF_hdr_t *hdr;
H5HF_direct_t *dblock = (H5HF_direct_t *)_thing;
H5HF_indirect_t *par_iblock;
unsigned par_entry = 0;
void *write_buf;
size_t write_size;
uint8_t *image;
unsigned dblock_flags = 0;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
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(new_addr);
HDassert(new_len);
HDassert(flags);
hdr = dblock->hdr;
dblock_addr = addr;
hdr->f = (H5F_t *)f;
HDassert(hdr);
HDassert(hdr->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(hdr->cache_info.type == H5AC_FHEAP_HDR);
if(dblock->parent) {
par_iblock = dblock->parent;
par_entry = dblock->par_entry;
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));
}
else {
par_iblock = NULL;
}
at_tmp_addr = H5F_IS_TMP_ADDR(f, addr);
HDassert(dblock->blk);
image = dblock->blk;
H5MM_memcpy(image, H5HF_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
image += H5_SIZEOF_MAGIC;
*image++ = H5HF_DBLOCK_VERSION;
H5F_addr_encode(f, &image, hdr->heap_addr);
UINT64ENCODE_VAR(image, dblock->block_off, hdr->heap_off_size);
if(hdr->checksum_dblocks) {
uint32_t metadata_chksum;
HDmemset(image, 0, (size_t)H5HF_SIZEOF_CHKSUM);
metadata_chksum = H5_checksum_metadata(dblock->blk, dblock->size, 0);
UINT32ENCODE(image, metadata_chksum);
}
HDassert((size_t)(image - dblock->blk) == (size_t)H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr));
if(hdr->filter_len > 0) {
H5Z_cb_t filter_cb;
size_t nbytes;
unsigned filter_mask = 0;
filter_cb.op_data = NULL;
filter_cb.func = NULL;
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")
H5MM_memcpy(write_buf, dblock->blk, write_size);
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")
write_size = nbytes;
if(dblock->parent == NULL) {
hbool_t hdr_changed = FALSE;
HDassert(H5F_addr_eq(hdr->man_dtable.table_addr, addr));
HDassert(hdr->pline_root_direct_size > 0);
if(hdr->pline_root_direct_filter_mask != filter_mask) {
hdr->pline_root_direct_filter_mask = filter_mask;
hdr_changed = TRUE;
}
HDassert(len == hdr->pline_root_direct_size);
if(hdr->pline_root_direct_size != write_size || at_tmp_addr) {
if(!at_tmp_addr)
if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, addr, (hsize_t)hdr->pline_root_direct_size) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
if(HADDR_UNDEF == (dblock_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FHEAP_DBLOCK, (hsize_t)write_size)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
HDassert(hdr->man_dtable.table_addr == addr);
HDassert(hdr->pline_root_direct_size == len);
hdr->man_dtable.table_addr = dblock_addr;
hdr->pline_root_direct_size = write_size;
hdr_changed = TRUE;
}
if(hdr_changed)
if(H5HF_hdr_dirty(hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
}
else {
hbool_t par_changed = FALSE;
HDassert(par_iblock);
HDassert(par_iblock->filt_ents[par_entry].size > 0);
if(par_iblock->filt_ents[par_entry].filter_mask != filter_mask) {
par_iblock->filt_ents[par_entry].filter_mask = filter_mask;
par_changed = TRUE;
}
HDassert(len == par_iblock->filt_ents[par_entry].size);
if(par_iblock->filt_ents[par_entry].size != write_size || at_tmp_addr) {
if(!at_tmp_addr)
if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, 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")
if(HADDR_UNDEF == (dblock_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FHEAP_DBLOCK, (hsize_t)write_size)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
HDassert(par_iblock->ents[par_entry].addr == addr);
HDassert(par_iblock->filt_ents[par_entry].size == len);
par_iblock->ents[par_entry].addr = dblock_addr;
par_iblock->filt_ents[par_entry].size = write_size;
par_changed = TRUE;
}
if(par_changed)
if(H5HF_iblock_dirty(par_iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
}
}
else {
write_buf = dblock->blk;
write_size = dblock->size;
if(at_tmp_addr) {
if(HADDR_UNDEF == (dblock_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FHEAP_DBLOCK, (hsize_t)write_size)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
if(NULL == dblock->parent) {
HDassert(H5F_addr_eq(hdr->man_dtable.table_addr, addr));
HDassert(!H5F_addr_eq(hdr->man_dtable.table_addr, dblock_addr));
hdr->man_dtable.table_addr = dblock_addr;
if(H5HF_hdr_dirty(hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
}
else {
HDassert(par_iblock);
HDassert(par_iblock->ents);
HDassert(H5F_addr_eq(par_iblock->ents[par_entry].addr, addr));
HDassert(!H5F_addr_eq(par_iblock->ents[par_entry].addr, dblock_addr));
par_iblock->ents[par_entry].addr = dblock_addr;
if(H5HF_iblock_dirty(par_iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
}
}
}
dblock->write_buf = (uint8_t *)write_buf;
dblock->write_size = write_size;
if(!H5F_addr_eq(addr, dblock_addr)) {
dblock_flags |= H5AC__SERIALIZE_MOVED_FLAG;
*new_addr = dblock_addr;
}
if((hdr->filter_len > 0) && (len != write_size)) {
dblock_flags |= H5AC__SERIALIZE_RESIZED_FLAG;
*new_len = write_size;
}
*flags = dblock_flags;
HDassert(dblock->write_buf);
HDassert(dblock->write_size > 0);
done:
if(write_buf && (write_buf != dblock->blk) && (dblock->write_buf == NULL))
H5MM_xfree(write_buf);
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__cache_dblock_serialize(const H5F_t H5_ATTR_NDEBUG_UNUSED *f, void *image,
size_t H5_ATTR_NDEBUG_UNUSED len, void *_thing)
{
H5HF_direct_t *dblock = (H5HF_direct_t *)_thing;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC_NOERR
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);
H5MM_memcpy(image, dblock->write_buf, dblock->write_size);
if(dblock->write_buf != dblock->blk)
H5MM_xfree(dblock->write_buf);
dblock->write_buf = NULL;
dblock->write_size = 0;
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__cache_dblock_notify(H5AC_notify_action_t action, void *_thing)
{
H5HF_direct_t *dblock = (H5HF_direct_t *)_thing;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(dblock);
HDassert(dblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(dblock->cache_info.type == H5AC_FHEAP_DBLOCK);
HDassert(dblock->hdr);
switch(action) {
case H5AC_NOTIFY_ACTION_AFTER_INSERT:
case H5AC_NOTIFY_ACTION_AFTER_LOAD:
if(dblock->fd_parent)
if(H5AC_create_flush_dependency(dblock->fd_parent, dblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
break;
case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
case H5AC_NOTIFY_ACTION_ENTRY_DIRTIED:
case H5AC_NOTIFY_ACTION_ENTRY_CLEANED:
case H5AC_NOTIFY_ACTION_CHILD_DIRTIED:
case H5AC_NOTIFY_ACTION_CHILD_CLEANED:
case H5AC_NOTIFY_ACTION_CHILD_UNSERIALIZED:
case H5AC_NOTIFY_ACTION_CHILD_SERIALIZED:
break;
case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
if(dblock->fd_parent) {
if(H5AC_destroy_flush_dependency(dblock->fd_parent, dblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
dblock->fd_parent = NULL;
}
break;
default:
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unknown action from metadata cache")
break;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__cache_dblock_free_icr(void *_thing)
{
H5HF_direct_t *dblock = (H5HF_direct_t *)_thing;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(dblock);
HDassert(dblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
HDassert(dblock->cache_info.type == H5AC_FHEAP_DBLOCK);
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)
}
static herr_t
H5HF__cache_dblock_fsf_size(const void *_thing, hsize_t *fsf_size)
{
const H5HF_direct_t *dblock = (const H5HF_direct_t *)_thing;
FUNC_ENTER_STATIC_NOERR
HDassert(dblock);
HDassert(dblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(dblock->cache_info.type == H5AC_FHEAP_DBLOCK);
HDassert(dblock->file_size > 0);
HDassert(fsf_size);
*fsf_size = dblock->file_size;
FUNC_LEAVE_NOAPI(SUCCEED)
}
#ifndef NDEBUG
static herr_t
H5HF__cache_verify_hdr_descendants_clean(H5F_t *f, H5HF_hdr_t *hdr,
hbool_t *fd_clean, hbool_t *clean)
{
hbool_t fd_exists = FALSE;
haddr_t hdr_addr;
unsigned hdr_status = 0;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(f);
HDassert(hdr);
HDassert(hdr->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(hdr->cache_info.type == H5AC_FHEAP_HDR);
HDassert(fd_clean);
HDassert(clean);
hdr_addr = hdr->cache_info.addr;
HDassert(hdr_addr == hdr->heap_addr);
if(H5AC_get_entry_status(f, hdr_addr, &hdr_status) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get hdr status")
HDassert(hdr_status & H5AC_ES__IN_CACHE);
if(hdr->root_iblock ||
((hdr->man_dtable.curr_root_rows > 0) &&
(HADDR_UNDEF != hdr->man_dtable.table_addr))) {
H5HF_indirect_t *root_iblock = hdr->root_iblock;
haddr_t root_iblock_addr;
unsigned root_iblock_status = 0;
hbool_t root_iblock_in_cache;
if(root_iblock == NULL)
root_iblock_addr = hdr->man_dtable.table_addr;
else
root_iblock_addr = root_iblock->addr;
HDassert(root_iblock_addr != HADDR_UNDEF);
if(H5AC_get_entry_status(f, root_iblock_addr, &root_iblock_status) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get root iblock status")
root_iblock_in_cache = ( (root_iblock_status & H5AC_ES__IN_CACHE) != 0);
HDassert(root_iblock_in_cache || (root_iblock == NULL));
if(!root_iblock_in_cache) {
*clean = TRUE;
*fd_clean = TRUE;
}
else if((root_iblock_status & H5AC_ES__IS_DIRTY) &&
(((root_iblock_status & H5AC_ES__IMAGE_IS_UP_TO_DATE) == 0) ||
(!H5AC_get_serialization_in_progress(f)))) {
*clean = FALSE;
if(H5AC_flush_dependency_exists(f, hdr->heap_addr, root_iblock_addr, &fd_exists) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't check flush dependency")
HDassert(fd_exists);
*fd_clean = FALSE;
}
else {
hbool_t unprotect_root_iblock = FALSE;
if(root_iblock == NULL) {
if(0 == (root_iblock_status & H5AC_ES__IS_PROTECTED)) {
H5_BEGIN_TAG(hdr->heap_addr)
if(NULL == (root_iblock = (H5HF_indirect_t *)H5AC_protect(f, H5AC_FHEAP_IBLOCK, root_iblock_addr, NULL, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR_TAG(H5E_HEAP, H5E_CANTPROTECT, FAIL, "H5AC_protect() failed.")
H5_END_TAG
unprotect_root_iblock = TRUE;
}
else {
if(H5AC_get_entry_ptr_from_addr(f, root_iblock_addr, (void **)(&root_iblock)) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "H5AC_get_entry_ptr_from_addr() failed.")
HDassert(root_iblock);
}
}
else {
H5HF_indirect_t * iblock = NULL;
if(((root_iblock_status & H5AC_ES__IS_PINNED) == 0) &&
((root_iblock_status & H5AC_ES__IS_PROTECTED) == 0)) {
H5_BEGIN_TAG(hdr->heap_addr)
if(NULL == (iblock = (H5HF_indirect_t *)H5AC_protect(f, H5AC_FHEAP_IBLOCK, root_iblock_addr, NULL, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR_TAG(H5E_HEAP, H5E_CANTPROTECT, FAIL, "H5AC_protect() failed.")
H5_END_TAG
unprotect_root_iblock = TRUE;
HDassert(iblock == root_iblock);
}
}
HDassert(root_iblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(root_iblock->cache_info.type == H5AC_FHEAP_IBLOCK);
if(H5HF__cache_verify_iblock_descendants_clean(f, hdr->heap_addr, root_iblock, &root_iblock_status, fd_clean, clean) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "can't verify root iblock & descendants clean.")
if(unprotect_root_iblock) {
HDassert(root_iblock);
if(H5AC_unprotect(f, H5AC_FHEAP_IBLOCK, root_iblock_addr, root_iblock, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "H5AC_unprotect() failed.")
}
}
}
else if((hdr->man_dtable.curr_root_rows == 0) &&
(HADDR_UNDEF != hdr->man_dtable.table_addr)) {
haddr_t root_dblock_addr;
unsigned root_dblock_status = 0;
hbool_t in_cache;
hbool_t type_ok;
root_dblock_addr = hdr->man_dtable.table_addr;
if(H5AC_get_entry_status(f, root_dblock_addr, &root_dblock_status) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get root dblock status")
if(root_dblock_status & H5AC_ES__IN_CACHE) {
if(H5AC_verify_entry_type(f, root_dblock_addr, &H5AC_FHEAP_DBLOCK[0], &in_cache, &type_ok) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't check dblock type")
HDassert(in_cache);
if(!type_ok)
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "root dblock addr doesn't refer to a dblock?!?")
if(H5AC_flush_dependency_exists(f, hdr->heap_addr, root_dblock_addr, &fd_exists) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't check flush dependency")
if(!fd_exists)
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "root dblock is not a flush dep parent of header.")
if(0 != (root_dblock_status & H5AC_ES__IS_FLUSH_DEP_PARENT))
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "root dblock in cache and is a flush dep parent.")
*clean = !((root_dblock_status & H5AC_ES__IS_DIRTY) &&
(((root_dblock_status &
H5AC_ES__IMAGE_IS_UP_TO_DATE) == 0) ||
(!H5AC_get_serialization_in_progress(f))));
*fd_clean = *clean;
}
else {
*fd_clean = TRUE;
*clean = TRUE;
}
}
else {
*fd_clean = TRUE;
*clean = TRUE;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
#endif
#ifndef NDEBUG
static herr_t
H5HF__cache_verify_iblock_descendants_clean(H5F_t *f, haddr_t fd_parent_addr,
H5HF_indirect_t *iblock, unsigned *iblock_status, hbool_t * fd_clean,
hbool_t *clean)
{
hbool_t has_dblocks = FALSE;
hbool_t has_iblocks = FALSE;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(f);
HDassert(H5F_addr_defined(fd_parent_addr));
HDassert(iblock);
HDassert(iblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(iblock->cache_info.type == H5AC_FHEAP_IBLOCK);
HDassert(iblock_status);
HDassert(fd_clean);
HDassert(*fd_clean);
HDassert(clean);
if((*fd_clean) && H5HF__cache_verify_iblocks_dblocks_clean(f, fd_parent_addr, iblock, fd_clean, clean, &has_dblocks) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "can't verify dblocks clean.")
if((*fd_clean) && H5HF__cache_verify_descendant_iblocks_clean(f, fd_parent_addr, iblock, fd_clean, clean, &has_iblocks) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "can't verify iblocks clean.")
if(0 == (*iblock_status & H5AC_ES__IS_FLUSH_DEP_CHILD))
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "iblock is not a flush dep child.")
if(((has_dblocks || has_iblocks)) && (0 == (*iblock_status & H5AC_ES__IS_FLUSH_DEP_PARENT)))
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "iblock has children and is not a flush dep parent.")
if(((has_dblocks || has_iblocks)) && (0 == (*iblock_status & H5AC_ES__IS_PINNED)))
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "iblock has children and is not pinned.")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
#endif
#ifndef NDEBUG
static herr_t
H5HF__cache_verify_iblocks_dblocks_clean(H5F_t *f, haddr_t fd_parent_addr,
H5HF_indirect_t *iblock, hbool_t *fd_clean, hbool_t *clean,
hbool_t *has_dblocks)
{
unsigned num_direct_rows;
unsigned max_dblock_index;
unsigned i;
haddr_t iblock_addr;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(f);
HDassert(H5F_addr_defined(fd_parent_addr));
HDassert(iblock);
HDassert(iblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(iblock->cache_info.type == H5AC_FHEAP_IBLOCK);
HDassert(fd_clean);
HDassert(*fd_clean);
HDassert(clean);
HDassert(has_dblocks);
i = 0;
num_direct_rows = MIN(iblock->nrows, iblock->hdr->man_dtable.max_direct_rows);
HDassert(num_direct_rows <= iblock->nrows);
max_dblock_index = (num_direct_rows * iblock->hdr->man_dtable.cparam.width) - 1;
iblock_addr = iblock->addr;
HDassert(H5F_addr_defined(iblock_addr));
while((*fd_clean) && (i <= max_dblock_index)) {
haddr_t dblock_addr;
dblock_addr = iblock->ents[i].addr;
if(H5F_addr_defined(dblock_addr)) {
hbool_t in_cache;
hbool_t type_ok;
if(H5AC_verify_entry_type(f, dblock_addr, &H5AC_FHEAP_DBLOCK[0], &in_cache, &type_ok) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't check dblock type")
if(in_cache) {
hbool_t fd_exists;
unsigned dblock_status = 0;
if(!type_ok)
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "dblock addr doesn't refer to a dblock?!?")
if(H5AC_get_entry_status(f, dblock_addr, &dblock_status) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get dblock status")
HDassert(dblock_status & H5AC_ES__IN_CACHE);
*has_dblocks = TRUE;
if((dblock_status & H5AC_ES__IS_DIRTY) &&
(((dblock_status & H5AC_ES__IMAGE_IS_UP_TO_DATE) == 0) ||
(!H5AC_get_serialization_in_progress(f)))) {
*clean = FALSE;
if(H5AC_flush_dependency_exists(f, fd_parent_addr, dblock_addr, &fd_exists) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't check flush dependency")
if(fd_exists)
*fd_clean = FALSE;
}
if(H5AC_flush_dependency_exists(f, iblock_addr, dblock_addr, &fd_exists) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't check flush dependency")
if(!fd_exists)
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "dblock in cache and not a flush dep child of iblock.")
}
}
i++;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
#endif
#ifndef NDEBUG
static herr_t
H5HF__cache_verify_descendant_iblocks_clean(H5F_t *f, haddr_t fd_parent_addr,
H5HF_indirect_t *iblock, hbool_t *fd_clean, hbool_t *clean,
hbool_t *has_iblocks)
{
unsigned first_iblock_index;
unsigned last_iblock_index;
unsigned num_direct_rows;
unsigned i;
haddr_t iblock_addr;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(f);
HDassert(H5F_addr_defined(fd_parent_addr));
HDassert(iblock);
HDassert(iblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(iblock->cache_info.type == H5AC_FHEAP_IBLOCK);
HDassert(fd_clean);
HDassert(*fd_clean);
HDassert(clean);
HDassert(has_iblocks);
num_direct_rows = MIN(iblock->nrows, iblock->hdr->man_dtable.max_direct_rows);
HDassert(num_direct_rows <= iblock->nrows);
iblock_addr = iblock->addr;
first_iblock_index = num_direct_rows * iblock->hdr->man_dtable.cparam.width;
last_iblock_index = (iblock->nrows * iblock->hdr->man_dtable.cparam.width) - 1;
i = first_iblock_index;
while((*fd_clean) && (i <= last_iblock_index)) {
haddr_t child_iblock_addr = iblock->ents[i].addr;
if(H5F_addr_defined(child_iblock_addr)) {
unsigned child_iblock_status = 0;
if(H5AC_get_entry_status(f, child_iblock_addr, &child_iblock_status) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get iblock status")
if(child_iblock_status & H5AC_ES__IN_CACHE) {
hbool_t fd_exists;
*has_iblocks = TRUE;
if((child_iblock_status & H5AC_ES__IS_DIRTY) &&
(((child_iblock_status & H5AC_ES__IMAGE_IS_UP_TO_DATE) == 0) ||
(!H5AC_get_serialization_in_progress(f)))) {
*clean = FALSE;
if(H5AC_flush_dependency_exists(f, fd_parent_addr, child_iblock_addr, &fd_exists) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't check flush dependency")
if(fd_exists)
*fd_clean = FALSE;
}
if(*fd_clean) {
H5HF_indirect_t *child_iblock = NULL;
hbool_t unprotect_child_iblock = FALSE;
if(0 == (child_iblock_status & H5AC_ES__IS_PINNED)) {
if(0 == (child_iblock_status & H5AC_ES__IS_PROTECTED)) {
H5_BEGIN_TAG(iblock->hdr->heap_addr)
if(NULL == (child_iblock = (H5HF_indirect_t *) H5AC_protect(f, H5AC_FHEAP_IBLOCK, child_iblock_addr, NULL, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR_TAG(H5E_HEAP, H5E_CANTPROTECT, FAIL, "H5AC_protect() failed.")
H5_END_TAG
unprotect_child_iblock = TRUE;
}
else {
if(H5AC_get_entry_ptr_from_addr(f, child_iblock_addr, (void **)(&child_iblock)) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "H5AC_get_entry_ptr_from_addr() failed.")
HDassert(child_iblock);
}
}
else {
HDassert(iblock->child_iblocks);
child_iblock = iblock->child_iblocks[i - first_iblock_index];
}
HDassert(child_iblock);
HDassert(child_iblock->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(child_iblock->cache_info.type == H5AC_FHEAP_IBLOCK);
HDassert(child_iblock->addr == child_iblock_addr);
if(H5HF__cache_verify_iblock_descendants_clean(f, fd_parent_addr, child_iblock, &child_iblock_status, fd_clean, clean) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "can't verify child iblock clean.")
if(fd_parent_addr != iblock_addr) {
if(H5AC_flush_dependency_exists(f, iblock_addr, child_iblock_addr, &fd_exists) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't check flush dependency")
if(!fd_exists)
HGOTO_ERROR(H5E_HEAP, H5E_SYSTEM, FAIL, "iblock is not a flush dep parent of child_iblock.")
}
if(unprotect_child_iblock) {
if(H5AC_unprotect(f, H5AC_FHEAP_IBLOCK, child_iblock_addr, child_iblock, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "H5AC_unprotect() failed.")
}
}
}
}
i++;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
#endif