mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-02-23 16:20:57 +08:00
Tested platform: Kagiso only since it is only a comment block change. If it works in one machine, it should work in all, I hope. Still need to check the parallel build on copper.
1701 lines
63 KiB
C
1701 lines
63 KiB
C
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||
* Copyright by The HDF Group. *
|
||
* Copyright by the Board of Trustees of the University of Illinois. *
|
||
* All rights reserved. *
|
||
* *
|
||
* This file is part of HDF5. The full HDF5 copyright notice, including *
|
||
* terms governing use, modification, and redistribution, is contained in *
|
||
* the files COPYING and Copyright.html. COPYING can be found at the root *
|
||
* of the source code distribution tree; Copyright.html can be found at the *
|
||
* root level of an installed copy of the electronic HDF5 document set and *
|
||
* is linked from the top-level documents page. It can also be found at *
|
||
* http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
|
||
* access to either file, you may request a copy from help@hdfgroup.org. *
|
||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||
|
||
/*-------------------------------------------------------------------------
|
||
*
|
||
* Created: H5HFcache.c
|
||
* Feb 24 2006
|
||
* Quincey Koziol <koziol@ncsa.uiuc.edu>
|
||
*
|
||
* Purpose: Implement fractal heap metadata cache methods.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
|
||
/****************/
|
||
/* Module Setup */
|
||
/****************/
|
||
|
||
#define H5HF_PACKAGE /*suppress error about including H5HFpkg */
|
||
|
||
/***********/
|
||
/* Headers */
|
||
/***********/
|
||
#include "H5private.h" /* Generic Functions */
|
||
#include "H5Eprivate.h" /* Error handling */
|
||
#include "H5HFpkg.h" /* Fractal heaps */
|
||
#include "H5MFprivate.h" /* File memory management */
|
||
#include "H5MMprivate.h" /* Memory management */
|
||
#include "H5Vprivate.h" /* Vectors and arrays */
|
||
|
||
/****************/
|
||
/* Local Macros */
|
||
/****************/
|
||
|
||
/* Fractal heap format version #'s */
|
||
#define H5HF_HDR_VERSION 0 /* Header */
|
||
#define H5HF_DBLOCK_VERSION 0 /* Direct block */
|
||
#define H5HF_IBLOCK_VERSION 0 /* Indirect block */
|
||
|
||
|
||
/******************/
|
||
/* Local Typedefs */
|
||
/******************/
|
||
|
||
|
||
/********************/
|
||
/* Package Typedefs */
|
||
/********************/
|
||
|
||
|
||
/********************/
|
||
/* Local Prototypes */
|
||
/********************/
|
||
|
||
/* Local encode/decode routines */
|
||
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);
|
||
|
||
/* Metadata cache (H5AC) callbacks */
|
||
static H5HF_hdr_t *H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata, void *udata2);
|
||
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 UNUSED * flags_ptr);
|
||
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, const void *udata, void *udata2);
|
||
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 UNUSED * flags_ptr);
|
||
static herr_t H5HF_cache_iblock_clear(H5F_t *f, H5HF_indirect_t *iblock, hbool_t destroy);
|
||
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, const void *udata, void *udata2);
|
||
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 UNUSED * flags_ptr);
|
||
static herr_t H5HF_cache_dblock_clear(H5F_t *f, H5HF_direct_t *dblock, hbool_t destroy);
|
||
static herr_t H5HF_cache_dblock_size(const H5F_t *f, const H5HF_direct_t *dblock, size_t *size_ptr);
|
||
|
||
/*********************/
|
||
/* Package Variables */
|
||
/*********************/
|
||
|
||
/* 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_size_func_t)H5HF_cache_hdr_size,
|
||
}};
|
||
|
||
/* 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_size_func_t)H5HF_cache_iblock_size,
|
||
}};
|
||
|
||
/* H5HF direct block inherits cache-like properties from H5AC */
|
||
const H5AC_class_t H5AC_FHEAP_DBLOCK[1] = {{
|
||
H5AC_FHEAP_DBLOCK_ID,
|
||
(H5AC_load_func_t)H5HF_cache_dblock_load,
|
||
(H5AC_flush_func_t)H5HF_cache_dblock_flush,
|
||
(H5AC_dest_func_t)H5HF_cache_dblock_dest,
|
||
(H5AC_clear_func_t)H5HF_cache_dblock_clear,
|
||
(H5AC_size_func_t)H5HF_cache_dblock_size,
|
||
}};
|
||
|
||
|
||
/*****************************/
|
||
/* Library Private Variables */
|
||
/*****************************/
|
||
|
||
|
||
/*******************/
|
||
/* Local Variables */
|
||
/*******************/
|
||
|
||
/* Declare a free list to manage heap header data to/from disk */
|
||
H5FL_BLK_DEFINE_STATIC(header_block);
|
||
|
||
/* Declare a free list to manage heap direct block data to/from disk */
|
||
H5FL_BLK_DEFINE(direct_block);
|
||
|
||
/* Declare a free list to manage heap indirect block data to/from disk */
|
||
H5FL_BLK_DEFINE_STATIC(indirect_block);
|
||
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_dtable_decode
|
||
*
|
||
* Purpose: Decodes the metadata for a doubling table
|
||
*
|
||
* Return: Success: Pointer to a new fractal heap
|
||
*
|
||
* Failure: NULL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Feb 27 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_dtable_decode(H5F_t *f, const uint8_t **pp, H5HF_dtable_t *dtable)
|
||
{
|
||
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_dtable_decode)
|
||
|
||
/* Check arguments */
|
||
HDassert(f);
|
||
HDassert(pp && *pp);
|
||
HDassert(dtable);
|
||
|
||
/* Table width */
|
||
UINT16DECODE(*pp, dtable->cparam.width);
|
||
|
||
/* Starting block size */
|
||
H5F_DECODE_LENGTH(f, *pp, dtable->cparam.start_block_size);
|
||
|
||
/* Maximum direct block size */
|
||
H5F_DECODE_LENGTH(f, *pp, dtable->cparam.max_direct_size);
|
||
|
||
/* Maximum heap size (as # of bits) */
|
||
UINT16DECODE(*pp, dtable->cparam.max_index);
|
||
|
||
/* Starting # of rows in root indirect block */
|
||
UINT16DECODE(*pp, dtable->cparam.start_root_rows);
|
||
|
||
/* Address of table */
|
||
H5F_addr_decode(f, pp, &(dtable->table_addr));
|
||
|
||
/* Current # of rows in root indirect block */
|
||
UINT16DECODE(*pp, dtable->curr_root_rows);
|
||
|
||
FUNC_LEAVE_NOAPI(SUCCEED)
|
||
} /* end H5HF_dtable_decode() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_dtable_encode
|
||
*
|
||
* Purpose: Encodes the metadata for a doubling table
|
||
*
|
||
* Return: Success: Pointer to a new fractal heap
|
||
*
|
||
* Failure: NULL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Feb 27 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_dtable_encode(H5F_t *f, uint8_t **pp, const H5HF_dtable_t *dtable)
|
||
{
|
||
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_dtable_encode)
|
||
|
||
/* Check arguments */
|
||
HDassert(f);
|
||
HDassert(pp && *pp);
|
||
HDassert(dtable);
|
||
|
||
/* Table width */
|
||
UINT16ENCODE(*pp, dtable->cparam.width);
|
||
|
||
/* Starting block size */
|
||
H5F_ENCODE_LENGTH(f, *pp, dtable->cparam.start_block_size);
|
||
|
||
/* Maximum direct block size */
|
||
H5F_ENCODE_LENGTH(f, *pp, dtable->cparam.max_direct_size);
|
||
|
||
/* Maximum heap size (as # of bits) */
|
||
UINT16ENCODE(*pp, dtable->cparam.max_index);
|
||
|
||
/* Starting # of rows in root indirect block */
|
||
UINT16ENCODE(*pp, dtable->cparam.start_root_rows);
|
||
|
||
/* Address of table */
|
||
H5F_addr_encode(f, pp, dtable->table_addr);
|
||
|
||
/* Current # of rows in root indirect block */
|
||
UINT16ENCODE(*pp, dtable->curr_root_rows);
|
||
|
||
FUNC_LEAVE_NOAPI(SUCCEED)
|
||
} /* end H5HF_dtable_encode() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_cache_hdr_load
|
||
*
|
||
* Purpose: Loads a fractal heap header from the disk.
|
||
*
|
||
* Return: Success: Pointer to a new fractal heap
|
||
*
|
||
* Failure: NULL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Feb 24 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static H5HF_hdr_t *
|
||
H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *udata1, void UNUSED *udata2)
|
||
{
|
||
H5HF_hdr_t *hdr = NULL; /* Fractal heap info */
|
||
size_t size; /* Header size */
|
||
uint8_t *buf = NULL; /* Temporary buffer */
|
||
const uint8_t *p; /* Pointer into raw data buffer */
|
||
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 */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT(H5HF_cache_hdr_load)
|
||
#ifdef QAK
|
||
HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr);
|
||
#endif /* QAK */
|
||
|
||
/* Check arguments */
|
||
HDassert(f);
|
||
HDassert(H5F_addr_defined(addr));
|
||
|
||
/* Allocate space for the fractal heap data structure */
|
||
if(NULL == (hdr = H5HF_hdr_alloc(f)))
|
||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
|
||
|
||
/* Set the heap header's address */
|
||
hdr->heap_addr = addr;
|
||
|
||
/* Compute the 'base' size of the fractal heap header on disk */
|
||
size = H5HF_HEADER_SIZE(hdr);
|
||
|
||
/* Allocate temporary buffer */
|
||
if((buf = H5FL_BLK_MALLOC(header_block, size)) == NULL)
|
||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
|
||
|
||
/* Read header from disk */
|
||
if(H5F_block_read(f, H5FD_MEM_FHEAP_HDR, addr, size, dxpl_id, buf) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "can't read fractal heap header")
|
||
|
||
p = buf;
|
||
|
||
/* Magic number */
|
||
if(HDmemcmp(p, H5HF_HDR_MAGIC, (size_t)H5HF_SIZEOF_MAGIC))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong fractal heap header signature")
|
||
p += H5HF_SIZEOF_MAGIC;
|
||
|
||
/* Version */
|
||
if(*p++ != H5HF_HDR_VERSION)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, 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 */
|
||
|
||
/* Heap status flags */
|
||
/* (bit 0: "huge" object IDs have wrapped) */
|
||
/* (bit 1: checksum direct blocks) */
|
||
heap_flags = *p++;
|
||
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(f, p, hdr->huge_next_id); /* Next ID to use for "huge" object */
|
||
H5F_addr_decode(f, &p, &hdr->huge_bt2_addr); /* Address of "huge" object tracker B-tree */
|
||
|
||
/* "Managed" object free space information */
|
||
H5F_DECODE_LENGTH(f, p, hdr->total_man_free); /* Internal free space in managed direct blocks */
|
||
H5F_addr_decode(f, &p, &hdr->fs_addr); /* Address of free section header */
|
||
|
||
/* Heap statistics */
|
||
H5F_DECODE_LENGTH(f, p, hdr->man_size);
|
||
H5F_DECODE_LENGTH(f, p, hdr->man_alloc_size);
|
||
H5F_DECODE_LENGTH(f, p, hdr->man_iter_off);
|
||
H5F_DECODE_LENGTH(f, p, hdr->man_nobjs);
|
||
H5F_DECODE_LENGTH(f, p, hdr->huge_size);
|
||
H5F_DECODE_LENGTH(f, p, hdr->huge_nobjs);
|
||
H5F_DECODE_LENGTH(f, p, hdr->tiny_size);
|
||
H5F_DECODE_LENGTH(f, p, hdr->tiny_nobjs);
|
||
|
||
/* Managed objects' doubling-table info */
|
||
if(H5HF_dtable_decode(hdr->f, &p, &(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 - buf) == (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 = p - buf;
|
||
|
||
/* Compute the size of the extra filter information */
|
||
filter_info_size = hdr->sizeof_size /* Size of size for filtered root direct block */
|
||
+ 4 /* Size of filter mask for filtered root direct block */
|
||
+ hdr->filter_len; /* Size of encoded I/O filter info */
|
||
|
||
/* Compute the heap header's size */
|
||
hdr->heap_size = size + filter_info_size;
|
||
|
||
/* Re-size current buffer */
|
||
if((buf = H5FL_BLK_REALLOC(header_block, buf, hdr->heap_size)) == NULL)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "can't allocate space to decode I/O pipeline filters")
|
||
|
||
/* 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")
|
||
|
||
/* Point at correct offset in header for the filter information */
|
||
p = buf + filter_info_off;
|
||
|
||
/* Decode the size of a filtered root direct block */
|
||
H5F_DECODE_LENGTH(f, p, hdr->pline_root_direct_size);
|
||
|
||
/* Decode the filter mask for a filtered root direct block */
|
||
UINT32DECODE(p, hdr->pline_root_direct_filter_mask);
|
||
|
||
/* Decode I/O filter information */
|
||
if(NULL == (pline = (H5O_pline_t *)H5O_msg_decode(hdr->f, dxpl_id, H5O_PLINE_ID, p)))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTDECODE, NULL, "can't decode I/O pipeline filters")
|
||
p += 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)))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTCOPY, NULL, "can't copy I/O filter pipeline")
|
||
|
||
/* Release the space allocated for the I/O pipeline filters */
|
||
H5O_msg_free(H5O_PLINE_ID, pline);
|
||
} /* end if */
|
||
else
|
||
/* Set the heap header's size */
|
||
hdr->heap_size = size;
|
||
|
||
/* Compute checksum on entire header */
|
||
/* (including the filter information, if present) */
|
||
computed_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
|
||
|
||
/* Metadata checksum */
|
||
UINT32DECODE(p, stored_chksum);
|
||
|
||
/* Sanity check */
|
||
HDassert((size_t)(p - buf) == hdr->heap_size);
|
||
|
||
/* Verify checksum */
|
||
if(stored_chksum != computed_chksum)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "incorrect metadata checksum for fractal heap header")
|
||
|
||
/* Finish initialization of heap header */
|
||
if(H5HF_hdr_finish_init(hdr) < 0)
|
||
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, NULL, "can't finish initializing shared fractal heap header")
|
||
#ifdef QAK
|
||
HDfprintf(stderr, "%s: hdr->fspace = %p\n", FUNC, hdr->fspace);
|
||
#endif /* QAK */
|
||
|
||
/* Set return value */
|
||
ret_value = hdr;
|
||
|
||
done:
|
||
if(buf)
|
||
buf = H5FL_BLK_FREE(header_block, buf);
|
||
if(!ret_value && hdr)
|
||
(void)H5HF_cache_hdr_dest(f, hdr);
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_cache_hdr_load() */ /*lint !e818 Can't make udata a pointer to const */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_cache_hdr_flush
|
||
*
|
||
* Purpose: Flushes a dirty fractal heap header to disk.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Feb 24 2006
|
||
* Changes: JRM -- 8/21/06
|
||
* Added the flags_ptr parameter. This parameter exists to
|
||
* allow the flush routine to report to the cache if the
|
||
* entry is resized or renamed as a result of the flush.
|
||
* *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_hdr_t *hdr, unsigned UNUSED * flags_ptr)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT(H5HF_cache_hdr_flush)
|
||
#ifdef QAK
|
||
HDfprintf(stderr, "%s: Flushing heap header, addr = %a, destroy = %u\n", FUNC, addr, (unsigned)destroy);
|
||
#endif /* QAK */
|
||
|
||
/* check arguments */
|
||
HDassert(f);
|
||
HDassert(H5F_addr_defined(addr));
|
||
HDassert(hdr);
|
||
|
||
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 */
|
||
|
||
/* Sanity check */
|
||
HDassert(hdr->dirty);
|
||
|
||
/* Set the shared heap header's file context for this operation */
|
||
hdr->f = f;
|
||
|
||
/* Compute the size of the heap header on disk */
|
||
size = hdr->heap_size;
|
||
|
||
/* Allocate temporary buffer */
|
||
if((buf = H5FL_BLK_MALLOC(header_block, size)) == NULL)
|
||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
|
||
|
||
p = buf;
|
||
|
||
/* Magic number */
|
||
HDmemcpy(p, H5HF_HDR_MAGIC, (size_t)H5HF_SIZEOF_MAGIC);
|
||
p += H5HF_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 |= (hdr->huge_ids_wrapped ? H5HF_HDR_FLAGS_HUGE_ID_WRAPPED : 0);
|
||
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);
|
||
|
||
/* Encode the filter mask for a filtered root direct block */
|
||
UINT32ENCODE(p, hdr->pline_root_direct_filter_mask);
|
||
|
||
/* 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 */
|
||
|
||
/* Compute metadata checksum */
|
||
metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
|
||
|
||
/* Metadata checksum */
|
||
UINT32ENCODE(p, metadata_chksum);
|
||
|
||
/* 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")
|
||
|
||
buf = H5FL_BLK_FREE(header_block, buf);
|
||
|
||
hdr->dirty = FALSE;
|
||
hdr->cache_info.is_dirty = FALSE;
|
||
} /* end if */
|
||
|
||
if(destroy)
|
||
if(H5HF_cache_hdr_dest(f, hdr) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap header")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_cache_hdr_flush() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_cache_hdr_dest
|
||
*
|
||
* Purpose: Destroys a fractal heap header in memory.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Feb 24 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
/* ARGSUSED */
|
||
herr_t
|
||
H5HF_cache_hdr_dest(H5F_t UNUSED *f, H5HF_hdr_t *hdr)
|
||
{
|
||
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_hdr_dest)
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
HDassert(hdr->rc == 0);
|
||
|
||
/* Free the block size lookup table for the doubling table */
|
||
H5HF_dtable_dest(&hdr->man_dtable);
|
||
|
||
/* Release any I/O pipeline filter information */
|
||
if(hdr->pline.nused)
|
||
H5O_msg_reset(H5O_PLINE_ID, &(hdr->pline));
|
||
|
||
/* Free the shared info itself */
|
||
H5FL_FREE(H5HF_hdr_t, hdr);
|
||
|
||
FUNC_LEAVE_NOAPI(SUCCEED)
|
||
} /* end H5HF_cache_hdr_dest() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_cache_hdr_clear
|
||
*
|
||
* Purpose: Mark a fractal heap header in memory as non-dirty.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Feb 24 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_cache_hdr_clear(H5F_t *f, H5HF_hdr_t *hdr, hbool_t destroy)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT(H5HF_cache_hdr_clear)
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
|
||
/* 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")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_cache_hdr_clear() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_cache_hdr_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.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Feb 24 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_cache_hdr_size(const H5F_t UNUSED *f, const H5HF_hdr_t *hdr, size_t *size_ptr)
|
||
{
|
||
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_hdr_size)
|
||
|
||
/* check arguments */
|
||
HDassert(f);
|
||
HDassert(hdr);
|
||
HDassert(size_ptr);
|
||
|
||
/* Set size value */
|
||
*size_ptr = hdr->heap_size;
|
||
|
||
FUNC_LEAVE_NOAPI(SUCCEED)
|
||
} /* H5HF_cache_hdr_size() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_cache_iblock_load
|
||
*
|
||
* Purpose: Loads a fractal heap indirect block from the disk.
|
||
*
|
||
* Return: Success: Pointer to a new fractal heap indirect block
|
||
*
|
||
* Failure: NULL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Feb 27 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static H5HF_indirect_t *
|
||
H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrows, void *_par_info)
|
||
{
|
||
H5HF_hdr_t *hdr; /* Shared fractal heap information */
|
||
const unsigned *nrows = (const unsigned *)_nrows; /* # of rows in indirect block */
|
||
H5HF_parent_t *par_info = (H5HF_parent_t *)_par_info; /* Shared parent information */
|
||
H5HF_indirect_t *iblock = NULL; /* Indirect block info */
|
||
uint8_t *buf = NULL; /* Temporary buffer */
|
||
const uint8_t *p; /* Pointer into raw data buffer */
|
||
haddr_t heap_addr; /* Address of heap header in the file */
|
||
uint32_t stored_chksum; /* Stored metadata checksum value */
|
||
uint32_t computed_chksum; /* Computed metadata checksum value */
|
||
size_t u; /* Local index variable */
|
||
H5HF_indirect_t *ret_value; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT(H5HF_cache_iblock_load)
|
||
#ifdef QAK
|
||
HDfprintf(stderr, "%s: Load indirect block, addr = %a\n", FUNC, addr);
|
||
#endif /* QAK */
|
||
|
||
/* Check arguments */
|
||
HDassert(f);
|
||
HDassert(H5F_addr_defined(addr));
|
||
HDassert(par_info);
|
||
|
||
/* 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")
|
||
HDmemset(&iblock->cache_info, 0, sizeof(H5AC_info_t));
|
||
|
||
/* Get the pointer to the shared heap header */
|
||
hdr = par_info->hdr;
|
||
|
||
/* Set the shared heap header's file context for this operation */
|
||
hdr->f = f;
|
||
|
||
/* Share common heap information */
|
||
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")
|
||
|
||
/* Set block's internal information */
|
||
iblock->rc = 0;
|
||
iblock->nrows = *nrows;
|
||
iblock->addr = addr;
|
||
iblock->nchildren = 0;
|
||
|
||
/* Compute size of indirect block */
|
||
iblock->size = H5HF_MAN_INDIRECT_SIZE(hdr, iblock);
|
||
|
||
/* Allocate buffer to decode block */
|
||
/* XXX: Use free list factories? */
|
||
if((buf = H5FL_BLK_MALLOC(indirect_block, iblock->size)) == NULL)
|
||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
|
||
|
||
/* 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")
|
||
|
||
p = buf;
|
||
|
||
/* Magic number */
|
||
if(HDmemcmp(p, H5HF_IBLOCK_MAGIC, (size_t)H5HF_SIZEOF_MAGIC))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong fractal heap indirect block signature")
|
||
p += H5HF_SIZEOF_MAGIC;
|
||
|
||
/* Version */
|
||
if(*p++ != H5HF_IBLOCK_VERSION)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong fractal heap direct block version")
|
||
|
||
/* Address of heap that owns this block */
|
||
H5F_addr_decode(f, &p, &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")
|
||
|
||
/* Address of parent block */
|
||
iblock->parent = par_info->iblock;
|
||
iblock->par_entry = par_info->entry;
|
||
if(iblock->parent) {
|
||
/* Share parent block */
|
||
if(H5HF_iblock_incr(iblock->parent) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block")
|
||
|
||
/* Set max. # of rows in this block */
|
||
iblock->max_rows = iblock->nrows;
|
||
} /* end if */
|
||
else {
|
||
/* Set max. # of rows in this block */
|
||
iblock->max_rows = hdr->man_dtable.max_root_rows;
|
||
} /* end else */
|
||
|
||
/* Offset of heap within the heap's address space */
|
||
UINT64DECODE_VAR(p, iblock->block_off, hdr->heap_off_size);
|
||
|
||
/* Allocate & decode child block entry tables */
|
||
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; /* Number of direct rows in this indirect block */
|
||
|
||
/* Compute the number of direct rows for this indirect block */
|
||
dir_rows = MIN(iblock->nrows, hdr->man_dtable.max_direct_rows);
|
||
|
||
/* Allocate indirect block filtered entry array */
|
||
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")
|
||
} /* end if */
|
||
else
|
||
iblock->filt_ents = NULL;
|
||
for(u = 0; u < (iblock->nrows * hdr->man_dtable.cparam.width); u++) {
|
||
/* Decode child block address */
|
||
H5F_addr_decode(f, &p, &(iblock->ents[u].addr));
|
||
|
||
/* Check for heap with I/O filters */
|
||
if(hdr->filter_len > 0) {
|
||
/* Sanity check */
|
||
HDassert(iblock->filt_ents);
|
||
|
||
/* 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(f, p, iblock->filt_ents[u].size);
|
||
|
||
/* 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));
|
||
|
||
/* I/O filter mask for filtered direct block */
|
||
UINT32DECODE(p, iblock->filt_ents[u].filter_mask);
|
||
} /* end if */
|
||
} /* end if */
|
||
|
||
/* Count child blocks */
|
||
if(H5F_addr_defined(iblock->ents[u].addr)) {
|
||
iblock->nchildren++;
|
||
iblock->max_child = u;
|
||
} /* end if */
|
||
#ifdef QAK
|
||
HDfprintf(stderr, "%s: iblock->ents[%Zu] = {%a}\n", FUNC, u, iblock->ents[u].addr);
|
||
#endif /* QAK */
|
||
} /* end for */
|
||
|
||
/* Sanity check */
|
||
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 - buf), 0);
|
||
|
||
/* Metadata checksum */
|
||
UINT32DECODE(p, stored_chksum);
|
||
|
||
/* Sanity check */
|
||
HDassert((size_t)(p - buf) == iblock->size);
|
||
|
||
/* Verify checksum */
|
||
if(stored_chksum != computed_chksum)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "incorrect metadata checksum for fractal heap indirect block")
|
||
|
||
/* 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 */
|
||
|
||
/* Compute the number of indirect rows for this indirect block */
|
||
indir_rows = iblock->nrows - hdr->man_dtable.max_direct_rows;
|
||
|
||
/* Allocate & initialize child indirect block pointer array */
|
||
if(NULL == (iblock->child_iblocks = H5FL_SEQ_CALLOC(H5HF_indirect_ptr_t, (size_t)(indir_rows * hdr->man_dtable.cparam.width))))
|
||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for block entries")
|
||
} /* end if */
|
||
else
|
||
iblock->child_iblocks = NULL;
|
||
|
||
/* Set return value */
|
||
ret_value = iblock;
|
||
|
||
done:
|
||
/* Free buffer */
|
||
/* XXX: Keep buffer around? */
|
||
buf = H5FL_BLK_FREE(indirect_block, buf);
|
||
|
||
if(!ret_value && iblock)
|
||
(void)H5HF_cache_iblock_dest(f, iblock);
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_cache_iblock_load() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_cache_iblock_flush
|
||
*
|
||
* Purpose: Flushes a dirty fractal heap indirect block to disk.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Mar 6 2006
|
||
*
|
||
* Changes: JRM -- 8/21/06
|
||
* Added the flags_ptr parameter. This parameter exists to
|
||
* allow the flush routine to report to the cache if the
|
||
* entry is resized or renamed as a result of the flush.
|
||
* *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_cache_iblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_indirect_t *iblock, unsigned UNUSED * flags_ptr)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT(H5HF_cache_iblock_flush)
|
||
#ifdef QAK
|
||
HDfprintf(stderr, "%s: Flushing indirect block, addr = %a, destroy = %u\n", FUNC, addr, (unsigned)destroy);
|
||
#endif /* QAK */
|
||
|
||
/* check arguments */
|
||
HDassert(f);
|
||
HDassert(H5F_addr_defined(addr));
|
||
HDassert(iblock);
|
||
|
||
if(iblock->cache_info.is_dirty) {
|
||
H5HF_hdr_t *hdr; /* Shared fractal heap information */
|
||
uint8_t *buf = NULL; /* 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 */
|
||
|
||
/* 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;
|
||
|
||
/* Allocate buffer to encode block */
|
||
/* XXX: Use free list factories? */
|
||
#ifdef QAK
|
||
HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows);
|
||
HDfprintf(stderr, "%s: iblock->size = %Zu\n", FUNC, iblock->size);
|
||
HDfprintf(stderr, "%s: iblock->block_off = %Hu\n", FUNC, iblock->block_off);
|
||
HDfprintf(stderr, "%s: hdr->man_dtable.cparam.width = %u\n", FUNC, hdr->man_dtable.cparam.width);
|
||
#endif /* QAK */
|
||
if((buf = H5FL_BLK_MALLOC(indirect_block, iblock->size)) == NULL)
|
||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
|
||
|
||
p = buf;
|
||
|
||
/* Magic number */
|
||
HDmemcpy(p, H5HF_IBLOCK_MAGIC, (size_t)H5HF_SIZEOF_MAGIC);
|
||
p += H5HF_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++) {
|
||
#ifdef QAK
|
||
HDfprintf(stderr, "%s: iblock->ents[%Zu] = {%a}\n", FUNC, u, iblock->ents[u].addr);
|
||
#endif /* QAK */
|
||
/* Encode child block address */
|
||
H5F_addr_encode(f, &p, 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)) {
|
||
#ifdef QAK
|
||
HDfprintf(stderr, "%s: iblock->filt_ents[%Zu] = {%Zu, %x}\n", FUNC, u, iblock->filt_ents[u].size, iblock->filt_ents[u].filter_mask);
|
||
#endif /* QAK */
|
||
/* 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, p, iblock->filt_ents[u].size);
|
||
|
||
/* I/O filter mask for filtered direct block */
|
||
UINT32ENCODE(p, 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(buf, (size_t)(p - buf), 0);
|
||
|
||
/* Metadata checksum */
|
||
UINT32ENCODE(p, metadata_chksum);
|
||
|
||
/* Sanity check */
|
||
HDassert((size_t)(p - buf) == iblock->size);
|
||
#ifndef NDEBUG
|
||
HDassert(nchildren == iblock->nchildren);
|
||
HDassert(max_child == iblock->max_child);
|
||
#endif /* NDEBUG */
|
||
|
||
/* 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")
|
||
|
||
/* Free buffer */
|
||
buf = H5FL_BLK_FREE(indirect_block, buf);
|
||
|
||
/* Reset dirty flags */
|
||
iblock->cache_info.is_dirty = FALSE;
|
||
} /* 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")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_cache_iblock_flush() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_cache_iblock_dest
|
||
*
|
||
* Purpose: Destroys a fractal heap indirect block in memory.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Mar 6 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
/* ARGSUSED */
|
||
herr_t
|
||
H5HF_cache_iblock_dest(H5F_t UNUSED *f, H5HF_indirect_t *iblock)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT(H5HF_cache_iblock_dest)
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(iblock);
|
||
HDassert(iblock->rc == 0);
|
||
#ifdef QAK
|
||
HDfprintf(stderr, "%s: Destroying indirect block\n", FUNC);
|
||
#endif /* QAK */
|
||
|
||
/* Set the shared heap header's file context for this operation */
|
||
iblock->hdr->f = f;
|
||
|
||
/* Decrement reference count on shared info */
|
||
HDassert(iblock->hdr);
|
||
if(H5HF_hdr_decr(iblock->hdr) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared heap header")
|
||
if(iblock->parent)
|
||
if(H5HF_iblock_decr(iblock->parent) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
|
||
|
||
/* Release entry tables */
|
||
if(iblock->ents)
|
||
H5FL_SEQ_FREE(H5HF_indirect_ent_t, iblock->ents);
|
||
if(iblock->filt_ents)
|
||
H5FL_SEQ_FREE(H5HF_indirect_filt_ent_t, iblock->filt_ents);
|
||
if(iblock->child_iblocks)
|
||
H5FL_SEQ_FREE(H5HF_indirect_ptr_t, iblock->child_iblocks);
|
||
|
||
/* Free fractal heap indirect block info */
|
||
H5FL_FREE(H5HF_indirect_t, iblock);
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_cache_iblock_dest() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* 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 */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT(H5HF_cache_iblock_clear)
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(iblock);
|
||
|
||
/* Reset the dirty flag. */
|
||
iblock->cache_info.is_dirty = FALSE;
|
||
|
||
if(destroy)
|
||
if(H5HF_cache_iblock_dest(f, 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_clear() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_cache_iblock_size
|
||
*
|
||
* 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.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Mar 6 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_cache_iblock_size(const H5F_t UNUSED *f, const H5HF_indirect_t *iblock, size_t *size_ptr)
|
||
{
|
||
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_iblock_size)
|
||
|
||
/* check arguments */
|
||
HDassert(iblock);
|
||
HDassert(size_ptr);
|
||
|
||
/* Set size value */
|
||
*size_ptr = iblock->size;
|
||
|
||
FUNC_LEAVE_NOAPI(SUCCEED)
|
||
} /* H5HF_cache_iblock_size() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_cache_dblock_load
|
||
*
|
||
* Purpose: Loads a fractal heap direct block from the disk.
|
||
*
|
||
* Return: Success: Pointer to a new fractal heap direct block
|
||
*
|
||
* Failure: NULL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Feb 27 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static H5HF_direct_t *
|
||
H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_size, void *_par_info)
|
||
{
|
||
const size_t *size = (const size_t *)_size; /* Size of block */
|
||
H5HF_hdr_t *hdr; /* Shared fractal heap information */
|
||
H5HF_parent_t *par_info = (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 */
|
||
haddr_t heap_addr; /* Address of heap header in the file */
|
||
H5HF_direct_t *ret_value; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT(H5HF_cache_dblock_load)
|
||
|
||
/* Check arguments */
|
||
HDassert(f);
|
||
HDassert(H5F_addr_defined(addr));
|
||
HDassert(par_info);
|
||
|
||
/* 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 */
|
||
hdr = par_info->hdr;
|
||
|
||
/* Set the shared heap header's file context for this operation */
|
||
hdr->f = f;
|
||
|
||
/* Share common heap information */
|
||
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")
|
||
|
||
/* Set block's internal information */
|
||
dblock->size = *size;
|
||
dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dblock->size);
|
||
|
||
/* Allocate block buffer */
|
||
/* XXX: Change to using free-list factories */
|
||
if((dblock->blk = H5FL_BLK_MALLOC(direct_block, (size_t)dblock->size)) == NULL)
|
||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
|
||
|
||
/* 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 in buffer, after applying reverse filters */
|
||
void *read_buf; /* Pointer to buffer to read in */
|
||
size_t read_size; /* Size of filtered direct block to read */
|
||
unsigned filter_mask; /* Excluded filters for direct block */
|
||
|
||
/* Check for root direct block */
|
||
if(par_info->iblock == NULL) {
|
||
#ifdef QAK
|
||
HDfprintf(stderr, "%s: hdr->pline_root_direct_size = %Zu, hdr->pline_root_direct_filter_mask = %x\n", FUNC, hdr->pline_root_direct_size, hdr->pline_root_direct_filter_mask);
|
||
HDfprintf(stderr, "%s: hdr->man_dtable.table_addr = %a, addr = %a\n", FUNC, hdr->man_dtable.table_addr, addr);
|
||
#endif /* QAK */
|
||
/* Sanity check */
|
||
HDassert(H5F_addr_eq(hdr->man_dtable.table_addr, addr));
|
||
|
||
/* Set up parameters to read filtered direct block */
|
||
read_size = hdr->pline_root_direct_size;
|
||
filter_mask = hdr->pline_root_direct_filter_mask;
|
||
} /* end if */
|
||
else {
|
||
#ifdef QAK
|
||
HDfprintf(stderr, "%s: par_info->iblock = %p, par_info->entry = %u\n", FUNC, par_info->iblock, par_info->entry);
|
||
HDfprintf(stderr, "%s: par_info->iblock->filt_ents[%u].size = %Zu, par_info->iblock->filt_ents[%u].filter_mask = %x\n", FUNC, par_info->entry, par_info->iblock->filt_ents[par_info->entry].size, par_info->entry, par_info->iblock->filt_ents[par_info->entry].filter_mask);
|
||
HDfprintf(stderr, "%s: par_info->iblock->ents[%u].addr = %a, addr = %a\n", FUNC, par_info->entry, par_info->iblock->ents[par_info->entry].addr, addr);
|
||
#endif /* QAK */
|
||
/* Sanity check */
|
||
HDassert(H5F_addr_eq(par_info->iblock->ents[par_info->entry].addr, addr));
|
||
|
||
/* Set up parameters to read filtered direct block */
|
||
read_size = par_info->iblock->filt_ents[par_info->entry].size;
|
||
filter_mask = par_info->iblock->filt_ents[par_info->entry].filter_mask;
|
||
} /* end else */
|
||
|
||
/* Allocate buffer to perform I/O filtering on */
|
||
if(NULL == (read_buf = H5MM_malloc(read_size)))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "memory allocation failed for pipeline buffer")
|
||
#ifdef QAK
|
||
HDfprintf(stderr, "%s: read_size = %Zu, read_buf = %p\n", FUNC, read_size, read_buf);
|
||
#endif /* QAK */
|
||
|
||
/* 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")
|
||
|
||
/* Push direct block data through I/O filter pipeline */
|
||
nbytes = read_size;
|
||
if(H5Z_pipeline(&(hdr->pline), H5Z_FLAG_REVERSE, &filter_mask, H5Z_ENABLE_EDC,
|
||
filter_cb, &nbytes, &read_size, &read_buf) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTFILTER, NULL, "output pipeline failed")
|
||
#ifdef QAK
|
||
HDfprintf(stderr, "%s: nbytes = %Zu, read_size = %Zu, read_buf = %p\n", FUNC, nbytes, read_size, read_buf);
|
||
#endif /* QAK */
|
||
|
||
/* Sanity check */
|
||
HDassert(nbytes == dblock->size);
|
||
|
||
/* Copy un-filtered data into block's buffer */
|
||
HDmemcpy(dblock->blk, read_buf, dblock->size);
|
||
|
||
/* Release the read buffer */
|
||
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")
|
||
} /* end else */
|
||
|
||
/* Start decoding direct block */
|
||
p = dblock->blk;
|
||
|
||
/* Magic number */
|
||
if(HDmemcmp(p, H5HF_DBLOCK_MAGIC, (size_t)H5HF_SIZEOF_MAGIC))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong fractal heap direct block signature")
|
||
p += H5HF_SIZEOF_MAGIC;
|
||
|
||
/* Version */
|
||
if(*p++ != H5HF_DBLOCK_VERSION)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong fractal heap direct block version")
|
||
|
||
/* Address of heap that owns this block (just for file integrity checks) */
|
||
H5F_addr_decode(f, &p, &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")
|
||
|
||
/* Address of parent block */
|
||
dblock->parent = par_info->iblock;
|
||
dblock->par_entry = par_info->entry;
|
||
if(dblock->parent) {
|
||
/* Share parent block */
|
||
if(H5HF_iblock_incr(dblock->parent) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block")
|
||
} /* end if */
|
||
|
||
/* Offset of heap within the heap's address space */
|
||
UINT64DECODE_VAR(p, dblock->block_off, hdr->heap_off_size);
|
||
|
||
/* Encode checksum on direct block, if requested */
|
||
if(hdr->checksum_dblocks) {
|
||
uint32_t stored_chksum; /* Metadata checksum value */
|
||
uint32_t computed_chksum; /* Computed metadata checksum value */
|
||
|
||
/* Metadata checksum */
|
||
UINT32DECODE(p, 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);
|
||
|
||
/* Compute checksum on entire direct block */
|
||
computed_chksum = H5_checksum_metadata(dblock->blk, dblock->size, 0);
|
||
|
||
/* Verify checksum */
|
||
if(stored_chksum != computed_chksum)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "incorrect metadata checksum for fractal heap direct block")
|
||
} /* end if */
|
||
|
||
/* Sanity check */
|
||
HDassert((size_t)(p - dblock->blk) == H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr));
|
||
|
||
/* Set return value */
|
||
ret_value = dblock;
|
||
|
||
done:
|
||
if(!ret_value && dblock)
|
||
(void)H5HF_cache_dblock_dest(f, dblock);
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_cache_dblock_load() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_cache_dblock_flush
|
||
*
|
||
* Purpose: Flushes a dirty fractal heap direct block to disk.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Feb 27 2006
|
||
*
|
||
* Changes: JRM -- 8/21/06
|
||
* Added the flags_ptr parameter. This parameter exists to
|
||
* allow the flush routine to report to the cache if the
|
||
* entry is resized or renamed as a result of the flush.
|
||
* *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_direct_t *dblock, unsigned UNUSED * flags_ptr)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT(H5HF_cache_dblock_flush)
|
||
|
||
/* check arguments */
|
||
HDassert(f);
|
||
HDassert(H5F_addr_defined(addr));
|
||
HDassert(dblock);
|
||
|
||
if(dblock->cache_info.is_dirty) {
|
||
H5HF_hdr_t *hdr; /* Shared fractal heap information */
|
||
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 */
|
||
|
||
/* Get the pointer to the shared heap header */
|
||
hdr = dblock->hdr;
|
||
|
||
/* Set the shared heap header's file context for this operation */
|
||
hdr->f = f;
|
||
|
||
HDassert(dblock->blk);
|
||
p = dblock->blk;
|
||
|
||
/* Magic number */
|
||
HDmemcpy(p, H5HF_DBLOCK_MAGIC, (size_t)H5HF_SIZEOF_MAGIC);
|
||
p += H5HF_SIZEOF_MAGIC;
|
||
|
||
/* Version # */
|
||
*p++ = H5HF_DBLOCK_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, dblock->block_off, hdr->heap_off_size);
|
||
|
||
/* Metadata checksum */
|
||
if(hdr->checksum_dblocks) {
|
||
uint32_t metadata_chksum; /* Computed metadata checksum value */
|
||
|
||
/* Clear the checksum field, to compute the checksum */
|
||
HDmemset(p, 0, (size_t)H5HF_SIZEOF_CHKSUM);
|
||
|
||
/* Compute checksum on entire direct block */
|
||
metadata_chksum = H5_checksum_metadata(dblock->blk, dblock->size, 0);
|
||
|
||
/* Metadata checksum */
|
||
UINT32ENCODE(p, metadata_chksum);
|
||
} /* end if */
|
||
|
||
/* Sanity check */
|
||
HDassert((size_t)(p - dblock->blk) == H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr));
|
||
|
||
/* 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; /* Filter mask for 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);
|
||
|
||
/* 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")
|
||
#ifdef QAK
|
||
HDfprintf(stderr, "%s: nbytes = %Zu, write_size = %Zu, write_buf = %p\n", FUNC, nbytes, write_size, write_buf);
|
||
HDfprintf(stderr, "%s: dblock->block_off = %Hu\n", FUNC, dblock->block_off);
|
||
HDfprintf(stderr, "%s: dblock->size = %Zu, dblock->blk = %p\n", FUNC, dblock->size, dblock->blk);
|
||
HDfprintf(stderr, "%s: dblock->parent = %p, dblock->par_entry = %u\n", FUNC, dblock->parent, dblock->par_entry);
|
||
#endif /* QAK */
|
||
|
||
/* Use the compressed number of bytes as the size to write */
|
||
write_size = nbytes;
|
||
|
||
/* Check for root direct block */
|
||
if(dblock->parent == NULL) {
|
||
hbool_t hdr_changed = FALSE; /* Whether the header information changed */
|
||
|
||
#ifdef QAK
|
||
HDfprintf(stderr, "%s: hdr->pline_root_direct_size = %Zu, hdr->pline_root_direct_filter_mask = %x\n", FUNC, hdr->pline_root_direct_size, hdr->pline_root_direct_filter_mask);
|
||
HDfprintf(stderr, "%s: hdr->man_dtable.table_addr = %a, addr = %a\n", FUNC, hdr->man_dtable.table_addr, addr);
|
||
#endif /* QAK */
|
||
/* Sanity check */
|
||
HDassert(H5F_addr_eq(hdr->man_dtable.table_addr, addr));
|
||
HDassert(hdr->pline_root_direct_size > 0);
|
||
|
||
/* 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 */
|
||
|
||
/* Check if we need to re-size the block on disk */
|
||
if(hdr->pline_root_direct_size != write_size) {
|
||
#ifdef QAK
|
||
HDfprintf(stderr, "%s: Need to re-allocate root direct block!\n", FUNC);
|
||
#endif /* QAK */
|
||
/* 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")
|
||
|
||
/* 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")
|
||
|
||
/* Let the metadata cache know, if the block moved */
|
||
if(!H5F_addr_eq(hdr->man_dtable.table_addr, addr))
|
||
if(H5AC_rename(f, H5AC_FHEAP_DBLOCK, hdr->man_dtable.table_addr, addr) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRENAME, FAIL, "unable to move direct block")
|
||
|
||
/* Update information about compressed direct block's location & size */
|
||
hdr->man_dtable.table_addr = addr;
|
||
hdr->pline_root_direct_size = write_size;
|
||
|
||
/* 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 {
|
||
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 */
|
||
|
||
/* Get parent information */
|
||
par_iblock = dblock->parent;
|
||
par_entry = dblock->par_entry;
|
||
|
||
#ifdef QAK
|
||
HDfprintf(stderr, "%s: par_iblock->filt_ents[%u].size = %Zu, par_iblock->filt_ents[%u].filter_mask = %x\n", FUNC, par_entry, par_iblock->filt_ents[par_entry].size, par_entry, par_iblock->filt_ents[par_entry].filter_mask);
|
||
HDfprintf(stderr, "%s: par_iblock->ents[%u].addr = %a, addr = %a\n", FUNC, par_entry, par_iblock->ents[par_entry].addr, addr);
|
||
#endif /* QAK */
|
||
/* Sanity check */
|
||
HDassert(H5F_addr_eq(par_iblock->ents[par_entry].addr, addr));
|
||
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 */
|
||
|
||
/* Check if we need to re-size the block on disk */
|
||
if(par_iblock->filt_ents[par_entry].size != write_size) {
|
||
#ifdef QAK
|
||
HDfprintf(stderr, "%s: Need to re-allocate non-root direct block!\n", FUNC);
|
||
#endif /* QAK */
|
||
/* 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")
|
||
|
||
/* 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")
|
||
|
||
/* Let the metadata cache know, if the block moved */
|
||
if(!H5F_addr_eq(par_iblock->ents[par_entry].addr, addr))
|
||
if(H5AC_rename(f, H5AC_FHEAP_DBLOCK, par_iblock->ents[par_entry].addr, addr) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRENAME, FAIL, "unable to move direct block")
|
||
|
||
/* 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;
|
||
|
||
/* 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 {
|
||
write_buf = dblock->blk;
|
||
write_size = dblock->size;
|
||
} /* end else */
|
||
|
||
/* Write the direct block */
|
||
#ifdef QAK
|
||
HDfprintf(stderr, "%s: addr = %a, write_size = %Zu\n", FUNC, addr, write_size);
|
||
#endif /* QAK */
|
||
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")
|
||
|
||
/* Release the write buffer, if it was allocated */
|
||
if(write_buf != dblock->blk)
|
||
H5MM_xfree(write_buf);
|
||
|
||
dblock->cache_info.is_dirty = FALSE;
|
||
} /* end if */
|
||
|
||
if(destroy)
|
||
if(H5HF_cache_dblock_dest(f, dblock) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap direct block")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_cache_dblock_flush() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_cache_dblock_dest
|
||
*
|
||
* Purpose: Destroys a fractal heap direct block in memory.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Feb 27 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
/* ARGSUSED */
|
||
herr_t
|
||
H5HF_cache_dblock_dest(H5F_t UNUSED *f, H5HF_direct_t *dblock)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT(H5HF_cache_dblock_dest)
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(dblock);
|
||
#ifdef QAK
|
||
HDfprintf(stderr, "%s: Destroying direct block, dblock = %p\n", FUNC, dblock);
|
||
#endif /* QAK */
|
||
|
||
/* Set the shared heap header's file context for this operation */
|
||
dblock->hdr->f = f;
|
||
|
||
/* Decrement reference count on shared fractal heap info */
|
||
HDassert(dblock->hdr);
|
||
if(H5HF_hdr_decr(dblock->hdr) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared heap header")
|
||
if(dblock->parent)
|
||
if(H5HF_iblock_decr(dblock->parent) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
|
||
|
||
/* Free block's buffer */
|
||
dblock->blk = H5FL_BLK_FREE(direct_block, dblock->blk);
|
||
|
||
/* Free fractal heap direct block info */
|
||
H5FL_FREE(H5HF_direct_t, dblock);
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_cache_dblock_dest() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_cache_dblock_clear
|
||
*
|
||
* Purpose: Mark a fractal heap direct block in memory as non-dirty.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Feb 27 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_cache_dblock_clear(H5F_t *f, H5HF_direct_t *dblock, hbool_t destroy)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT(H5HF_cache_dblock_clear)
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(dblock);
|
||
|
||
/* Reset the dirty flag. */
|
||
dblock->cache_info.is_dirty = FALSE;
|
||
|
||
if(destroy)
|
||
if(H5HF_cache_dblock_dest(f, dblock) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap direct block")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_cache_dblock_clear() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_cache_dblock_size
|
||
*
|
||
* Purpose: Compute the size in bytes of a fractal heap direct block
|
||
* on disk, and return it in *size_ptr. On failure,
|
||
* the value of *size_ptr is undefined.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Feb 24 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_cache_dblock_size(const H5F_t UNUSED *f, const H5HF_direct_t *dblock, size_t *size_ptr)
|
||
{
|
||
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_dblock_size)
|
||
|
||
/* check arguments */
|
||
HDassert(dblock);
|
||
HDassert(size_ptr);
|
||
|
||
/* Set size value */
|
||
*size_ptr = dblock->size;
|
||
|
||
FUNC_LEAVE_NOAPI(SUCCEED)
|
||
} /* H5HF_cache_dblock_size() */
|
||
|