From 2db47ff504a58278019957f9e5bc446d58894fed Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Mon, 20 Mar 2006 21:59:06 -0500 Subject: [svn-r12125] Purpose: Code checkpoint Description: Update fractal heap code to insert & read heaps up to 64MB in size (with my current configuration paramaters) and add initial support for iteratively walking down nested indirect blocks. Platforms tested: FreeBSD 4.11 (sleipnir) Linux 2.4 (chicago) Solaris 9 (shanti) Linux 2.4 (mir) w/64-bit --- src/H5HF.c | 9 +- src/H5HFcache.c | 112 +++++----- src/H5HFdbg.c | 48 ++--- src/H5HFflist.c | 195 +++++++++++++++-- src/H5HFint.c | 474 ++++++++++++++++++++++++++--------------- src/H5HFpkg.h | 80 +++---- src/H5private.h | 19 +- test/fheap.c | 646 +++++++++++++++++++++++++++++++++++++++++++++++++++----- 8 files changed, 1191 insertions(+), 392 deletions(-) diff --git a/src/H5HF.c b/src/H5HF.c index ac5990b..feb88be 100644 --- a/src/H5HF.c +++ b/src/H5HF.c @@ -99,6 +99,7 @@ herr_t H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_create_t *cparam, haddr_t *addr_p) { H5HF_t *fh = NULL; /* The new fractal heap header information */ + H5HF_shared_t *shared = NULL; /* Shared fractal heap information */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5HF_create, FAIL) @@ -119,12 +120,16 @@ H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_create_t *cparam, haddr_t *addr_p) /* Reset the metadata cache info for the heap header */ HDmemset(&fh->cache_info, 0, sizeof(H5AC_info_t)); + /* Allocate & basic initialization for the shared info struct */ + if(NULL == (shared = H5HF_shared_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(f)))) + if(HADDR_UNDEF == (*addr_p = H5MF_alloc(f, H5FD_MEM_FHEAP_HDR, dxpl_id, (hsize_t)H5HF_HEADER_SIZE(shared)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap header") /* Initialize shared fractal heap info */ - if(H5HF_shared_create(f, fh, *addr_p, cparam) < 0) + if(H5HF_shared_init(shared, fh, *addr_p, cparam) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create shared fractal heap info") /* Cache the new fractal heap header */ diff --git a/src/H5HFcache.c b/src/H5HFcache.c index fbeecc8..1fd3b51 100644 --- a/src/H5HFcache.c +++ b/src/H5HFcache.c @@ -283,7 +283,7 @@ H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *ud shared->heap_addr = addr; /* Compute the size of the fractal heap header on disk */ - size = H5HF_HEADER_SIZE(f); + size = H5HF_HEADER_SIZE(shared); /* Allocate temporary buffer */ if((buf = H5FL_BLK_MALLOC(header_block, size)) == NULL) @@ -399,7 +399,7 @@ H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5H HDassert(shared->dirty); /* Compute the size of the heap header on disk */ - size = H5HF_HEADER_SIZE(f); + size = H5HF_HEADER_SIZE(shared); /* Allocate temporary buffer */ if((buf = H5FL_BLK_MALLOC(header_block, size)) == NULL) @@ -554,16 +554,23 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5HF_cache_hdr_size(const H5F_t *f, const H5HF_t UNUSED *fh, size_t *size_ptr) +H5HF_cache_hdr_size(const H5F_t *f, const H5HF_t *fh, size_t *size_ptr) { + H5HF_shared_t *shared; /* Shared fractal heap information */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_hdr_size) /* check arguments */ HDassert(f); + HDassert(fh); HDassert(size_ptr); + /* Get the pointer to the shared heap info */ + shared = H5RC_GET_OBJ(fh->shared); + HDassert(shared); + /* Set size value */ - *size_ptr = H5HF_HEADER_SIZE(f); + *size_ptr = H5HF_HEADER_SIZE(shared); FUNC_LEAVE_NOAPI(SUCCEED) } /* H5HF_cache_hdr_size() */ @@ -994,14 +1001,10 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrows /* Set block's internal information */ iblock->nrows = *nrows; - if(iblock->nrows > shared->man_dtable.max_direct_rows) { - iblock->ndir_rows = shared->man_dtable.max_direct_rows; - iblock->nindir_rows = iblock->nrows - iblock->ndir_rows; - } /* end if */ - else { - iblock->ndir_rows = iblock->nrows; - iblock->nindir_rows = 0; - } /* end else */ + if(!iblock->parent) + iblock->max_rows = shared->man_dtable.max_root_rows; + else + iblock->max_rows = *nrows; /* Compute size of indirect block */ iblock->size = H5HF_MAN_INDIRECT_SIZE(shared, iblock); @@ -1037,7 +1040,7 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrows if(metadata_chksum != 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect metadata checksum for fractal heap direct block") - /* Address of heap that owns this block (skip) */ + /* Address of heap that owns this block */ H5F_addr_decode(f, &p, &heap_addr); if(H5F_addr_ne(heap_addr, shared->heap_addr)) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect heap header address for direct block") @@ -1045,47 +1048,28 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrows /* Offset of heap within the heap's address space */ UINT64DECODE_VAR(p, iblock->block_off, shared->heap_off_size); + /* Offset of next entry to allocate within this block */ + UINT32DECODE(p, iblock->next_entry); + + /* Compute next block column, row & size */ + iblock->next_col = iblock->next_entry % shared->man_dtable.cparam.width; + iblock->next_row = iblock->next_entry / shared->man_dtable.cparam.width; + iblock->next_size = shared->man_dtable.row_block_size[iblock->next_row]; + /* Allocate & decode indirect block entry tables */ - HDassert(iblock->ndir_rows > 0); - if(NULL == (iblock->dblock_ents = H5FL_SEQ_MALLOC(H5HF_indirect_dblock_ent_t, (iblock->ndir_rows * shared->man_dtable.cparam.width)))) + HDassert(iblock->nrows > 0); + if(NULL == (iblock->ents = H5FL_SEQ_MALLOC(H5HF_indirect_ent_t, (iblock->nrows * shared->man_dtable.cparam.width)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for direct entries") - iblock->dir_full = TRUE; - for(u = 0; u < (iblock->ndir_rows * shared->man_dtable.cparam.width); u++) { - H5F_addr_decode(f, &p, &(iblock->dblock_ents[u].addr)); - UINT32DECODE_VAR(p, iblock->dblock_ents[u].free_space, shared->man_dtable.max_dir_blk_off_size); - - /* Check for direct block being undefined and use that for the next one to allocate from this indirect block */ - if(iblock->dir_full) { - if(!H5F_addr_defined(iblock->dblock_ents[u].addr)) { - iblock->next_dir_col = u % shared->man_dtable.cparam.width; - iblock->next_dir_row = u / shared->man_dtable.cparam.width; - iblock->next_dir_entry = u; - if(iblock->next_dir_row == 0) - iblock->next_dir_size = shared->man_dtable.cparam.start_block_size; - else - iblock->next_dir_size = shared->man_dtable.cparam.start_block_size * (1 << (iblock->next_dir_row - 1)); - if(iblock->block_off == 0) - iblock->max_direct_rows = shared->man_dtable.max_direct_rows; - else - HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, NULL, "computing max direct rows for non-root indirect block not supported yet") - - /* Set the flag to indicate the direct blocks aren't full */ - iblock->dir_full = FALSE; - } /* end if */ - } /* end if */ + for(u = 0; u < (iblock->nrows * shared->man_dtable.cparam.width); u++) { + /* Decode block address */ + H5F_addr_decode(f, &p, &(iblock->ents[u].addr)); + + /* Decode direct & indirect blocks differently */ + if(u < (shared->man_dtable.max_direct_rows * shared->man_dtable.cparam.width)) + UINT32DECODE_VAR(p, iblock->ents[u].free_space, shared->man_dtable.max_dir_blk_off_size) + else + UINT64DECODE_VAR(p, iblock->ents[u].free_space, shared->heap_off_size) } /* end for */ - if(iblock->nindir_rows > 0) { - if(NULL == (iblock->iblock_ents = H5FL_SEQ_MALLOC(H5HF_indirect_iblock_ent_t, (iblock->nindir_rows * shared->man_dtable.cparam.width)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for indirect entries") - - /* Decode indirect block-specific fields */ - for(u = 0; u < (iblock->nindir_rows * shared->man_dtable.cparam.width); u++) { - H5F_addr_decode(f, &p, &(iblock->iblock_ents[u].addr)); - UINT64DECODE_VAR(p, iblock->iblock_ents[u].free_space, shared->heap_off_size); - } /* end for */ - } /* end if */ - else - iblock->iblock_ents = NULL; /* Sanity check */ HDassert((size_t)(p - buf) == iblock->size); @@ -1150,8 +1134,6 @@ HDfprintf(stderr, "%s: Flushing indirect block\n", FUNC); /* XXX: Use free list factories? */ #ifdef QAK HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows); -HDfprintf(stderr, "%s: iblock->ndir_rows = %u\n", FUNC, iblock->ndir_rows); -HDfprintf(stderr, "%s: iblock->nindir_rows = %u\n", FUNC, iblock->nindir_rows); HDfprintf(stderr, "%s: iblock->size = %Zu\n", FUNC, iblock->size); HDfprintf(stderr, "%s: iblock->block_off = %Hu\n", FUNC, iblock->block_off); HDfprintf(stderr, "%s: shared->man_dtable.cparam.width = %u\n", FUNC, shared->man_dtable.cparam.width); @@ -1182,21 +1164,21 @@ HDfprintf(stderr, "%s: shared->man_dtable.cparam.width = %u\n", FUNC, shared->ma /* Offset of block in heap */ UINT64ENCODE_VAR(p, iblock->block_off, shared->heap_off_size); -/* XXX: Fix this when we start writing recursive indirect blocks */ -if(iblock->block_off != 0) - HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "fix computing max direct rows for non-root indirect block for loading") + + /* Next block entry to allocate from */ + UINT32ENCODE(p, iblock->next_entry); /* Encode indirect block-specific fields */ - HDassert(iblock->ndir_rows > 0); - for(u = 0; u < (iblock->ndir_rows * shared->man_dtable.cparam.width); u++) { - H5F_addr_encode(f, &p, iblock->dblock_ents[u].addr); - UINT32ENCODE_VAR(p, iblock->dblock_ents[u].free_space, shared->man_dtable.max_dir_blk_off_size); + for(u = 0; u < (iblock->nrows * shared->man_dtable.cparam.width); u++) { + /* Encode block address */ + H5F_addr_encode(f, &p, iblock->ents[u].addr); + + /* Encode direct & indirect blocks differently */ + if(u < (shared->man_dtable.max_direct_rows * shared->man_dtable.cparam.width)) + UINT32ENCODE_VAR(p, iblock->ents[u].free_space, shared->man_dtable.max_dir_blk_off_size) + else + UINT64ENCODE_VAR(p, iblock->ents[u].free_space, shared->heap_off_size) } /* end for */ - if(iblock->nindir_rows > 0) - for(u = 0; u < (iblock->nindir_rows * shared->man_dtable.cparam.width); u++) { - H5F_addr_encode(f, &p, iblock->iblock_ents[u].addr); - UINT64ENCODE_VAR(p, iblock->iblock_ents[u].free_space, shared->heap_off_size); - } /* end for */ /* Sanity check */ HDassert((size_t)(p - buf) == iblock->size); diff --git a/src/H5HFdbg.c b/src/H5HFdbg.c index 5dddac7..43a6064 100644 --- a/src/H5HFdbg.c +++ b/src/H5HFdbg.c @@ -133,7 +133,7 @@ H5HF_dtable_debug(H5HF_dtable_t *dtable, FILE *stream, int indent, int fwidth) /* Computed values */ HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Max. # of rows in root indirect block:", - dtable->max_root_indirect_rows); + dtable->max_root_rows); HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Max. # of direct rows in any indirect block:", dtable->max_direct_rows); @@ -476,35 +476,28 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, "Size of indirect block:", iblock->size); HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Total # of rows:", + "Current # of rows:", iblock->nrows); HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "# of direct rows:", - iblock->ndir_rows); - HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "# of indirect rows:", - iblock->nindir_rows); - HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, - "Direct blocks full:", - (iblock->dir_full ? "TRUE" : "FALSE")); + "Max. # of rows:", + iblock->max_rows); HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Max direct block rows:", - iblock->max_direct_rows); + shared->man_dtable.max_direct_rows); HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Next direct block column:", - iblock->next_dir_col); + "Next block column:", + iblock->next_col); HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Next direct block row:", - iblock->next_dir_row); - HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Next direct block size:", - iblock->next_dir_size); + "Next block row:", + iblock->next_row); + HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, + "Next block size:", + iblock->next_size); /* Print the entry tables */ - dblock_size = shared->man_dtable.cparam.start_block_size; HDfprintf(stream, "%*sDirect Block Entries (address, free space):\n", indent, ""); - for(u = 0; u < iblock->ndir_rows; u++) { - sprintf(temp_str, "Row #%u: (block size: %lu)", (unsigned)u, (unsigned long)dblock_size); + for(u = 0; u < shared->man_dtable.max_direct_rows && u < iblock->nrows; u++) { + sprintf(temp_str, "Row #%u: (block size: %lu)", (unsigned)u, (unsigned long)shared->man_dtable.row_block_size[u]); HDfprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(0, fwidth - 3), temp_str); for(v = 0; v < shared->man_dtable.cparam.width; v++) { @@ -513,14 +506,14 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, sprintf(temp_str, "Col #%u:", (unsigned)v); HDfprintf(stream, "%*s%-*s %8a, %8Zu\n", indent + 6, "", MAX(0, fwidth - 6), temp_str, - iblock->dblock_ents[off].addr, - iblock->dblock_ents[off].free_space); + iblock->ents[off].addr, + iblock->ents[off].free_space); } /* end for */ dblock_size *= 2; } /* end for */ HDfprintf(stream, "%*sIndirect Block Entries:\n", indent, ""); - if(iblock->nindir_rows > 0) { - for(u = 0; u < iblock->nindir_rows; u++) { + if(iblock->nrows > shared->man_dtable.max_direct_rows) { + for(u = shared->man_dtable.max_direct_rows; u < iblock->nrows; u++) { sprintf(temp_str, "Row #%u:", (unsigned)u); HDfprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(0, fwidth - 3), temp_str); @@ -528,9 +521,10 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, size_t off = (u * shared->man_dtable.cparam.width) + v; sprintf(temp_str, "Col #%u:", (unsigned)v); - HDfprintf(stream, "%*s%-*s %8a\n", indent + 6, "", MAX(0, fwidth - 6), + HDfprintf(stream, "%*s%-*s %8a, %8Zu\n", indent + 6, "", MAX(0, fwidth - 6), temp_str, - iblock->iblock_ents[off].addr); + iblock->ents[off].addr, + iblock->ents[off].free_space); } /* end for */ } /* end for */ } /* end if */ diff --git a/src/H5HFflist.c b/src/H5HFflist.c index 361bb37..97e30e9 100644 --- a/src/H5HFflist.c +++ b/src/H5HFflist.c @@ -44,6 +44,13 @@ /* Local Typedefs */ /******************/ +/* Structure for storing single free list section */ +typedef struct H5HF_flist_single_t { + void *node; /* Pointer to section's node */ + size_t *size_key; /* Pointer to size key for section */ + haddr_t *addr_key; /* Pointer to address key for section */ +} H5HF_flist_single_t; + /* Free list node for free list sections of the same size */ typedef struct H5HF_flist_node_t { size_t sec_size; /* Size of all sections on list */ @@ -58,6 +65,8 @@ typedef struct H5HF_flist_node_t { /* Main free list info */ struct H5HF_freelist_t { hsize_t tot_space; /* Total amount of space in free list */ + size_t sec_count; /* # of sections on free list */ + H5HF_flist_single_t single; /* Section information when free list has only one free section */ unsigned nbins; /* Number of bins */ H5SL_operator_t node_free_op; /* Callback for freeing nodes when free list is destroyed */ H5SL_t **bins; /* Pointer to array of lists of free nodes */ @@ -128,12 +137,13 @@ H5HF_flist_create(size_t max_block_size, H5SL_operator_t node_free_op) /* Set free list parameters */ flist->tot_space = 0; + flist->sec_count = 0; + flist->single.node = NULL; + flist->single.size_key = NULL; + flist->single.addr_key = NULL; flist->nbins = H5V_log2_of2(max_block_size); flist->node_free_op = node_free_op; - - /* Allocate the bins for free space sizes */ - if(NULL == (flist->bins = H5FL_SEQ_CALLOC(H5SL_ptr_t, flist->nbins))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for free list bins") + flist->bins = NULL; /* Set return value */ ret_value = flist; @@ -144,27 +154,28 @@ done: /*------------------------------------------------------------------------- - * Function: H5HF_flist_add + * Function: H5HF_flist_add_bin_node * * Purpose: Add a section of free space in a direct block to the free list + * bins * * Return: Success: non-negative * * Failure: negative * * Programmer: Quincey Koziol - * Tuesday, March 7, 2006 + * Monday, March 20, 2006 * *------------------------------------------------------------------------- */ -herr_t -H5HF_flist_add(H5HF_freelist_t *flist, void *node, size_t *size_key, haddr_t *addr_key) +static herr_t +H5HF_flist_add_bin_node(H5HF_freelist_t *flist, void *node, size_t *size_key, haddr_t *addr_key) { H5HF_flist_node_t *flist_node = NULL; /* Pointer to free list node of the correct size */ unsigned bin; /* Bin to put the free space section in */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HF_flist_add) + FUNC_ENTER_NOAPI_NOINIT(H5HF_flist_add_bin_node) #ifdef QAK HDfprintf(stderr, "%s: *size_key = %Zu, *addr_key = %a\n", FUNC, *size_key, *addr_key); #endif /* QAK */ @@ -208,13 +219,83 @@ HDfprintf(stderr, "%s: *size_key = %Zu, *addr_key = %a\n", FUNC, *size_key, *add done: FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_flist_add_bin_node() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_flist_add + * + * Purpose: Add a section of free space in a direct block to the free list + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, March 7, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_flist_add(H5HF_freelist_t *flist, void *node, size_t *size_key, haddr_t *addr_key) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_flist_add) +#ifdef QAK +HDfprintf(stderr, "%s: *size_key = %Zu, *addr_key = %a\n", FUNC, *size_key, *addr_key); +#endif /* QAK */ + + /* Check arguments. */ + HDassert(flist); + HDassert(node); + HDassert(size_key); + HDassert(addr_key); + + /* Check for special cases of # of sections on free list */ + if(flist->sec_count == 0) { + HDassert(flist->single.node == NULL); + + /* Capture single section's information */ + flist->single.node = node; + flist->single.size_key = size_key; + flist->single.addr_key = addr_key; + } /* end if */ + else { + /* Have a single section, put it into the bins */ + if(flist->sec_count == 1) { + HDassert(flist->single.node); + + /* Check if we should allocate the bins */ + if(flist->bins == NULL) + /* Allocate the bins for free space sizes */ + if(NULL == (flist->bins = H5FL_SEQ_CALLOC(H5SL_ptr_t, flist->nbins))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for free list bins") + + /* Insert the current single section into the bins */ + if(H5HF_flist_add_bin_node(flist, flist->single.node, flist->single.size_key, flist->single.addr_key) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "can't insert free list node into skip list") + flist->single.node = NULL; + } /* end if */ + HDassert(flist->single.node == NULL); + + /* Put new section into bins */ + if(H5HF_flist_add_bin_node(flist, node, size_key, addr_key) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "can't insert free list node into skip list") + } /* end else */ + + /* Increment # of sections on free list */ + flist->sec_count++; + +done: + FUNC_LEAVE_NOAPI(ret_value) } /* H5HF_flist_add() */ /*------------------------------------------------------------------------- - * Function: H5HF_flist_find + * Function: H5HF_flist_find_bin_node * - * Purpose: Locate a section of free space (in existing free list) that + * Purpose: Locate a section of free space (in existing free list bins) that * is large enough to fulfill request. * * Return: Success: non-negative @@ -222,18 +303,18 @@ done: * Failure: negative * * Programmer: Quincey Koziol - * Tuesday, March 7, 2006 + * Monday, March 20, 2006 * *------------------------------------------------------------------------- */ -htri_t -H5HF_flist_find(H5HF_freelist_t *flist, size_t request, void **node) +static htri_t +H5HF_flist_find_bin_node(H5HF_freelist_t *flist, size_t request, void **node) { H5HF_flist_node_t *flist_node; /* Free list size node */ unsigned bin; /* Bin to put the free space section in */ - herr_t ret_value = FALSE; /* Return value */ + htri_t ret_value = FALSE; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HF_flist_find) + FUNC_ENTER_NOAPI_NOINIT(H5HF_flist_find_bin_node) /* Check arguments. */ HDassert(flist); @@ -289,6 +370,64 @@ HDfprintf(stderr, "%s: bin = %u\n", FUNC, bin); done: FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_flist_find_bin_node() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_flist_find + * + * Purpose: Locate a section of free space (in existing free list) that + * is large enough to fulfill request. + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, March 7, 2006 + * + *------------------------------------------------------------------------- + */ +htri_t +H5HF_flist_find(H5HF_freelist_t *flist, size_t request, void **node) +{ + htri_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_flist_find) + + /* Check arguments. */ + HDassert(flist); + HDassert(request > 0); + HDassert(node); + + /* Check for any sections on free list */ + if(flist->sec_count > 0) { + /* Check for single section */ + if(flist->sec_count == 1) { + HDassert(flist->single.node); + + /* See if single section is large enough */ + if(*(flist->single.size_key) >= request) { + *node = flist->single.node; + flist->single.node = NULL; + ret_value = TRUE; + } /* end if */ + } /* end if */ + else { + HDassert(flist->single.node == NULL); + + /* Look for node in bins */ + if((ret_value = H5HF_flist_find_bin_node(flist, request, node)) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "can't remove section from bins") + } /* end else */ + + /* Decrement # of sections on free list */ + flist->sec_count--; +/* XXX: Should check for only one section in bins & convert to single section */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) } /* H5HF_flist_find() */ @@ -349,15 +488,25 @@ H5HF_flist_free(H5HF_freelist_t *flist) /* Check arguments. */ HDassert(flist); - /* Clear out lists of nodes */ - for(u = 0; u < flist->nbins; u++) - if(flist->bins[u]) { - H5SL_destroy(flist->bins[u], H5HF_flist_node_free_cb, (void *)flist->node_free_op); - flist->bins[u] = NULL; - } /* end if */ + /* Check for single section to free */ + if(flist->sec_count == 1) { + HDassert(flist->single.node != NULL); + flist->node_free_op(flist->single.node, flist->single.addr_key, NULL); + flist->single.node = NULL; + } /* end if */ + HDassert(flist->single.node == NULL); /* Release bins for skip lists */ - H5FL_SEQ_FREE(H5SL_ptr_t, flist->bins); + if(flist->bins) { + /* Clear out lists of nodes */ + for(u = 0; u < flist->nbins; u++) + if(flist->bins[u]) { + H5SL_destroy(flist->bins[u], H5HF_flist_node_free_cb, (void *)flist->node_free_op); + flist->bins[u] = NULL; + } /* end if */ + + H5FL_SEQ_FREE(H5SL_ptr_t, flist->bins); + } /* end if */ /* Free fractal heap free list info */ H5FL_FREE(H5HF_freelist_t, flist); diff --git a/src/H5HFint.c b/src/H5HFint.c index bbae6a2..e25ad64 100644 --- a/src/H5HFint.c +++ b/src/H5HFint.c @@ -98,7 +98,7 @@ static H5HF_indirect_t * H5HF_man_iblock_place_dblock(H5RC_t *fh_shared, hid_t d size_t min_dblock_size, haddr_t *addr_p, size_t *entry_p, size_t *dblock_size); static herr_t H5HF_man_iblock_create(H5RC_t *fh_shared, hid_t dxpl_id, - hsize_t block_off, unsigned nrows, unsigned max_dir_rows, haddr_t *addr_p); + hsize_t block_off, unsigned nrows, unsigned max_rows, haddr_t *addr_p); /*********************/ /* Package Variables */ @@ -119,11 +119,8 @@ H5FL_DEFINE(H5HF_section_free_node_t); /* Declare a free list to manage the H5HF_indirect_t struct */ H5FL_DEFINE(H5HF_indirect_t); -/* Declare a free list to manage the H5HF_indirect_dblock_ent_t sequence information */ -H5FL_SEQ_DEFINE(H5HF_indirect_dblock_ent_t); - -/* Declare a free list to manage the H5HF_indirect_iblock_ent_t sequence information */ -H5FL_SEQ_DEFINE(H5HF_indirect_iblock_ent_t); +/* Declare a free list to manage the H5HF_indirect_ent_t sequence information */ +H5FL_SEQ_DEFINE(H5HF_indirect_ent_t); /*****************************/ @@ -171,18 +168,18 @@ H5HF_dtable_init(const H5HF_shared_t *shared, H5HF_dtable_t *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_indirect_rows = (dtable->cparam.max_index - dtable->first_row_bits) + 1; + 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_indirect_rows * sizeof(hsize_t)))) + 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") tmp_block_size = dtable->cparam.start_block_size; dtable->row_block_size[0] = dtable->cparam.start_block_size; - for(u = 1; u < dtable->max_root_indirect_rows; u++) { + for(u = 1; u < dtable->max_root_rows; u++) { dtable->row_block_size[u] = tmp_block_size; tmp_block_size *= 2; } /* end for */ @@ -266,6 +263,8 @@ H5HF_shared_alloc(H5F_t *f) /* Set the internal parameters for the heap */ shared->f = f; + shared->sizeof_size = H5F_SIZEOF_SIZE(f); + shared->sizeof_addr = H5F_SIZEOF_ADDR(f); /* Set the return value */ ret_value = shared; @@ -338,17 +337,16 @@ done: *------------------------------------------------------------------------- */ herr_t -H5HF_shared_create(H5F_t *f, H5HF_t *fh, haddr_t fh_addr, H5HF_create_t *cparam) +H5HF_shared_init(H5HF_shared_t *shared, H5HF_t *fh, haddr_t fh_addr, H5HF_create_t *cparam) { - H5HF_shared_t *shared = NULL; /* Shared fractal heap information */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HF_shared_create) + FUNC_ENTER_NOAPI_NOINIT(H5HF_shared_init) /* * Check arguments. */ - HDassert(f); + HDassert(shared); HDassert(fh); HDassert(cparam); @@ -363,14 +361,10 @@ H5HF_shared_create(H5F_t *f, H5HF_t *fh, haddr_t fh_addr, H5HF_create_t *cparam) 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 * H5F_SIZEOF_SIZE(f)) || cparam->managed.max_index == 0) + if(cparam->managed.max_index > (8 * shared->sizeof_size) || cparam->managed.max_index == 0) HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. direct block size not power of two") #endif /* NDEBUG */ - /* Allocate & basic initialization for the shared info struct */ - if(NULL == (shared = H5HF_shared_alloc(f))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate space for shared heap info") - /* Set the creation parameters for the heap */ shared->heap_addr = fh_addr; shared->addrmap = cparam->addrmap; @@ -394,7 +388,7 @@ done: H5HF_shared_free(shared); FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_shared_create() */ +} /* end H5HF_shared_init() */ /*------------------------------------------------------------------------- @@ -451,8 +445,9 @@ static herr_t H5HF_man_iblock_inc_loc(H5HF_indirect_t *iblock) { H5HF_shared_t *shared; /* Pointer to shared heap info */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_man_iblock_inc_loc) + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_inc_loc) /* * Check arguments. @@ -463,33 +458,44 @@ H5HF_man_iblock_inc_loc(H5HF_indirect_t *iblock) shared = H5RC_GET_OBJ(iblock->shared); HDassert(shared); + /* Increment block entry */ + iblock->next_entry++; + /* Increment column */ - iblock->next_dir_col++; + iblock->next_col++; /* Check for walking off end of column */ - if(iblock->next_dir_col == shared->man_dtable.cparam.width) { + if(iblock->next_col == shared->man_dtable.cparam.width) { /* Reset column */ - iblock->next_dir_col = 0; + iblock->next_col = 0; - /* Increment row & direct block size */ - iblock->next_dir_row++; - iblock->next_dir_size *= 2; + /* Increment row & block size */ + iblock->next_row++; + iblock->next_size *= 2; - /* Check for filling up all direct block entries in indirect block */ - if(iblock->next_dir_row == iblock->max_direct_rows) - iblock->dir_full = TRUE; + /* Check for filling up indirect block */ + if(iblock->next_row == iblock->max_rows) { + /* Check for "full" heap */ + if(iblock->parent == NULL) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't advance fractal heap block location") + + /* Increment location for parent indirect block */ + iblock = H5RC_GET_OBJ(iblock->parent); + if(H5HF_man_iblock_inc_loc(iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't advance fractal heap block location") + } /* end if */ } /* end if */ #ifdef QAK -HDfprintf(stderr, "%s: iblock->next_dir_row = %u\n", "H5HF_man_iblock_inc_loc", iblock->next_dir_row); -HDfprintf(stderr, "%s: iblock->next_dir_col = %u\n", "H5HF_man_iblock_inc_loc", iblock->next_dir_col); -HDfprintf(stderr, "%s: iblock->next_dir_size = %Zu\n", "H5HF_man_iblock_inc_loc", iblock->next_dir_size); -HDfprintf(stderr, "%s: iblock->dir_full = %u\n", "H5HF_man_iblock_inc_loc", (unsigned)iblock->dir_full); +HDfprintf(stderr, "%s: iblock->next_row = %u\n", FUNC, iblock->next_row); +HDfprintf(stderr, "%s: iblock->next_col = %u\n", FUNC, iblock->next_col); +HDfprintf(stderr, "%s: iblock->next_size = %Zu\n", FUNC, iblock->next_size); #endif /* QAK */ /* Mark heap header as modified */ shared->dirty = TRUE; - FUNC_LEAVE_NOAPI(SUCCEED) +done: + FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_man_iblock_inc_loc() */ @@ -851,7 +857,7 @@ HDfprintf(stderr, "%s: amt = %Zd\n", "H5HF_man_dblock_adj_free", amt); #ifdef QAK HDfprintf(stderr, "%s: iblock->child_free_space = %Hu\n", "H5HF_man_dblock_adj_free", iblock->child_free_space); #endif /* QAK */ - iblock->dblock_ents[dblock->parent_entry].free_space += amt; + iblock->ents[dblock->parent_entry].free_space += amt; iblock->child_free_space += amt; /* Mark indirect block as dirty */ @@ -867,7 +873,7 @@ HDfprintf(stderr, "%s: iblock->child_free_space = %Hu\n", "H5HF_man_dblock_adj_f HDassert(iblock); /* Adjust this indirect block's child free space */ - iblock->iblock_ents[parent_entry].free_space += amt; + iblock->ents[parent_entry].free_space += amt; iblock->child_free_space += amt; /* Mark indirect block as dirty */ @@ -988,14 +994,10 @@ HDfprintf(stderr, "%s: dblock_size = %Zu\n", FUNC, dblock_size); #ifdef QAK HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr); -HDfprintf(stderr, "%s: shared->man_dtable.next_dir_block = %Hu\n", FUNC, shared->man_dtable.next_dir_block); #endif /* QAK */ /* Point indirect block at new direct block */ - iblock->dblock_ents[dblock_entry].addr = dblock_addr; - - /* Increment size of next block from this indirect block */ - H5HF_man_iblock_inc_loc(iblock); + iblock->ents[dblock_entry].addr = dblock_addr; /* Mark indirect block as modified */ iblock->dirty = TRUE; @@ -1287,8 +1289,14 @@ done: herr_t H5HF_man_read(H5RC_t *fh_shared, hid_t dxpl_id, hsize_t obj_off, void *obj) { + H5HF_parent_shared_t par_shared; /* Parent shared information */ H5HF_shared_t *shared; /* Pointer to shared heap info */ - unsigned row, col; /* Row & column for object's block */ + H5HF_direct_t *dblock; /* Pointer to direct block to query */ + size_t blk_off; /* Offset of object in block */ + uint8_t *p; /* Temporary pointer to obj info in block */ + size_t obj_size; /* Size of object */ + haddr_t dblock_addr; /* Direct block address */ + size_t dblock_size; /* Direct block size */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_read) @@ -1306,52 +1314,125 @@ H5HF_man_read(H5RC_t *fh_shared, hid_t dxpl_id, hsize_t obj_off, void *obj) /* Check for root direct block */ if(shared->man_dtable.curr_root_rows == 0) { - H5HF_parent_shared_t par_shared; /* Parent shared information */ - H5HF_direct_t *dblock; /* Pointer to direct block to query */ - size_t blk_off; /* Offset of object in block */ - uint8_t *p; /* Temporary pointer to obj info in block */ - size_t obj_size; /* Size of object */ + /* Set direct block info */ + par_shared.shared = fh_shared; + par_shared.parent = NULL; + par_shared.parent_entry = 0; + par_shared.parent_free_space = shared->total_man_free; + + dblock_addr = shared->man_dtable.table_addr; + dblock_size = shared->man_dtable.cparam.start_block_size; + + /* Lock direct block */ + if(NULL == (dblock = H5AC_protect(shared->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, &dblock_size, &par_shared, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block") + } /* end if */ + else { + haddr_t iblock_addr; /* Indirect block's address */ + H5HF_indirect_t *iblock; /* Pointer to indirect block */ + unsigned row, col; /* Row & column for object's block */ + size_t entry; /* Entry of block */ -#ifdef QAK /* Look up row & column for object */ if(H5HF_dtable_lookup(&shared->man_dtable, obj_off, &row, &col) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of object") +#ifdef QAK HDfprintf(stderr, "%s: row = %u, col = %u\n", FUNC, row, col); #endif /* QAK */ - /* Lock first (root) direct block */ + /* Set initial indirect block info */ + iblock_addr = shared->man_dtable.table_addr; + + /* Lock indirect block */ par_shared.shared = fh_shared; par_shared.parent = NULL; par_shared.parent_entry = 0; par_shared.parent_free_space = shared->total_man_free; - if(NULL == (dblock = H5AC_protect(shared->f, dxpl_id, H5AC_FHEAP_DBLOCK, shared->man_dtable.table_addr, &shared->man_dtable.cparam.start_block_size, &par_shared, H5AC_READ))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap direct block") + if(NULL == (iblock = H5AC_protect(shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &shared->man_dtable.curr_root_rows, &par_shared, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") - /* Compute offset of object within block */ - HDassert((obj_off - dblock->block_off) < (hsize_t)shared->man_dtable.cparam.start_block_size); - blk_off = (size_t)(obj_off - dblock->block_off); + /* Check for indirect block row */ + while(row >= shared->man_dtable.max_direct_rows) { + haddr_t new_iblock_addr; /* New indirect block's address */ + H5HF_indirect_t *new_iblock; /* Pointer to new indirect block */ + unsigned nrows; /* Number of rows in new indirect block */ - /* Point to location for object */ - p = dblock->blk + blk_off; + /* Compute # of rows in child indirect block */ + nrows = (H5V_log2_gen(shared->man_dtable.row_block_size[row]) - shared->man_dtable.first_row_bits) + 1; - /* Decode the length */ - UINT64DECODE_VAR(p, obj_size, dblock->blk_off_size); + /* Compute indirect block's entry */ + entry = (row * shared->man_dtable.cparam.width) + col; - /* Skip over the free fragment size & ref count */ - p += 1 + (shared->ref_count_obj ? shared->ref_count_size : 0); + /* Locate child indirect block */ + new_iblock_addr = iblock->ents[entry].addr; - /* Copy the object's data into the heap */ - HDmemcpy(obj, p, obj_size); + /* Lock new indirect block */ + par_shared.shared = fh_shared; + par_shared.parent = iblock->self; + par_shared.parent_entry = entry; + par_shared.parent_free_space = iblock->ents[entry].free_space; + if(NULL == (new_iblock = H5AC_protect(shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, new_iblock_addr, &nrows, &par_shared, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") + + /* Release the current indirect block (possibly marked as dirty) */ + if(H5AC_unprotect(shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + + /* Switch variables to use new indirect block */ + iblock = new_iblock; + iblock_addr = new_iblock_addr; + + /* Look up row & column in new indirect block for object */ + if(H5HF_dtable_lookup(&shared->man_dtable, (obj_off - iblock->block_off), &row, &col) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of object") + } /* end while */ - /* Unlock first (root) direct block */ - if(H5AC_unprotect(shared->f, dxpl_id, H5AC_FHEAP_DBLOCK, shared->man_dtable.table_addr, dblock, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release fractal heap direct block") - dblock = NULL; - } /* end if */ - else { -HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "root indirect blocks not supported yet") + /* Compute direct block's entry */ + entry = (row * shared->man_dtable.cparam.width) + col; +#ifdef QAK +HDfprintf(stderr, "%s: entry address = %a\n", FUNC, iblock->dblock_ents[entry].addr); +#endif /* QAK */ + + /* Set direct block info */ + par_shared.shared = fh_shared; + par_shared.parent = iblock->self; + par_shared.parent_entry = entry; + par_shared.parent_free_space = iblock->ents[entry].free_space; + + dblock_addr = iblock->ents[entry].addr; + dblock_size = shared->man_dtable.row_block_size[row]; + + /* Lock direct block */ + if(NULL == (dblock = H5AC_protect(shared->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, &dblock_size, &par_shared, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block") + + /* Unlock indirect block */ + if(H5AC_unprotect(shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + iblock = NULL; } /* end else */ + /* Compute offset of object within block */ + HDassert((obj_off - dblock->block_off) < (hsize_t)dblock_size); + blk_off = (size_t)(obj_off - dblock->block_off); + + /* Point to location for object */ + p = dblock->blk + blk_off; + + /* Decode the length */ + UINT64DECODE_VAR(p, obj_size, dblock->blk_off_size); + + /* Skip over the free fragment size & ref count */ + p += 1 + (shared->ref_count_obj ? shared->ref_count_size : 0); + + /* Copy the object's data into the heap */ + HDmemcpy(obj, p, obj_size); + + /* Unlock direct block */ + if(H5AC_unprotect(shared->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block") + dblock = NULL; + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_man_read() */ @@ -1390,10 +1471,8 @@ HDfprintf(stderr, "%s: Freeing indirect block\n", "H5HF_iblock_free"); H5RC_DEC(iblock->parent); /* Release entry tables */ - if(iblock->dblock_ents) - H5FL_SEQ_FREE(H5HF_indirect_dblock_ent_t, iblock->dblock_ents); - if(iblock->iblock_ents) - H5FL_SEQ_FREE(H5HF_indirect_iblock_ent_t, iblock->iblock_ents); + if(iblock->ents) + H5FL_SEQ_FREE(H5HF_indirect_ent_t, iblock->ents); /* Free fractal heap indirect block info */ H5FL_FREE(H5HF_indirect_t, iblock); @@ -1425,6 +1504,7 @@ H5HF_man_iblock_place_dblock(H5RC_t *fh_shared, hid_t dxpl_id, H5HF_parent_shared_t par_shared; /* Parent shared information */ H5HF_shared_t *shared; /* Pointer to shared heap info */ H5HF_indirect_t *iblock; /* Pointer to indirect block */ + haddr_t iblock_addr; /* Indirect block's address */ H5HF_indirect_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_place_dblock) @@ -1445,26 +1525,20 @@ H5HF_man_iblock_place_dblock(H5RC_t *fh_shared, hid_t dxpl_id, H5HF_direct_t *dblock; /* Pointer to direct block to query */ unsigned nrows; /* Number of rows for root indirect block */ - /* Check for skipping over blocks */ - if(min_dblock_size != shared->man_dtable.cparam.start_block_size) { -HDfprintf(stderr, "%s: Skipping direct block sizes not supported\n", FUNC); -HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, NULL, "skipping direct block sizes not supported yet") - } /* end if */ - #ifdef QAK HDfprintf(stderr, "%s: creating first indirect block\n", FUNC); #endif /* QAK */ /* Check for allocating entire root indirect block initially */ if(shared->man_dtable.cparam.start_root_rows == 0) - nrows = shared->man_dtable.max_root_indirect_rows; + nrows = shared->man_dtable.max_root_rows; else nrows = shared->man_dtable.cparam.start_root_rows; /* Allocate root indirect block */ - if(H5HF_man_iblock_create(fh_shared, dxpl_id, (hsize_t)0, nrows, shared->man_dtable.max_direct_rows, addr_p) < 0) + if(H5HF_man_iblock_create(fh_shared, dxpl_id, (hsize_t)0, nrows, shared->man_dtable.max_root_rows, &iblock_addr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate fractal heap indirect block") #ifdef QAK -HDfprintf(stderr, "%s: *addr_p = %a\n", FUNC, *addr_p); +HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr); #endif /* QAK */ /* Move current direct block (used as root) into new indirect block */ @@ -1474,7 +1548,7 @@ HDfprintf(stderr, "%s: *addr_p = %a\n", FUNC, *addr_p); par_shared.parent = NULL; par_shared.parent_entry = 0; par_shared.parent_free_space = 0; - if(NULL == (iblock = H5AC_protect(shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, *addr_p, &nrows, &par_shared, H5AC_WRITE))) + if(NULL == (iblock = H5AC_protect(shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &nrows, &par_shared, H5AC_WRITE))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") /* Lock first (root) direct block */ @@ -1483,8 +1557,8 @@ HDfprintf(stderr, "%s: *addr_p = %a\n", FUNC, *addr_p); HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap direct block") /* Point indirect block at direct block to add */ - iblock->dblock_ents[0].addr = shared->man_dtable.table_addr; - iblock->dblock_ents[0].free_space = dblock->blk_free_space; + iblock->ents[0].addr = shared->man_dtable.table_addr; + iblock->ents[0].free_space = dblock->blk_free_space; iblock->child_free_space += dblock->blk_free_space; /* Make direct block share parent indirect block */ @@ -1499,23 +1573,18 @@ HDfprintf(stderr, "%s: *addr_p = %a\n", FUNC, *addr_p); /* Increment size of next block from this indirect block */ /* (account for the already existing direct block */ - H5HF_man_iblock_inc_loc(iblock); + if(H5HF_man_iblock_inc_loc(iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't advance fractal heap block location") /* Mark indirect block as modified */ iblock->dirty = TRUE; /* Point heap header at new indirect block */ shared->man_dtable.curr_root_rows = nrows; - shared->man_dtable.table_addr = *addr_p; + shared->man_dtable.table_addr = iblock_addr; /* Mark heap header as modified */ shared->dirty = TRUE; - - /* Set entry for direct block */ - *entry_p = 1; - - /* Set size of direct block to create */ - *dblock_size = iblock->next_dir_size; } /* end if */ else { #ifdef QAK @@ -1527,62 +1596,44 @@ HDfprintf(stderr, "%s: searching root indirect block\n", FUNC); par_shared.parent = NULL; par_shared.parent_entry = 0; par_shared.parent_free_space = shared->total_man_free; - if(NULL == (iblock = H5AC_protect(shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, shared->man_dtable.table_addr, &shared->man_dtable.curr_root_rows, &par_shared, H5AC_WRITE))) + iblock_addr = shared->man_dtable.table_addr; + if(NULL == (iblock = H5AC_protect(shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &shared->man_dtable.curr_root_rows, &par_shared, H5AC_WRITE))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") #ifdef QAK -HDfprintf(stderr, "%s: iblock->next_dir_row = %u\n", FUNC, iblock->next_dir_row); -HDfprintf(stderr, "%s: iblock->next_dir_col = %u\n", FUNC, iblock->next_dir_col); -HDfprintf(stderr, "%s: iblock->next_dir_size = %Zu\n", FUNC, iblock->next_dir_size); -HDfprintf(stderr, "%s: iblock->dir_full = %u\n", FUNC, (unsigned)iblock->dir_full); +HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows); #endif /* QAK */ - /* Check for full direct block entries in root */ - if(iblock->dir_full) { -HDfprintf(stderr, "%s: Adding nested indirect block to heap not supported\n", FUNC); -HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, NULL, "Adding nested indirect block not supported yet") - } /* end if */ - - /* Check for skipping over blocks */ - if(min_dblock_size > iblock->next_dir_size) { -HDfprintf(stderr, "%s: Skipping direct block sizes not supported\n", FUNC); -HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, NULL, "skipping direct block sizes not supported yet") - } /* end if */ - - /* Check if we need a direct block past current allocation */ - if(iblock->next_dir_row == iblock->ndir_rows) { - haddr_t old_addr; /* Old address of indirect block */ + /* Check if we need a block past current allocation */ + if(iblock->next_row == iblock->nrows) { haddr_t new_addr; /* New address of indirect block */ unsigned new_nrows; /* New # of direct rows */ size_t u; /* Local index variable */ /* Check for special case of second row, which has blocks the same size as first row */ - if(iblock->next_dir_row == 1) - iblock->next_dir_size = shared->man_dtable.cparam.start_block_size; + if(iblock->next_row == 1) + iblock->next_size = shared->man_dtable.cparam.start_block_size; /* Compute new # of rows in indirect block */ - new_nrows = 2 * iblock->ndir_rows; - if(new_nrows > iblock->max_direct_rows) - new_nrows = iblock->max_direct_rows; + new_nrows = MIN(2 * iblock->nrows, iblock->max_rows); #ifdef QAK HDfprintf(stderr, "%s: new_nrows = %u\n", FUNC, new_nrows); #endif /* QAK */ /* Currently, the old chunk data is "thrown away" after the space is reallocated, - * so avoid data copy in H5MF_realloc() call by just free'ing the space and - * allocating new space. - * - * This should keep the file smaller also, by freeing the space and then - * allocating new space, instead of vice versa (in H5MF_realloc). - * - * QAK - 3/14/2006 - */ +* so avoid data copy in H5MF_realloc() call by just free'ing the space and +* allocating new space. +* +* This should keep the file smaller also, by freeing the space and then +* allocating new space, instead of vice versa (in H5MF_realloc). +* +* QAK - 3/14/2006 +*/ /* Free previous indirect block disk space */ - old_addr = shared->man_dtable.table_addr; - if(H5MF_xfree(shared->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, old_addr, (hsize_t)iblock->size)<0) + if(H5MF_xfree(shared->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, iblock_addr, (hsize_t)iblock->size)<0) HGOTO_ERROR(H5E_STORAGE, H5E_CANTFREE, NULL, "unable to free fractal heap indirect block") /* Compute size of buffer needed for new indirect block */ - iblock->ndir_rows = new_nrows; + iblock->nrows = new_nrows; iblock->size = H5HF_MAN_INDIRECT_SIZE(shared, iblock); /* Allocate space for the new indirect block on disk */ @@ -1590,31 +1641,31 @@ HDfprintf(stderr, "%s: new_nrows = %u\n", FUNC, new_nrows); HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, NULL, "file allocation failed for fractal heap indirect block") /* Re-allocate direct block entry table */ - if(NULL == (iblock->dblock_ents = H5FL_SEQ_REALLOC(H5HF_indirect_dblock_ent_t, iblock->dblock_ents, (iblock->ndir_rows * shared->man_dtable.cparam.width)))) + if(NULL == (iblock->ents = H5FL_SEQ_REALLOC(H5HF_indirect_ent_t, iblock->ents, (iblock->nrows * shared->man_dtable.cparam.width)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for direct entries") /* Initialize new direct block entries */ - for(u = (iblock->next_dir_row * shared->man_dtable.cparam.width); - u < (iblock->ndir_rows * shared->man_dtable.cparam.width); + for(u = (iblock->next_row * shared->man_dtable.cparam.width); + u < (iblock->nrows * shared->man_dtable.cparam.width); u++) { - iblock->dblock_ents[u].addr = HADDR_UNDEF; - iblock->dblock_ents[u].free_space = 0; + iblock->ents[u].addr = HADDR_UNDEF; + iblock->ents[u].free_space = 0; } /* end for */ /* Mark indirect block as dirty */ iblock->dirty = TRUE; /* Release the indirect block (marked as dirty) */ - if(H5AC_unprotect(shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, old_addr, iblock, H5AC__DIRTIED_FLAG) < 0) + if(H5AC_unprotect(shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, H5AC__DIRTIED_FLAG) < 0) HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release fractal heap indirect block") /* Move object in cache */ - if(H5AC_rename(shared->f, H5AC_FHEAP_IBLOCK, old_addr, new_addr) < 0) + if(H5AC_rename(shared->f, H5AC_FHEAP_IBLOCK, iblock_addr, new_addr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTSPLIT, NULL, "unable to move fractal heap root indirect block") /* Update other shared header info */ shared->man_dtable.curr_root_rows = new_nrows; - shared->man_dtable.table_addr = new_addr; + shared->man_dtable.table_addr = iblock_addr = new_addr; /* Mark heap header as modified */ shared->dirty = TRUE; @@ -1624,20 +1675,113 @@ HDfprintf(stderr, "%s: new_nrows = %u\n", FUNC, new_nrows); par_shared.parent = NULL; par_shared.parent_entry = 0; par_shared.parent_free_space = shared->total_man_free; - if(NULL == (iblock = H5AC_protect(shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, shared->man_dtable.table_addr, &shared->man_dtable.curr_root_rows, &par_shared, H5AC_WRITE))) + if(NULL == (iblock = H5AC_protect(shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &shared->man_dtable.curr_root_rows, &par_shared, H5AC_WRITE))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") } /* end if */ - /* Set address of indirect block */ - *addr_p = shared->man_dtable.table_addr; +#ifdef QAK +HDfprintf(stderr, "%s: iblock->next_row = %u\n", FUNC, iblock->next_row); +HDfprintf(stderr, "%s: iblock->next_col = %u\n", FUNC, iblock->next_col); +HDfprintf(stderr, "%s: iblock->next_size = %Zu\n", FUNC, iblock->next_size); +HDfprintf(stderr, "%s: iblock->next_entry = %u\n", FUNC, iblock->next_entry); +#endif /* QAK */ + /* Check for full direct block entries in current indirect block */ + while(iblock->next_row >= shared->man_dtable.max_direct_rows) { + haddr_t new_iblock_addr; /* New indirect block's address */ + H5HF_indirect_t *new_iblock; /* Pointer to new indirect block */ + unsigned hdr_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for header */ + unsigned nrows; /* Number of rows in new indirect block */ + + /* Compute # of rows in child indirect block */ + nrows = (H5V_log2_gen(iblock->next_size) - shared->man_dtable.first_row_bits) + 1; +#ifdef QAK +HDfprintf(stderr, "%s: iblock->next_size = %Hu, nrows = %u\n", FUNC, iblock->next_size, nrows); +#endif /* QAK */ + + /* Check for allocating new indirect block */ + if(!H5F_addr_defined(iblock->ents[iblock->next_entry].addr)) { +#ifdef QAK +HDfprintf(stderr, "%s: Allocating new indirect block\n", FUNC); +#endif /* QAK */ + /* Allocate new indirect block */ + if(H5HF_man_iblock_create(fh_shared, dxpl_id, shared->man_dtable.next_dir_block, nrows, nrows, &new_iblock_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate fractal heap indirect block") + + /* Lock new indirect block */ + par_shared.shared = fh_shared; + par_shared.parent = iblock->self; + par_shared.parent_entry = iblock->next_entry; + par_shared.parent_free_space = 0; + if(NULL == (new_iblock = H5AC_protect(shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, new_iblock_addr, &nrows, &par_shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") +#ifdef QAK +HDfprintf(stderr, "%s: new_iblock->next_row = %u\n", FUNC, new_iblock->next_row); +HDfprintf(stderr, "%s: new_iblock->next_col = %u\n", FUNC, new_iblock->next_col); +HDfprintf(stderr, "%s: new_iblock->next_size = %Zu\n", FUNC, new_iblock->next_size); +HDfprintf(stderr, "%s: new_iblock->next_entry = %u\n", FUNC, new_iblock->next_entry); +#endif /* QAK */ + + /* Point current indirect block at new indirect block */ + iblock->ents[iblock->next_entry].addr = new_iblock_addr; - /* Set entry for direct block */ - *entry_p = iblock->next_dir_entry; + /* Increment location of next block from current indirect block */ + if(H5HF_man_iblock_inc_loc(iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't advance fractal heap block location") - /* Set size of direct block to create */ - *dblock_size = iblock->next_dir_size; + /* Mark current indirect block as modified */ + iblock->dirty = TRUE; + + /* Release the current indirect block (marked as dirty) */ + hdr_flags |= H5AC__DIRTIED_FLAG; + } /* end if */ + else { +#ifdef QAK +HDfprintf(stderr, "%s: Descending existing indirect block\n", FUNC); +#endif /* QAK */ + /* Locate child indirect block */ + new_iblock_addr = iblock->ents[iblock->next_entry].addr; + + /* Lock new indirect block */ + par_shared.shared = fh_shared; + par_shared.parent = iblock->self; + par_shared.parent_entry = iblock->next_entry; + par_shared.parent_free_space = iblock->ents[iblock->next_entry].free_space; + if(NULL == (new_iblock = H5AC_protect(shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, new_iblock_addr, &nrows, &par_shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") + } /* end else */ + + /* Release the current indirect block (possibly marked as dirty) */ + if(H5AC_unprotect(shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, hdr_flags) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release fractal heap indirect block") + + /* Switch variables to use new indirect block */ + iblock = new_iblock; + iblock_addr = new_iblock_addr; +#ifdef QAK +HDfprintf(stderr, "%s: new_iblock_addr = %a\n", FUNC, new_iblock_addr); +#endif /* QAK */ + } /* end while */ } /* end else */ + /* Check for skipping over blocks */ + if(min_dblock_size > iblock->next_size) { +HDfprintf(stderr, "%s: Skipping direct block sizes not supported\n", FUNC); +HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, NULL, "skipping direct block sizes not supported yet") + } /* end if */ + + /* Set address of indirect block that's the immediate parent of new direct block */ + *addr_p = iblock_addr; + + /* Set entry for new direct block to use */ + *entry_p = iblock->next_entry; + + /* Set size of direct block to create */ + *dblock_size = iblock->next_size; + + /* Increment location of next block from this indirect block */ + if(H5HF_man_iblock_inc_loc(iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't advance fractal heap block location") + /* Set return value */ ret_value = iblock; @@ -1661,7 +1805,7 @@ done: */ static herr_t H5HF_man_iblock_create(H5RC_t *fh_shared, hid_t dxpl_id, - hsize_t block_off, unsigned nrows, unsigned max_dir_rows, haddr_t *addr_p) + hsize_t block_off, unsigned nrows, unsigned max_rows, haddr_t *addr_p) { H5HF_shared_t *shared; /* Pointer to shared heap info */ H5HF_indirect_t *iblock = NULL; /* Pointer to indirect block */ @@ -1699,7 +1843,7 @@ H5HF_man_iblock_create(H5RC_t *fh_shared, hid_t dxpl_id, HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for indirect fractal heap block") #ifdef QAK -HDfprintf(stderr, "%s: nrows = %u\n", FUNC, nrows); +HDfprintf(stderr, "%s: nrows = %u, max_nrows = %u\n", FUNC, nrows, max_nrows); #endif /* QAK */ /* Set info for direct block */ iblock->parent = NULL; /* Temporary, except for root indirect block */ @@ -1707,41 +1851,24 @@ HDfprintf(stderr, "%s: nrows = %u\n", FUNC, nrows); iblock->block_off = block_off; iblock->child_free_space = 0; iblock->nrows = nrows; - iblock->dir_full = FALSE; - iblock->next_dir_col = 0; - iblock->next_dir_row = 0; - iblock->next_dir_entry = 0; - iblock->next_dir_size = shared->man_dtable.cparam.start_block_size; - iblock->max_direct_rows = max_dir_rows; - if(iblock->nrows > shared->man_dtable.max_direct_rows) { - iblock->ndir_rows = shared->man_dtable.max_direct_rows; - iblock->nindir_rows = iblock->nrows - iblock->ndir_rows; - } /* end if */ - else { - iblock->ndir_rows = iblock->nrows; - iblock->nindir_rows = 0; - } /* end else */ + iblock->max_rows = max_rows; + iblock->next_col = 0; + iblock->next_row = 0; + iblock->next_entry = 0; + iblock->next_size = shared->man_dtable.cparam.start_block_size; /* Compute size of buffer needed for indirect block */ iblock->size = H5HF_MAN_INDIRECT_SIZE(shared, iblock); /* Allocate indirect block entry tables */ - if(NULL == (iblock->dblock_ents = H5FL_SEQ_MALLOC(H5HF_indirect_dblock_ent_t, (iblock->ndir_rows * shared->man_dtable.cparam.width)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct entries") - if(iblock->nindir_rows > 0) { - if(NULL == (iblock->iblock_ents = H5FL_SEQ_MALLOC(H5HF_indirect_iblock_ent_t, (iblock->nindir_rows * shared->man_dtable.cparam.width)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for indirect entries") - } /* end if */ - else - iblock->iblock_ents = NULL; + if(NULL == (iblock->ents = H5FL_SEQ_MALLOC(H5HF_indirect_ent_t, (iblock->nrows * shared->man_dtable.cparam.width)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for block entries") /* Initialize indirect block entry tables */ - for(u = 0; u < (iblock->ndir_rows * shared->man_dtable.cparam.width); u++) { - iblock->dblock_ents[u].addr = HADDR_UNDEF; - iblock->dblock_ents[u].free_space = 0; + for(u = 0; u < (iblock->nrows * shared->man_dtable.cparam.width); u++) { + iblock->ents[u].addr = HADDR_UNDEF; + iblock->ents[u].free_space = 0; } /* end for */ - for(u = 0; u < (iblock->nindir_rows * shared->man_dtable.cparam.width); u++) - iblock->iblock_ents[u].addr = HADDR_UNDEF; /* Allocate space for the indirect block on disk */ if(HADDR_UNDEF == (*addr_p = H5MF_alloc(shared->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, (hsize_t)iblock->size))) @@ -1751,7 +1878,6 @@ HDfprintf(stderr, "%s: nrows = %u\n", FUNC, nrows); #ifdef LATER /* Update shared heap info */ shared->total_man_free += dblock->blk_free_space; - shared->man_dtable.next_dir_block += dblock->size; shared->total_size += dblock->size; shared->man_size += dblock->size; diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h index 33a9d37..175b521 100644 --- a/src/H5HFpkg.h +++ b/src/H5HFpkg.h @@ -57,19 +57,19 @@ ) /* Size of doubling-table information */ -#define H5HF_DTABLE_INFO_SIZE(f) ( \ +#define H5HF_DTABLE_INFO_SIZE(s) ( \ 2 /* Width of table (i.e. # of columns) */ \ - + H5F_SIZEOF_SIZE(f) /* Starting block size */ \ - + H5F_SIZEOF_SIZE(f) /* Maximum direct block size */ \ + + (s)->sizeof_size /* Starting block size */ \ + + (s)->sizeof_size /* Maximum direct block size */ \ + 2 /* Max. size of heap (log2 of actual value - i.e. the # of bits) */ \ + 2 /* Starting # of rows in root indirect block */ \ - + H5F_SIZEOF_ADDR(f) /* File address of table managed */ \ + + (s)->sizeof_addr /* File address of table managed */ \ + 2 /* Current # of rows in root indirect block */ \ - + H5F_SIZEOF_SIZE(f) /* Next direct block's heap offset */ \ + + (s)->sizeof_size /* Next direct block's heap offset */ \ ) /* Size of the fractal heap header on disk */ -#define H5HF_HEADER_SIZE(f) ( \ +#define H5HF_HEADER_SIZE(s) ( \ /* General metadata fields */ \ H5HF_METADATA_PREFIX_SIZE \ \ @@ -77,13 +77,13 @@ + 1 /* Address mapping */ \ + 4 /* Min. size of standalone object */ \ + 1 /* Size of ref. count for objects */ \ - + H5F_SIZEOF_SIZE(f) /* Total man. free space */ \ - + H5F_SIZEOF_SIZE(f) /* Total std. free entries */ \ - + H5F_SIZEOF_SIZE(f) /* Total size of heap */ \ - + H5F_SIZEOF_SIZE(f) /* Size of man. space in heap */ \ - + H5F_SIZEOF_SIZE(f) /* Size of std. space in heap */ \ - + H5F_SIZEOF_SIZE(f) /* Number of objects in heap */ \ - + H5HF_DTABLE_INFO_SIZE(f) /* Size of managed obj. doubling-table info */ \ + + (s)->sizeof_size /* Total man. free space */ \ + + (s)->sizeof_size /* Total std. free entries */ \ + + (s)->sizeof_size /* Total size of heap */ \ + + (s)->sizeof_size /* Size of man. space in heap */ \ + + (s)->sizeof_size /* Size of std. space in heap */ \ + + (s)->sizeof_size /* Number of objects in heap */ \ + + H5HF_DTABLE_INFO_SIZE(s) /* Size of managed obj. doubling-table info */ \ ) /* Size of free space description in an absolute managed direct block */ @@ -107,7 +107,7 @@ H5HF_METADATA_PREFIX_SIZE \ \ /* Fractal heap managed, absolutely mapped direct block specific fields */ \ - + H5F_SIZEOF_ADDR((s)->f) /* File address of heap owning the block */ \ + + (s)->sizeof_addr /* File address of heap owning the block */ \ + (s)->heap_off_size /* Offset of the block in the heap */ \ + H5HF_SIZEOF_OFFSET_LEN(o) /* Total free space in a block */ \ + H5HF_SIZEOF_OFFSET_LEN(o) /* Offset of first descriptor in free list */ \ @@ -117,7 +117,7 @@ H5HF_METADATA_PREFIX_SIZE \ \ /* Fractal heap managed, absolutely mapped direct block specific fields */ \ - + H5F_SIZEOF_ADDR((s)->f) /* File address of heap owning the block */ \ + + (s)->sizeof_addr /* File address of heap owning the block */ \ + (s)->heap_off_size /* Offset of the block in the heap */ \ + (d)->blk_off_size /* Offset of first descriptor in free list */ \ ) @@ -128,10 +128,11 @@ H5HF_METADATA_PREFIX_SIZE \ \ /* Fractal heap managed, absolutely mapped indirect block specific fields */ \ - + H5F_SIZEOF_ADDR((s)->f) /* File address of heap owning the block */ \ + + (s)->sizeof_addr /* File address of heap owning the block */ \ + (s)->heap_off_size /* Offset of the block in the heap */ \ - + ((i)->ndir_rows * (s)->man_dtable.cparam.width * (H5F_SIZEOF_ADDR((s)->f) + (s)->man_dtable.max_dir_blk_off_size)) /* Size of entries for direct blocks */ \ - + ((i)->nindir_rows * (s)->man_dtable.cparam.width * (H5F_SIZEOF_ADDR((s)->f) + (s)->heap_off_size)) /* Size of entries for indirect blocks */ \ + + 4 /* Next block entry to allocate from */ \ + + (MIN((i)->nrows, (s)->man_dtable.max_direct_rows) * (s)->man_dtable.cparam.width * ((s)->sizeof_addr + (s)->man_dtable.max_dir_blk_off_size)) /* Size of entries for direct blocks */ \ + + ((((i)->nrows > (s)->man_dtable.max_direct_rows) ? ((i)->nrows - (s)->man_dtable.max_direct_rows) : 0) * (s)->man_dtable.cparam.width * ((s)->sizeof_addr + (s)->heap_off_size)) /* Size of entries for indirect blocks */ \ ) @@ -160,7 +161,7 @@ typedef struct H5HF_dtable_t { hsize_t next_dir_block; /* Offset of next direct managed block */ /* Computed information (not stored) */ - unsigned max_root_indirect_rows; /* Maximum # of rows in root indirect block */ + unsigned max_root_rows; /* Maximum # of rows in root indirect block */ unsigned max_direct_rows; /* Maximum # of direct rows in any indirect block */ unsigned max_dir_blk_off_size; /* Max. size of offsets in direct blocks */ unsigned first_row_bits; /* # of bits in address of first row */ @@ -192,6 +193,8 @@ typedef struct H5HF_shared_t { hbool_t dirty; /* Shared info is modified */ haddr_t heap_addr; /* Address of heap header in the file */ H5F_t *f; /* Pointer to file for heap */ + size_t sizeof_size; /* Size of file sizes */ + size_t sizeof_addr; /* Size of file addresses */ H5HF_freelist_t *flist; /* Free list for objects in heap */ /* Doubling table information */ @@ -256,18 +259,12 @@ typedef struct H5HF_direct_t { size_t free_list_head; /* Offset of head of free list in block */ } H5HF_direct_t; -/* Indirect block direct block entry */ -typedef struct H5HF_indirect_dblock_ent_t { +/* Indirect block entry */ +typedef struct H5HF_indirect_ent_t { haddr_t addr; /* Direct block's address */ - size_t free_space; /* Amount of free space in direct block */ + hsize_t free_space; /* Amount of free space in block pointed to */ /* XXX: Will need space for block size, for blocks with I/O filters */ -} H5HF_indirect_dblock_ent_t; - -/* Indirect block indirect block entry */ -typedef struct H5HF_indirect_iblock_ent_t { - haddr_t addr; /* Indirect block's address */ - hsize_t free_space; /* Amount of free space in indirect block child */ -} H5HF_indirect_iblock_ent_t; +} H5HF_indirect_ent_t; /* Fractal heap indirect block */ typedef struct H5HF_indirect_t { @@ -281,17 +278,13 @@ typedef struct H5HF_indirect_t { size_t parent_entry; /* Entry in parent's table */ H5RC_t *self; /* Ref-counted shared 'self' block info */ unsigned nrows; /* Total # of rows in indirect block */ - unsigned ndir_rows; /* # of direct rows in indirect block */ - unsigned nindir_rows; /* # of indirect rows in indirect block */ + unsigned max_rows; /* Max. # of rows in indirect block */ size_t size; /* Size of indirect block on disk */ - hbool_t dir_full; /* Flag to indicate that all direct blocks are allocated */ - unsigned next_dir_col; /* "Column" of next managed direct block (in doubling table) */ - unsigned next_dir_row; /* "Row" of next managed direct block (in doubling table) */ - unsigned next_dir_entry; /* Entry of next managed direct block */ - size_t next_dir_size; /* Size of next managed direct block */ - unsigned max_direct_rows; /* Maximum # of direct rows in indirect block */ - H5HF_indirect_dblock_ent_t *dblock_ents; /* Pointer to direct block entry table */ - H5HF_indirect_iblock_ent_t *iblock_ents; /* Pointer to indirect block entry table */ + unsigned next_col; /* "Column" of next managed block (in doubling table) */ + unsigned next_row; /* "Row" of next managed block (in doubling table) */ + unsigned next_entry; /* Entry of next managed block */ + hsize_t next_size; /* Size of next managed block */ + H5HF_indirect_ent_t *ents; /* Pointer to block entry table */ /* Stored values */ hsize_t block_off; /* Offset of the block within the heap's address space */ @@ -347,11 +340,8 @@ H5FL_BLK_EXTERN(direct_block); /* Declare a free list to manage the H5HF_indirect_t struct */ H5FL_EXTERN(H5HF_indirect_t); -/* Declare a free list to manage the H5HF_indirect_dblock_ent_t sequence information */ -H5FL_SEQ_EXTERN(H5HF_indirect_dblock_ent_t); - -/* Declare a free list to manage the H5HF_indirect_iblock_ent_t sequence information */ -H5FL_SEQ_EXTERN(H5HF_indirect_iblock_ent_t); +/* Declare a free list to manage the H5HF_indirect_ent_t sequence information */ +H5FL_SEQ_EXTERN(H5HF_indirect_ent_t); /******************************/ @@ -360,7 +350,7 @@ H5FL_SEQ_EXTERN(H5HF_indirect_iblock_ent_t); /* Routines for managing shared fractal heap info */ H5_DLL H5HF_shared_t * H5HF_shared_alloc(H5F_t *f); -H5_DLL herr_t H5HF_shared_create(H5F_t *f, H5HF_t *fh, haddr_t heap_addr, H5HF_create_t *cparam); +H5_DLL herr_t H5HF_shared_init(H5HF_shared_t *shared, H5HF_t *fh, haddr_t heap_addr, H5HF_create_t *cparam); H5_DLL herr_t H5HF_shared_own(H5HF_t *fh, H5HF_shared_t *shared); /* Indirect block routines */ diff --git a/src/H5private.h b/src/H5private.h index a67a6aa..8a10783 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -1192,12 +1192,23 @@ static herr_t H5_INTERFACE_INIT_FUNC(void); #endif /* H5_INTERFACE_INIT_FUNC */ +#ifndef NDEBUG #define FUNC_ENTER_COMMON_NOFUNC(func_name,asrt) \ - /* Check API status */ \ - assert(asrt); \ + static hbool_t func_check = FALSE; \ + \ + if(!func_check) { \ + /* Check API status */ \ + HDassert(asrt); \ + \ + /* Check function name */ \ + H5_CHECK_FUNCNAME(func_name); \ \ - /* Check function name */ \ - H5_CHECK_FUNCNAME(func_name); + /* Don't check again */ \ + func_check = TRUE; \ + } /* end if */ +#else /* NDEBUG */ +#define FUNC_ENTER_COMMON_NOFUNC(func_name,asrt) +#endif /* NDEBUG */ #define FUNC_ENTER_COMMON(func_name,asrt) \ static const char FUNC[]=#func_name; \ diff --git a/test/fheap.c b/test/fheap.c index 00dca95..6ae7830 100644 --- a/test/fheap.c +++ b/test/fheap.c @@ -27,6 +27,7 @@ /* Other private headers that this test requires */ #include "H5Iprivate.h" +#include "H5MMprivate.h" /* Memory management */ /* "Standard" creation table parameters */ #define STD_ADDRMAP H5HF_ABSOLUTE /* Heap address mapping */ @@ -106,7 +107,6 @@ check_stats(H5F_t *f, hid_t dxpl, haddr_t fh_addr, hsize_t total_size, H5HF_stat_t heap_stats; /* Statistics about the heap */ /* Get statistics for heap and verify they are correct */ - HDmemset(&heap_stats, 0, sizeof(H5HF_stat_t)); if(H5HF_stat_info(f, dxpl, fh_addr, &heap_stats) < 0) FAIL_STACK_ERROR if(heap_stats.total_size != total_size) { @@ -155,13 +155,33 @@ error: */ static int fill_heap(H5F_t *f, hid_t dxpl, haddr_t fh_addr, hsize_t heap_size, - unsigned start_nobjs, unsigned *nobjs_ptr) + size_t block_size, unsigned start_nobjs, unsigned *nobjs_ptr) { H5HF_stat_t heap_stats; /* Statistics about the heap */ hsize_t heap_id; /* Heap ID for object inserted */ - unsigned char obj[10]; /* Buffer for first object to insert */ + unsigned char obj[10]; /* Buffer for object to insert */ + unsigned char robj[10]; /* Buffer for reading object */ unsigned nobjs = 0; /* Number of objects inserted */ - unsigned u; /* Local index variable */ + unsigned alloc_ids = 0; /* # of heap IDs allocated in array */ + hsize_t *ids = NULL; /* Array of heap IDs */ + size_t data_size; /* Size of data portion of heap block */ + size_t obj_overhead; /* Size of overhead for each object */ + size_t free_overhead; /* Size of free space overhead for each object */ + unsigned free_frag_size; /* Size of free space fragment */ + size_t last_obj_len; /* Size of last object inserted into heap */ + unsigned u, v; /* Local index variable */ + + /* Initialize variables */ + if(block_size <= (64 * 1024)) { + data_size = block_size - 28; /* '28' is the size of the direct block's overhead */ + obj_overhead = 3; + free_overhead = 4; + } /* end if */ + else { + data_size = block_size - 29; /* '29' is the size of the direct block's overhead */ + obj_overhead = 4; /* Will handle blocks up to 2^24 */ + free_overhead = 6; + } /* end else */ /* Initialize object buffer */ for(u = 0; u < sizeof(obj); u++) @@ -175,17 +195,24 @@ fill_heap(H5F_t *f, hid_t dxpl, haddr_t fh_addr, hsize_t heap_size, /* Increment object count */ nobjs++; - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, heap_size, heap_size, (hsize_t)0, (hsize_t)(996 - (nobjs * (sizeof(obj) + 3))), (hsize_t)(start_nobjs + nobjs))) + /* Check for needing to increase size of heap ID array */ + if(nobjs > alloc_ids) { + alloc_ids = MAX(1024, (alloc_ids * 2)); + if(NULL == (ids = H5MM_realloc(ids, sizeof(hsize_t) * alloc_ids))) + FAIL_STACK_ERROR + } /* end if */ + ids[nobjs - 1] = heap_id; + + if(check_stats(f, dxpl, fh_addr, heap_size, heap_size, (hsize_t)0, (hsize_t)(data_size - (nobjs * (sizeof(obj) + obj_overhead))), (hsize_t)(start_nobjs + nobjs))) FAIL_STACK_ERROR /* Get statistics for heap */ - HDmemset(&heap_stats, 0, sizeof(H5HF_stat_t)); if(H5HF_stat_info(f, dxpl, fh_addr, &heap_stats) < 0) FAIL_STACK_ERROR /* Loop over inserting objects into the root direct block, until there's no more space */ - /* (The "+ 2" in the equation below allows for the length of the object) */ - while(heap_stats.man_free_space > (sizeof(obj) + 2)) { + free_frag_size = 0; + while(heap_stats.man_free_space > (sizeof(obj) + obj_overhead)) { /* Initialize object buffer */ for(u = 0; u < sizeof(obj); u++) obj[u] = u + nobjs; @@ -197,39 +224,79 @@ fill_heap(H5F_t *f, hid_t dxpl, haddr_t fh_addr, hsize_t heap_size, /* Increment object count */ nobjs++; - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, heap_size, heap_size, (hsize_t)0, (hsize_t)(996 - (nobjs * (sizeof(obj) + 3))), (hsize_t)(start_nobjs + nobjs))) + /* Check for needing to increase size of heap ID array */ + if(nobjs > alloc_ids) { + alloc_ids = MAX(1024, (alloc_ids * 2)); + if(NULL == (ids = H5MM_realloc(ids, sizeof(hsize_t) * alloc_ids))) + FAIL_STACK_ERROR + } /* end if */ + ids[nobjs - 1] = heap_id; + + /* Check stats for heap */ + if((heap_stats.man_free_space - (sizeof(obj) + obj_overhead)) < free_overhead) + free_frag_size = heap_stats.man_free_space - (sizeof(obj) + obj_overhead); + if(check_stats(f, dxpl, fh_addr, heap_size, heap_size, (hsize_t)0, (hsize_t)(data_size - ((nobjs * (sizeof(obj) + obj_overhead)) + free_frag_size)), (hsize_t)(start_nobjs + nobjs))) FAIL_STACK_ERROR /* Get statistics for heap */ - HDmemset(&heap_stats, 0, sizeof(H5HF_stat_t)); if(H5HF_stat_info(f, dxpl, fh_addr, &heap_stats) < 0) FAIL_STACK_ERROR } /* end while */ - /* Initialize object buffer */ - for(u = 0; u < sizeof(obj); u++) - obj[u] = u + nobjs; + /* Check for adding smaller last object to heap block */ + if(heap_stats.man_free_space > 0) { + last_obj_len = (size_t)(heap_stats.man_free_space - obj_overhead); - /* Insert last object into the heap, using the remaining free space */ - heap_id = 0; - if(H5HF_insert(f, dxpl, fh_addr, (size_t)(heap_stats.man_free_space - 3), obj, &heap_id) < 0) - FAIL_STACK_ERROR + /* Initialize object buffer */ + for(u = 0; u < sizeof(obj); u++) + obj[u] = u + nobjs; - /* Increment object count */ - nobjs++; + /* Insert last object into the heap, using the remaining free space */ + heap_id = 0; + if(H5HF_insert(f, dxpl, fh_addr, last_obj_len, obj, &heap_id) < 0) + FAIL_STACK_ERROR - /* Verify that the heap is full */ - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, heap_size, heap_size, (hsize_t)0, (hsize_t)0, (hsize_t)(start_nobjs + nobjs))) - FAIL_STACK_ERROR + /* Increment object count */ + nobjs++; + + /* Check for needing to increase size of heap ID array */ + if(nobjs > alloc_ids) { + alloc_ids = MAX(1024, (alloc_ids * 2)); + if(NULL == (ids = H5MM_realloc(ids, sizeof(hsize_t) * alloc_ids))) + FAIL_STACK_ERROR + } /* end if */ + ids[nobjs - 1] = heap_id; + + /* Verify that the heap is full */ + if(check_stats(f, dxpl, fh_addr, heap_size, heap_size, (hsize_t)0, (hsize_t)0, (hsize_t)(start_nobjs + nobjs))) + FAIL_STACK_ERROR + } /* end if */ + else + last_obj_len = sizeof(obj); /* Normal sized last object */ + + /* Verify reading the objects written out */ + for(v = 0; v < nobjs; v++) { + /* Initialize object buffer */ + for(u = 0; u < sizeof(obj); u++) + obj[u] = u + v; + + /* Read in object */ + if(H5HF_read(f, dxpl, fh_addr, &ids[v], robj) < 0) + FAIL_STACK_ERROR + if(HDmemcmp(obj, robj, (v == (nobjs - 1) ? last_obj_len : sizeof(obj)))) + FAIL_STACK_ERROR + } /* end for */ /* Set the number of objects, if requested */ if(nobjs_ptr) *nobjs_ptr = nobjs; /* Operations succeeded */ + H5MM_xfree(ids); return(0); error: + H5MM_xfree(ids); return(1); } /* fill_heap() */ @@ -352,7 +419,7 @@ test_abs_insert_first(hid_t fapl) H5HF_create_t cparam; /* Creation parameters for heap */ haddr_t fh_addr; /* Address of fractal heap created */ unsigned char obj[10]; /* Buffer for object to insert */ - unsigned char obj2[10]; /* Buffer for object to read */ + unsigned char robj[10]; /* Buffer for object to read */ hsize_t heap_id; /* Heap ID for object inserted */ unsigned u; /* Local index variable */ @@ -391,9 +458,9 @@ test_abs_insert_first(hid_t fapl) FAIL_STACK_ERROR /* Check reading back in the object */ - if(H5HF_read(f, dxpl, fh_addr, &heap_id, obj2) < 0) + if(H5HF_read(f, dxpl, fh_addr, &heap_id, robj) < 0) FAIL_STACK_ERROR - if(HDmemcmp(obj, obj2, sizeof(obj))) + if(HDmemcmp(obj, robj, sizeof(obj))) FAIL_STACK_ERROR PASSED() @@ -437,7 +504,9 @@ test_abs_insert_second(hid_t fapl) H5HF_create_t cparam; /* Creation parameters for heap */ haddr_t fh_addr; /* Address of fractal heap created */ unsigned char obj[10]; /* Buffer for first object to insert */ + unsigned char robj[10]; /* Buffer for reading first object */ unsigned char obj2[20]; /* Buffer for second object to insert */ + unsigned char robj2[20]; /* Buffer for reading second object */ hsize_t heap_id; /* Heap ID for object inserted */ unsigned u; /* Local index variable */ @@ -475,11 +544,24 @@ test_abs_insert_second(hid_t fapl) if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)1024, (hsize_t)1024, (hsize_t)0, (hsize_t)983, (hsize_t)1)) FAIL_STACK_ERROR + /* Check reading back in the first object */ + if(H5HF_read(f, dxpl, fh_addr, &heap_id, robj) < 0) + FAIL_STACK_ERROR + if(HDmemcmp(obj, robj, sizeof(obj))) + FAIL_STACK_ERROR + heap_id = 0; if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj2), obj2, &heap_id) < 0) FAIL_STACK_ERROR if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)1024, (hsize_t)1024, (hsize_t)0, (hsize_t)960, (hsize_t)2)) FAIL_STACK_ERROR + + /* Check reading back in the second object */ + if(H5HF_read(f, dxpl, fh_addr, &heap_id, robj2) < 0) + FAIL_STACK_ERROR + if(HDmemcmp(obj2, robj2, sizeof(obj2))) + FAIL_STACK_ERROR + PASSED() /* Close the file */ @@ -546,7 +628,7 @@ test_abs_insert_root_mult(hid_t fapl) TESTING("inserting objects to fill absolute heap's root direct block"); /* Fill the heap up */ - if(fill_heap(f, dxpl, fh_addr, (hsize_t)1024, 0, NULL)) + if(fill_heap(f, dxpl, fh_addr, (hsize_t)1024, STD_MAN_START_BLOCK_SIZE, 0, NULL)) FAIL_STACK_ERROR PASSED() @@ -617,10 +699,10 @@ test_abs_insert_force_indirect(hid_t fapl) /* * Test forcing creation of indirect root block & second direct block */ - TESTING("inserting enough objects to create root indirect block"); + TESTING("inserting objects to create root indirect block"); /* Fill the heap up */ - if(fill_heap(f, dxpl, fh_addr, (hsize_t)1024, 0, &nobjs)) + if(fill_heap(f, dxpl, fh_addr, (hsize_t)1024, STD_MAN_START_BLOCK_SIZE, 0, &nobjs)) FAIL_STACK_ERROR /* Insert one more object, to force root indirect block creation */ @@ -706,15 +788,15 @@ test_abs_insert_fill_second(hid_t fapl) /* * Test inserting mult. (small) objects to fill second direct block */ - TESTING("inserting enough objects to fill second direct block"); + TESTING("inserting objects to fill second direct block"); /* Fill the first direct block heap up */ - if(fill_heap(f, dxpl, fh_addr, (hsize_t)1024, tot_nobjs, &nobjs)) + if(fill_heap(f, dxpl, fh_addr, (hsize_t)1024, STD_MAN_START_BLOCK_SIZE, tot_nobjs, &nobjs)) FAIL_STACK_ERROR tot_nobjs += nobjs; /* Fill the second direct block heap up (also creates initial root indirect block) */ - if(fill_heap(f, dxpl, fh_addr, (hsize_t)2048, tot_nobjs, &nobjs)) + if(fill_heap(f, dxpl, fh_addr, (hsize_t)2048, STD_MAN_START_BLOCK_SIZE, tot_nobjs, &nobjs)) FAIL_STACK_ERROR PASSED() @@ -761,6 +843,7 @@ test_abs_insert_third_direct(hid_t fapl) H5HF_create_t cparam; /* Creation parameters for heap */ haddr_t fh_addr; /* Address of fractal heap created */ unsigned char obj[10]; /* Buffer for first object to insert */ + unsigned char robj[10]; /* Buffer for reading object */ hsize_t heap_id; /* Heap ID for object inserted */ unsigned nobjs = 0; /* Number of objects inserted */ unsigned tot_nobjs = 0; /* Total number of objects inserted */ @@ -787,15 +870,15 @@ test_abs_insert_third_direct(hid_t fapl) /* * Test inserting mult. (small) objects to create third direct block */ - TESTING("inserting enough objects to create third direct block"); + TESTING("inserting objects to create third direct block"); /* Fill the first direct block heap up */ - if(fill_heap(f, dxpl, fh_addr, (hsize_t)1024, tot_nobjs, &nobjs)) + if(fill_heap(f, dxpl, fh_addr, (hsize_t)1024, STD_MAN_START_BLOCK_SIZE, tot_nobjs, &nobjs)) FAIL_STACK_ERROR tot_nobjs += nobjs; /* Fill the second direct block heap up (also creates initial root indirect block) */ - if(fill_heap(f, dxpl, fh_addr, (hsize_t)2048, tot_nobjs, &nobjs)) + if(fill_heap(f, dxpl, fh_addr, (hsize_t)2048, STD_MAN_START_BLOCK_SIZE, tot_nobjs, &nobjs)) FAIL_STACK_ERROR tot_nobjs += nobjs; @@ -816,6 +899,12 @@ test_abs_insert_third_direct(hid_t fapl) if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)3072, (hsize_t)3072, (hsize_t)0, (hsize_t)983, (hsize_t)tot_nobjs)) FAIL_STACK_ERROR + /* Read in object */ + if(H5HF_read(f, dxpl, fh_addr, &heap_id, robj) < 0) + FAIL_STACK_ERROR + if(HDmemcmp(obj, robj, sizeof(obj))) + FAIL_STACK_ERROR + PASSED() /* Close the file */ @@ -883,12 +972,12 @@ test_abs_fill_first_row(hid_t fapl) /* * Test inserting mult. (small) objects to fill first row in root indirect block */ - TESTING("inserting enough objects to fill first row of root indirect block"); + TESTING("inserting objects to fill first row of root indirect block"); /* Loop over filling direct blocks, until first root indirect row is full */ for(u = 0; u < STD_MAN_WIDTH; u++) { /* Fill a direct heap block up */ - if(fill_heap(f, dxpl, fh_addr, (hsize_t)(u + 1) * STD_MAN_START_BLOCK_SIZE, tot_nobjs, &nobjs)) + if(fill_heap(f, dxpl, fh_addr, (hsize_t)(u + 1) * STD_MAN_START_BLOCK_SIZE, STD_MAN_START_BLOCK_SIZE, tot_nobjs, &nobjs)) FAIL_STACK_ERROR tot_nobjs += nobjs; } /* end for */ @@ -935,7 +1024,8 @@ test_abs_start_second_row(hid_t fapl) H5F_t *f = NULL; /* Internal file object pointer */ H5HF_create_t cparam; /* Creation parameters for heap */ haddr_t fh_addr; /* Address of fractal heap created */ - unsigned char obj[10]; /* Buffer for first object to insert */ + unsigned char obj[10]; /* Buffer for object to insert */ + unsigned char robj[10]; /* Buffer for reading object */ hsize_t heap_id; /* Heap ID for object inserted */ unsigned nobjs = 0; /* Number of objects inserted */ unsigned tot_nobjs = 0; /* Total number of objects inserted */ @@ -958,24 +1048,21 @@ test_abs_start_second_row(hid_t fapl) FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR -#ifdef QAK -HDfprintf(stderr, "Fractal heap header address = %a\n", fh_addr); -#endif /* QAK */ /* * Test inserting mult. (small) objects to start second row in root indirect block */ - TESTING("inserting enough objects to start second row of root indirect block"); + TESTING("inserting objects to start second row of root indirect block"); /* Loop over filling direct blocks, until first root indirect row is full */ for(u = 0; u < STD_MAN_WIDTH; u++) { /* Fill a direct heap block up */ - if(fill_heap(f, dxpl, fh_addr, (hsize_t)(u + 1) * STD_MAN_START_BLOCK_SIZE, tot_nobjs, &nobjs)) + if(fill_heap(f, dxpl, fh_addr, (hsize_t)(u + 1) * STD_MAN_START_BLOCK_SIZE, STD_MAN_START_BLOCK_SIZE, tot_nobjs, &nobjs)) FAIL_STACK_ERROR tot_nobjs += nobjs; } /* end for */ - /* Insert one more object, to force root indirect block creation */ + /* Insert one more object, to force expanding root indirect block to two rows */ /* Initialize object buffer */ for(u = 0; u < sizeof(obj); u++) @@ -992,6 +1079,12 @@ HDfprintf(stderr, "Fractal heap header address = %a\n", fh_addr); if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)((STD_MAN_WIDTH + 1) * STD_MAN_START_BLOCK_SIZE), (hsize_t)((STD_MAN_WIDTH + 1) * STD_MAN_START_BLOCK_SIZE), (hsize_t)0, (hsize_t)983, (hsize_t)tot_nobjs)) FAIL_STACK_ERROR + /* Read in object */ + if(H5HF_read(f, dxpl, fh_addr, &heap_id, robj) < 0) + FAIL_STACK_ERROR + if(HDmemcmp(obj, robj, sizeof(obj))) + FAIL_STACK_ERROR + PASSED() /* Close the file */ @@ -1055,19 +1148,16 @@ test_abs_fill_second_row(hid_t fapl) FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR -#ifndef QAK -HDfprintf(stderr, "Fractal heap header address = %a\n", fh_addr); -#endif /* QAK */ /* * Test inserting mult. (small) objects to start second row in root indirect block */ - TESTING("inserting enough objects to fill second row of root indirect block"); + TESTING("inserting objects to fill second row of root indirect block"); /* Loop over filling direct blocks, until first root indirect row is full */ for(u = 0; u < STD_MAN_WIDTH; u++) { /* Fill a direct heap block up */ - if(fill_heap(f, dxpl, fh_addr, (hsize_t)(u + 1) * STD_MAN_START_BLOCK_SIZE, tot_nobjs, &nobjs)) + if(fill_heap(f, dxpl, fh_addr, (hsize_t)(u + 1) * STD_MAN_START_BLOCK_SIZE, STD_MAN_START_BLOCK_SIZE, tot_nobjs, &nobjs)) FAIL_STACK_ERROR tot_nobjs += nobjs; } /* end for */ @@ -1075,7 +1165,7 @@ HDfprintf(stderr, "Fractal heap header address = %a\n", fh_addr); /* Loop over filling direct blocks, until second root indirect row is full */ for(u = 0; u < STD_MAN_WIDTH; u++) { /* Fill a direct heap block up */ - if(fill_heap(f, dxpl, fh_addr, (hsize_t)((STD_MAN_WIDTH * STD_MAN_START_BLOCK_SIZE) + (u + 1) * STD_MAN_START_BLOCK_SIZE), tot_nobjs, &nobjs)) + if(fill_heap(f, dxpl, fh_addr, (hsize_t)((STD_MAN_WIDTH * STD_MAN_START_BLOCK_SIZE) + (u + 1) * STD_MAN_START_BLOCK_SIZE), STD_MAN_START_BLOCK_SIZE, tot_nobjs, &nobjs)) FAIL_STACK_ERROR tot_nobjs += nobjs; } /* end for */ @@ -1098,6 +1188,455 @@ error: /*------------------------------------------------------------------------- + * Function: test_abs_start_third_row + * + * Purpose: Test inserting mult. objects into absolute heap, creating + * enough direct blocks to fill first row of root indirect + * block, fill the second row also, then add another object to + * start the third row. + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, March 20, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_start_third_row(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ + char filename[1024]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5HF_create_t cparam; /* Creation parameters for heap */ + haddr_t fh_addr; /* Address of fractal heap created */ + unsigned char obj[10]; /* Buffer for object to insert */ + unsigned char robj[10]; /* Buffer for reading object */ + hsize_t heap_id; /* Heap ID for object inserted */ + unsigned nobjs = 0; /* Number of objects inserted */ + unsigned tot_nobjs = 0; /* Total number of objects inserted */ + hsize_t heap_size; /* Total size of heap */ + unsigned u; /* Local index variable */ + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Create absolute heap */ + init_std_cparam(&cparam); + if(H5HF_create(f, dxpl, &cparam, &fh_addr/*out*/) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + + /* + * Test inserting mult. (small) objects to start third row in root indirect block + */ + TESTING("inserting objects to start third row of root indirect block"); + + /* Loop over filling direct blocks, until first root indirect row is full */ + for(u = 0; u < STD_MAN_WIDTH; u++) { + /* Fill a direct heap block up */ + if(fill_heap(f, dxpl, fh_addr, (hsize_t)(u + 1) * STD_MAN_START_BLOCK_SIZE, STD_MAN_START_BLOCK_SIZE, tot_nobjs, &nobjs)) + FAIL_STACK_ERROR + tot_nobjs += nobjs; + } /* end for */ + + /* Loop over filling direct blocks, until second root indirect row is full */ + for(u = 0; u < STD_MAN_WIDTH; u++) { + /* Fill a direct heap block up */ + if(fill_heap(f, dxpl, fh_addr, (hsize_t)((STD_MAN_WIDTH * STD_MAN_START_BLOCK_SIZE) + (u + 1) * STD_MAN_START_BLOCK_SIZE), STD_MAN_START_BLOCK_SIZE, tot_nobjs, &nobjs)) + FAIL_STACK_ERROR + tot_nobjs += nobjs; + } /* end for */ + + /* Insert one more object, to force expanding root indirect block to three rows */ + + /* Initialize object buffer */ + for(u = 0; u < sizeof(obj); u++) + obj[u] = u + tot_nobjs; + + /* Insert object */ + heap_id = 0; + if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj), obj, &heap_id) < 0) + FAIL_STACK_ERROR + + /* Increment object count */ + tot_nobjs++; + + heap_size = (2 * STD_MAN_WIDTH) * STD_MAN_START_BLOCK_SIZE + + (2 * STD_MAN_START_BLOCK_SIZE); + if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, heap_size, heap_size, (hsize_t)0, (hsize_t)2007, (hsize_t)tot_nobjs)) + FAIL_STACK_ERROR + + /* Read in object */ + if(H5HF_read(f, dxpl, fh_addr, &heap_id, robj) < 0) + FAIL_STACK_ERROR + if(HDmemcmp(obj, robj, sizeof(obj))) + FAIL_STACK_ERROR + + PASSED() + + /* Close the file */ + if(H5Fclose(file) < 0) + TEST_ERROR + + /* All tests passed */ + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_abs_start_third_row() */ + + +/*------------------------------------------------------------------------- + * Function: test_abs_fill_fourth_row + * + * Purpose: Test inserting mult. objects into absolute heap, creating + * enough direct blocks to fill first four rows of root indirect + * block. + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, March 20, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_fill_fourth_row(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ + char filename[1024]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5HF_create_t cparam; /* Creation parameters for heap */ + haddr_t fh_addr; /* Address of fractal heap created */ + unsigned nobjs = 0; /* Number of objects inserted */ + unsigned tot_nobjs = 0; /* Total number of objects inserted */ + size_t block_size; /* Size of block added */ + hsize_t heap_size; /* Total size of heap */ + unsigned u, v; /* Local index variables */ + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Create absolute heap */ + init_std_cparam(&cparam); + if(H5HF_create(f, dxpl, &cparam, &fh_addr/*out*/) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + + /* + * Test inserting mult. (small) objects to fill four rows in root indirect block + */ + TESTING("inserting objects to fill four rows of root indirect block"); + + /* Loop over rows */ + block_size = STD_MAN_START_BLOCK_SIZE; + heap_size = 0; + for(v = 0; v < 4; v++) { + /* Loop over filling direct blocks for a row */ + for(u = 0; u < STD_MAN_WIDTH; u++) { + /* Fill a direct heap block up */ + heap_size += block_size; + if(fill_heap(f, dxpl, fh_addr, heap_size, block_size, tot_nobjs, &nobjs)) + FAIL_STACK_ERROR + tot_nobjs += nobjs; + } /* end for */ + + /* Adjust block size for row */ + if(v > 0) + block_size *= 2; + } /* end for */ + + PASSED() + + /* Close the file */ + if(H5Fclose(file) < 0) + TEST_ERROR + + /* All tests passed */ + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_abs_fill_fourth_row() */ + + +/*------------------------------------------------------------------------- + * Function: test_abs_fill_all_root_direct + * + * Purpose: Test inserting mult. objects into absolute heap, creating + * enough direct blocks to fill all direct rows of root indirect + * block. + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, March 20, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_fill_all_root_direct(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ + char filename[1024]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5HF_create_t cparam; /* Creation parameters for heap */ + haddr_t fh_addr; /* Address of fractal heap created */ + unsigned nobjs = 0; /* Number of objects inserted */ + unsigned tot_nobjs = 0; /* Total number of objects inserted */ + size_t block_size; /* Size of block added */ + hsize_t heap_size; /* Total size of heap */ + unsigned nrows; /* Number of rows inserted */ + unsigned u; /* Local index variable */ + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Create absolute heap */ + init_std_cparam(&cparam); + if(H5HF_create(f, dxpl, &cparam, &fh_addr/*out*/) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR +#ifdef QAK +HDfprintf(stderr, "Fractal heap header address = %a\n", fh_addr); +#endif /* QAK */ + + /* + * Test inserting mult. (small) objects to fill all direct rows in root indirect block + */ + TESTING("inserting objects to fill all direct rows of root indirect block"); + + /* Loop over rows */ + block_size = STD_MAN_START_BLOCK_SIZE; + heap_size = 0; + nrows = 0; + while(block_size <= STD_MAN_MAX_DIRECT_SIZE) { +#ifdef QAK +HDfprintf(stderr, "block_size = %Zu\n", block_size); +#endif /* QAK */ + /* Loop over filling direct blocks for a row */ +#ifdef QAK +HDfprintf(stderr, "block number: "); +#endif /* QAK */ + for(u = 0; u < STD_MAN_WIDTH; u++) { +#ifdef QAK +HDfprintf(stderr, "%u ", u); +#endif /* QAK */ + /* Fill a direct heap block up */ + heap_size += block_size; + if(fill_heap(f, dxpl, fh_addr, heap_size, block_size, tot_nobjs, &nobjs)) + FAIL_STACK_ERROR + tot_nobjs += nobjs; + } /* end for */ +#ifdef QAK +HDfprintf(stderr, "\n"); +#endif /* QAK */ + + /* Adjust block size for row */ + if(nrows > 0) + block_size *= 2; + + /* Increment row count */ + nrows++; + } /* end for */ + + PASSED() + + /* Close the file */ + if(H5Fclose(file) < 0) + TEST_ERROR + + /* All tests passed */ + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_abs_fill_all_root_direct() */ + + +/*------------------------------------------------------------------------- + * Function: test_abs_first_recursive_indirec5 + * + * Purpose: Test inserting mult. objects into absolute heap, creating + * enough direct blocks to fill all direct rows of root indirect + * block and create first recursive indirect block. + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, March 20, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_first_recursive_indirect(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ + char filename[1024]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5HF_create_t cparam; /* Creation parameters for heap */ + haddr_t fh_addr; /* Address of fractal heap created */ + unsigned char obj[10]; /* Buffer for object to insert */ + unsigned char robj[10]; /* Buffer for reading object */ + hsize_t heap_id; /* Heap ID for object inserted */ + unsigned nobjs = 0; /* Number of objects inserted */ + unsigned tot_nobjs = 0; /* Total number of objects inserted */ + size_t block_size; /* Size of block added */ + hsize_t heap_size; /* Total size of heap */ + unsigned nrows; /* Number of rows inserted */ + unsigned u; /* Local index variable */ + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Create absolute heap */ + init_std_cparam(&cparam); + if(H5HF_create(f, dxpl, &cparam, &fh_addr/*out*/) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR +#ifdef QAK +HDfprintf(stderr, "Fractal heap header address = %a\n", fh_addr); +#endif /* QAK */ + + /* + * Test inserting mult. (small) objects to force creation of first recursive indirect block + */ + TESTING("inserting objects to create first recursive indirect block"); + + /* Loop over rows */ + block_size = STD_MAN_START_BLOCK_SIZE; + heap_size = 0; + nrows = 0; + while(block_size <= STD_MAN_MAX_DIRECT_SIZE) { +#ifdef QAK +HDfprintf(stderr, "block_size = %Zu\n", block_size); +#endif /* QAK */ + /* Loop over filling direct blocks for a row */ +#ifdef QAK +HDfprintf(stderr, "block number: "); +#endif /* QAK */ + for(u = 0; u < STD_MAN_WIDTH; u++) { +#ifdef QAK +HDfprintf(stderr, "%u ", u); +#endif /* QAK */ + /* Fill a direct heap block up */ + heap_size += block_size; + if(fill_heap(f, dxpl, fh_addr, heap_size, block_size, tot_nobjs, &nobjs)) + FAIL_STACK_ERROR + tot_nobjs += nobjs; + } /* end for */ +#ifdef QAK +HDfprintf(stderr, "\n"); +#endif /* QAK */ + + /* Adjust block size for row */ + if(nrows > 0) + block_size *= 2; + + /* Increment row count */ + nrows++; + } /* end for */ + + /* Insert one more object, to force creation of first recursive indirect block */ + + /* Initialize object buffer */ + for(u = 0; u < sizeof(obj); u++) + obj[u] = u + tot_nobjs; + + /* Insert object */ + heap_id = 0; + if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj), obj, &heap_id) < 0) + FAIL_STACK_ERROR + + /* Increment object count */ + tot_nobjs++; + + heap_size += STD_MAN_START_BLOCK_SIZE; + if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, heap_size, heap_size, (hsize_t)0, (hsize_t)983, (hsize_t)tot_nobjs)) + FAIL_STACK_ERROR + + /* Read in object */ + if(H5HF_read(f, dxpl, fh_addr, &heap_id, robj) < 0) + FAIL_STACK_ERROR + if(HDmemcmp(obj, robj, sizeof(obj))) + FAIL_STACK_ERROR + + PASSED() + + /* Close the file */ + if(H5Fclose(file) < 0) + TEST_ERROR + + /* All tests passed */ + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_abs_first_recursive_indirect() */ + + +/*------------------------------------------------------------------------- * Function: main * * Purpose: Test the fractal heap code @@ -1133,13 +1672,16 @@ main(void) nerrors += test_abs_insert_fill_second(fapl); nerrors += test_abs_insert_third_direct(fapl); nerrors += test_abs_fill_first_row(fapl); - nerrors += test_abs_fill_first_row(fapl); nerrors += test_abs_start_second_row(fapl); + nerrors += test_abs_fill_second_row(fapl); + nerrors += test_abs_start_third_row(fapl); + nerrors += test_abs_fill_fourth_row(fapl); + nerrors += test_abs_fill_all_root_direct(fapl); #else /* QAK */ HDfprintf(stderr, "Uncomment tests!\n"); #endif /* QAK */ + nerrors += test_abs_first_recursive_indirect(fapl); #ifdef QAK - nerrors += test_abs_fill_second_row(fapl); #else /* QAK */ HDfprintf(stderr, "Uncomment tests!\n"); #endif /* QAK */ @@ -1147,7 +1689,7 @@ HDfprintf(stderr, "Uncomment tests!\n"); if(nerrors) goto error; puts("All fractal heap tests passed."); -#ifndef QAK +#ifdef QAK h5_cleanup(FILENAME, fapl); #else /* QAK */ HDfprintf(stderr, "Uncomment cleanup!\n"); -- cgit v0.12