diff options
author | Scot Breitenfeld <brtnfld@hdfgroup.org> | 2015-07-02 19:12:03 (GMT) |
---|---|---|
committer | Scot Breitenfeld <brtnfld@hdfgroup.org> | 2015-07-02 19:12:03 (GMT) |
commit | 985e8d02a47c7e282e9d5eb7ed11dc6d47e7ae0e (patch) | |
tree | 98599798b2d21610307b4109ce76679e3948f6ca /src/H5HLcache.c | |
parent | 2a567e8155a883a1d79a7879e953449ed7505945 (diff) | |
parent | 9804fed58f4f30843d406861a2daf67944c244de (diff) | |
download | hdf5-985e8d02a47c7e282e9d5eb7ed11dc6d47e7ae0e.zip hdf5-985e8d02a47c7e282e9d5eb7ed11dc6d47e7ae0e.tar.gz hdf5-985e8d02a47c7e282e9d5eb7ed11dc6d47e7ae0e.tar.bz2 |
[svn-r27327] svn merge -r27208:27326 https://svn.hdfgroup.uiuc.edu/hdf5/trunk
Diffstat (limited to 'src/H5HLcache.c')
-rw-r--r-- | src/H5HLcache.c | 788 |
1 files changed, 397 insertions, 391 deletions
diff --git a/src/H5HLcache.c b/src/H5HLcache.c index b2c764d..2054e34 100644 --- a/src/H5HLcache.c +++ b/src/H5HLcache.c @@ -69,18 +69,26 @@ /********************/ /* Metadata cache callbacks */ -static void *H5HL_prefix_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata); -static herr_t H5HL_prefix_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, - void *thing, unsigned *flags_ptr); -static herr_t H5HL_prefix_dest(H5F_t *f, void *thing); -static herr_t H5HL_prefix_clear(H5F_t *f, void *thing, hbool_t destroy); -static herr_t H5HL_prefix_size(const H5F_t *f, const void *thing, size_t *size_ptr); -static void *H5HL_datablock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata); -static herr_t H5HL_datablock_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, - void *thing, unsigned *flags_ptr); -static herr_t H5HL_datablock_dest(H5F_t *f, void *thing); -static herr_t H5HL_datablock_clear(H5F_t *f, void *thing, hbool_t destroy); -static herr_t H5HL_datablock_size(const H5F_t *f, const void *thing, size_t *size_ptr); +static herr_t H5HL__cache_prefix_get_load_size(const void *udata, size_t *image_len); +static void *H5HL__cache_prefix_deserialize(const void *image, size_t len, + void *udata, hbool_t *dirty); +static herr_t H5HL__cache_prefix_image_len(const void *thing, + size_t *image_len, hbool_t *compressed_ptr, + size_t *compressed_image_len_ptr); +static herr_t H5HL__cache_prefix_serialize(const H5F_t *f, void *image, + size_t len, void *thing); +static herr_t H5HL__cache_prefix_free_icr(void *thing); + +static herr_t H5HL__cache_datablock_get_load_size(const void *udata, + size_t *image_len); +static void *H5HL__cache_datablock_deserialize(const void *image, size_t len, + void *udata, hbool_t *dirty); +static herr_t H5HL__cache_datablock_image_len(const void *thing, + size_t *image_len, hbool_t *compressed_ptr, + size_t *compressed_image_len_ptr); +static herr_t H5HL__cache_datablock_serialize(const H5F_t *f, void *image, + size_t len, void *thing); +static herr_t H5HL__cache_datablock_free_icr(void *thing); /*********************/ @@ -89,23 +97,35 @@ static herr_t H5HL_datablock_size(const H5F_t *f, const void *thing, size_t *siz /* H5HL inherits cache-like properties from H5AC */ const H5AC_class_t H5AC_LHEAP_PRFX[1] = {{ - H5AC_LHEAP_PRFX_ID, - H5HL_prefix_load, - H5HL_prefix_flush, - H5HL_prefix_dest, - H5HL_prefix_clear, - NULL, - H5HL_prefix_size, + H5AC_LHEAP_PRFX_ID, /* Metadata client ID */ + "local heap prefix", /* Metadata client name (for debugging) */ + H5FD_MEM_LHEAP, /* File space memory type for client */ + H5AC__CLASS_SPECULATIVE_LOAD_FLAG, /* Client class behavior flags */ + H5HL__cache_prefix_get_load_size, /* 'get_load_size' callback */ + H5HL__cache_prefix_deserialize, /* 'deserialize' callback */ + H5HL__cache_prefix_image_len, /* 'image_len' callback */ + NULL, /* 'pre_serialize' callback */ + H5HL__cache_prefix_serialize, /* 'serialize' callback */ + NULL, /* 'notify' callback */ + H5HL__cache_prefix_free_icr, /* 'free_icr' callback */ + NULL, /* 'clear' callback */ + NULL, /* 'fsf_size' callback */ }}; const H5AC_class_t H5AC_LHEAP_DBLK[1] = {{ - H5AC_LHEAP_DBLK_ID, - H5HL_datablock_load, - H5HL_datablock_flush, - H5HL_datablock_dest, - H5HL_datablock_clear, - NULL, - H5HL_datablock_size, + H5AC_LHEAP_DBLK_ID, /* Metadata client ID */ + "local heap datablock", /* Metadata client name (for debugging) */ + H5FD_MEM_LHEAP, /* File space memory type for client */ + H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */ + H5HL__cache_datablock_get_load_size,/* 'get_load_size' callback */ + H5HL__cache_datablock_deserialize, /* 'deserialize' callback */ + H5HL__cache_datablock_image_len, /* 'image_len' callback */ + NULL, /* 'pre_serialize' callback */ + H5HL__cache_datablock_serialize, /* 'serialize' callback */ + NULL, /* 'notify' callback */ + H5HL__cache_datablock_free_icr, /* 'free_icr' callback */ + NULL, /* 'clear' callback */ + NULL, /* 'fsf_size' callback */ }}; @@ -149,7 +169,7 @@ H5HL__fl_deserialize(H5HL_t *heap) /* Build free list */ free_block = heap->free_block; while(H5HL_FREE_NULL != free_block) { - const uint8_t *p; /* Pointer into image buffer */ + const uint8_t *image; /* Pointer into image buffer */ /* Sanity check */ if(free_block >= heap->dblk_size) @@ -163,13 +183,13 @@ H5HL__fl_deserialize(H5HL_t *heap) fl->next = NULL; /* Decode offset of next free block */ - p = heap->dblk_image + free_block; - H5F_DECODE_LENGTH_LEN(p, free_block, heap->sizeof_size); + image = heap->dblk_image + free_block; + H5F_DECODE_LENGTH_LEN(image, free_block, heap->sizeof_size); if(free_block == 0) HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "free block size is zero?") /* Decode length of this free block */ - H5F_DECODE_LENGTH_LEN(p, fl->size, heap->sizeof_size); + H5F_DECODE_LENGTH_LEN(image, fl->size, heap->sizeof_size); if((fl->offset + fl->size) > heap->dblk_size) HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "bad heap free list") @@ -217,17 +237,17 @@ H5HL__fl_serialize(const H5HL_t *heap) /* Serialize the free list into the heap data's image */ for(fl = heap->freelist; fl; fl = fl->next) { - uint8_t *p; /* Pointer into raw data buffer */ + uint8_t *image; /* Pointer into raw data buffer */ HDassert(fl->offset == H5HL_ALIGN(fl->offset)); - p = heap->dblk_image + fl->offset; + image = heap->dblk_image + fl->offset; if(fl->next) - H5F_ENCODE_LENGTH_LEN(p, fl->next->offset, heap->sizeof_size) + H5F_ENCODE_LENGTH_LEN(image, fl->next->offset, heap->sizeof_size) else - H5F_ENCODE_LENGTH_LEN(p, H5HL_FREE_NULL, heap->sizeof_size) + H5F_ENCODE_LENGTH_LEN(image, H5HL_FREE_NULL, heap->sizeof_size) - H5F_ENCODE_LENGTH_LEN(p, fl->size, heap->sizeof_size) + H5F_ENCODE_LENGTH_LEN(image, fl->size, heap->sizeof_size) } /* end for */ FUNC_LEAVE_NOAPI_VOID @@ -235,69 +255,88 @@ H5HL__fl_serialize(const H5HL_t *heap) /*------------------------------------------------------------------------- - * Function: H5HL_prefix_load + * Function: H5HL__cache_prefix_get_load_size() * - * Purpose: Loads a local heap prefix from disk. + * Purpose: Return the size of the buffer the metadata cache should + * load from file and pass to the deserialize routine. * - * Return: Success: Ptr to a local heap memory data structure. - * Failure: NULL + * The version 2 metadata cache callbacks included a test to + * ensure that the read did not pass the end of file, but this + * functionality has been moved to H5C_load_entry(). Thus + * all this function does is set *image_len equal to + * H5HL_SPEC_READ_SIZE, leaving it to the metadata cache to + * reduce the size of the read if appropriate. * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 17 1997 + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: John Mainzer + * 6/21/14 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HL__cache_prefix_get_load_size(const void H5_ATTR_UNUSED *_udata, size_t *image_len) +{ + FUNC_ENTER_STATIC_NOERR + + HDassert(image_len); + + *image_len = H5HL_SPEC_READ_SIZE; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HL__cache_prefix_get_load_size() */ + + +/*------------------------------------------------------------------------- + * Function: H5HL__cache_prefix_deserialize + * + * Purpose: Given a buffer containing the on disk image of the local + * heap prefix, deserialize it, load its contents into a newly allocated + * instance of H5HL_prfx_t, and return a pointer to the new instance. + * + * Return: Success: Pointer to in core representation + * Failure: NULL + * + * Programmer: John Mainzer + * 6/21/14 * *------------------------------------------------------------------------- */ static void * -H5HL_prefix_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata) +H5HL__cache_prefix_deserialize(const void *_image, size_t len, void *_udata, + hbool_t H5_ATTR_UNUSED *dirty) { - H5HL_t *heap = NULL; /* Local heap */ - H5HL_prfx_t *prfx = NULL; /* Heap prefix deserialized */ + H5HL_t *heap = NULL; /* Local heap */ + H5HL_prfx_t *prfx = NULL; /* Heap prefix deserialized */ + const uint8_t *image = (const uint8_t *)_image; /* Pointer into decoding buffer */ H5HL_cache_prfx_ud_t *udata = (H5HL_cache_prfx_ud_t *)_udata; /* User data for callback */ - uint8_t buf[H5HL_SPEC_READ_SIZE]; /* Buffer for decoding */ - size_t spec_read_size; /* Size of buffer to speculatively read in */ - const uint8_t *p; /* Pointer into decoding buffer */ - haddr_t eoa; /* Relative end of file address */ - hsize_t min; /* temp min value to avoid macro nesting */ - H5HL_prfx_t *ret_value; /* Return value */ + void *ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC - /* check arguments */ - HDassert(f); - HDassert(H5F_addr_defined(addr)); + /* Check arguments */ + HDassert(image); + HDassert(len > 0); HDassert(udata); HDassert(udata->sizeof_size > 0); HDassert(udata->sizeof_addr > 0); HDassert(udata->sizeof_prfx > 0); - HDassert(udata->sizeof_prfx <= sizeof(buf)); - - /* Make certain we don't speculatively read off the end of the file */ - if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_LHEAP))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "unable to determine file size") - - /* Compute the size of the speculative local heap prefix buffer */ - min = MIN(eoa - addr, H5HL_SPEC_READ_SIZE); - H5_CHECKED_ASSIGN(spec_read_size, size_t, min, hsize_t); - HDassert(spec_read_size >= udata->sizeof_prfx); - - /* Attempt to speculatively read both local heap prefix and heap data */ - if(H5F_block_read(f, H5FD_MEM_LHEAP, addr, spec_read_size, dxpl_id, buf) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read local heap prefix") - p = buf; + HDassert(H5F_addr_defined(udata->prfx_addr)); + HDassert(dirty); /* Check magic number */ - if(HDmemcmp(p, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC)) - HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "bad local heap signature") - p += H5_SIZEOF_MAGIC; + if(HDmemcmp(image, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC)) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "bad local heap signature") + image += H5_SIZEOF_MAGIC; /* Version */ - if(H5HL_VERSION != *p++) - HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "wrong version number in local heap") + if(H5HL_VERSION != *image++) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "wrong version number in local heap") /* Reserved */ - p += 3; - + image += 3; + /* Allocate space in memory for the heap */ if(NULL == (heap = H5HL_new(udata->sizeof_size, udata->sizeof_addr, udata->sizeof_prfx))) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate local heap structure") @@ -311,16 +350,16 @@ H5HL_prefix_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata) heap->prfx_size = udata->sizeof_prfx; /* Heap data size */ - H5F_DECODE_LENGTH_LEN(p, heap->dblk_size, udata->sizeof_size); + H5F_DECODE_LENGTH_LEN(image, heap->dblk_size, udata->sizeof_size); /* Free list head */ - H5F_DECODE_LENGTH_LEN(p, heap->free_block, udata->sizeof_size); + H5F_DECODE_LENGTH_LEN(image, heap->free_block, udata->sizeof_size); if((heap->free_block != H5HL_FREE_NULL) && (heap->free_block >= heap->dblk_size)) HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "bad heap free list") /* Heap data address */ - H5F_addr_decode_len(udata->sizeof_addr, &p, &(heap->dblk_addr)); + H5F_addr_decode_len(udata->sizeof_addr, &image, &(heap->dblk_addr)); /* Check if heap block exists */ if(heap->dblk_size) { @@ -329,35 +368,53 @@ H5HL_prefix_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata) /* Note that the heap should be a single object in the cache */ heap->single_cache_obj = TRUE; - /* Allocate space for the heap data image */ - if(NULL == (heap->dblk_image = H5FL_BLK_MALLOC(lheap_chunk, heap->dblk_size))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed") + /* Check if the current buffer from the speculative read + * already has the heap data + */ + if(len >= (heap->prfx_size + heap->dblk_size)) { + /* Allocate space for the heap data image */ + if(NULL == (heap->dblk_image = H5FL_BLK_MALLOC(lheap_chunk, heap->dblk_size))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed") - /* Check if the current buffer from the speculative read already has the heap data */ - if(spec_read_size >= (heap->prfx_size + heap->dblk_size)) { - /* Set p to the start of the data block. This is necessary + /* Set image to the start of the data block. This is necessary * because there may be a gap between the used portion of the * prefix and the data block due to alignment constraints. */ - p = buf + heap->prfx_size; + image = ((const uint8_t *)_image) + heap->prfx_size; /* Copy the heap data from the speculative read buffer */ - HDmemcpy(heap->dblk_image, p, heap->dblk_size); + HDmemcpy(heap->dblk_image, image, heap->dblk_size); + + /* Build free list */ + if(H5HL__fl_deserialize(heap) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't initialize free list") } /* end if */ else { - /* Read the local heap data block directly into buffer */ - if(H5F_block_read(f, H5FD_MEM_LHEAP, heap->dblk_addr, heap->dblk_size, dxpl_id, heap->dblk_image) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read heap data") - } /* end else */ - - /* Build free list */ - if(H5HL__fl_deserialize(heap) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't initialize free list") + /* the supplied buffer is too small -- We have already made note + * of the correct size, so simply return success. H5C_load_entry() + * will notice the size discrepency, and re-try the load. + */ + + /* Make certain that this is the first try ... */ + HDassert(!udata->made_attempt); + + /* ... and mark the udata so that we know that we have used up + * our first try. + */ + udata->made_attempt = TRUE; + } /* end else */ } /* end if */ - else - /* Note that the heap should _NOT_ be a single object in the cache */ + else { + /* Note that the heap should _NOT_ be a single + * object in the cache + */ heap->single_cache_obj = FALSE; + + } /* end else */ } /* end if */ + /* Set flag to indicate prefix from loaded from file */ + udata->loaded = TRUE; + /* Set return value */ ret_value = prfx; @@ -375,273 +432,269 @@ done: } /* end if */ FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HL_prefix_load() */ +} /* end H5HL__cache_prefix_deserialize() */ /*------------------------------------------------------------------------- - * Function: H5HL_prefix_flush + * Function: H5HL__cache_prefix_image_len * - * Purpose: Flushes a heap from memory to disk if it's dirty. Optionally - * deletes the heap from memory. + * Purpose: Return the on disk image size of a local heap prefix to the + * metadata cache via the image_len. * - * Return: Non-negative on success/Negative on failure + * Return: Success: SUCCEED + * Failure: FAIL * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 17 1997 + * Programmer: John Mainzer + * 6/21/14 * *------------------------------------------------------------------------- */ static herr_t -H5HL_prefix_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, - void *thing, unsigned H5_ATTR_UNUSED *flags_ptr) +H5HL__cache_prefix_image_len(const void *_thing, size_t *image_len, + hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr) { - H5HL_prfx_t *prfx = (H5HL_prfx_t *)thing; /* Local heap prefix to flush */ - H5WB_t *wb = NULL; /* Wrapped buffer for heap data */ - uint8_t heap_buf[H5HL_SPEC_READ_SIZE]; /* Buffer for heap */ - herr_t ret_value = SUCCEED; /* Return value */ + const H5HL_prfx_t *prfx = (const H5HL_prfx_t *)_thing; /* Pointer to local heap prefix to query */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC_NOERR - /* check arguments */ - HDassert(f); - HDassert(H5F_addr_defined(addr)); + /* Check arguments */ HDassert(prfx); + HDassert(prfx->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); + HDassert(prfx->cache_info.type == H5AC_LHEAP_PRFX); + HDassert(image_len); - if(prfx->cache_info.is_dirty) { - H5HL_t *heap = prfx->heap; /* Pointer to the local heap */ - uint8_t *buf; /* Pointer to heap buffer */ - size_t buf_size; /* Size of buffer for encoding & writing heap info */ - uint8_t *p; /* Pointer into raw data buffer */ - - /* Wrap the local buffer for serialized heap info */ - if(NULL == (wb = H5WB_wrap(heap_buf, sizeof(heap_buf)))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't wrap buffer") - - /* Compute the size of the buffer to encode & write */ - buf_size = heap->prfx_size; - if(heap->single_cache_obj) - buf_size += heap->dblk_size; - - /* Get a pointer to a buffer that's large enough for serialized heap */ - if(NULL == (buf = (uint8_t *)H5WB_actual(wb, buf_size))) - HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "can't get actual buffer") - - /* Update the free block value from the free list */ - heap->free_block = heap->freelist ? heap->freelist->offset : H5HL_FREE_NULL; - - /* Serialize the heap prefix */ - p = buf; - HDmemcpy(p, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC); - p += H5_SIZEOF_MAGIC; - *p++ = H5HL_VERSION; - *p++ = 0; /*reserved*/ - *p++ = 0; /*reserved*/ - *p++ = 0; /*reserved*/ - H5F_ENCODE_LENGTH_LEN(p, heap->dblk_size, heap->sizeof_size); - H5F_ENCODE_LENGTH_LEN(p, heap->free_block, heap->sizeof_size); - H5F_addr_encode_len(heap->sizeof_addr, &p, heap->dblk_addr); - - /* Check if the local heap is a single object in cache */ - if(heap->single_cache_obj) { - if((size_t)(p - buf) < heap->prfx_size) { - size_t gap; /* Size of gap between prefix and data block */ - - /* Set p to the start of the data block. This is necessary because - * there may be a gap between the used portion of the prefix and the - * data block due to alignment constraints. */ - gap = heap->prfx_size - (size_t)(p - buf); - HDmemset(p, 0, gap); - p += gap; - } /* end if */ - - /* Serialize the free list into the heap data's image */ - H5HL__fl_serialize(heap); - - /* Copy the heap data block into the cache image */ - HDmemcpy(p, heap->dblk_image, heap->dblk_size); - } /* end if */ - - /* Write the prefix [and possibly the data block] to the file */ - if(H5F_block_write(f, H5FD_MEM_LHEAP, addr, buf_size, dxpl_id, buf) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header and data to file") + /* Set the prefix's size */ + *image_len = prfx->heap->prfx_size; - prfx->cache_info.is_dirty = FALSE; - } /* end if */ + /* If the heap is stored as a single object, add in the + * data block size also + */ + if(prfx->heap->single_cache_obj) + *image_len += prfx->heap->dblk_size; - /* Should we destroy the memory version? */ - if(destroy) - if(H5HL_prefix_dest(f, prfx) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap prefix") -done: - /* Release resources */ - if(wb && H5WB_unwrap(wb) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer") + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HL__cache_prefix_image_len() */ - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HL_prefix_flush() */ +/****************************************/ +/* no H5HL_cache_prefix_pre_serialize() */ +/****************************************/ /*------------------------------------------------------------------------- - * Function: H5HL_prefix_dest + * Function: H5HL__cache_prefix_serialize * - * Purpose: Destroys a heap prefix in memory. + * Purpose: Given a pointer to an instance of H5HL_prfx_t and an + * appropriately sized buffer, serialize the contents of the + * instance for writing to disk, and copy the serialized data + * into the buffer. * - * Return: Non-negative on success/Negative on failure + * Return: Success: SUCCEED + * Failure: FAIL * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Jan 15 2003 + * Programmer: John Mainzer + * 7/21/14 * *------------------------------------------------------------------------- */ static herr_t -H5HL_prefix_dest(H5F_t *f, void *thing) +H5HL__cache_prefix_serialize(const H5F_t *f, void *_image, size_t len, + void *_thing) { - H5HL_prfx_t *prfx = (H5HL_prfx_t *)thing; /* Local heap prefix to destroy */ - herr_t ret_value = SUCCEED; /* Return value */ + H5HL_prfx_t *prfx = (H5HL_prfx_t *)_thing; /* Pointer to local heap prefix to query */ + H5HL_t *heap; /* Pointer to the local heap */ + uint8_t *image = (uint8_t *)_image; /* Pointer into image buffer */ + size_t buf_size; /* expected size of the image buffer */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC_NOERR - /* check arguments */ + /* Check arguments */ + HDassert(f); + HDassert(image); HDassert(prfx); - HDassert(prfx->heap); + HDassert(prfx->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); + HDassert(prfx->cache_info.type == H5AC_LHEAP_PRFX); HDassert(H5F_addr_eq(prfx->cache_info.addr, prfx->heap->prfx_addr)); + HDassert(prfx->heap); - /* Verify that entry is clean */ - HDassert(prfx->cache_info.is_dirty == FALSE); + /* Get the pointer to the heap */ + heap = prfx->heap; + HDassert(heap); - /* If we're going to free the space on disk, the address must be valid */ - HDassert(!prfx->cache_info.free_file_space_on_destroy || H5F_addr_defined(prfx->cache_info.addr)); + /* Compute the buffer size */ + buf_size = heap->prfx_size; + if(heap->single_cache_obj) + buf_size += heap->dblk_size; + HDassert(len == buf_size); + + /* Update the free block value from the free list */ + heap->free_block = heap->freelist ? heap->freelist->offset : H5HL_FREE_NULL; + + /* Serialize the heap prefix */ + HDmemcpy(image, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC); + image += H5_SIZEOF_MAGIC; + *image++ = H5HL_VERSION; + *image++ = 0; /*reserved*/ + *image++ = 0; /*reserved*/ + *image++ = 0; /*reserved*/ + H5F_ENCODE_LENGTH_LEN(image, heap->dblk_size, heap->sizeof_size); + H5F_ENCODE_LENGTH_LEN(image, heap->free_block, heap->sizeof_size); + H5F_addr_encode_len(heap->sizeof_addr, &image, heap->dblk_addr); + + /* Check if the local heap is a single object in cache */ + if(heap->single_cache_obj) { + if((size_t)(image - (uint8_t *)_image) < heap->prfx_size) { + size_t gap; /* Size of gap between prefix and data block */ + + /* Set image to the start of the data block. This is necessary + * because there may be a gap between the used portion of + * the prefix and the data block due to alignment constraints. + */ + gap = heap->prfx_size - (size_t)(image - (uint8_t *)_image); + HDmemset(image, 0, gap); + image += gap; + } /* end if */ - /* Check for freeing file space for local heap prefix */ - if(prfx->cache_info.free_file_space_on_destroy) { - hsize_t free_size; /* Size of region to free in file */ + /* Serialize the free list into the heap data's image */ + H5HL__fl_serialize(heap); - /* Compute size to free for later */ - free_size = prfx->heap->prfx_size; - if(prfx->heap->single_cache_obj) - free_size += prfx->heap->dblk_size; + /* Copy the heap data block into the cache image */ + HDmemcpy(image, heap->dblk_image, heap->dblk_size); - /* Free the local heap prefix [and possible the data block] on disk */ - /* (XXX: Nasty usage of internal DXPL value! -QAK) */ - if(H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, prfx->cache_info.addr, free_size) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap prefix") + /* Sanity check */ + HDassert((size_t)(image - (uint8_t *)_image) + heap->dblk_size == len); } /* end if */ + else { + /* Sanity check */ + HDassert((size_t)(image - (uint8_t *)_image) <= len); - /* Destroy local heap prefix */ - if(H5HL_prfx_dest(prfx) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't destroy local heap prefix") +#ifdef H5_CLEAR_MEMORY + /* Clear rest of local heap */ + HDmemset(image, 0, len - (size_t)(image - (uint8_t *)_image)); +#endif /* H5_CLEAR_MEMORY */ + } /* end else */ -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HL_prefix_dest() */ + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HL__cache_prefix_serialize() */ + +/******************************************/ +/* no H5HL_cache_prefix_notify() function */ +/******************************************/ /*------------------------------------------------------------------------- - * Function: H5HL_prefix_clear + * Function: H5HL__cache_prefix_free_icr * - * Purpose: Mark a local heap prefix in memory as non-dirty. + * Purpose: Free the supplied in core representation of a local heap + * prefix. * - * Return: Non-negative on success/Negative on failure + * Note that this function handles the partially initialize prefix + * from a failed speculative load attempt. See comments below for + * details. * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 20 2003 + * Note: The metadata cache sets the object's cache_info.magic to + * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr + * callback (checked in assert). + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: John Mainzer + * 6/21/14 * *------------------------------------------------------------------------- */ static herr_t -H5HL_prefix_clear(H5F_t H5_ATTR_UNUSED *f, void *thing, hbool_t destroy) +H5HL__cache_prefix_free_icr(void *_thing) { - H5HL_prfx_t *prfx = (H5HL_prfx_t *)thing; /* The local heap prefix to operate on */ - herr_t ret_value = SUCCEED; /* Return value */ + H5HL_prfx_t *prfx = (H5HL_prfx_t *)_thing; /* Pointer to local heap prefix to query */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC - /* check arguments */ + /* Check arguments */ HDassert(prfx); + HDassert(prfx->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC); + HDassert(prfx->cache_info.type == H5AC_LHEAP_PRFX); + HDassert(H5F_addr_eq(prfx->cache_info.addr, prfx->heap->prfx_addr)); - /* Mark heap prefix as clean */ - prfx->cache_info.is_dirty = FALSE; - - if(destroy) - if(H5HL_prefix_dest(f, prfx) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap prefix") + /* Destroy local heap prefix */ + if(H5HL_prfx_dest(prfx) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't destroy local heap prefix") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HL_prefix_clear() */ +} /* end H5HL__cache_prefix_free_icr() */ /*------------------------------------------------------------------------- - * Function: H5HL_prefix_size + * Function: H5HL__cache_datablock_get_load_size() * - * Purpose: Compute the size in bytes of the heap prefix on disk, - * and return it in *len_ptr. On failure, the value of *len_ptr - * is undefined. + * Purpose: Tell the metadata cache how large a buffer to read from + * file when loading a datablock. In this case, we simply lookup + * the correct value in the user data, and return it in *image_len. * - * Return: Non-negative on success/Negative on failure + * Return: Success: SUCCEED + * Failure: FAIL * - * Programmer: John Mainzer - * 5/13/04 + * Programmer: John Mainzer + * 6/21/14 * *------------------------------------------------------------------------- */ static herr_t -H5HL_prefix_size(const H5F_t H5_ATTR_UNUSED *f, const void *thing, size_t *size_ptr) +H5HL__cache_datablock_get_load_size(const void *_udata, size_t *image_len) { - const H5HL_prfx_t *prfx = (const H5HL_prfx_t *)thing; /* Pointer to local heap prefix to query */ + const H5HL_cache_dblk_ud_t *udata = (const H5HL_cache_dblk_ud_t *)_udata; /* User data for callback */ - FUNC_ENTER_NOAPI_NOINIT_NOERR - - /* check arguments */ - HDassert(prfx); - HDassert(prfx->heap); - HDassert(size_ptr); + FUNC_ENTER_STATIC_NOERR - /* Calculate size of prefix in cache */ - *size_ptr = prfx->heap->prfx_size; + /* Check arguments */ + HDassert(udata); + HDassert(udata->heap); + HDassert(udata->heap->dblk_size > 0); + HDassert(image_len); - /* If the heap is stored as a single object, add in the data block size also */ - if(prfx->heap->single_cache_obj) - *size_ptr += prfx->heap->dblk_size; + *image_len = udata->heap->dblk_size; FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5HL_prefix_size() */ +} /* end H5HL__cache_datablock_get_load_size() */ /*------------------------------------------------------------------------- - * Function: H5HL_datablock_load + * Function: H5HL__cache_datablock_deserialize * - * Purpose: Loads a local heap data block from disk. + * Purpose: Given a buffer containing the on disk image of a local + * heap data block, deserialize it, load its contents into a newly allocated + * instance of H5HL_dblk_t, and return a pointer to the new instance. * - * Return: Success: Ptr to a local heap data block memory data structure. - * Failure: NULL + * Return: Success: Pointer to in core representation + * Failure: NULL * - * Programmer: Quincey Koziol - * koziol@hdfgroup.org - * Jan 5 2010 + * Programmer: John Mainzer + * 6/21/14 * *------------------------------------------------------------------------- */ static void * -H5HL_datablock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata) +H5HL__cache_datablock_deserialize(const void *image, size_t len, void *_udata, + hbool_t H5_ATTR_UNUSED *dirty) { - H5HL_dblk_t *dblk = NULL; /* Local heap data block deserialized */ - H5HL_cache_dblk_ud_t *udata = (H5HL_cache_dblk_ud_t *)_udata; /* User data for callback */ - H5HL_dblk_t *ret_value; /* Return value */ + H5HL_dblk_t *dblk = NULL; /* Local heap data block deserialized */ + H5HL_cache_dblk_ud_t *udata = (H5HL_cache_dblk_ud_t *)_udata; /* User data for callback */ + void * ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC /* Check arguments */ - HDassert(f); - HDassert(H5F_addr_defined(addr)); + HDassert(image); + HDassert(len > 0); HDassert(udata); HDassert(udata->heap); + HDassert(udata->heap->dblk_size == len); HDassert(!udata->heap->single_cache_obj); HDassert(NULL == udata->heap->dblk); + HDassert(dirty); /* Allocate space in memory for the heap data block */ if(NULL == (dblk = H5HL_dblk_new(udata->heap))) @@ -653,9 +706,8 @@ H5HL_datablock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata) if(NULL == (udata->heap->dblk_image = H5FL_BLK_MALLOC(lheap_chunk, udata->heap->dblk_size))) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate data block image buffer") - /* Read local heap data block */ - if(H5F_block_read(f, H5FD_MEM_LHEAP, udata->heap->dblk_addr, udata->heap->dblk_size, dxpl_id, udata->heap->dblk_image) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read local heap data block") + /* copy the datablock from the read buffer */ + HDmemcpy(udata->heap->dblk_image, image, len); /* Build free list */ if(H5HL__fl_deserialize(udata->heap) < 0) @@ -675,180 +727,134 @@ done: HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, NULL, "unable to destroy local heap data block") FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HL_datablock_load() */ +} /* end H5HL__cache_datablock_deserialize() */ /*------------------------------------------------------------------------- - * Function: H5HL_datablock_flush + * Function: H5HL__cache_datablock_image_len * - * Purpose: Flushes a heap's data block from memory to disk if it's dirty. - * Optionally deletes the heap data block from memory. + * Purpose: Return the size of the on disk image of the datablock. * - * Return: Non-negative on success/Negative on failure + * Return: Success: SUCCEED + * Failure: FAIL * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 17 1997 + * Programmer: John Mainzer + * 6/21/14 * *------------------------------------------------------------------------- */ static herr_t -H5HL_datablock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, - void *_thing, unsigned H5_ATTR_UNUSED * flags_ptr) +H5HL__cache_datablock_image_len(const void *_thing, size_t *image_len, + hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr) { - H5HL_dblk_t *dblk = (H5HL_dblk_t *)_thing; /* Pointer to the local heap data block */ - herr_t ret_value = SUCCEED; /* Return value */ + const H5HL_dblk_t *dblk = (const H5HL_dblk_t *)_thing; /* Pointer to the local heap data block */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC_NOERR - /* check arguments */ - HDassert(f); - HDassert(H5F_addr_defined(addr)); + /* Check arguments */ HDassert(dblk); + HDassert(dblk->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); + HDassert(dblk->cache_info.type == H5AC_LHEAP_DBLK); HDassert(dblk->heap); - HDassert(!dblk->heap->single_cache_obj); - - if(dblk->cache_info.is_dirty) { - H5HL_t *heap = dblk->heap; /* Pointer to the local heap */ + HDassert(dblk->heap->dblk_size > 0); + HDassert(image_len); - /* Update the free block value from the free list */ - heap->free_block = heap->freelist ? heap->freelist->offset : H5HL_FREE_NULL; + *image_len = dblk->heap->dblk_size; - /* Serialize the free list into the heap data's image */ - H5HL__fl_serialize(heap); - - /* Write the data block to the file */ - if(H5F_block_write(f, H5FD_MEM_LHEAP, heap->dblk_addr, heap->dblk_size, dxpl_id, heap->dblk_image) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap data block to file") - - dblk->cache_info.is_dirty = FALSE; - } /* end if */ - - /* Should we destroy the memory version? */ - if(destroy) - if(H5HL_datablock_dest(f, dblk) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap data block") + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HL__cache_datablock_image_len() */ -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HL_datablock_flush() */ +/*******************************************/ +/* no H5HL_cache_datablock_pre_serialize() */ +/*******************************************/ /*------------------------------------------------------------------------- - * Function: H5HL_datablock_dest + * Function: H5HL__cache_datablock_serialize * - * Purpose: Destroys a local heap data block in memory. + * Purpose: Serialize the supplied datablock, and copy the serialized + * image into the supplied image buffer. * - * Return: Non-negative on success/Negative on failure + * Return: Success: SUCCEED + * Failure: FAIL * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Jan 15 2003 + * Programmer: John Mainzer + * 6/21/14 * *------------------------------------------------------------------------- */ static herr_t -H5HL_datablock_dest(H5F_t *f, void *_thing) +H5HL__cache_datablock_serialize(const H5F_t *f, void *image, size_t len, + void *_thing) { - H5HL_dblk_t *dblk = (H5HL_dblk_t *)_thing; /* Pointer to the local heap data block */ - herr_t ret_value = SUCCEED; /* Return value */ + H5HL_t *heap; /* Pointer to the local heap */ + H5HL_dblk_t *dblk = (H5HL_dblk_t *)_thing; /* Pointer to the local heap data block */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC_NOERR /* Check arguments */ + HDassert(f); + HDassert(image); HDassert(dblk); + HDassert(dblk->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); + HDassert(dblk->cache_info.type == H5AC_LHEAP_DBLK); HDassert(dblk->heap); - HDassert(!dblk->heap->single_cache_obj); - HDassert(H5F_addr_eq(dblk->cache_info.addr, dblk->heap->dblk_addr)); + heap = dblk->heap; + HDassert(heap->dblk_size == len); + HDassert(!heap->single_cache_obj); - /* Verify that entry is clean */ - HDassert(dblk->cache_info.is_dirty == FALSE); + /* Update the free block value from the free list */ + heap->free_block = heap->freelist ? heap->freelist->offset : H5HL_FREE_NULL; - /* If we're going to free the space on disk, the address must be valid */ - HDassert(!dblk->cache_info.free_file_space_on_destroy || H5F_addr_defined(dblk->cache_info.addr)); + /* Serialize the free list into the heap data's image */ + H5HL__fl_serialize(heap); - /* Check for freeing file space for local heap data block */ - if(dblk->cache_info.free_file_space_on_destroy) { - /* Free the local heap data block on disk */ - /* (XXX: Nasty usage of internal DXPL value! -QAK) */ - if(H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, dblk->cache_info.addr, (hsize_t)dblk->heap->dblk_size) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap data block") - } /* end if */ + /* Copy the heap's data block into the cache's image */ + HDmemcpy(image, heap->dblk_image, heap->dblk_size); - /* Destroy local heap data block */ - if(H5HL_dblk_dest(dblk) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't destroy local heap data block") + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HL__cache_datablock_serialize() */ -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HL_datablock_dest() */ +/*********************************************/ +/* no H5HL_cache_datablock_notify() function */ +/*********************************************/ /*------------------------------------------------------------------------- - * Function: H5HL_datablock_clear + * Function: H5HL__cache_datablock_free_icr * - * Purpose: Mark a local heap data block in memory as non-dirty. + * Purpose: Free the in memory representation of the supplied local heap data block. * - * Return: Non-negative on success/Negative on failure + * Note: The metadata cache sets the object's cache_info.magic to + * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr + * callback (checked in assert). * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 20 2003 + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: John Mainzer + * 6/21/14 * *------------------------------------------------------------------------- */ static herr_t -H5HL_datablock_clear(H5F_t *f, void *_thing, hbool_t destroy) +H5HL__cache_datablock_free_icr(void *_thing) { H5HL_dblk_t *dblk = (H5HL_dblk_t *)_thing; /* Pointer to the local heap data block */ - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC /* Check arguments */ HDassert(dblk); + HDassert(dblk->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC); + HDassert(dblk->cache_info.type == H5AC_LHEAP_DBLK); - /* Mark local heap data block as clean */ - dblk->cache_info.is_dirty = FALSE; - - if(destroy) - if(H5HL_datablock_dest(f, dblk) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap data block") + /* Destroy the data block */ + if(H5HL_dblk_dest(dblk) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap data block") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HL_datablock_clear() */ - - -/*------------------------------------------------------------------------- - * Function: H5HL_datablock_size - * - * Purpose: Compute the size in bytes of the local heap data block on disk, - * and return it in *len_ptr. On failure, the value of *len_ptr - * is undefined. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: John Mainzer - * 5/13/04 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HL_datablock_size(const H5F_t H5_ATTR_UNUSED *f, const void *_thing, size_t *size_ptr) -{ - const H5HL_dblk_t *dblk = (const H5HL_dblk_t *)_thing; /* Pointer to the local heap data block */ - - FUNC_ENTER_NOAPI_NOINIT_NOERR - - /* check arguments */ - HDassert(dblk); - HDassert(dblk->heap); - HDassert(size_ptr); - - /* Set size of data block in cache */ - *size_ptr = dblk->heap->dblk_size; - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5HL_datablock_size() */ +} /* end H5HL__cache_datablock_free_icr() */ |