[svn-r12258] Purpose:

Code checkpoint

Description:
    Add in more fractal heap support for odd allocation patterns (entries that
are too large for various block sizes, etc.)

    Broke out fractal heap code into more source code modules.

    Refactored fractal heap test to make it more understandable and
maintainable for the long term.

Platforms tested:
    FreeBSD 4.11 (sleipnir)
    Linux 2.4 (heping)
    Linux 2.4/64 (mir)
    Solaris 2.9 (shanti)
This commit is contained in:
Quincey Koziol 2006-04-15 16:11:42 -05:00
parent 838b4449cf
commit c83c1eb42d
18 changed files with 5050 additions and 4741 deletions

View File

@ -498,7 +498,11 @@
./src/H5HF.c
./src/H5HFcache.c
./src/H5HFdbg.c
./src/H5HFdblock.c
./src/H5HFdtable.c
./src/H5HFflist.c
./src/H5HFhdr.c
./src/H5HFiblock.c
./src/H5HFint.c
./src/H5HFpkg.h
./src/H5HFprivate.h

View File

@ -72,6 +72,7 @@ hid_t H5E_CANTGETSIZE_g = FAIL; /* Unable to compute size */
/* Heap errors */
hid_t H5E_CANTRESTORE_g = FAIL; /* Can't restore condition */
hid_t H5E_CANTCOMPUTE_g = FAIL; /* Can't compute value */
hid_t H5E_CANTEXTEND_g = FAIL; /* Can't extend heap's space */
/* Function entry/exit interface errors */
hid_t H5E_CANTINIT_g = FAIL; /* Unable to initialize object */

View File

