summaryrefslogtreecommitdiffstats
path: root/src/H5HFcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5HFcache.c')
-rw-r--r--src/H5HFcache.c239
1 files changed, 207 insertions, 32 deletions
diff --git a/src/H5HFcache.c b/src/H5HFcache.c
index e174260..63e4e46 100644
--- a/src/H5HFcache.c
+++ b/src/H5HFcache.c
@@ -35,6 +35,7 @@
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5HFpkg.h" /* Fractal heaps */
+#include "H5MMprivate.h" /* Memory management */
#include "H5Vprivate.h" /* Vectors and arrays */
/****************/
@@ -309,8 +310,9 @@ HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr);
if(metadata_chksum != 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect metadata checksum for fractal heap header")
- /* Heap ID length */
- UINT16DECODE(p, hdr->id_len);
+ /* 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) */
@@ -333,13 +335,62 @@ HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr);
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 */
HDassert((size_t)(p - buf) == size);
+ /* Check for I/O filter information to decode */
+ if(hdr->filter_len > 0) {
+ size_t filter_info_size; /* Size of filter information */
+ H5O_pline_t *pline; /* Pipeline information from the header on disk */
+
+ /* 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 */
+
+ /* Check if the current buffer can be re-used, or needs to be re-sized */
+ if(filter_info_size > size) {
+ if((buf = H5FL_BLK_REALLOC(header_block, buf, filter_info_size)) == NULL)
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "can't allocate space to decode I/O pipeline filters")
+ } /* end if */
+
+ /* Read in I/O filter information */
+ if(H5F_block_read(f, H5FD_MEM_FHEAP_HDR, (addr + size), filter_info_size, dxpl_id, buf) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "can't read fractal heap header's I/O pipeline filter info")
+
+ p = buf;
+
+ /* 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_decode(hdr->f, p, H5O_PLINE_ID)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDECODE, NULL, "can't decode I/O pipeline filters")
+
+ /* Copy the information into the header's I/O pipeline structure */
+ if(NULL == H5O_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_free(H5O_PLINE_ID, pline);
+
+ /* Compute the heap header's size */
+ hdr->heap_size = size + filter_info_size;
+ } /* end if */
+ else
+ /* Set the heap header's size */
+ hdr->heap_size = size;
+
/* 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")
@@ -398,7 +449,7 @@ HDfprintf(stderr, "%s: Flushing heap header, addr = %a, destroy = %u\n", FUNC, a
HDassert(hdr->dirty);
/* Compute the size of the heap header on disk */
- size = H5HF_HEADER_SIZE(hdr);
+ size = hdr->heap_size;
/* Allocate temporary buffer */
if((buf = H5FL_BLK_MALLOC(header_block, size)) == NULL)
@@ -422,8 +473,9 @@ HDfprintf(stderr, "%s: Flushing heap header, addr = %a, destroy = %u\n", FUNC, a
HDmemset(p, 0, (size_t)4);
p += 4;
- /* Heap ID length */
- UINT16ENCODE(p, hdr->id_len);
+ /* 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) */
@@ -447,11 +499,27 @@ HDfprintf(stderr, "%s: Flushing heap header, addr = %a, destroy = %u\n", FUNC, a
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_encode(hdr->f, p, &(hdr->pline), H5O_PLINE_ID) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, FAIL, "can't encode I/O pipeline fiters")
+ p += hdr->filter_len;
+ } /* end if */
+
/* 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)
@@ -500,6 +568,10 @@ H5HF_cache_hdr_dest(H5F_t UNUSED *f, H5HF_hdr_t *hdr)
/* 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_reset(H5O_PLINE_ID, &(hdr->pline));
+
/* Free the shared info itself */
H5FL_FREE(H5HF_hdr_t, hdr);
@@ -570,7 +642,7 @@ H5HF_cache_hdr_size(const H5F_t UNUSED *f, const H5HF_hdr_t *hdr, size_t *size_p
HDassert(size_ptr);
/* Set size value */
- *size_ptr = H5HF_HEADER_SIZE(hdr);
+ *size_ptr = hdr->heap_size;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5HF_cache_hdr_size() */
@@ -595,6 +667,7 @@ 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 */
@@ -614,11 +687,22 @@ H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_size,
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;
+
/* Share common heap information */
- dblock->hdr = par_info->hdr;
- if(H5HF_hdr_incr(dblock->hdr) < 0)
+ 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")
+#ifdef LATER
+ /* Check for I/O filters on this heap */
+ if(hdr->filter_len > 0) {
+HDfprintf(stderr, "%s: I/O filters not supported yet!\n", FUNC);
+HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, NULL, "I/O filters not supported yet")
+ } /* end if */
+#endif /* LATER */
+
/* Set block's internal information */
dblock->size = *size;
dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dblock->size);
@@ -656,7 +740,7 @@ H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_size,
/* Address of heap that owns this block (skip) */
H5F_addr_decode(f, &p, &heap_addr);
- if(H5F_addr_ne(heap_addr, dblock->hdr->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 */
@@ -669,7 +753,7 @@ H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_size,
} /* end if */
/* Offset of heap within the heap's address space */
- UINT64DECODE_VAR(p, dblock->block_off, dblock->hdr->heap_off_size);
+ UINT64DECODE_VAR(p, dblock->block_off, hdr->heap_off_size);
/* Set return value */
ret_value = dblock;
@@ -709,6 +793,8 @@ H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
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 */
@@ -742,10 +828,46 @@ H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
/* Sanity check */
HDassert((size_t)(p - dblock->blk) == H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr));
+#ifdef LATER
+ /* 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")
+HDfprintf(stderr, "%s: nbytes = %Zu, write_size = %Zu, write_buf = %p\n", FUNC, nbytes, write_size, write_buf);
+HDfprintf(stderr, "%s: dblock->size = %Zu, dblock->blk = %p\n", FUNC, dblock->size, dblock->blk);
+
+HDfprintf(stderr, "%s: I/O filters not supported yet!\n", FUNC);
+HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "I/O filters not supported yet")
+ } /* end if */
+ else {
+#endif /* LATER */
+ write_buf = dblock->blk;
+ write_size = dblock->size;
+#ifdef LATER
+ } /* end else */
+#endif /* LATER */
+
/* Write the direct block */
- if(H5F_block_write(f, H5FD_MEM_FHEAP_DBLOCK, addr, (size_t)dblock->size, dxpl_id, dblock->blk) < 0)
+ 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 */
@@ -892,6 +1014,7 @@ H5HF_cache_dblock_size(const H5F_t UNUSED *f, const H5HF_direct_t *dblock, size_
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 */
@@ -917,9 +1040,12 @@ HDfprintf(stderr, "%s: Load indirect block, addr = %a\n", FUNC, addr);
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;
+
/* Share common heap information */
- iblock->hdr = par_info->hdr;
- if(H5HF_hdr_incr(iblock->hdr) < 0)
+ 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 */
@@ -929,7 +1055,7 @@ HDfprintf(stderr, "%s: Load indirect block, addr = %a\n", FUNC, addr);
iblock->nchildren = 0;
/* Compute size of indirect block */
- iblock->size = H5HF_MAN_INDIRECT_SIZE(iblock->hdr, iblock);
+ iblock->size = H5HF_MAN_INDIRECT_SIZE(hdr, iblock);
/* Allocate buffer to decode block */
/* XXX: Use free list factories? */
@@ -964,7 +1090,7 @@ HDfprintf(stderr, "%s: Load indirect block, addr = %a\n", FUNC, addr);
/* Address of heap that owns this block */
H5F_addr_decode(f, &p, &heap_addr);
- if(H5F_addr_ne(heap_addr, iblock->hdr->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 */
@@ -980,31 +1106,59 @@ HDfprintf(stderr, "%s: Load indirect block, addr = %a\n", FUNC, addr);
} /* end if */
else {
/* Set max. # of rows in this block */
- iblock->max_rows = iblock->hdr->man_dtable.max_root_rows;
+ 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, iblock->hdr->heap_off_size);
+ UINT64DECODE_VAR(p, iblock->block_off, hdr->heap_off_size);
- /* Allocate & decode indirect block entry tables */
+ /* 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 * iblock->hdr->man_dtable.cparam.width))))
+ 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")
- for(u = 0; u < (iblock->nrows * iblock->hdr->man_dtable.cparam.width); u++) {
+ 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 LATER
- /* Decode direct & indirect blocks differently (later, when direct blocks can be compressed) */
- if(u < (iblock->hdr->man_dtable.max_direct_rows * iblock->hdr->man_dtable.cparam.width))
- UINT32DECODE_VAR(p, iblock->ents[u].free_space, iblock->hdr->man_dtable.max_dir_blk_off_size)
-#endif /* LATER */
#ifdef QAK
HDfprintf(stderr, "%s: iblock->ents[%Zu] = {%a}\n", FUNC, u, iblock->ents[u].addr);
#endif /* QAK */
@@ -1113,6 +1267,31 @@ HDfprintf(stderr, "%s: iblock->ents[%Zu] = {%a}\n", FUNC, u, iblock->ents[u].add
/* 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)) {
@@ -1121,12 +1300,6 @@ HDfprintf(stderr, "%s: iblock->ents[%Zu] = {%a}\n", FUNC, u, iblock->ents[u].add
max_child = u;
} /* end if */
#endif /* NDEBUG */
-
-#ifdef LATER
- /* Encode direct & indirect blocks differently (when direct blocks can be compressed) */
- if(u < (hdr->man_dtable.max_direct_rows * hdr->man_dtable.cparam.width))
- UINT32ENCODE_VAR(p, iblock->ents[u].free_space, hdr->man_dtable.max_dir_blk_off_size)
-#endif /* LATER */
} /* end for */
/* Sanity check */
@@ -1197,6 +1370,8 @@ HDfprintf(stderr, "%s: Destroying indirect block\n", FUNC);
/* 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);
/* Free fractal heap indirect block info */
H5FL_FREE(H5HF_indirect_t, iblock);