diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2006-08-22 17:13:17 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2006-08-22 17:13:17 (GMT) |
commit | dfd71ce12683526f1fdb6abeb43d4a1a107cfe49 (patch) | |
tree | 609ee7979f4a4e6732c36f41817e071e17a8764e /src/H5HFcache.c | |
parent | 058eb9921de06d297f80f2f633fb6638fd8d6f68 (diff) | |
download | hdf5-dfd71ce12683526f1fdb6abeb43d4a1a107cfe49.zip hdf5-dfd71ce12683526f1fdb6abeb43d4a1a107cfe49.tar.gz hdf5-dfd71ce12683526f1fdb6abeb43d4a1a107cfe49.tar.bz2 |
[svn-r12610] Description:
Add support for checksumming fractal heaps. This is always enabled for
the heap header and indirect blocks (as they are "pure" metadata) and is
optional for direct blocks, since they may be used for "raw" data.
Also, rearrange direct block routines in H5HFcache.c to be in a more
sensible location in the file. (probably should have been a separate checkin,
since the diffs are mostly useless for this checkin... *sigh*)
Tested on:
Linux/32 2.6 (chicago)
Linux/64 2.6 (chicago2)
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() */ + |