@ -254,6 +254,11 @@ if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't compute value"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
if((H5E_CANTCOMPUTE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTEXTEND_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't extend heap's space"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
if((H5E_CANTEXTEND_g = H5I_register(H5I_ERROR_MSG, msg))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
/* Function entry/exit interface errors */
assert(H5E_CANTINIT_g==(-1));

View File

@ -119,8 +119,10 @@ H5_DLLVAR hid_t H5E_CANTGETSIZE_g; /* Unable to compute size */
/* Heap errors */
#define H5E_CANTRESTORE (H5OPEN H5E_CANTRESTORE_g)
#define H5E_CANTCOMPUTE (H5OPEN H5E_CANTCOMPUTE_g)
#define H5E_CANTEXTEND (H5OPEN H5E_CANTEXTEND_g)
H5_DLLVAR hid_t H5E_CANTRESTORE_g; /* Can't restore condition */
H5_DLLVAR hid_t H5E_CANTCOMPUTE_g; /* Can't compute value */
H5_DLLVAR hid_t H5E_CANTEXTEND_g; /* Can't extend heap's space */
/* Function entry/exit interface errors */
#define H5E_CANTINIT (H5OPEN H5E_CANTINIT_g)

View File

@ -73,7 +73,8 @@ H5E_CANTGETSIZE_g=
/* Heap errors */
H5E_CANTRESTORE_g=
H5E_CANTCOMPUTE_g=
H5E_CANTCOMPUTE_g=
H5E_CANTEXTEND_g=
/* Function entry/exit interface errors */
H5E_CANTINIT_g=

View File

@ -99,7 +99,7 @@ herr_t
H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_create_t *cparam, haddr_t *addr_p,
size_t *id_len_p)
{
H5HF_t *fh = NULL; /* The new fractal heap header information */
H5HF_t *hdr = NULL; /* The new fractal heap header information */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5HF_create, FAIL)
@ -113,31 +113,31 @@ H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_create_t *cparam, haddr_t *addr_p,
HDassert(id_len_p);
/* Allocate & basic initialization for the shared header */
if(NULL == (fh = H5HF_alloc(f)))
if(NULL == (hdr = H5HF_hdr_alloc(f)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate space for shared heap info")
/* Allocate space for the header on disk */
if(HADDR_UNDEF == (*addr_p = H5MF_alloc(f, H5FD_MEM_FHEAP_HDR, dxpl_id, (hsize_t)H5HF_HEADER_SIZE(fh))))
if(HADDR_UNDEF == (*addr_p = H5MF_alloc(f, H5FD_MEM_FHEAP_HDR, dxpl_id, (hsize_t)H5HF_HEADER_SIZE(hdr))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap header")
/* Initialize shared fractal heap header */
if(H5HF_init(fh, *addr_p, cparam) < 0)
if(H5HF_hdr_init(hdr, *addr_p, cparam) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't initialize shared fractal heap header")
/* Set the length of heap IDs */
*id_len_p = fh->id_len;
*id_len_p = hdr->id_len;
#ifdef QAK
HDfprintf(stderr, "%s: fh->id_len = %Zu\n", FUNC, fh->id_len);
HDfprintf(stderr, "%s: hdr->id_len = %Zu\n", FUNC, hdr->id_len);
#endif /* QAK */
/* Cache the new fractal heap header */
if(H5AC_set(f, dxpl_id, H5AC_FHEAP_HDR, *addr_p, fh, H5AC__NO_FLAGS_SET) < 0)
if(H5AC_set(f, dxpl_id, H5AC_FHEAP_HDR, *addr_p, hdr, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add fractal heap header to cache")
done:
if(ret_value < 0) {
if(fh)
(void)H5HF_cache_hdr_dest(f, fh);
if(hdr)
(void)H5HF_cache_hdr_dest(f, hdr);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@ -162,7 +162,7 @@ herr_t
H5HF_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t size,
const void *obj, void *id/*out*/)
{
H5HF_t *fh = NULL; /* The fractal heap header information */
H5HF_t *hdr = NULL; /* The fractal heap header information */
unsigned hdr_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for header */
herr_t ret_value = SUCCEED;
@ -183,37 +183,37 @@ HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size);
/*
* Load the fractal heap header.
*/
if(NULL == (fh = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, addr, NULL, NULL, H5AC_WRITE)))
if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, addr, NULL, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header")
/* Check if object is large enough to be standalone */
if(size >= fh->standalone_size) {
if(size >= hdr->standalone_size) {
HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "standalone blocks not supported yet")
} /* end if */
else {
/* Check if we are in "append only" mode, or if there's enough room for the object */
if(fh->write_once) {
if(hdr->write_once) {
HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'write once' managed blocks not supported yet")
} /* end if */
else {
H5HF_section_free_node_t *sec_node; /* Pointer to free space section */
H5HF_free_section_t *sec_node; /* Pointer to free space section */
/* Find free space in heap */
if(H5HF_man_find(fh, dxpl_id, size, &sec_node) < 0)
if(H5HF_man_find(hdr, dxpl_id, size, &sec_node) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate space in fractal heap")
/* Use free space for allocating object */
if(H5HF_man_insert(fh, dxpl_id, sec_node, size, obj, id) < 0)
if(H5HF_man_insert(hdr, dxpl_id, sec_node, size, obj, id) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate space for object in fractal heap")
} /* end else */
} /* end else */
/* Check for making header dirty */
if(fh->dirty)
if(hdr->dirty)
hdr_flags |= H5AC__DIRTIED_FLAG;
done:
if(fh && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, addr, fh, hdr_flags) < 0)
if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, addr, hdr, hdr_flags) < 0)
HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap header")
FUNC_LEAVE_NOAPI(ret_value)
@ -237,7 +237,7 @@ herr_t
H5HF_read(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_id,
void *obj/*out*/)
{
H5HF_t *fh = NULL; /* The fractal heap header information */
H5HF_t *hdr = NULL; /* The fractal heap header information */
const uint8_t *id = (const uint8_t *)_id; /* Object ID */
hsize_t obj_off; /* Object's offset in heap */
size_t obj_len; /* Object's length in heap */
@ -256,12 +256,12 @@ H5HF_read(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_id,
/*
* Load the fractal heap header.
*/
if(NULL == (fh = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, addr, NULL, NULL, H5AC_READ)))
if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header")
/* Decode the object offset within the heap & it's length */
UINT64DECODE_VAR(id, obj_off, fh->heap_off_size);
UINT64DECODE_VAR(id, obj_len, fh->id_len);
UINT64DECODE_VAR(id, obj_off, hdr->heap_off_size);
UINT64DECODE_VAR(id, obj_len, hdr->id_len);
#ifdef QAK
HDfprintf(stderr, "%s: obj_off = %Hu, obj_len = %Zu\n", FUNC, obj_off, obj_len);
#endif /* QAK */
@ -272,12 +272,12 @@ HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "standalone blocks not supported ye
} /* end if */
else {
/* Read object from managed heap blocks */
if(H5HF_man_read(fh, dxpl_id, obj_off, obj_len, obj) < 0)
if(H5HF_man_read(hdr, dxpl_id, obj_off, obj_len, obj) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't read object from fractal heap")
} /* end else */
done:
if(fh && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, addr, fh, H5AC__NO_FLAGS_SET) < 0)
if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, addr, hdr, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap header")
FUNC_LEAVE_NOAPI(ret_value)

View File

@ -63,9 +63,9 @@
/* Metadata cache callbacks */
static H5HF_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_t *fh);
static herr_t H5HF_cache_hdr_clear(H5F_t *f, H5HF_t *fh, hbool_t destroy);
static herr_t H5HF_cache_hdr_size(const H5F_t *f, const H5HF_t *fh, size_t *size_ptr);
static herr_t H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_t *hdr);
static herr_t H5HF_cache_hdr_clear(H5F_t *f, H5HF_t *hdr, hbool_t destroy);
static herr_t H5HF_cache_hdr_size(const H5F_t *f, const H5HF_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);
@ -252,7 +252,7 @@ H5HF_dtable_encode(H5F_t *f, uint8_t **pp, const H5HF_dtable_t *dtable)
static H5HF_t *
H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *udata1, void UNUSED *udata2)
{
H5HF_t *fh = NULL; /* Fractal heap info */
H5HF_t *hdr = NULL; /* Fractal heap info */
size_t size; /* Header size */
uint8_t *buf = NULL; /* Temporary buffer */
const uint8_t *p; /* Pointer into raw data buffer */
@ -269,14 +269,14 @@ HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr);
HDassert(H5F_addr_defined(addr));
/* Allocate space for the fractal heap data structure */
if(NULL == (fh = H5HF_alloc(f)))
if(NULL == (hdr = H5HF_hdr_alloc(f)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Set the heap header's address */
fh->heap_addr = addr;
hdr->heap_addr = addr;
/* Compute the size of the fractal heap header on disk */
size = H5HF_HEADER_SIZE(fh);
size = H5HF_HEADER_SIZE(hdr);
/* Allocate temporary buffer */
if((buf = H5FL_BLK_MALLOC(header_block, size)) == NULL)
@ -309,42 +309,42 @@ HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr);
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect metadata checksum for fractal heap header")
/* Heap address mapping */
fh->addrmap = *p++;
hdr->addrmap = *p++;
HDassert(H5HF_ABSOLUTE == 0);
if(fh->addrmap > H5HF_MAPPED)
if(hdr->addrmap > H5HF_MAPPED)
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect fractal heap address mapping")
/* Min. size of standalone objects */
UINT32DECODE(p, fh->standalone_size);
UINT32DECODE(p, hdr->standalone_size);
/* Internal management information */
H5F_DECODE_LENGTH(f, p, fh->total_man_free);
H5F_DECODE_LENGTH(f, p, fh->total_std_free);
H5F_DECODE_LENGTH(f, p, hdr->total_man_free);
H5F_DECODE_LENGTH(f, p, hdr->total_std_free);
/* Statistics information */
H5F_DECODE_LENGTH(f, p, fh->total_size);
H5F_DECODE_LENGTH(f, p, fh->man_size);
H5F_DECODE_LENGTH(f, p, fh->std_size);
H5F_DECODE_LENGTH(f, p, fh->nobjs);
H5F_DECODE_LENGTH(f, p, hdr->total_size);
H5F_DECODE_LENGTH(f, p, hdr->man_size);
H5F_DECODE_LENGTH(f, p, hdr->std_size);
H5F_DECODE_LENGTH(f, p, hdr->nobjs);
/* Managed objects' doubling-table info */
if(H5HF_dtable_decode(fh->f, &p, &(fh->man_dtable)) < 0)
if(H5HF_dtable_decode(hdr->f, &p, &(hdr->man_dtable)) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, NULL, "unable to encode managed obj. doubling table info")
HDassert((size_t)(p - buf) == size);
/* Make shared heap info reference counted */
if(H5HF_finish_init(fh) < 0)
if(H5HF_hdr_finish_init(hdr) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't create ref-count wrapper for shared fractal heap header")
/* Set return value */
ret_value = fh;
ret_value = hdr;
done:
if(buf)
H5FL_BLK_FREE(header_block, buf);
if(!ret_value && fh)
(void)H5HF_cache_hdr_dest(f, fh);
if(!ret_value && hdr)
(void)H5HF_cache_hdr_dest(f, hdr);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_cache_hdr_load() */ /*lint !e818 Can't make udata a pointer to const */
@ -364,7 +364,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_t *fh)
H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_t *hdr)
{
herr_t ret_value = SUCCEED; /* Return value */
@ -376,18 +376,18 @@ HDfprintf(stderr, "%s: Flushing heap header, addr = %a, destroy = %u\n", FUNC, a
/* check arguments */
HDassert(f);
HDassert(H5F_addr_defined(addr));
HDassert(fh);
HDassert(hdr);
if(fh->cache_info.is_dirty) {
if(hdr->cache_info.is_dirty) {
uint8_t *buf = NULL; /* Temporary raw data buffer */
uint8_t *p; /* Pointer into raw data buffer */
size_t size; /* Header size on disk */
/* Sanity check */
HDassert(fh->dirty);
HDassert(hdr->dirty);
/* Compute the size of the heap header on disk */
size = H5HF_HEADER_SIZE(fh);
size = H5HF_HEADER_SIZE(hdr);
/* Allocate temporary buffer */
if((buf = H5FL_BLK_MALLOC(header_block, size)) == NULL)
@ -412,23 +412,23 @@ HDfprintf(stderr, "%s: Flushing heap header, addr = %a, destroy = %u\n", FUNC, a
p += 4;
/* Heap address mapping */
*p++ = fh->addrmap;
*p++ = hdr->addrmap;
/* Min. size of standalone objects */
UINT32ENCODE(p, fh->standalone_size);
UINT32ENCODE(p, hdr->standalone_size);
/* Internal management information */
H5F_ENCODE_LENGTH(f, p, fh->total_man_free);
H5F_ENCODE_LENGTH(f, p, fh->total_std_free);
H5F_ENCODE_LENGTH(f, p, hdr->total_man_free);
H5F_ENCODE_LENGTH(f, p, hdr->total_std_free);
/* Statistics information */
H5F_ENCODE_LENGTH(f, p, fh->total_size);
H5F_ENCODE_LENGTH(f, p, fh->man_size);
H5F_ENCODE_LENGTH(f, p, fh->std_size);
H5F_ENCODE_LENGTH(f, p, fh->nobjs);
H5F_ENCODE_LENGTH(f, p, hdr->total_size);
H5F_ENCODE_LENGTH(f, p, hdr->man_size);
H5F_ENCODE_LENGTH(f, p, hdr->std_size);
H5F_ENCODE_LENGTH(f, p, hdr->nobjs);
/* Managed objects' doubling-table info */
if(H5HF_dtable_encode(fh->f, &p, &(fh->man_dtable)) < 0)
if(H5HF_dtable_encode(hdr->f, &p, &(hdr->man_dtable)) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, FAIL, "unable to encode managed obj. doubling table info")
/* Write the heap header. */
@ -438,12 +438,12 @@ HDfprintf(stderr, "%s: Flushing heap header, addr = %a, destroy = %u\n", FUNC, a
H5FL_BLK_FREE(header_block, buf);
fh->dirty = FALSE;
fh->cache_info.is_dirty = FALSE;
hdr->dirty = FALSE;
hdr->cache_info.is_dirty = FALSE;
} /* end if */
if(destroy)
if(H5HF_cache_hdr_dest(f, fh) < 0)
if(H5HF_cache_hdr_dest(f, hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap header")
done:
@ -465,27 +465,27 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
H5HF_cache_hdr_dest_real(H5HF_t *fh)
H5HF_cache_hdr_dest_real(H5HF_t *hdr)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_hdr_dest_real)
/*
* Check arguments.
*/
HDassert(fh);
HDassert(hdr);
/* XXX: Take out this goofy routine, after metadata cache is supporting
* "un-evictable" flag
*/
if(fh->rc == 0 && fh->evicted == TRUE) {
if(hdr->rc == 0 && hdr->evicted == TRUE) {
/* Free the free list information for the heap */
if(fh->flist)
H5HF_flist_free(fh->flist);
if(hdr->flist)
H5HF_flist_free(hdr->flist);
/* Free the block size lookup table for the doubling table */
H5HF_dtable_dest(&fh->man_dtable);
H5HF_dtable_dest(&hdr->man_dtable);
/* Free the shared info itself */
H5FL_FREE(H5HF_t, fh);
H5FL_FREE(H5HF_t, hdr);
} /* end if */
FUNC_LEAVE_NOAPI(SUCCEED)
@ -507,25 +507,25 @@ H5HF_cache_hdr_dest_real(H5HF_t *fh)
*/
/* ARGSUSED */
herr_t
H5HF_cache_hdr_dest(H5F_t UNUSED *f, H5HF_t *fh)
H5HF_cache_hdr_dest(H5F_t UNUSED *f, H5HF_t *hdr)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_hdr_dest)
/*
* Check arguments.
*/
HDassert(fh);
HDassert(hdr);
/* XXX: Enable this after the metadata cache supports the "un-evictable" flag */
/* HDassert(fh->rc == 0); */
/* HDassert(hdr->rc == 0); */
/* XXX: Take out this goofy 'if' statement, after metadata cache is supporting
* "un-evictable" flag
*/
/* XXX: Take out 'evicted' flag after "un-evictable" flag is working */
fh->evicted = TRUE;
hdr->evicted = TRUE;
/* XXX: Take out this goofy routine, after metadata cache is supporting
* "un-evictable" flag
*/
H5HF_cache_hdr_dest_real(fh);
H5HF_cache_hdr_dest_real(hdr);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5HF_cache_hdr_dest() */
@ -545,7 +545,7 @@ H5HF_cache_hdr_dest(H5F_t UNUSED *f, H5HF_t *fh)
*-------------------------------------------------------------------------
*/
static herr_t
H5HF_cache_hdr_clear(H5F_t *f, H5HF_t *fh, hbool_t destroy)
H5HF_cache_hdr_clear(H5F_t *f, H5HF_t *hdr, hbool_t destroy)
{
herr_t ret_value = SUCCEED; /* Return value */
@ -554,13 +554,13 @@ H5HF_cache_hdr_clear(H5F_t *f, H5HF_t *fh, hbool_t destroy)
/*
* Check arguments.
*/
HDassert(fh);
HDassert(hdr);
/* Reset the dirty flag. */
fh->cache_info.is_dirty = FALSE;
hdr->cache_info.is_dirty = FALSE;
if(destroy)
if(H5HF_cache_hdr_dest(f, fh) < 0)
if(H5HF_cache_hdr_dest(f, hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap header")
done:
@ -584,17 +584,17 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5HF_cache_hdr_size(const H5F_t *f, const H5HF_t *fh, size_t *size_ptr)
H5HF_cache_hdr_size(const H5F_t *f, const H5HF_t *hdr, size_t *size_ptr)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_hdr_size)
/* check arguments */
HDassert(f);
HDassert(fh);
HDassert(hdr);
HDassert(size_ptr);
/* Set size value */
*size_ptr = H5HF_HEADER_SIZE(fh);
*size_ptr = H5HF_HEADER_SIZE(hdr);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5HF_cache_hdr_size() */
@ -1023,6 +1023,9 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrows
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 */
#ifndef NDEBUG
hsize_t acc_child_free_space; /* Accumulated child free space */
#endif /* NDEBUG */
size_t u; /* Local index variable */
H5HF_indirect_t *ret_value; /* Return value */
@ -1151,6 +1154,10 @@ HDfprintf(stderr, "%s: Load indirect block, addr = %a\n", FUNC, addr);
HDassert(iblock->nrows > 0);
if(NULL == (iblock->ents = H5FL_SEQ_MALLOC(H5HF_indirect_ent_t, (iblock->nrows * hdr->man_dtable.cparam.width))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for direct entries")
#ifndef NDEBUG
/* Reset child free space */
acc_child_free_space = 0;
#endif /* NDEBUG */
for(u = 0; u < (iblock->nrows * hdr->man_dtable.cparam.width); u++) {
/* Decode block address */
H5F_addr_decode(f, &p, &(iblock->ents[u].addr));
@ -1160,8 +1167,15 @@ HDfprintf(stderr, "%s: Load indirect block, addr = %a\n", FUNC, addr);
UINT32DECODE_VAR(p, iblock->ents[u].free_space, hdr->man_dtable.max_dir_blk_off_size)
else
UINT64DECODE_VAR(p, iblock->ents[u].free_space, hdr->heap_off_size)
#ifndef NDEBUG
acc_child_free_space += iblock->ents[u].free_space;
#endif /* NDEBUG */
/* XXX: Add code to indirect block cache load routine to create range sections for skipped blocks */
/* XXX: ?? How to add code to indirect block cache load routine to create indirect sections for skipped blocks ?? */
} /* end for */
#ifndef NDEBUG
HDassert(acc_child_free_space == iblock->child_free_space);
#endif /* NDEBUG */
/* Sanity check */
HDassert((size_t)(p - buf) == iblock->size);

585
src/H5HFdblock.c Normal file
View File

@ -0,0 +1,585 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by the Board of Trustees of the University of Illinois. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the files COPYING and Copyright.html. COPYING can be found at the root *
* of the source code distribution tree; Copyright.html can be found at the *
* root level of an installed copy of the electronic HDF5 document set and *
* is linked from the top-level documents page. It can also be found at *
* http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have *
* access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*-------------------------------------------------------------------------
*
* Created: H5HFdblock.c
* Apr 10 2006
* Quincey Koziol <koziol@ncsa.uiuc.edu>
*
* Purpose: Direct block routines for fractal heaps.
*
*-------------------------------------------------------------------------
*/
/****************/
/* Module Setup */
/****************/
#define H5HF_PACKAGE /*suppress error about including H5HFpkg */
/***********/
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5HFpkg.h" /* Fractal heaps */
#include "H5MFprivate.h" /* File memory management */
#include "H5Vprivate.h" /* Vectors and arrays */
/****************/
/* Local Macros */
/****************/
/******************/
/* Local Typedefs */
/******************/
/********************/
/* Package Typedefs */
/********************/
/********************/
/* Local Prototypes */
/********************/
/*********************/
/* Package Variables */
/*********************/
/* Declare a free list to manage the H5HF_direct_t struct */
H5FL_DEFINE(H5HF_direct_t);
/* Declare a free list to manage the H5HF_direct_free_head_t struct */
H5FL_DEFINE(H5HF_direct_free_head_t);
/* Declare a free list to manage the H5HF_direct_free_node_t struct */
H5FL_DEFINE(H5HF_direct_free_node_t);
/*****************************/
/* Library Private Variables */
/*****************************/
/*******************/
/* Local Variables */
/*******************/
/*-------------------------------------------------------------------------
* Function: H5HF_man_dblock_create
*
* Purpose: Allocate & initialize a managed direct block
*
* Return: Pointer to new direct block on success, NULL on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Feb 27 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_man_dblock_create(hid_t dxpl_id, H5HF_t *hdr, H5HF_indirect_t *par_iblock,
unsigned par_entry, size_t block_size, hsize_t block_off, haddr_t *addr_p,
H5HF_free_section_t **ret_sec_node)
{
H5HF_direct_free_node_t *node; /* Pointer to free list node for block */
H5HF_free_section_t *sec_node; /* Pointer to free list section for block */
H5HF_direct_t *dblock = NULL; /* Pointer to direct block */
size_t free_space; /* Free space in new block */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_create)
/*
* Check arguments.
*/
HDassert(hdr);
HDassert(block_size > 0);
HDassert(addr_p);
/*
* Allocate file and memory data structures.
*/
if(NULL == (dblock = H5FL_MALLOC(H5HF_direct_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fractal heap direct block")
/* Reset the metadata cache info for the heap header */
HDmemset(&dblock->cache_info, 0, sizeof(H5AC_info_t));
/* Share common heap information */
dblock->shared = hdr;
if(H5HF_hdr_incr(hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared heap header")
/* Set info for direct block */
#ifdef QAK
HDfprintf(stderr, "%s: size = %Zu, block_off = %Hu\n", FUNC, block_size, block_off);
#endif /* QAK */
dblock->parent = par_iblock;
if(dblock->parent) {
if(H5HF_iblock_incr(par_iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
dblock->par_addr = par_iblock->addr;
dblock->par_nrows = par_iblock->nrows;
} /* end if */
else {
dblock->par_addr = HADDR_UNDEF;
dblock->par_nrows = 0;
} /* end else */
dblock->par_entry = par_entry;
dblock->size = block_size;
dblock->block_off = block_off;
dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(block_size);
dblock->free_list_head = H5HF_MAN_ABS_DIRECT_OVERHEAD_DBLOCK(hdr, dblock);
dblock->blk_free_space = block_size -
(H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, block_size) + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr));
free_space = block_size - dblock->free_list_head;
/* Allocate buffer for block */
/* XXX: Change to using free-list factories */
if((dblock->blk = H5FL_BLK_MALLOC(direct_block, block_size)) == NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
#ifdef H5_USING_PURIFY
HDmemset(dblock->blk, 0, dblock->size);
#endif /* H5_USING_PURIFY */
/* Set up free list head */
if(NULL == (dblock->free_list = H5FL_MALLOC(H5HF_direct_free_head_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list head")
dblock->free_list->dirty = TRUE;
/* Set up free list node for all unused space in block */
if(NULL == (node = H5FL_MALLOC(H5HF_direct_free_node_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list node")
/* Set node's information */
node->size = free_space;
node->my_offset = dblock->free_list_head;
node->next_offset = 0;
node->prev = node->next = NULL;
/* Attach to free list head */
/* XXX: Convert this list to a skip list? */
dblock->free_list->first = node;
/* Allocate space for the header on disk */
if(HADDR_UNDEF == (*addr_p = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)block_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
/* Create free list section node */
if(NULL == (sec_node = H5FL_MALLOC(H5HF_free_section_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section")
/* Set section's information */
sec_node->sect_addr = block_off + node->my_offset;
/* (section size is "object size", without the metadata overhead) */
sec_node->sect_size = node->size - H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr);
sec_node->type = H5HF_SECT_SINGLE;
sec_node->u.single.dblock_addr = *addr_p;
sec_node->u.single.dblock_size = block_size;
/* Check what to do with section node */
if(ret_sec_node)
/* Pass back the pointer to the section instead of adding it to the free list */
*ret_sec_node = sec_node;
else {
/* Add new free space to the global list of space */
if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list")
} /* end else */
/* Cache the new fractal heap direct block */
if(H5AC_set(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, *addr_p, dblock, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add fractal heap direct block to cache")
done:
if(ret_value < 0)
if(dblock)
(void)H5HF_cache_dblock_dest(hdr->f, dblock);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_man_dblock_create() */
/*-------------------------------------------------------------------------
* Function: H5HF_man_dblock_build_freelist
*
* Purpose: Parse the free list information for a direct block and build
* block's free list
*
* Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Feb 28 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_man_dblock_build_freelist(H5HF_direct_t *dblock, haddr_t dblock_addr)
{
H5HF_direct_free_head_t *head = NULL; /* Pointer to free list head for block */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_build_freelist)
/*
* Check arguments.
*/
HDassert(dblock);
/* Allocate head of list */
if(NULL == (head = H5FL_MALLOC(H5HF_direct_free_head_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list head")
head->dirty = FALSE;
/* Check for any nodes on free list */
if(dblock->free_list_head == 0)
head->first = NULL;
else {
H5HF_t *hdr; /* Pointer to shared heap header */
H5HF_free_section_t *sec_node; /* Pointer to free list section for block */
H5HF_direct_free_node_t *node = NULL; /* Pointer to free list node for block */
H5HF_direct_free_node_t *prev_node; /* Pointer to previous free list node for block */
hsize_t free_len; /* Length of free list info */
hsize_t next_off; /* Next node offset in block */
hsize_t prev_off; /* Prev node offset in block */
uint8_t *p; /* Temporary pointer to free node info */
/* Get the pointer to the shared heap info */
hdr = dblock->shared;
/* Point to first node in free list */
p = dblock->blk + dblock->free_list_head;
/* Decode information for first node on free list */
UINT64DECODE_VAR(p, free_len, dblock->blk_off_size);
UINT64DECODE_VAR(p, next_off, dblock->blk_off_size);
/* Allocate node on list */
if(NULL == (node = H5FL_MALLOC(H5HF_direct_free_node_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list node")
/* Set node's information */
node->size = free_len;
node->my_offset = dblock->free_list_head;
node->next_offset = next_off;
node->prev = node->next = NULL;
/* Attach to free list head */
head->first = node;
/* Set block's free space */
dblock->blk_free_space = free_len;
/* Create free list section node */
if(NULL == (sec_node = H5FL_MALLOC(H5HF_free_section_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section")
/* Set section's information */
sec_node->sect_addr = dblock->block_off + node->my_offset;
/* (section size is "object size", without the metadata overhead) */
sec_node->sect_size = node->size - H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr);
sec_node->type = H5HF_SECT_SINGLE;
sec_node->u.single.dblock_addr = dblock_addr;
sec_node->u.single.dblock_size = dblock->size;
/* Add new free space to the global list of space */
if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list")
/* Set up trailing node pointer */
prev_node = node;
prev_off = next_off;
/* Bring in rest of node on free list */
while(next_off != 0) {
/* Point to first node in free list */
p = dblock->blk + next_off;
/* Decode information for first node on free list */
UINT64DECODE_VAR(p, free_len, dblock->blk_off_size);
UINT64DECODE_VAR(p, next_off, dblock->blk_off_size);
/* Allocate node on list */
if(NULL == (node = H5FL_MALLOC(H5HF_direct_free_node_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list node")
/* Set node's information */
node->size = free_len;
node->my_offset = prev_off;
node->next_offset = next_off;
node->prev = prev_node;
node->next = NULL;
/* Adjust block's free space */
dblock->blk_free_space += free_len;
/* Create free list section node */
if(NULL == (sec_node = H5FL_MALLOC(H5HF_free_section_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section")
/* Set section's information */
sec_node->sect_addr = dblock->block_off + node->my_offset;
/* (section size is "object size", without the metadata overhead) */
sec_node->sect_size = node->size - H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr);
sec_node->type = H5HF_SECT_SINGLE;
sec_node->u.single.dblock_addr = dblock_addr;
sec_node->u.single.dblock_size = dblock->size;
/* Add new free space to the global list of space */
if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list")
/* Update trailing info */
prev_node->next = node;
prev_off = next_off;
/* Advance to next node */
prev_node = node;
} /* end while */
} /* end else */
/* Assign free list head to block */
dblock->free_list = head;
done:
/* XXX: cleanup on failure? */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_man_dblock_build_freelist() */
/*-------------------------------------------------------------------------
* Function: H5HF_man_dblock_adj_free
*
* Purpose: Adjust the free space for a direct block, and it's parents
*
* Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Mar 14 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_man_dblock_adj_free(hid_t dxpl_id, H5HF_direct_t *dblock, ssize_t amt)
{
H5HF_t *hdr; /* Shared heap information */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_adj_free)
#ifdef QAK
HDfprintf(stderr, "%s: amt = %Zd\n", FUNC, amt);
#endif /* QAK */
/*
* Check arguments.
*/
HDassert(dblock);
/* Get the pointer to the shared heap header */
hdr = dblock->shared;
/* Adjust space available in block */
HDassert(amt > 0 || dblock->blk_free_space >= (size_t)-amt);
dblock->blk_free_space += amt;
/* Check if the parent info is set */
if(dblock->parent) {
H5HF_indirect_t *iblock; /* Block's parent */
/* Get the pointer to the shared parent indirect block */
iblock = dblock->parent;
/* Adjust this indirect block's child free space */
#ifdef QAK
HDfprintf(stderr, "%s: dblock->par_entry = %u\n", FUNC, dblock->par_entry);
HDfprintf(stderr, "%s: iblock->block_off = %a\n", FUNC, iblock->block_off);
HDfprintf(stderr, "%s: iblock->child_free_space = %Hu\n", FUNC, iblock->child_free_space);
HDfprintf(stderr, "%s: iblock->ents[dblock->par_entry].free_space = %Hu\n", FUNC, iblock->ents[dblock->par_entry].free_space);
#endif /* QAK */
HDassert(amt > 0 || iblock->ents[dblock->par_entry].free_space >= (hsize_t)-amt);
iblock->ents[dblock->par_entry].free_space += amt;
HDassert(amt > 0 || iblock->child_free_space >= (hsize_t)-amt);
iblock->child_free_space += amt;
/* Mark indirect block as dirty */
if(H5HF_iblock_dirty(dxpl_id, iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty")
/* Modify the free space in parent block(s) */
while(iblock->parent) {
size_t par_entry; /* Entry in parent */
/* Get the pointer to the shared parent indirect block */
par_entry = iblock->par_entry;
iblock = iblock->parent;
HDassert(iblock);
/* Adjust this indirect block's child free space */
HDassert(amt > 0 || iblock->ents[par_entry].free_space >= (hsize_t)-amt);
iblock->ents[par_entry].free_space += amt;
HDassert(amt > 0 || iblock->child_free_space >= (hsize_t)-amt);
iblock->child_free_space += amt;
/* Mark indirect block as dirty */
if(H5HF_iblock_dirty(dxpl_id, iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty")
} /* end while */
} /* end if */
/* Update shared heap free space header */
HDassert(amt > 0 || hdr->total_man_free >= (hsize_t)-amt);
hdr->total_man_free += amt;
#ifdef QAK
HDfprintf(stderr, "%s: hdr->total_man_free = %Hu\n", FUNC, hdr->total_man_free);
#endif /* QAK */
/* Mark heap header as modified */
if(H5HF_hdr_dirty(dxpl_id, hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_man_dblock_adj_free() */
/*-------------------------------------------------------------------------
* Function: H5HF_man_dblock_new
*
* Purpose: Create a direct block large enough to hold an object of
* the requested size
*
* Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Mar 13 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_man_dblock_new(H5HF_t *hdr, hid_t dxpl_id, size_t request)
{
haddr_t dblock_addr; /* Address of new direct block */
size_t dblock_size; /* Size of new direct block */
size_t min_dblock_size; /* Min. size of direct block to allocate */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_new)
#ifdef QAK
HDfprintf(stderr, "%s: request = %Zu\n", FUNC, request);
#endif /* QAK */
/*
* Check arguments.
*/
HDassert(hdr);
HDassert(request > 0);
/* Compute the min. size of the direct block needed to fulfill the request */
if(request < hdr->man_dtable.cparam.start_block_size)
min_dblock_size = hdr->man_dtable.cparam.start_block_size;
else {
min_dblock_size = 1 << (1 + H5V_log2_gen((hsize_t)request));
HDassert(min_dblock_size <= hdr->man_dtable.cparam.max_direct_size);
} /* end else */
/* Adjust the size of block needed to fulfill request, with overhead */
#ifdef QAK
HDfprintf(stderr, "%s: Check 1 - min_dblock_size = %Zu\n", FUNC, min_dblock_size);
HDfprintf(stderr, "%s: H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE = %u\n", FUNC, H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, hdr->man_dtable.cparam.start_block_size));
HDfprintf(stderr, "%s: H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN = %u\n", FUNC, H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr));
#endif /* QAK */
if((min_dblock_size - request) < (H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, min_dblock_size)
+ H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr)))
min_dblock_size *= 2;
#ifdef QAK
HDfprintf(stderr, "%s: Check 2 - min_dblock_size = %Zu\n", FUNC, min_dblock_size);
#endif /* QAK */
/* Check if this is the first block in the heap */
if(!H5F_addr_defined(hdr->man_dtable.table_addr) &&
min_dblock_size == hdr->man_dtable.cparam.start_block_size) {
/* Create new direct block at starting offset */
dblock_size = hdr->man_dtable.cparam.start_block_size;
if(H5HF_man_dblock_create(dxpl_id, hdr, NULL, 0, dblock_size, (hsize_t)0, &dblock_addr, NULL) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block")
#ifdef QAK
HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr);
#endif /* QAK */
/* Point root at new direct block */
hdr->man_dtable.curr_root_rows = 0;
hdr->man_dtable.table_addr = dblock_addr;
/* Extend heap to cover new direct block */
if(H5HF_hdr_extend_heap(hdr, (hsize_t)dblock_size, hdr->man_dtable.row_dblock_free[0]) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "can't increase space to cover root direct block")
} /* end if */
/* Root entry already exists, go get indirect block for new direct block */
else {
H5HF_indirect_t *iblock; /* Pointer to indirect block to create */
haddr_t iblock_addr; /* Indirect block's address */
size_t dblock_entry; /* Direct entry for new direct block */
hsize_t dblock_off; /* Direct block offset in heap address space */
/* Find indirect block with room for block of correct size */
if(NULL == (iblock = H5HF_man_iblock_place_dblock(hdr, dxpl_id, min_dblock_size, &iblock_addr, &dblock_entry, &dblock_size)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to locate indirect block with space for direct block")
#ifdef QAK
HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr);
HDfprintf(stderr, "%s: dblock_entry = %Zu\n", FUNC, dblock_entry);
HDfprintf(stderr, "%s: dblock_size = %Zu\n", FUNC, dblock_size);
#endif /* QAK */
/* Compute the direct block's offset in the heap's address space */
dblock_off = iblock->block_off;
dblock_off += hdr->man_dtable.row_block_off[dblock_entry / hdr->man_dtable.cparam.width];
dblock_off += hdr->man_dtable.row_block_size[dblock_entry / hdr->man_dtable.cparam.width] * (dblock_entry % hdr->man_dtable.cparam.width);
/* Create new direct block at current location*/
if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, dblock_entry, dblock_size, dblock_off, &dblock_addr, NULL) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block")
#ifdef QAK
HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr);
#endif /* QAK */
/* Point indirect block at new direct block */
iblock->ents[dblock_entry].addr = dblock_addr;
/* Mark indirect block as modified */
if(H5HF_iblock_dirty(dxpl_id, iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty")
/* Release the indirect block (marked as dirty) */
if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, H5AC__DIRTIED_FLAG) < 0)
HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
} /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_man_dblock_new() */

213
src/H5HFdtable.c Normal file
View File

@ -0,0 +1,213 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by the Board of Trustees of the University of Illinois. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the files COPYING and Copyright.html. COPYING can be found at the root *
* of the source code distribution tree; Copyright.html can be found at the *
* root level of an installed copy of the electronic HDF5 document set and *
* is linked from the top-level documents page. It can also be found at *
* http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have *
* access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*-------------------------------------------------------------------------
*
* Created: H5HFdtable.c
* Apr 10 2006
* Quincey Koziol <koziol@ncsa.uiuc.edu>
*
* Purpose: "Doubling table" routines for fractal heaps.
*
*-------------------------------------------------------------------------
*/
/****************/
/* Module Setup */
/****************/
#define H5HF_PACKAGE /*suppress error about including H5HFpkg */
/***********/
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5HFpkg.h" /* Fractal heaps */
#include "H5MMprivate.h" /* Memory management */
#include "H5Vprivate.h" /* Vectors and arrays */
/****************/
/* Local Macros */
/****************/
/******************/
/* Local Typedefs */
/******************/
/********************/
/* Package Typedefs */
/********************/
/********************/
/* Local Prototypes */
/********************/
/*********************/
/* Package Variables */
/*********************/
/*****************************/
/* Library Private Variables */
/*****************************/
/*******************/
/* Local Variables */
/*******************/
/*-------------------------------------------------------------------------
* Function: H5HF_dtable_init
*
* Purpose: Initialize values for doubling table
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Mar 6 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_dtable_init(H5HF_dtable_t *dtable)
{
hsize_t tmp_block_size; /* Temporary block size */
hsize_t acc_block_off; /* Accumulated block offset */
size_t u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_dtable_init)
/*
* Check arguments.
*/
HDassert(dtable);
/* Compute/cache some values */
dtable->first_row_bits = H5V_log2_of2(dtable->cparam.start_block_size) +
H5V_log2_of2(dtable->cparam.width);
dtable->max_root_rows = (dtable->cparam.max_index - dtable->first_row_bits) + 1;
dtable->max_direct_rows = (H5V_log2_of2(dtable->cparam.max_direct_size) -
H5V_log2_of2(dtable->cparam.start_block_size)) + 2;
dtable->num_id_first_row = dtable->cparam.start_block_size * dtable->cparam.width;
dtable->max_dir_blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dtable->cparam.max_direct_size);
/* Build table of block sizes for each row */
if(NULL == (dtable->row_block_size = H5MM_malloc(dtable->max_root_rows * sizeof(hsize_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create doubling table block size table")
if(NULL == (dtable->row_block_off = H5MM_malloc(dtable->max_root_rows * sizeof(hsize_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create doubling table block offset table")
if(NULL == (dtable->row_dblock_free = H5MM_malloc(dtable->max_root_rows * sizeof(hsize_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create doubling table direct block free space table")
tmp_block_size = dtable->cparam.start_block_size;
acc_block_off = dtable->cparam.start_block_size * dtable->cparam.width;
dtable->row_block_size[0] = dtable->cparam.start_block_size;
dtable->row_block_off[0] = 0;
for(u = 1; u < dtable->max_root_rows; u++) {
dtable->row_block_size[u] = tmp_block_size;
dtable->row_block_off[u] = acc_block_off;
tmp_block_size *= 2;
acc_block_off *= 2;
} /* end for */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_dtable_init() */
/*-------------------------------------------------------------------------
* Function: H5HF_dtable_lookup
*
* Purpose: Compute the row & col of an offset in a doubling-table
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Mar 6 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_dtable_lookup(const H5HF_dtable_t *dtable, hsize_t off, unsigned *row, unsigned *col)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_dtable_lookup)
/*
* Check arguments.
*/
HDassert(dtable);
HDassert(row);
HDassert(col);
/* Check for offset in first row */
if(off < dtable->num_id_first_row) {
*row = 0;
*col = off / dtable->cparam.start_block_size;
} /* end if */
else {
unsigned high_bit = H5V_log2_gen(off); /* Determine the high bit in the offset */
hsize_t off_mask = 1 << high_bit; /* Compute mask for determining column */
*row = (high_bit - dtable->first_row_bits) + 1;
*col = (off - off_mask) / dtable->row_block_size[*row];
} /* end else */
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5HF_dtable_lookup() */
/*-------------------------------------------------------------------------
* Function: H5HF_dtable_dest
*
* Purpose: Release information for doubling table
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Mar 27 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_dtable_dest(H5HF_dtable_t *dtable)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_dtable_dest)
/*
* Check arguments.
*/
HDassert(dtable);
/* Free the block size lookup table for the doubling table */
H5MM_xfree(dtable->row_block_size);
/* Free the block offset lookup table for the doubling table */
H5MM_xfree(dtable->row_block_off);
/* Free the direct block free space lookup table for the doubling table */
H5MM_xfree(dtable->row_dblock_free);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5HF_dtable_dest() */

458
src/H5HFhdr.c Normal file
View File

@ -0,0 +1,458 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by the Board of Trustees of the University of Illinois. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the files COPYING and Copyright.html. COPYING can be found at the root *
* of the source code distribution tree; Copyright.html can be found at the *
* root level of an installed copy of the electronic HDF5 document set and *
* is linked from the top-level documents page. It can also be found at *
* http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have *
* access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*-------------------------------------------------------------------------
*
* Created: H5HFhdr.c
* Apr 10 2006
* Quincey Koziol <koziol@ncsa.uiuc.edu>
*
* Purpose: Heap header routines for fractal heaps.
*
*-------------------------------------------------------------------------
*/
/****************/
/* Module Setup */
/****************/
#define H5HF_PACKAGE /*suppress error about including H5HFpkg */
/***********/
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5HFpkg.h" /* Fractal heaps */
#include "H5Vprivate.h" /* Vectors and arrays */
/****************/
/* Local Macros */
/****************/
/* Limit on the size of the max. direct block size */
/* (This is limited to 32-bits currently, because I think it's unlikely to
* need to be larger, the 32-bit limit for H5V_log2_of2(n), and
* some offsets/sizes are encoded with a maxiumum of 32-bits - QAK)
*/
#define H5HL_MAX_DIRECT_SIZE_LIMIT ((hsize_t)2 * 1024 * 1024 * 1024)
/******************/
/* Local Typedefs */
/******************/
/********************/
/* Package Typedefs */
/********************/
/********************/
/* Local Prototypes */
/********************/
/*********************/
/* Package Variables */
/*********************/
/*****************************/
/* Library Private Variables */
/*****************************/
/*******************/
/* Local Variables */
/*******************/
/*-------------------------------------------------------------------------
* Function: H5HF_hdr_alloc
*
* Purpose: Allocate shared fractal heap header
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Mar 21 2006
*
*-------------------------------------------------------------------------
*/
H5HF_t *
H5HF_hdr_alloc(H5F_t *f)
{
H5HF_t *fh = NULL; /* Shared fractal heap header */
H5HF_t *ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_alloc)
/*
* Check arguments.
*/
HDassert(f);
/* Allocate space for the shared information */
if(NULL == (fh = H5FL_CALLOC(H5HF_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fractal heap shared header")
/* Set the internal parameters for the heap */
fh->f = f;
fh->sizeof_size = H5F_SIZEOF_SIZE(f);
fh->sizeof_addr = H5F_SIZEOF_ADDR(f);
/* Set the return value */
ret_value = fh;
done:
if(!ret_value)
if(fh)
(void)H5HF_cache_hdr_dest(f, fh);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_hdr_alloc() */
/*-------------------------------------------------------------------------
* Function: H5HF_hdr_free_space
*
* Purpose: Compute direct block free space, for indirect blocks of
* different sizes.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Mar 21 2006
*
*-------------------------------------------------------------------------
*/
static hsize_t
H5HF_hdr_compute_free_space(H5HF_t *hdr, hsize_t iblock_size)
{
hsize_t acc_heap_size; /* Accumumated heap space */
hsize_t acc_dblock_free; /* Accumumated direct block free space */
unsigned curr_row; /* Current row in block */
hsize_t ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_hdr_compute_free_space)
/*
* Check arguments.
*/
HDassert(hdr);
HDassert(iblock_size > hdr->man_dtable.cparam.max_direct_size);
/* Set the free space in direct blocks */
acc_heap_size = 0;
acc_dblock_free = 0;
curr_row = 0;
while(acc_heap_size < iblock_size) {
acc_heap_size += hdr->man_dtable.row_block_size[curr_row] *
hdr->man_dtable.cparam.width;
acc_dblock_free += hdr->man_dtable.row_dblock_free[curr_row] *
hdr->man_dtable.cparam.width;
curr_row++;
} /* end while */
/* Set return value */
ret_value = acc_dblock_free;
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_hdr_compute_free_space() */
/*-------------------------------------------------------------------------
* Function: H5HF_hdr_finish_init
*
* Purpose: Finish initializing info in shared heap header
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Mar 21 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_hdr_finish_init(H5HF_t *hdr)
{
size_t u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_finish_init)
/*
* Check arguments.
*/
HDassert(hdr);
/* Compute/cache some values */
hdr->heap_off_size = H5HF_SIZEOF_OFFSET_BITS(hdr->man_dtable.cparam.max_index);
if(H5HF_dtable_init(&hdr->man_dtable) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize doubling table info")
/* Create the free-list structure for the heap */
if(NULL == (hdr->flist = H5HF_flist_create(hdr->man_dtable.cparam.max_direct_size, H5HF_free_section_free_cb)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize free list info")
/* Set the size of heap IDs */
hdr->id_len = hdr->heap_off_size + MIN(hdr->man_dtable.max_dir_blk_off_size,
((H5V_log2_gen((hsize_t)hdr->standalone_size) + 7) / 8));
/* Set the free space in direct blocks */
for(u = 0; u < hdr->man_dtable.max_root_rows; u++) {
if(u < hdr->man_dtable.max_direct_rows)
hdr->man_dtable.row_dblock_free[u] = hdr->man_dtable.row_block_size[u] -
(H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, hdr->man_dtable.row_block_size[u])
+ H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr));
else
hdr->man_dtable.row_dblock_free[u] = H5HF_hdr_compute_free_space(hdr, hdr->man_dtable.row_block_size[u]);
#ifdef QAK
HDfprintf(stderr, "%s: row_block_size[%Zu] = %Hu\n", FUNC, u, hdr->man_dtable.row_block_size[u]);
HDfprintf(stderr, "%s: row_block_off[%Zu] = %Hu\n", FUNC, u, hdr->man_dtable.row_block_off[u]);
HDfprintf(stderr, "%s: row_dblock_free[%Zu] = %Hu\n", FUNC, u, hdr->man_dtable.row_dblock_free[u]);
#endif /* QAK */
} /* end for */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_hdr_finish_init() */
/*-------------------------------------------------------------------------
* Function: H5HF_hdr_init
*
* Purpose: Initialize shared fractal heap header for new heap
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Mar 21 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_hdr_init(H5HF_t *fh, haddr_t fh_addr, H5HF_create_t *cparam)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_init)
/*
* Check arguments.
*/
HDassert(fh);
HDassert(cparam);
#ifndef NDEBUG
/* Check for valid parameters */
if(!POWER_OF_TWO(cparam->managed.width) || cparam->managed.width == 0)
HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "width not power of two")
if(!POWER_OF_TWO(cparam->managed.start_block_size) || cparam->managed.start_block_size == 0)
HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "starting block size not power of two")
if(!POWER_OF_TWO(cparam->managed.max_direct_size) ||
(cparam->managed.max_direct_size == 0 || cparam->managed.max_direct_size > H5HL_MAX_DIRECT_SIZE_LIMIT))
HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. direct block size not power of two")
if(cparam->managed.max_direct_size < cparam->standalone_size)
HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. direct block size not large enough to hold all managed blocks")
if(cparam->managed.max_index > (8 * fh->sizeof_size) || cparam->managed.max_index == 0)
HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. direct block size not power of two")
#endif /* NDEBUG */
/* Set the creation parameters for the heap */
fh->heap_addr = fh_addr;
fh->addrmap = cparam->addrmap;
fh->standalone_size = cparam->standalone_size;
HDmemcpy(&(fh->man_dtable.cparam), &(cparam->managed), sizeof(H5HF_dtable_cparam_t));
/* Set root table address */
fh->man_dtable.table_addr = HADDR_UNDEF;
/* Note that the shared info is dirty (it's not written to the file yet) */
fh->dirty = TRUE;
/* Make shared heap info reference counted */
if(H5HF_hdr_finish_init(fh) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for shared fractal heap header")
done:
if(ret_value < 0)
if(fh)
(void)H5HF_cache_hdr_dest(NULL, fh);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_hdr_init() */
/*-------------------------------------------------------------------------
* Function: H5HF_hdr_incr
*
* Purpose: Increment reference count on shared heap header
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Mar 27 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_hdr_incr(H5HF_t *hdr)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_hdr_incr)
/* Sanity check */
HDassert(hdr);
/* XXX: When "un-evictable" feature is finished, mark the header as
* unevictable on the first block to share it. - QAK
*/
/* Increment reference count on shared header */
hdr->rc++;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5HF_hdr_incr() */
/*-------------------------------------------------------------------------
* Function: H5HF_hdr_decr
*
* Purpose: Decrement reference count on shared heap header
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Mar 27 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_hdr_decr(H5HF_t *hdr)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_hdr_decr)
/* Sanity check */
HDassert(hdr);
/* Decrement reference count on shared header */
hdr->rc--;
/* XXX: When "un-evictable" feature is finished, mark the header as
* evictable when the ref. count drops to zero. - QAK
*/
/* XXX: Take this call out after "un-evictable" flag is working */
H5HF_cache_hdr_dest_real(hdr);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5HF_hdr_decr() */
/*-------------------------------------------------------------------------
* Function: H5HF_hdr_dirty
*
* Purpose: Mark heap header as dirty
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Mar 27 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_hdr_dirty(hid_t dxpl_id, H5HF_t *hdr)
{
H5HF_t *tmp_hdr; /* Temporary pointer to heap header */
hbool_t is_protected; /* Whether the indirect block is protected */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_dirty)
#ifdef QAK
HDfprintf(stderr, "%s: Marking heap header as dirty\n", FUNC);
#endif /* QAK */
/* Sanity check */
HDassert(hdr);
/* XXX: When "un-evictable" feature is finished, just mark the header as dirty
* in the cache, instead of this protect -> unprotect kludge - QAK
*/
/* Protect the header */
is_protected = hdr->cache_info.is_protected;
if(!is_protected) {
#ifdef QAK
HDfprintf(stderr, "%s: hdr->heap_addr = %a\n", FUNC, hdr->heap_addr);
#endif /* QAK */
if(NULL == (tmp_hdr = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_HDR, hdr->heap_addr, NULL, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
HDassert(hdr == tmp_hdr);
} /* end if */
/* Set the dirty flags for the heap header */
hdr->dirty = TRUE;
/* Release the heap header (marked as dirty) */
if(!is_protected) {
if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_HDR, hdr->heap_addr, tmp_hdr, H5AC__DIRTIED_FLAG) < 0)
HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
} /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_hdr_dirty() */
/*-------------------------------------------------------------------------
* Function: H5HF_hdr_extend_heap
*
* Purpose: Extend heap to cover more space
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Apr 10 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_hdr_extend_heap(H5HF_t *hdr, hsize_t new_size, hsize_t extra_free)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_hdr_extend_heap)
/*
* Check arguments.
*/
HDassert(hdr);
HDassert(new_size >= hdr->total_size);
/* Set the total space in heap */
hdr->total_size = new_size;
hdr->man_size = new_size;
/* Increment the free space in direct blocks */
hdr->total_man_free += extra_free;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5HF_hdr_extend_heap() */

1410
src/H5HFiblock.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -93,7 +93,7 @@
)
/* Size of overhead for a direct block */
#define H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(h, o) ( \
#define H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(h, s) ( \
/* General metadata fields */ \
H5HF_METADATA_PREFIX_SIZE \
\
@ -103,7 +103,7 @@
+ 2 /* Entry within parent block */ \
+ 2 /* # of rows for parent block */ \
+ (h)->heap_off_size /* Offset of the block in the heap */ \
+ H5HF_SIZEOF_OFFSET_LEN(o) /* Offset of first descriptor in free list */ \
+ H5HF_SIZEOF_OFFSET_LEN(s) /* Offset of first descriptor in free list */ \
)
#define H5HF_MAN_ABS_DIRECT_OVERHEAD_DBLOCK(h, d) ( \
/* General metadata fields */ \
@ -165,13 +165,50 @@ typedef struct H5HF_dtable_t {
hsize_t num_id_first_row; /* Number of IDs in first row of table */
hsize_t *row_block_size; /* Block size per row of indirect block */
hsize_t *row_block_off; /* Cumulative offset per row of indirect block */
hsize_t *row_dblock_free; /* Free space in dblocks for this row */
/* (For indirect block rows, it's the total
* free space in all direct blocks referenced
* from the indirect block
*/
} H5HF_dtable_t;
/* Fractal heap free list info (forward decl - defined in H5HFflist.c) */
typedef struct H5HF_freelist_t H5HF_freelist_t;
/* Fractal heap free list section info (forward decl - defined in H5HFint.c) */
typedef struct H5HF_section_free_node_t H5HF_section_free_node_t;
/* Fractal heap free list section info */
typedef struct H5HF_free_section_t {
haddr_t sect_addr; /* Address of free list section in the file */
/* (Not actually used as address, used as unique ID for free list node) */
size_t sect_size; /* Size of free space section */
/* (section size is "object size", without the metadata overhead, since metadata overhead varies from block to block) */
/* (for range sections, this is the largest single section within the range) */
enum {H5HF_SECT_SINGLE, H5HF_SECT_RANGE, H5HF_SECT_INDIRECT} type; /* Type of free space section */
union {
struct {
haddr_t dblock_addr; /* Address of direct block for free section */
size_t dblock_size; /* Size of direct block */
/* (Needed to retrieve direct block) */
} single;
struct {
haddr_t iblock_addr; /* Address of indirect block for free section */
unsigned iblock_nrows; /* Number of rows in indirect block */
/* (Needed to retrieve indirect block) */
unsigned row; /* Row for range of blocks */
unsigned col; /* Column for range of blocks */
unsigned num_entries; /* Number of entries covered */
} range;
struct {
haddr_t iblock_addr; /* Address of indirect block for free section */
unsigned iblock_nrows; /* Number of rows in indirect block */
/* (Needed to retrieve indirect block) */
unsigned row; /* Row for range of blocks */
unsigned col; /* Column for range of blocks */
unsigned num_entries; /* Number of entries covered */
unsigned indir_row; /* Row for indirect range of blocks */
unsigned indir_nrows; /* Number of rows in indirect blocks */
} indirect;
} u;
} H5HF_free_section_t;
/* The fractal heap header information */
/* (Each fractal heap header has certain information that is shared across all
@ -337,35 +374,60 @@ H5FL_EXTERN(H5HF_indirect_t);
/* Declare a free list to manage the H5HF_indirect_ent_t sequence information */
H5FL_SEQ_EXTERN(H5HF_indirect_ent_t);
/* Declare a free list to manage the H5HF_free_section_t struct */
H5FL_EXTERN(H5HF_free_section_t);
/******************************/
/* Package Private Prototypes */
/******************************/
/* Routines for managing shared fractal heap header */
H5_DLL H5HF_t * H5HF_alloc(H5F_t *f);
H5_DLL herr_t H5HF_init(H5HF_t *fh, haddr_t heap_addr, H5HF_create_t *cparam);
H5_DLL herr_t H5HF_finish_init(H5HF_t *fh);
H5_DLL H5HF_t * H5HF_hdr_alloc(H5F_t *f);
H5_DLL herr_t H5HF_hdr_init(H5HF_t *hdr, haddr_t heap_addr, H5HF_create_t *cparam);
H5_DLL herr_t H5HF_hdr_finish_init(H5HF_t *hdr);
/* Doubling table routines */
H5_DLL herr_t H5HF_dtable_init(H5HF_dtable_t *dtable);
H5_DLL herr_t H5HF_dtable_dest(H5HF_dtable_t *dtable);
H5_DLL herr_t H5HF_dtable_lookup(const H5HF_dtable_t *dtable, hsize_t off,
unsigned *row, unsigned *col);
/* Heap header routines */
H5_DLL herr_t H5HF_cache_hdr_dest_real(H5HF_t *hdr);
H5_DLL herr_t H5HF_hdr_incr(H5HF_t *hdr);
H5_DLL herr_t H5HF_hdr_decr(H5HF_t *hdr);
H5_DLL herr_t H5HF_hdr_dirty(hid_t dxpl_id, H5HF_t *hdr);
H5_DLL herr_t H5HF_hdr_extend_heap(H5HF_t *hdr, hsize_t new_size, hsize_t extra_free);
/* Indirect block routines */
H5_DLL herr_t H5HF_cache_iblock_dest_real(H5HF_indirect_t *iblock);
H5_DLL herr_t H5HF_iblock_incr(H5HF_indirect_t *iblock);
H5_DLL herr_t H5HF_iblock_decr(H5HF_indirect_t *iblock);
H5_DLL herr_t H5HF_iblock_dirty(hid_t dxpl_id, H5HF_indirect_t *iblock);
H5_DLL H5HF_indirect_t * H5HF_man_iblock_place_dblock(H5HF_t *fh, hid_t dxpl_id,
size_t min_dblock_size, haddr_t *addr_p, size_t *entry_p,
size_t *dblock_size);
H5_DLL herr_t H5HF_man_iblock_alloc_range(H5HF_t *hdr, hid_t dxpl_id,
H5HF_free_section_t **sec_node, size_t obj_size);
H5_DLL herr_t H5HF_man_iblock_alloc_indirect(H5HF_t *hdr, hid_t dxpl_id,
H5HF_free_section_t **sec_node, size_t obj_size);
/* Routines for allocating space */
/* Direct block routines */
H5_DLL herr_t H5HF_man_dblock_new(H5HF_t *fh, hid_t dxpl_id, size_t request);
H5_DLL herr_t H5HF_man_dblock_create(hid_t dxpl_id, H5HF_t *hdr,
H5HF_indirect_t *par_iblock, unsigned par_entry, size_t block_size,
hsize_t block_off, haddr_t *addr_p, H5HF_free_section_t **ret_sec_node);
H5_DLL herr_t H5HF_man_dblock_adj_free(hid_t dxpl_id, H5HF_direct_t *dblock, ssize_t amt);
H5_DLL herr_t H5HF_man_dblock_build_freelist(H5HF_direct_t *dblock, haddr_t dblock_addr);
/* Routines for internal operations */
H5_DLL herr_t H5HF_free_section_free_cb(void *item, void UNUSED *key,
void UNUSED *op_data);
H5_DLL herr_t H5HF_man_find(H5HF_t *fh, hid_t dxpl_id, size_t request,
H5HF_section_free_node_t **sec_node/*out*/);
H5HF_free_section_t **sec_node/*out*/);
H5_DLL herr_t H5HF_man_insert(H5HF_t *fh, hid_t dxpl_id,
H5HF_section_free_node_t *sec_node, size_t obj_size, const void *obj,
H5HF_free_section_t *sec_node, size_t obj_size, const void *obj,
void *id);
H5_DLL herr_t H5HF_man_read(H5HF_t *fh, hid_t dxpl_id, hsize_t obj_off,
size_t obj_len, void *obj);
@ -400,6 +462,8 @@ H5_DLL herr_t H5HF_flist_free(H5HF_freelist_t *flist);
#ifdef H5HF_TESTING
H5_DLL herr_t H5HF_get_cparam_test(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr,
H5HF_create_t *cparam);
H5_DLL hsize_t H5HF_get_dblock_free_test(H5F_t *f, hid_t dxpl_id,
haddr_t fh_addr, unsigned row);
#endif /* H5HF_TESTING */
#endif /* _H5HFpkg_H */

View File

@ -113,3 +113,46 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5HF_get_cparam_test() */
/*-------------------------------------------------------------------------
* Function: H5HF_get_dblock_free_test
*
* Purpose: Retrieve the size of direct block free space for a given
* direct or indirect block size
*
* Return: Success: Size of direct block free space
*
* Failure: 0
*
* Programmer: Quincey Koziol
* Monday, April 10, 2006
*
*-------------------------------------------------------------------------
*/
hsize_t
H5HF_get_dblock_free_test(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr, unsigned row)
{
H5HF_t *hdr = NULL; /* Pointer to the fractal heap header */
hsize_t ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_get_dblock_free_test)
/* Check arguments. */
HDassert(f);
HDassert(H5F_addr_defined(fh_addr));
/* Look up the fractal heap header */
if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, 0, "unable to load fractal heap header")
/* Return direct block free space */
ret_value = hdr->man_dtable.row_dblock_free[row];
done:
/* Release fractal heap header node */
if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, hdr, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, 0, "unable to release fractal heap header info")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5HF_get_dblock_free_test() */

View File

@ -211,6 +211,7 @@ MINOR, MPI, H5E_MPIERRSTR, MPI Error String
# Heap errors
MINOR, HEAP, H5E_CANTRESTORE, Can't restore condition
MINOR, HEAP, H5E_CANTCOMPUTE, Can't compute value
MINOR, HEAP, H5E_CANTEXTEND, Can't extend heap's space
# FPHDF5 errors
MINOR, FPH5, H5E_CANTRECV, Can't receive messages from processes

View File

@ -55,7 +55,8 @@ libhdf5_la_SOURCES= H5.c H5dbg.c H5A.c H5AC.c H5B.c H5Bcache.c \
H5Gstab.c \
H5Gtest.c \
H5Gtraverse.c \
H5HF.c H5HFcache.c H5HFdbg.c H5HFflist.c H5HFint.c H5HFstat.c H5HFtest.c \
H5HF.c H5HFcache.c H5HFdbg.c H5HFdblock.c H5HDdtable.c H5HFflist.c \
H5HFhdr.c H5HFiblock.c H5HFint.c H5HFstat.c H5HFtest.c \
H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5MF.c H5MM.c \
H5MP.c H5MPtest.c \
H5O.c \

View File

@ -94,6 +94,10 @@ am_libhdf5_la_OBJECTS = H5.lo H5dbg.lo H5A.lo H5AC.lo H5B.lo \
H5FPserver.lo H5FS.lo H5G.lo H5Gent.lo H5Glink.lo H5Gloc.lo \
H5Gname.lo H5Gnode.lo H5Gobj.lo H5Goh.lo H5Gstab.lo H5Gtest.lo \
H5Gtraverse.lo H5HF.lo H5HFcache.lo H5HFdbg.lo H5HFflist.lo \
H5HFdblock.lo \
H5HFdtable.lo \
H5HFhdr.lo \
H5HFiblock.lo \
H5HFint.lo H5HFstat.lo H5HFtest.lo H5HG.lo H5HGdbg.lo H5HL.lo \
H5HLdbg.lo H5HP.lo H5I.lo H5MF.lo H5MM.lo H5MP.lo H5MPtest.lo \
H5O.lo H5Oattr.lo H5Obogus.lo H5Ocache.lo H5Ocont.lo \
@ -410,7 +414,12 @@ libhdf5_la_SOURCES = H5.c H5dbg.c H5A.c H5AC.c H5B.c H5Bcache.c \
H5Gstab.c \
H5Gtest.c \
H5Gtraverse.c \
H5HF.c H5HFcache.c H5HFdbg.c H5HFflist.c H5HFint.c H5HFstat.c H5HFtest.c \
H5HF.c H5HFcache.c H5HFdbg.c H5HFflist.c \
H5HFdblock.c \
H5HFdtable.c \
H5HFhdr.c \
H5HFiblock.c \
H5HFint.c H5HFstat.c H5HFtest.c \
H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5MF.c H5MM.c \
H5MP.c H5MPtest.c \
H5O.c \
@ -624,6 +633,10 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFcache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFdbg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFflist.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFdblock.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFdtable.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFhdr.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFiblock.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFint.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFstat.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFtest.Plo@am__quote@

File diff suppressed because it is too large Load Diff