diff options
Diffstat (limited to 'src/H5HFcache.c')
-rw-r--r-- | src/H5HFcache.c | 871 |
1 files changed, 462 insertions, 409 deletions
diff --git a/src/H5HFcache.c b/src/H5HFcache.c index e0b0c16..2f3a78e 100644 --- a/src/H5HFcache.c +++ b/src/H5HFcache.c @@ -62,23 +62,23 @@ /* Local Prototypes */ /********************/ -/* Metadata cache callbacks */ +/* 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); 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_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); -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); 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); 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); - -/* 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); +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); +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 */ @@ -94,16 +94,6 @@ const H5AC_class_t H5AC_FHEAP_HDR[1] = {{ (H5AC_size_func_t)H5HF_cache_hdr_size, }}; -/* H5HF direct block inherits cache-like properties from H5AC */ -const H5AC_class_t H5AC_FHEAP_DBLOCK[1] = {{ - H5AC_FHEAP_DBLOCK_ID, - (H5AC_load_func_t)H5HF_cache_dblock_load, - (H5AC_flush_func_t)H5HF_cache_dblock_flush, - (H5AC_dest_func_t)H5HF_cache_dblock_dest, - (H5AC_clear_func_t)H5HF_cache_dblock_clear, - (H5AC_size_func_t)H5HF_cache_dblock_size, -}}; - /* H5HF indirect block inherits cache-like properties from H5AC */ const H5AC_class_t H5AC_FHEAP_IBLOCK[1] = {{ H5AC_FHEAP_IBLOCK_ID, @@ -114,6 +104,16 @@ const H5AC_class_t H5AC_FHEAP_IBLOCK[1] = {{ (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 */ @@ -257,7 +257,8 @@ H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *ud size_t size; /* Header size */ uint8_t *buf = NULL; /* Temporary buffer */ const uint8_t *p; /* Pointer into raw data buffer */ - uint32_t metadata_chksum; /* Metadata checksum value */ + 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 */ @@ -277,7 +278,7 @@ HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr); /* Set the heap header's address */ hdr->heap_addr = addr; - /* Compute the size of the fractal heap header on disk */ + /* Compute the 'base' size of the fractal heap header on disk */ size = H5HF_HEADER_SIZE(hdr); /* Allocate temporary buffer */ @@ -304,12 +305,6 @@ HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr); if(*p++ != 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unknown metadata flag in fractal heap header") - /* Metadata checksum (unused, currently) */ - UINT32DECODE(p, metadata_chksum); -/* XXX: Verify checksum */ - if(metadata_chksum != 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect metadata checksum for fractal heap header") - /* General heap information */ UINT16DECODE(p, hdr->id_len); /* Heap ID length */ UINT16DECODE(p, hdr->filter_len); /* I/O filters' encoded length */ @@ -318,6 +313,7 @@ HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr); /* (bit 0: "huge" object IDs have wrapped) */ 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 */ @@ -343,29 +339,37 @@ HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr); HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, NULL, "unable to encode managed obj. doubling table info") /* Sanity check */ - HDassert((size_t)(p - buf) == size); + /* (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_size; /* Size of filter information */ - H5O_pline_t *pline; /* Pipeline information from the header on disk */ + 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 */ - /* 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 */ + /* 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 */ - if(H5F_block_read(f, H5FD_MEM_FHEAP_HDR, (addr + size), filter_info_size, dxpl_id, buf) < 0) + /* (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") - p = buf; + /* 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); @@ -376,6 +380,7 @@ HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr); /* 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") + p += hdr->filter_len; /* Copy the information into the header's I/O pipeline structure */ if(NULL == H5O_copy(H5O_PLINE_ID, pline, &(hdr->pline))) @@ -383,14 +388,25 @@ HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr); /* 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; + /* Metadata checksum */ + UINT32DECODE(p, stored_chksum); + + /* Sanity check */ + HDassert((size_t)(p - buf) == hdr->heap_size); + + /* Compute checksum on entire header */ + /* (including the filter information, if present) */ + computed_chksum = H5_fletcher32(buf, (hdr->heap_size - H5HF_SIZEOF_CHKSUM)); + + /* Verify checksum */ + if(stored_chksum != computed_chksum) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, 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") @@ -444,6 +460,7 @@ HDfprintf(stderr, "%s: Flushing heap header, addr = %a, destroy = %u\n", FUNC, a 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); @@ -468,11 +485,6 @@ HDfprintf(stderr, "%s: Flushing heap header, addr = %a, destroy = %u\n", FUNC, a /* XXX: Set this? */ *p++ = 0; - /* Metadata checksum */ -/* XXX: Set this! (After all the metadata is in the buffer) */ - HDmemset(p, 0, (size_t)4); - p += 4; - /* General heap information */ UINT16ENCODE(p, hdr->id_len); /* Heap ID length */ UINT16ENCODE(p, hdr->filter_len); /* I/O filters' encoded length */ @@ -481,6 +493,7 @@ HDfprintf(stderr, "%s: Flushing heap header, addr = %a, destroy = %u\n", FUNC, a /* (bit 0: "huge" object IDs have wrapped) */ 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 */ @@ -520,6 +533,12 @@ HDfprintf(stderr, "%s: Flushing heap header, addr = %a, destroy = %u\n", FUNC, a p += hdr->filter_len; } /* end if */ + /* Compute metadata checksum */ + metadata_chksum = H5_fletcher32(buf, hdr->heap_size - H5HF_SIZEOF_CHKSUM); + + /* 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) @@ -649,354 +668,6 @@ H5HF_cache_hdr_size(const H5F_t UNUSED *f, const H5HF_hdr_t *hdr, size_t *size_p /*------------------------------------------------------------------------- - * 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 */ - uint32_t metadata_chksum; /* Metadata checksum value */ - 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; - - /* 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") - -#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); - - /* 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") - - /* Read direct block from disk */ - if(H5F_block_read(f, H5FD_MEM_FHEAP_DBLOCK, addr, (size_t)dblock->size, dxpl_id, dblock->blk) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "can't read fractal heap 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") - - /* Metadata flags (unused, currently) */ -/* XXX: Plan out metadata flags (including "read-only duplicate" feature) */ - if(*p++ != 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unknown metadata flag in fractal heap direct block") - - /* Metadata checksum (unused, currently) */ - UINT32DECODE(p, metadata_chksum); -/* XXX: Verify checksum */ - if(metadata_chksum != 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect metadata checksum for fractal heap direct block") - - /* Address of heap that owns this block (skip) */ - H5F_addr_decode(f, &p, &heap_addr); - if(H5F_addr_ne(heap_addr, 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); - - /* Set return value */ - ret_value = dblock; - -done: - if(!ret_value && dblock) - (void)H5HF_cache_dblock_dest(f, dblock); - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_cache_dblock_load() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_cache_dblock_flush - * - * Purpose: Flushes a dirty fractal heap direct block to disk. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 27 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_direct_t *dblock) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_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; - - 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; - - /* Metadata status flags */ -/* XXX: Set this? */ - *p++ = 0; - - /* Metadata checksum */ -/* XXX: Set this! (After all the metadata is in the buffer) */ - HDmemset(p, 0, (size_t)4); - p += 4; - - /* 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); - - /* 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, 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 */ - - /* 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 */ - 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() */ - - -/*------------------------------------------------------------------------- * Function: H5HF_cache_iblock_load * * Purpose: Loads a fractal heap indirect block from the disk. @@ -1021,7 +692,8 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrows uint8_t *buf = NULL; /* Temporary buffer */ const uint8_t *p; /* Pointer into raw data buffer */ haddr_t heap_addr; /* Address of heap header in the file */ - uint32_t metadata_chksum; /* Metadata checksum value */ + 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 */ @@ -1082,12 +754,6 @@ HDfprintf(stderr, "%s: Load indirect block, addr = %a\n", FUNC, addr); if(*p++ != 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unknown metadata flag in fractal heap direct block") - /* Metadata checksum (unused, currently) */ - UINT32DECODE(p, metadata_chksum); -/* XXX: Verify checksum */ - if(metadata_chksum != 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect metadata checksum for fractal heap direct block") - /* Address of heap that owns this block */ H5F_addr_decode(f, &p, &heap_addr); if(H5F_addr_ne(heap_addr, hdr->heap_addr)) @@ -1164,6 +830,22 @@ HDfprintf(stderr, "%s: iblock->ents[%Zu] = {%a}\n", FUNC, u, iblock->ents[u].add #endif /* QAK */ } /* end for */ + /* Sanity check */ + HDassert(iblock->nchildren); /* indirect blocks w/no children should have been deleted */ + + /* Metadata checksum */ + UINT32DECODE(p, stored_chksum); + + /* Sanity check */ + HDassert((size_t)(p - buf) == iblock->size); + + /* Compute checksum on indirect block */ + computed_chksum = H5_fletcher32(buf, (iblock->size - H5HF_SIZEOF_CHKSUM)); + + /* Verify checksum */ + if(stored_chksum != computed_chksum) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, 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 */ @@ -1178,10 +860,6 @@ HDfprintf(stderr, "%s: iblock->ents[%Zu] = {%a}\n", FUNC, u, iblock->ents[u].add else iblock->child_iblocks = NULL; - /* Sanity checks */ - HDassert((size_t)(p - buf) == iblock->size); - HDassert(iblock->nchildren); /* indirect blocks w/no children should have been deleted */ - /* Set return value */ ret_value = iblock; @@ -1233,6 +911,7 @@ HDfprintf(stderr, "%s: Flushing indirect block, addr = %a, destroy = %u\n", FUNC 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 */ @@ -1262,11 +941,6 @@ HDfprintf(stderr, "%s: hdr->man_dtable.cparam.width = %u\n", FUNC, hdr->man_dtab /* XXX: Set this? */ *p++ = 0; - /* Metadata checksum */ -/* XXX: Set this! (After all the metadata is in the buffer) */ - HDmemset(p, 0, (size_t)4); - p += 4; - /* Address of heap header for heap which owns this block */ H5F_addr_encode(f, &p, hdr->heap_addr); @@ -1316,6 +990,12 @@ HDfprintf(stderr, "%s: iblock->filt_ents[%Zu] = {%Zu, %x}\n", FUNC, u, iblock->f #endif /* NDEBUG */ } /* end for */ + /* Compute checksum */ + metadata_chksum = H5_fletcher32(buf, iblock->size - H5HF_SIZEOF_CHKSUM); + + /* Metadata checksum */ + UINT32ENCODE(p, metadata_chksum); + /* Sanity check */ HDassert((size_t)(p - buf) == iblock->size); #ifndef NDEBUG @@ -1464,3 +1144,376 @@ H5HF_cache_iblock_size(const H5F_t UNUSED *f, const H5HF_indirect_t *iblock, siz 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; + + /* 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") + +#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); + + /* 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") + + /* Read direct block from disk */ + if(H5F_block_read(f, H5FD_MEM_FHEAP_DBLOCK, addr, (size_t)dblock->size, dxpl_id, dblock->blk) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "can't read fractal heap 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") + + /* Metadata flags (unused, currently) */ +/* XXX: Plan out metadata flags (including "read-only duplicate" feature) */ + if(*p++ != 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unknown metadata flag in fractal heap direct block") + + /* 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_fletcher32(dblock->blk, dblock->size); + + /* Verify checksum */ + if(stored_chksum != computed_chksum) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, 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 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_direct_t *dblock) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_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; + + 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; + + /* Metadata status flags */ +/* XXX: Set this? */ + *p++ = 0; + + /* 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_fletcher32(dblock->blk, dblock->size); + + /* Metadata checksum */ + UINT32ENCODE(p, metadata_chksum); + } /* end if */ + + /* 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, 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 */ + + /* 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 */ + 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() */ + |