diff options
-rw-r--r-- | MANIFEST | 4 | ||||
-rw-r--r-- | src/H5Edefin.h | 1 | ||||
-rw-r--r-- | src/H5Einit.h | 5 | ||||
-rw-r--r-- | src/H5Epubgen.h | 2 | ||||
-rw-r--r-- | src/H5Eterm.h | 3 | ||||
-rw-r--r-- | src/H5HF.c | 48 | ||||
-rw-r--r-- | src/H5HFcache.c | 128 | ||||
-rw-r--r-- | src/H5HFdblock.c | 585 | ||||
-rw-r--r-- | src/H5HFdtable.c | 213 | ||||
-rw-r--r-- | src/H5HFhdr.c | 458 | ||||
-rw-r--r-- | src/H5HFiblock.c | 1410 | ||||
-rw-r--r-- | src/H5HFint.c | 2037 | ||||
-rw-r--r-- | src/H5HFpkg.h | 86 | ||||
-rw-r--r-- | src/H5HFtest.c | 43 | ||||
-rw-r--r-- | src/H5err.txt | 1 | ||||
-rwxr-xr-x | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/Makefile.in | 15 | ||||
-rw-r--r-- | test/fheap.c | 4705 |
18 files changed, 5028 insertions, 4719 deletions
@@ -498,7 +498,11 @@ ./src/H5HF.c ./src/H5HFcache.c ./src/H5HFdbg.c +./src/H5HFdblock.c +./src/H5HFdtable.c ./src/H5HFflist.c +./src/H5HFhdr.c +./src/H5HFiblock.c ./src/H5HFint.c ./src/H5HFpkg.h ./src/H5HFprivate.h diff --git a/src/H5Edefin.h b/src/H5Edefin.h index 234fc30..f9c4fb5 100644 --- a/src/H5Edefin.h +++ b/src/H5Edefin.h @@ -72,6 +72,7 @@ hid_t H5E_CANTGETSIZE_g = FAIL; /* Unable to compute size */ /* Heap errors */ hid_t H5E_CANTRESTORE_g = FAIL; /* Can't restore condition */ hid_t H5E_CANTCOMPUTE_g = FAIL; /* Can't compute value */ +hid_t H5E_CANTEXTEND_g = FAIL; /* Can't extend heap's space */ /* Function entry/exit interface errors */ hid_t H5E_CANTINIT_g = FAIL; /* Unable to initialize object */ diff --git a/src/H5Einit.h b/src/H5Einit.h index 1b28419..32f9037 100644 --- a/src/H5Einit.h +++ b/src/H5Einit.h @@ -254,6 +254,11 @@ if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't compute value"))==NULL) HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") if((H5E_CANTCOMPUTE_g = H5I_register(H5I_ERROR_MSG, msg))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") +assert(H5E_CANTEXTEND_g==(-1)); +if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't extend heap's space"))==NULL) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") +if((H5E_CANTEXTEND_g = H5I_register(H5I_ERROR_MSG, msg))<0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") /* Function entry/exit interface errors */ assert(H5E_CANTINIT_g==(-1)); diff --git a/src/H5Epubgen.h b/src/H5Epubgen.h index 4139589..d16c95e 100644 --- a/src/H5Epubgen.h +++ b/src/H5Epubgen.h @@ -119,8 +119,10 @@ H5_DLLVAR hid_t H5E_CANTGETSIZE_g; /* Unable to compute size */ /* Heap errors */ #define H5E_CANTRESTORE (H5OPEN H5E_CANTRESTORE_g) #define H5E_CANTCOMPUTE (H5OPEN H5E_CANTCOMPUTE_g) +#define H5E_CANTEXTEND (H5OPEN H5E_CANTEXTEND_g) H5_DLLVAR hid_t H5E_CANTRESTORE_g; /* Can't restore condition */ H5_DLLVAR hid_t H5E_CANTCOMPUTE_g; /* Can't compute value */ +H5_DLLVAR hid_t H5E_CANTEXTEND_g; /* Can't extend heap's space */ /* Function entry/exit interface errors */ #define H5E_CANTINIT (H5OPEN H5E_CANTINIT_g) diff --git a/src/H5Eterm.h b/src/H5Eterm.h index 0a48b62..4f92303 100644 --- a/src/H5Eterm.h +++ b/src/H5Eterm.h @@ -73,7 +73,8 @@ H5E_CANTGETSIZE_g= /* Heap errors */ H5E_CANTRESTORE_g= -H5E_CANTCOMPUTE_g= +H5E_CANTCOMPUTE_g= +H5E_CANTEXTEND_g= /* Function entry/exit interface errors */ H5E_CANTINIT_g= @@ -99,7 +99,7 @@ herr_t H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_create_t *cparam, haddr_t *addr_p, size_t *id_len_p) { - H5HF_t *fh = NULL; /* The new fractal heap header information */ + H5HF_t *hdr = NULL; /* The new fractal heap header information */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5HF_create, FAIL) @@ -113,31 +113,31 @@ H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_create_t *cparam, haddr_t *addr_p, HDassert(id_len_p); /* Allocate & basic initialization for the shared header */ - if(NULL == (fh = H5HF_alloc(f))) + if(NULL == (hdr = H5HF_hdr_alloc(f))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate space for shared heap info") /* Allocate space for the header on disk */ - if(HADDR_UNDEF == (*addr_p = H5MF_alloc(f, H5FD_MEM_FHEAP_HDR, dxpl_id, (hsize_t)H5HF_HEADER_SIZE(fh)))) + if(HADDR_UNDEF == (*addr_p = H5MF_alloc(f, H5FD_MEM_FHEAP_HDR, dxpl_id, (hsize_t)H5HF_HEADER_SIZE(hdr)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap header") /* Initialize shared fractal heap header */ - if(H5HF_init(fh, *addr_p, cparam) < 0) + if(H5HF_hdr_init(hdr, *addr_p, cparam) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't initialize shared fractal heap header") /* Set the length of heap IDs */ - *id_len_p = fh->id_len; + *id_len_p = hdr->id_len; #ifdef QAK -HDfprintf(stderr, "%s: fh->id_len = %Zu\n", FUNC, fh->id_len); +HDfprintf(stderr, "%s: hdr->id_len = %Zu\n", FUNC, hdr->id_len); #endif /* QAK */ /* Cache the new fractal heap header */ - if(H5AC_set(f, dxpl_id, H5AC_FHEAP_HDR, *addr_p, fh, H5AC__NO_FLAGS_SET) < 0) + if(H5AC_set(f, dxpl_id, H5AC_FHEAP_HDR, *addr_p, hdr, H5AC__NO_FLAGS_SET) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add fractal heap header to cache") done: if(ret_value < 0) { - if(fh) - (void)H5HF_cache_hdr_dest(f, fh); + if(hdr) + (void)H5HF_cache_hdr_dest(f, hdr); } /* end if */ FUNC_LEAVE_NOAPI(ret_value) @@ -162,7 +162,7 @@ herr_t H5HF_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t size, const void *obj, void *id/*out*/) { - H5HF_t *fh = NULL; /* The fractal heap header information */ + H5HF_t *hdr = NULL; /* The fractal heap header information */ unsigned hdr_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for header */ herr_t ret_value = SUCCEED; @@ -183,37 +183,37 @@ HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size); /* * Load the fractal heap header. */ - if(NULL == (fh = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, addr, NULL, NULL, H5AC_WRITE))) + if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, addr, NULL, NULL, H5AC_WRITE))) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header") /* Check if object is large enough to be standalone */ - if(size >= fh->standalone_size) { + if(size >= hdr->standalone_size) { HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "standalone blocks not supported yet") } /* end if */ else { /* Check if we are in "append only" mode, or if there's enough room for the object */ - if(fh->write_once) { + if(hdr->write_once) { HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'write once' managed blocks not supported yet") } /* end if */ else { - H5HF_section_free_node_t *sec_node; /* Pointer to free space section */ + H5HF_free_section_t *sec_node; /* Pointer to free space section */ /* Find free space in heap */ - if(H5HF_man_find(fh, dxpl_id, size, &sec_node) < 0) + if(H5HF_man_find(hdr, dxpl_id, size, &sec_node) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate space in fractal heap") /* Use free space for allocating object */ - if(H5HF_man_insert(fh, dxpl_id, sec_node, size, obj, id) < 0) + if(H5HF_man_insert(hdr, dxpl_id, sec_node, size, obj, id) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate space for object in fractal heap") } /* end else */ } /* end else */ /* Check for making header dirty */ - if(fh->dirty) + if(hdr->dirty) hdr_flags |= H5AC__DIRTIED_FLAG; done: - if(fh && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, addr, fh, hdr_flags) < 0) + if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, addr, hdr, hdr_flags) < 0) HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap header") FUNC_LEAVE_NOAPI(ret_value) @@ -237,7 +237,7 @@ herr_t H5HF_read(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_id, void *obj/*out*/) { - H5HF_t *fh = NULL; /* The fractal heap header information */ + H5HF_t *hdr = NULL; /* The fractal heap header information */ const uint8_t *id = (const uint8_t *)_id; /* Object ID */ hsize_t obj_off; /* Object's offset in heap */ size_t obj_len; /* Object's length in heap */ @@ -256,12 +256,12 @@ H5HF_read(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_id, /* * Load the fractal heap header. */ - if(NULL == (fh = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, addr, NULL, NULL, H5AC_READ))) + if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, addr, NULL, NULL, H5AC_READ))) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header") /* Decode the object offset within the heap & it's length */ - UINT64DECODE_VAR(id, obj_off, fh->heap_off_size); - UINT64DECODE_VAR(id, obj_len, fh->id_len); + UINT64DECODE_VAR(id, obj_off, hdr->heap_off_size); + UINT64DECODE_VAR(id, obj_len, hdr->id_len); #ifdef QAK HDfprintf(stderr, "%s: obj_off = %Hu, obj_len = %Zu\n", FUNC, obj_off, obj_len); #endif /* QAK */ @@ -272,12 +272,12 @@ HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "standalone blocks not supported ye } /* end if */ else { /* Read object from managed heap blocks */ - if(H5HF_man_read(fh, dxpl_id, obj_off, obj_len, obj) < 0) + if(H5HF_man_read(hdr, dxpl_id, obj_off, obj_len, obj) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't read object from fractal heap") } /* end else */ done: - if(fh && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, addr, fh, H5AC__NO_FLAGS_SET) < 0) + if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, addr, hdr, H5AC__NO_FLAGS_SET) < 0) HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap header") FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5HFcache.c b/src/H5HFcache.c index d59d164..6305fb8 100644 --- a/src/H5HFcache.c +++ b/src/H5HFcache.c @@ -63,9 +63,9 @@ /* Metadata cache callbacks */ static H5HF_t *H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata, void *udata2); -static herr_t H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_t *fh); -static herr_t H5HF_cache_hdr_clear(H5F_t *f, H5HF_t *fh, hbool_t destroy); -static herr_t H5HF_cache_hdr_size(const H5F_t *f, const H5HF_t *fh, size_t *size_ptr); +static herr_t H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_t *hdr); +static herr_t H5HF_cache_hdr_clear(H5F_t *f, H5HF_t *hdr, hbool_t destroy); +static herr_t H5HF_cache_hdr_size(const H5F_t *f, const H5HF_t *hdr, size_t *size_ptr); static H5HF_direct_t *H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata, void *udata2); static herr_t H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_direct_t *dblock); static herr_t H5HF_cache_dblock_clear(H5F_t *f, H5HF_direct_t *dblock, hbool_t destroy); @@ -252,7 +252,7 @@ H5HF_dtable_encode(H5F_t *f, uint8_t **pp, const H5HF_dtable_t *dtable) static H5HF_t * H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *udata1, void UNUSED *udata2) { - H5HF_t *fh = NULL; /* Fractal heap info */ + H5HF_t *hdr = NULL; /* Fractal heap info */ size_t size; /* Header size */ uint8_t *buf = NULL; /* Temporary buffer */ const uint8_t *p; /* Pointer into raw data buffer */ @@ -269,14 +269,14 @@ HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr); HDassert(H5F_addr_defined(addr)); /* Allocate space for the fractal heap data structure */ - if(NULL == (fh = H5HF_alloc(f))) + if(NULL == (hdr = H5HF_hdr_alloc(f))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Set the heap header's address */ - fh->heap_addr = addr; + hdr->heap_addr = addr; /* Compute the size of the fractal heap header on disk */ - size = H5HF_HEADER_SIZE(fh); + size = H5HF_HEADER_SIZE(hdr); /* Allocate temporary buffer */ if((buf = H5FL_BLK_MALLOC(header_block, size)) == NULL) @@ -309,42 +309,42 @@ HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr); HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect metadata checksum for fractal heap header") /* Heap address mapping */ - fh->addrmap = *p++; + hdr->addrmap = *p++; HDassert(H5HF_ABSOLUTE == 0); - if(fh->addrmap > H5HF_MAPPED) + if(hdr->addrmap > H5HF_MAPPED) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect fractal heap address mapping") /* Min. size of standalone objects */ - UINT32DECODE(p, fh->standalone_size); + UINT32DECODE(p, hdr->standalone_size); /* Internal management information */ - H5F_DECODE_LENGTH(f, p, fh->total_man_free); - H5F_DECODE_LENGTH(f, p, fh->total_std_free); + H5F_DECODE_LENGTH(f, p, hdr->total_man_free); + H5F_DECODE_LENGTH(f, p, hdr->total_std_free); /* Statistics information */ - H5F_DECODE_LENGTH(f, p, fh->total_size); - H5F_DECODE_LENGTH(f, p, fh->man_size); - H5F_DECODE_LENGTH(f, p, fh->std_size); - H5F_DECODE_LENGTH(f, p, fh->nobjs); + H5F_DECODE_LENGTH(f, p, hdr->total_size); + H5F_DECODE_LENGTH(f, p, hdr->man_size); + H5F_DECODE_LENGTH(f, p, hdr->std_size); + H5F_DECODE_LENGTH(f, p, hdr->nobjs); /* Managed objects' doubling-table info */ - if(H5HF_dtable_decode(fh->f, &p, &(fh->man_dtable)) < 0) + if(H5HF_dtable_decode(hdr->f, &p, &(hdr->man_dtable)) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, NULL, "unable to encode managed obj. doubling table info") HDassert((size_t)(p - buf) == size); /* Make shared heap info reference counted */ - if(H5HF_finish_init(fh) < 0) + if(H5HF_hdr_finish_init(hdr) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't create ref-count wrapper for shared fractal heap header") /* Set return value */ - ret_value = fh; + ret_value = hdr; done: if(buf) H5FL_BLK_FREE(header_block, buf); - if(!ret_value && fh) - (void)H5HF_cache_hdr_dest(f, fh); + if(!ret_value && hdr) + (void)H5HF_cache_hdr_dest(f, hdr); FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_cache_hdr_load() */ /*lint !e818 Can't make udata a pointer to const */ @@ -364,7 +364,7 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_t *fh) +H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HF_t *hdr) { herr_t ret_value = SUCCEED; /* Return value */ @@ -376,18 +376,18 @@ HDfprintf(stderr, "%s: Flushing heap header, addr = %a, destroy = %u\n", FUNC, a /* check arguments */ HDassert(f); HDassert(H5F_addr_defined(addr)); - HDassert(fh); + HDassert(hdr); - if(fh->cache_info.is_dirty) { + if(hdr->cache_info.is_dirty) { uint8_t *buf = NULL; /* Temporary raw data buffer */ uint8_t *p; /* Pointer into raw data buffer */ size_t size; /* Header size on disk */ /* Sanity check */ - HDassert(fh->dirty); + HDassert(hdr->dirty); /* Compute the size of the heap header on disk */ - size = H5HF_HEADER_SIZE(fh); + size = H5HF_HEADER_SIZE(hdr); /* Allocate temporary buffer */ if((buf = H5FL_BLK_MALLOC(header_block, size)) == NULL) @@ -412,23 +412,23 @@ HDfprintf(stderr, "%s: Flushing heap header, addr = %a, destroy = %u\n", FUNC, a p += 4; /* Heap address mapping */ - *p++ = fh->addrmap; + *p++ = hdr->addrmap; /* Min. size of standalone objects */ - UINT32ENCODE(p, fh->standalone_size); + UINT32ENCODE(p, hdr->standalone_size); /* Internal management information */ - H5F_ENCODE_LENGTH(f, p, fh->total_man_free); - H5F_ENCODE_LENGTH(f, p, fh->total_std_free); + H5F_ENCODE_LENGTH(f, p, hdr->total_man_free); + H5F_ENCODE_LENGTH(f, p, hdr->total_std_free); /* Statistics information */ - H5F_ENCODE_LENGTH(f, p, fh->total_size); - H5F_ENCODE_LENGTH(f, p, fh->man_size); - H5F_ENCODE_LENGTH(f, p, fh->std_size); - H5F_ENCODE_LENGTH(f, p, fh->nobjs); + H5F_ENCODE_LENGTH(f, p, hdr->total_size); + H5F_ENCODE_LENGTH(f, p, hdr->man_size); + H5F_ENCODE_LENGTH(f, p, hdr->std_size); + H5F_ENCODE_LENGTH(f, p, hdr->nobjs); /* Managed objects' doubling-table info */ - if(H5HF_dtable_encode(fh->f, &p, &(fh->man_dtable)) < 0) + if(H5HF_dtable_encode(hdr->f, &p, &(hdr->man_dtable)) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTENCODE, FAIL, "unable to encode managed obj. doubling table info") /* Write the heap header. */ @@ -438,12 +438,12 @@ HDfprintf(stderr, "%s: Flushing heap header, addr = %a, destroy = %u\n", FUNC, a H5FL_BLK_FREE(header_block, buf); - fh->dirty = FALSE; - fh->cache_info.is_dirty = FALSE; + hdr->dirty = FALSE; + hdr->cache_info.is_dirty = FALSE; } /* end if */ if(destroy) - if(H5HF_cache_hdr_dest(f, fh) < 0) + if(H5HF_cache_hdr_dest(f, hdr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap header") done: @@ -465,27 +465,27 @@ done: *------------------------------------------------------------------------- */ herr_t -H5HF_cache_hdr_dest_real(H5HF_t *fh) +H5HF_cache_hdr_dest_real(H5HF_t *hdr) { FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_hdr_dest_real) /* * Check arguments. */ - HDassert(fh); + HDassert(hdr); /* XXX: Take out this goofy routine, after metadata cache is supporting * "un-evictable" flag */ - if(fh->rc == 0 && fh->evicted == TRUE) { + if(hdr->rc == 0 && hdr->evicted == TRUE) { /* Free the free list information for the heap */ - if(fh->flist) - H5HF_flist_free(fh->flist); + if(hdr->flist) + H5HF_flist_free(hdr->flist); /* Free the block size lookup table for the doubling table */ - H5HF_dtable_dest(&fh->man_dtable); + H5HF_dtable_dest(&hdr->man_dtable); /* Free the shared info itself */ - H5FL_FREE(H5HF_t, fh); + H5FL_FREE(H5HF_t, hdr); } /* end if */ FUNC_LEAVE_NOAPI(SUCCEED) @@ -507,25 +507,25 @@ H5HF_cache_hdr_dest_real(H5HF_t *fh) */ /* ARGSUSED */ herr_t -H5HF_cache_hdr_dest(H5F_t UNUSED *f, H5HF_t *fh) +H5HF_cache_hdr_dest(H5F_t UNUSED *f, H5HF_t *hdr) { FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_hdr_dest) /* * Check arguments. */ - HDassert(fh); + HDassert(hdr); /* XXX: Enable this after the metadata cache supports the "un-evictable" flag */ -/* HDassert(fh->rc == 0); */ +/* HDassert(hdr->rc == 0); */ /* XXX: Take out this goofy 'if' statement, after metadata cache is supporting * "un-evictable" flag */ /* XXX: Take out 'evicted' flag after "un-evictable" flag is working */ - fh->evicted = TRUE; + hdr->evicted = TRUE; /* XXX: Take out this goofy routine, after metadata cache is supporting * "un-evictable" flag */ - H5HF_cache_hdr_dest_real(fh); + H5HF_cache_hdr_dest_real(hdr); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5HF_cache_hdr_dest() */ @@ -545,7 +545,7 @@ H5HF_cache_hdr_dest(H5F_t UNUSED *f, H5HF_t *fh) *------------------------------------------------------------------------- */ static herr_t -H5HF_cache_hdr_clear(H5F_t *f, H5HF_t *fh, hbool_t destroy) +H5HF_cache_hdr_clear(H5F_t *f, H5HF_t *hdr, hbool_t destroy) { herr_t ret_value = SUCCEED; /* Return value */ @@ -554,13 +554,13 @@ H5HF_cache_hdr_clear(H5F_t *f, H5HF_t *fh, hbool_t destroy) /* * Check arguments. */ - HDassert(fh); + HDassert(hdr); /* Reset the dirty flag. */ - fh->cache_info.is_dirty = FALSE; + hdr->cache_info.is_dirty = FALSE; if(destroy) - if(H5HF_cache_hdr_dest(f, fh) < 0) + if(H5HF_cache_hdr_dest(f, hdr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap header") done: @@ -584,17 +584,17 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5HF_cache_hdr_size(const H5F_t *f, const H5HF_t *fh, size_t *size_ptr) +H5HF_cache_hdr_size(const H5F_t *f, const H5HF_t *hdr, size_t *size_ptr) { FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_hdr_size) /* check arguments */ HDassert(f); - HDassert(fh); + HDassert(hdr); HDassert(size_ptr); /* Set size value */ - *size_ptr = H5HF_HEADER_SIZE(fh); + *size_ptr = H5HF_HEADER_SIZE(hdr); FUNC_LEAVE_NOAPI(SUCCEED) } /* H5HF_cache_hdr_size() */ @@ -1023,6 +1023,9 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrows const uint8_t *p; /* Pointer into raw data buffer */ haddr_t heap_addr; /* Address of heap header in the file */ uint32_t metadata_chksum; /* Metadata checksum value */ +#ifndef NDEBUG + hsize_t acc_child_free_space; /* Accumulated child free space */ +#endif /* NDEBUG */ size_t u; /* Local index variable */ H5HF_indirect_t *ret_value; /* Return value */ @@ -1151,6 +1154,10 @@ HDfprintf(stderr, "%s: Load indirect block, addr = %a\n", FUNC, addr); HDassert(iblock->nrows > 0); if(NULL == (iblock->ents = H5FL_SEQ_MALLOC(H5HF_indirect_ent_t, (iblock->nrows * hdr->man_dtable.cparam.width)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for direct entries") +#ifndef NDEBUG + /* Reset child free space */ + acc_child_free_space = 0; +#endif /* NDEBUG */ for(u = 0; u < (iblock->nrows * hdr->man_dtable.cparam.width); u++) { /* Decode block address */ H5F_addr_decode(f, &p, &(iblock->ents[u].addr)); @@ -1160,8 +1167,15 @@ HDfprintf(stderr, "%s: Load indirect block, addr = %a\n", FUNC, addr); UINT32DECODE_VAR(p, iblock->ents[u].free_space, hdr->man_dtable.max_dir_blk_off_size) else UINT64DECODE_VAR(p, iblock->ents[u].free_space, hdr->heap_off_size) +#ifndef NDEBUG + acc_child_free_space += iblock->ents[u].free_space; +#endif /* NDEBUG */ /* XXX: Add code to indirect block cache load routine to create range sections for skipped blocks */ +/* XXX: ?? How to add code to indirect block cache load routine to create indirect sections for skipped blocks ?? */ } /* end for */ +#ifndef NDEBUG + HDassert(acc_child_free_space == iblock->child_free_space); +#endif /* NDEBUG */ /* Sanity check */ HDassert((size_t)(p - buf) == iblock->size); diff --git a/src/H5HFdblock.c b/src/H5HFdblock.c new file mode 100644 index 0000000..dcb704c --- /dev/null +++ b/src/H5HFdblock.c @@ -0,0 +1,585 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5HFdblock.c + * Apr 10 2006 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Direct block routines for fractal heaps. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5HF_PACKAGE /*suppress error about including H5HFpkg */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5HFpkg.h" /* Fractal heaps */ +#include "H5MFprivate.h" /* File memory management */ +#include "H5Vprivate.h" /* Vectors and arrays */ + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + +/* Declare a free list to manage the H5HF_direct_t struct */ +H5FL_DEFINE(H5HF_direct_t); + +/* Declare a free list to manage the H5HF_direct_free_head_t struct */ +H5FL_DEFINE(H5HF_direct_free_head_t); + +/* Declare a free list to manage the H5HF_direct_free_node_t struct */ +H5FL_DEFINE(H5HF_direct_free_node_t); + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5HF_man_dblock_create + * + * Purpose: Allocate & initialize a managed direct block + * + * Return: Pointer to new direct block on success, NULL on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 27 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_man_dblock_create(hid_t dxpl_id, H5HF_t *hdr, H5HF_indirect_t *par_iblock, + unsigned par_entry, size_t block_size, hsize_t block_off, haddr_t *addr_p, + H5HF_free_section_t **ret_sec_node) +{ + H5HF_direct_free_node_t *node; /* Pointer to free list node for block */ + H5HF_free_section_t *sec_node; /* Pointer to free list section for block */ + H5HF_direct_t *dblock = NULL; /* Pointer to direct block */ + size_t free_space; /* Free space in new block */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_create) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(block_size > 0); + HDassert(addr_p); + + /* + * Allocate file and memory data structures. + */ + if(NULL == (dblock = H5FL_MALLOC(H5HF_direct_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fractal heap direct block") + + /* Reset the metadata cache info for the heap header */ + HDmemset(&dblock->cache_info, 0, sizeof(H5AC_info_t)); + + /* Share common heap information */ + dblock->shared = hdr; + if(H5HF_hdr_incr(hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared heap header") + + /* Set info for direct block */ +#ifdef QAK +HDfprintf(stderr, "%s: size = %Zu, block_off = %Hu\n", FUNC, block_size, block_off); +#endif /* QAK */ + dblock->parent = par_iblock; + if(dblock->parent) { + if(H5HF_iblock_incr(par_iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") + dblock->par_addr = par_iblock->addr; + dblock->par_nrows = par_iblock->nrows; + } /* end if */ + else { + dblock->par_addr = HADDR_UNDEF; + dblock->par_nrows = 0; + } /* end else */ + dblock->par_entry = par_entry; + dblock->size = block_size; + dblock->block_off = block_off; + dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(block_size); + dblock->free_list_head = H5HF_MAN_ABS_DIRECT_OVERHEAD_DBLOCK(hdr, dblock); + dblock->blk_free_space = block_size - + (H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, block_size) + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr)); + free_space = block_size - dblock->free_list_head; + + /* Allocate buffer for block */ +/* XXX: Change to using free-list factories */ + if((dblock->blk = H5FL_BLK_MALLOC(direct_block, block_size)) == NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") +#ifdef H5_USING_PURIFY +HDmemset(dblock->blk, 0, dblock->size); +#endif /* H5_USING_PURIFY */ + + /* Set up free list head */ + if(NULL == (dblock->free_list = H5FL_MALLOC(H5HF_direct_free_head_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list head") + dblock->free_list->dirty = TRUE; + + /* Set up free list node for all unused space in block */ + if(NULL == (node = H5FL_MALLOC(H5HF_direct_free_node_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list node") + + /* Set node's information */ + node->size = free_space; + node->my_offset = dblock->free_list_head; + node->next_offset = 0; + node->prev = node->next = NULL; + + /* Attach to free list head */ +/* XXX: Convert this list to a skip list? */ + dblock->free_list->first = node; + + /* Allocate space for the header on disk */ + if(HADDR_UNDEF == (*addr_p = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)block_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block") + + /* Create free list section node */ + if(NULL == (sec_node = H5FL_MALLOC(H5HF_free_section_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") + + /* Set section's information */ + sec_node->sect_addr = block_off + node->my_offset; + /* (section size is "object size", without the metadata overhead) */ + sec_node->sect_size = node->size - H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr); + sec_node->type = H5HF_SECT_SINGLE; + sec_node->u.single.dblock_addr = *addr_p; + sec_node->u.single.dblock_size = block_size; + + /* Check what to do with section node */ + if(ret_sec_node) + /* Pass back the pointer to the section instead of adding it to the free list */ + *ret_sec_node = sec_node; + else { + /* Add new free space to the global list of space */ + if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list") + } /* end else */ + + /* Cache the new fractal heap direct block */ + if(H5AC_set(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, *addr_p, dblock, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add fractal heap direct block to cache") + +done: + if(ret_value < 0) + if(dblock) + (void)H5HF_cache_dblock_dest(hdr->f, dblock); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_man_dblock_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_man_dblock_build_freelist + * + * Purpose: Parse the free list information for a direct block and build + * block's free list + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 28 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_man_dblock_build_freelist(H5HF_direct_t *dblock, haddr_t dblock_addr) +{ + H5HF_direct_free_head_t *head = NULL; /* Pointer to free list head for block */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_build_freelist) + + /* + * Check arguments. + */ + HDassert(dblock); + + /* Allocate head of list */ + if(NULL == (head = H5FL_MALLOC(H5HF_direct_free_head_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list head") + head->dirty = FALSE; + + /* Check for any nodes on free list */ + if(dblock->free_list_head == 0) + head->first = NULL; + else { + H5HF_t *hdr; /* Pointer to shared heap header */ + H5HF_free_section_t *sec_node; /* Pointer to free list section for block */ + H5HF_direct_free_node_t *node = NULL; /* Pointer to free list node for block */ + H5HF_direct_free_node_t *prev_node; /* Pointer to previous free list node for block */ + hsize_t free_len; /* Length of free list info */ + hsize_t next_off; /* Next node offset in block */ + hsize_t prev_off; /* Prev node offset in block */ + uint8_t *p; /* Temporary pointer to free node info */ + + /* Get the pointer to the shared heap info */ + hdr = dblock->shared; + + /* Point to first node in free list */ + p = dblock->blk + dblock->free_list_head; + + /* Decode information for first node on free list */ + UINT64DECODE_VAR(p, free_len, dblock->blk_off_size); + UINT64DECODE_VAR(p, next_off, dblock->blk_off_size); + + /* Allocate node on list */ + if(NULL == (node = H5FL_MALLOC(H5HF_direct_free_node_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list node") + + /* Set node's information */ + node->size = free_len; + node->my_offset = dblock->free_list_head; + node->next_offset = next_off; + node->prev = node->next = NULL; + + /* Attach to free list head */ + head->first = node; + + /* Set block's free space */ + dblock->blk_free_space = free_len; + + /* Create free list section node */ + if(NULL == (sec_node = H5FL_MALLOC(H5HF_free_section_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") + + /* Set section's information */ + sec_node->sect_addr = dblock->block_off + node->my_offset; + /* (section size is "object size", without the metadata overhead) */ + sec_node->sect_size = node->size - H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr); + sec_node->type = H5HF_SECT_SINGLE; + sec_node->u.single.dblock_addr = dblock_addr; + sec_node->u.single.dblock_size = dblock->size; + + /* Add new free space to the global list of space */ + if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list") + + /* Set up trailing node pointer */ + prev_node = node; + prev_off = next_off; + + /* Bring in rest of node on free list */ + while(next_off != 0) { + /* Point to first node in free list */ + p = dblock->blk + next_off; + + /* Decode information for first node on free list */ + UINT64DECODE_VAR(p, free_len, dblock->blk_off_size); + UINT64DECODE_VAR(p, next_off, dblock->blk_off_size); + + /* Allocate node on list */ + if(NULL == (node = H5FL_MALLOC(H5HF_direct_free_node_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list node") + + /* Set node's information */ + node->size = free_len; + node->my_offset = prev_off; + node->next_offset = next_off; + node->prev = prev_node; + node->next = NULL; + + /* Adjust block's free space */ + dblock->blk_free_space += free_len; + + /* Create free list section node */ + if(NULL == (sec_node = H5FL_MALLOC(H5HF_free_section_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") + + /* Set section's information */ + sec_node->sect_addr = dblock->block_off + node->my_offset; + /* (section size is "object size", without the metadata overhead) */ + sec_node->sect_size = node->size - H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr); + sec_node->type = H5HF_SECT_SINGLE; + sec_node->u.single.dblock_addr = dblock_addr; + sec_node->u.single.dblock_size = dblock->size; + + /* Add new free space to the global list of space */ + if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list") + + /* Update trailing info */ + prev_node->next = node; + prev_off = next_off; + + /* Advance to next node */ + prev_node = node; + } /* end while */ + } /* end else */ + + /* Assign free list head to block */ + dblock->free_list = head; + +done: +/* XXX: cleanup on failure? */ + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_man_dblock_build_freelist() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_man_dblock_adj_free + * + * Purpose: Adjust the free space for a direct block, and it's parents + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 14 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_man_dblock_adj_free(hid_t dxpl_id, H5HF_direct_t *dblock, ssize_t amt) +{ + H5HF_t *hdr; /* Shared heap information */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_adj_free) +#ifdef QAK +HDfprintf(stderr, "%s: amt = %Zd\n", FUNC, amt); +#endif /* QAK */ + + /* + * Check arguments. + */ + HDassert(dblock); + + /* Get the pointer to the shared heap header */ + hdr = dblock->shared; + + /* Adjust space available in block */ + HDassert(amt > 0 || dblock->blk_free_space >= (size_t)-amt); + dblock->blk_free_space += amt; + + /* Check if the parent info is set */ + if(dblock->parent) { + H5HF_indirect_t *iblock; /* Block's parent */ + + /* Get the pointer to the shared parent indirect block */ + iblock = dblock->parent; + + /* Adjust this indirect block's child free space */ +#ifdef QAK +HDfprintf(stderr, "%s: dblock->par_entry = %u\n", FUNC, dblock->par_entry); +HDfprintf(stderr, "%s: iblock->block_off = %a\n", FUNC, iblock->block_off); +HDfprintf(stderr, "%s: iblock->child_free_space = %Hu\n", FUNC, iblock->child_free_space); +HDfprintf(stderr, "%s: iblock->ents[dblock->par_entry].free_space = %Hu\n", FUNC, iblock->ents[dblock->par_entry].free_space); +#endif /* QAK */ + HDassert(amt > 0 || iblock->ents[dblock->par_entry].free_space >= (hsize_t)-amt); + iblock->ents[dblock->par_entry].free_space += amt; + HDassert(amt > 0 || iblock->child_free_space >= (hsize_t)-amt); + iblock->child_free_space += amt; + + /* Mark indirect block as dirty */ + if(H5HF_iblock_dirty(dxpl_id, iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") + + /* Modify the free space in parent block(s) */ + while(iblock->parent) { + size_t par_entry; /* Entry in parent */ + + /* Get the pointer to the shared parent indirect block */ + par_entry = iblock->par_entry; + iblock = iblock->parent; + HDassert(iblock); + + /* Adjust this indirect block's child free space */ + HDassert(amt > 0 || iblock->ents[par_entry].free_space >= (hsize_t)-amt); + iblock->ents[par_entry].free_space += amt; + HDassert(amt > 0 || iblock->child_free_space >= (hsize_t)-amt); + iblock->child_free_space += amt; + + /* Mark indirect block as dirty */ + if(H5HF_iblock_dirty(dxpl_id, iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") + } /* end while */ + } /* end if */ + + /* Update shared heap free space header */ + HDassert(amt > 0 || hdr->total_man_free >= (hsize_t)-amt); + hdr->total_man_free += amt; +#ifdef QAK +HDfprintf(stderr, "%s: hdr->total_man_free = %Hu\n", FUNC, hdr->total_man_free); +#endif /* QAK */ + + /* Mark heap header as modified */ + if(H5HF_hdr_dirty(dxpl_id, hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_man_dblock_adj_free() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_man_dblock_new + * + * Purpose: Create a direct block large enough to hold an object of + * the requested size + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 13 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_man_dblock_new(H5HF_t *hdr, hid_t dxpl_id, size_t request) +{ + haddr_t dblock_addr; /* Address of new direct block */ + size_t dblock_size; /* Size of new direct block */ + size_t min_dblock_size; /* Min. size of direct block to allocate */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_new) +#ifdef QAK +HDfprintf(stderr, "%s: request = %Zu\n", FUNC, request); +#endif /* QAK */ + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(request > 0); + + /* Compute the min. size of the direct block needed to fulfill the request */ + if(request < hdr->man_dtable.cparam.start_block_size) + min_dblock_size = hdr->man_dtable.cparam.start_block_size; + else { + min_dblock_size = 1 << (1 + H5V_log2_gen((hsize_t)request)); + HDassert(min_dblock_size <= hdr->man_dtable.cparam.max_direct_size); + } /* end else */ + + /* Adjust the size of block needed to fulfill request, with overhead */ +#ifdef QAK +HDfprintf(stderr, "%s: Check 1 - min_dblock_size = %Zu\n", FUNC, min_dblock_size); +HDfprintf(stderr, "%s: H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE = %u\n", FUNC, H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, hdr->man_dtable.cparam.start_block_size)); +HDfprintf(stderr, "%s: H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN = %u\n", FUNC, H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr)); +#endif /* QAK */ + if((min_dblock_size - request) < (H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, min_dblock_size) + + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr))) + min_dblock_size *= 2; +#ifdef QAK +HDfprintf(stderr, "%s: Check 2 - min_dblock_size = %Zu\n", FUNC, min_dblock_size); +#endif /* QAK */ + + /* Check if this is the first block in the heap */ + if(!H5F_addr_defined(hdr->man_dtable.table_addr) && + min_dblock_size == hdr->man_dtable.cparam.start_block_size) { + /* Create new direct block at starting offset */ + dblock_size = hdr->man_dtable.cparam.start_block_size; + if(H5HF_man_dblock_create(dxpl_id, hdr, NULL, 0, dblock_size, (hsize_t)0, &dblock_addr, NULL) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block") + +#ifdef QAK +HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr); +#endif /* QAK */ + + /* Point root at new direct block */ + hdr->man_dtable.curr_root_rows = 0; + hdr->man_dtable.table_addr = dblock_addr; + + /* Extend heap to cover new direct block */ + if(H5HF_hdr_extend_heap(hdr, (hsize_t)dblock_size, hdr->man_dtable.row_dblock_free[0]) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "can't increase space to cover root direct block") + } /* end if */ + /* Root entry already exists, go get indirect block for new direct block */ + else { + H5HF_indirect_t *iblock; /* Pointer to indirect block to create */ + haddr_t iblock_addr; /* Indirect block's address */ + size_t dblock_entry; /* Direct entry for new direct block */ + hsize_t dblock_off; /* Direct block offset in heap address space */ + + /* Find indirect block with room for block of correct size */ + if(NULL == (iblock = H5HF_man_iblock_place_dblock(hdr, dxpl_id, min_dblock_size, &iblock_addr, &dblock_entry, &dblock_size))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to locate indirect block with space for direct block") +#ifdef QAK +HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr); +HDfprintf(stderr, "%s: dblock_entry = %Zu\n", FUNC, dblock_entry); +HDfprintf(stderr, "%s: dblock_size = %Zu\n", FUNC, dblock_size); +#endif /* QAK */ + + /* Compute the direct block's offset in the heap's address space */ + dblock_off = iblock->block_off; + dblock_off += hdr->man_dtable.row_block_off[dblock_entry / hdr->man_dtable.cparam.width]; + dblock_off += hdr->man_dtable.row_block_size[dblock_entry / hdr->man_dtable.cparam.width] * (dblock_entry % hdr->man_dtable.cparam.width); + + /* Create new direct block at current location*/ + if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, dblock_entry, dblock_size, dblock_off, &dblock_addr, NULL) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block") + +#ifdef QAK +HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr); +#endif /* QAK */ + + /* Point indirect block at new direct block */ + iblock->ents[dblock_entry].addr = dblock_addr; + + /* Mark indirect block as modified */ + if(H5HF_iblock_dirty(dxpl_id, iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") + + /* Release the indirect block (marked as dirty) */ + if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, H5AC__DIRTIED_FLAG) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_man_dblock_new() */ + diff --git a/src/H5HFdtable.c b/src/H5HFdtable.c new file mode 100644 index 0000000..e571b85 --- /dev/null +++ b/src/H5HFdtable.c @@ -0,0 +1,213 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5HFdtable.c + * Apr 10 2006 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: "Doubling table" routines for fractal heaps. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5HF_PACKAGE /*suppress error about including H5HFpkg */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5HFpkg.h" /* Fractal heaps */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Vprivate.h" /* Vectors and arrays */ + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5HF_dtable_init + * + * Purpose: Initialize values for doubling table + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 6 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_dtable_init(H5HF_dtable_t *dtable) +{ + hsize_t tmp_block_size; /* Temporary block size */ + hsize_t acc_block_off; /* Accumulated block offset */ + size_t u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_dtable_init) + + /* + * Check arguments. + */ + HDassert(dtable); + + /* Compute/cache some values */ + dtable->first_row_bits = H5V_log2_of2(dtable->cparam.start_block_size) + + H5V_log2_of2(dtable->cparam.width); + dtable->max_root_rows = (dtable->cparam.max_index - dtable->first_row_bits) + 1; + dtable->max_direct_rows = (H5V_log2_of2(dtable->cparam.max_direct_size) - + H5V_log2_of2(dtable->cparam.start_block_size)) + 2; + dtable->num_id_first_row = dtable->cparam.start_block_size * dtable->cparam.width; + dtable->max_dir_blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dtable->cparam.max_direct_size); + + /* Build table of block sizes for each row */ + if(NULL == (dtable->row_block_size = H5MM_malloc(dtable->max_root_rows * sizeof(hsize_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create doubling table block size table") + if(NULL == (dtable->row_block_off = H5MM_malloc(dtable->max_root_rows * sizeof(hsize_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create doubling table block offset table") + if(NULL == (dtable->row_dblock_free = H5MM_malloc(dtable->max_root_rows * sizeof(hsize_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create doubling table direct block free space table") + tmp_block_size = dtable->cparam.start_block_size; + acc_block_off = dtable->cparam.start_block_size * dtable->cparam.width; + dtable->row_block_size[0] = dtable->cparam.start_block_size; + dtable->row_block_off[0] = 0; + for(u = 1; u < dtable->max_root_rows; u++) { + dtable->row_block_size[u] = tmp_block_size; + dtable->row_block_off[u] = acc_block_off; + tmp_block_size *= 2; + acc_block_off *= 2; + } /* end for */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_dtable_init() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_dtable_lookup + * + * Purpose: Compute the row & col of an offset in a doubling-table + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 6 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_dtable_lookup(const H5HF_dtable_t *dtable, hsize_t off, unsigned *row, unsigned *col) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_dtable_lookup) + + /* + * Check arguments. + */ + HDassert(dtable); + HDassert(row); + HDassert(col); + + /* Check for offset in first row */ + if(off < dtable->num_id_first_row) { + *row = 0; + *col = off / dtable->cparam.start_block_size; + } /* end if */ + else { + unsigned high_bit = H5V_log2_gen(off); /* Determine the high bit in the offset */ + hsize_t off_mask = 1 << high_bit; /* Compute mask for determining column */ + + *row = (high_bit - dtable->first_row_bits) + 1; + *col = (off - off_mask) / dtable->row_block_size[*row]; + } /* end else */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_dtable_lookup() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_dtable_dest + * + * Purpose: Release information for doubling table + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 27 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_dtable_dest(H5HF_dtable_t *dtable) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_dtable_dest) + + /* + * Check arguments. + */ + HDassert(dtable); + + /* Free the block size lookup table for the doubling table */ + H5MM_xfree(dtable->row_block_size); + + /* Free the block offset lookup table for the doubling table */ + H5MM_xfree(dtable->row_block_off); + + /* Free the direct block free space lookup table for the doubling table */ + H5MM_xfree(dtable->row_dblock_free); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_dtable_dest() */ + diff --git a/src/H5HFhdr.c b/src/H5HFhdr.c new file mode 100644 index 0000000..04d3959 --- /dev/null +++ b/src/H5HFhdr.c @@ -0,0 +1,458 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5HFhdr.c + * Apr 10 2006 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Heap header routines for fractal heaps. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5HF_PACKAGE /*suppress error about including H5HFpkg */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5HFpkg.h" /* Fractal heaps */ +#include "H5Vprivate.h" /* Vectors and arrays */ + +/****************/ +/* Local Macros */ +/****************/ + +/* Limit on the size of the max. direct block size */ +/* (This is limited to 32-bits currently, because I think it's unlikely to + * need to be larger, the 32-bit limit for H5V_log2_of2(n), and + * some offsets/sizes are encoded with a maxiumum of 32-bits - QAK) + */ +#define H5HL_MAX_DIRECT_SIZE_LIMIT ((hsize_t)2 * 1024 * 1024 * 1024) + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_alloc + * + * Purpose: Allocate shared fractal heap header + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 21 2006 + * + *------------------------------------------------------------------------- + */ +H5HF_t * +H5HF_hdr_alloc(H5F_t *f) +{ + H5HF_t *fh = NULL; /* Shared fractal heap header */ + H5HF_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_alloc) + + /* + * Check arguments. + */ + HDassert(f); + + /* Allocate space for the shared information */ + if(NULL == (fh = H5FL_CALLOC(H5HF_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fractal heap shared header") + + /* Set the internal parameters for the heap */ + fh->f = f; + fh->sizeof_size = H5F_SIZEOF_SIZE(f); + fh->sizeof_addr = H5F_SIZEOF_ADDR(f); + + /* Set the return value */ + ret_value = fh; + +done: + if(!ret_value) + if(fh) + (void)H5HF_cache_hdr_dest(f, fh); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_alloc() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_free_space + * + * Purpose: Compute direct block free space, for indirect blocks of + * different sizes. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 21 2006 + * + *------------------------------------------------------------------------- + */ +static hsize_t +H5HF_hdr_compute_free_space(H5HF_t *hdr, hsize_t iblock_size) +{ + hsize_t acc_heap_size; /* Accumumated heap space */ + hsize_t acc_dblock_free; /* Accumumated direct block free space */ + unsigned curr_row; /* Current row in block */ + hsize_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_hdr_compute_free_space) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(iblock_size > hdr->man_dtable.cparam.max_direct_size); + + /* Set the free space in direct blocks */ + acc_heap_size = 0; + acc_dblock_free = 0; + curr_row = 0; + while(acc_heap_size < iblock_size) { + acc_heap_size += hdr->man_dtable.row_block_size[curr_row] * + hdr->man_dtable.cparam.width; + acc_dblock_free += hdr->man_dtable.row_dblock_free[curr_row] * + hdr->man_dtable.cparam.width; + curr_row++; + } /* end while */ + + /* Set return value */ + ret_value = acc_dblock_free; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_compute_free_space() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_finish_init + * + * Purpose: Finish initializing info in shared heap header + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 21 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_finish_init(H5HF_t *hdr) +{ + size_t u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_finish_init) + + /* + * Check arguments. + */ + HDassert(hdr); + + /* Compute/cache some values */ + hdr->heap_off_size = H5HF_SIZEOF_OFFSET_BITS(hdr->man_dtable.cparam.max_index); + if(H5HF_dtable_init(&hdr->man_dtable) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize doubling table info") + + /* Create the free-list structure for the heap */ + if(NULL == (hdr->flist = H5HF_flist_create(hdr->man_dtable.cparam.max_direct_size, H5HF_free_section_free_cb))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize free list info") + + /* Set the size of heap IDs */ + hdr->id_len = hdr->heap_off_size + MIN(hdr->man_dtable.max_dir_blk_off_size, + ((H5V_log2_gen((hsize_t)hdr->standalone_size) + 7) / 8)); + + /* Set the free space in direct blocks */ + for(u = 0; u < hdr->man_dtable.max_root_rows; u++) { + if(u < hdr->man_dtable.max_direct_rows) + hdr->man_dtable.row_dblock_free[u] = hdr->man_dtable.row_block_size[u] - + (H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, hdr->man_dtable.row_block_size[u]) + + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr)); + else + hdr->man_dtable.row_dblock_free[u] = H5HF_hdr_compute_free_space(hdr, hdr->man_dtable.row_block_size[u]); +#ifdef QAK +HDfprintf(stderr, "%s: row_block_size[%Zu] = %Hu\n", FUNC, u, hdr->man_dtable.row_block_size[u]); +HDfprintf(stderr, "%s: row_block_off[%Zu] = %Hu\n", FUNC, u, hdr->man_dtable.row_block_off[u]); +HDfprintf(stderr, "%s: row_dblock_free[%Zu] = %Hu\n", FUNC, u, hdr->man_dtable.row_dblock_free[u]); +#endif /* QAK */ + } /* end for */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_finish_init() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_init + * + * Purpose: Initialize shared fractal heap header for new heap + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 21 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_init(H5HF_t *fh, haddr_t fh_addr, H5HF_create_t *cparam) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_init) + + /* + * Check arguments. + */ + HDassert(fh); + HDassert(cparam); + +#ifndef NDEBUG + /* Check for valid parameters */ + if(!POWER_OF_TWO(cparam->managed.width) || cparam->managed.width == 0) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "width not power of two") + if(!POWER_OF_TWO(cparam->managed.start_block_size) || cparam->managed.start_block_size == 0) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "starting block size not power of two") + if(!POWER_OF_TWO(cparam->managed.max_direct_size) || + (cparam->managed.max_direct_size == 0 || cparam->managed.max_direct_size > H5HL_MAX_DIRECT_SIZE_LIMIT)) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. direct block size not power of two") + if(cparam->managed.max_direct_size < cparam->standalone_size) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. direct block size not large enough to hold all managed blocks") + if(cparam->managed.max_index > (8 * fh->sizeof_size) || cparam->managed.max_index == 0) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. direct block size not power of two") +#endif /* NDEBUG */ + + /* Set the creation parameters for the heap */ + fh->heap_addr = fh_addr; + fh->addrmap = cparam->addrmap; + fh->standalone_size = cparam->standalone_size; + HDmemcpy(&(fh->man_dtable.cparam), &(cparam->managed), sizeof(H5HF_dtable_cparam_t)); + + /* Set root table address */ + fh->man_dtable.table_addr = HADDR_UNDEF; + + /* Note that the shared info is dirty (it's not written to the file yet) */ + fh->dirty = TRUE; + + /* Make shared heap info reference counted */ + if(H5HF_hdr_finish_init(fh) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for shared fractal heap header") + +done: + if(ret_value < 0) + if(fh) + (void)H5HF_cache_hdr_dest(NULL, fh); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_init() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_incr + * + * Purpose: Increment reference count on shared heap header + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 27 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_incr(H5HF_t *hdr) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_hdr_incr) + + /* Sanity check */ + HDassert(hdr); + +/* XXX: When "un-evictable" feature is finished, mark the header as + * unevictable on the first block to share it. - QAK + */ + + /* Increment reference count on shared header */ + hdr->rc++; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_hdr_incr() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_decr + * + * Purpose: Decrement reference count on shared heap header + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 27 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_decr(H5HF_t *hdr) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_hdr_decr) + + /* Sanity check */ + HDassert(hdr); + + /* Decrement reference count on shared header */ + hdr->rc--; + +/* XXX: When "un-evictable" feature is finished, mark the header as + * evictable when the ref. count drops to zero. - QAK + */ +/* XXX: Take this call out after "un-evictable" flag is working */ + H5HF_cache_hdr_dest_real(hdr); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_hdr_decr() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_dirty + * + * Purpose: Mark heap header as dirty + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 27 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_dirty(hid_t dxpl_id, H5HF_t *hdr) +{ + H5HF_t *tmp_hdr; /* Temporary pointer to heap header */ + hbool_t is_protected; /* Whether the indirect block is protected */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_dirty) +#ifdef QAK +HDfprintf(stderr, "%s: Marking heap header as dirty\n", FUNC); +#endif /* QAK */ + + /* Sanity check */ + HDassert(hdr); + +/* XXX: When "un-evictable" feature is finished, just mark the header as dirty + * in the cache, instead of this protect -> unprotect kludge - QAK + */ + /* Protect the header */ + is_protected = hdr->cache_info.is_protected; + if(!is_protected) { +#ifdef QAK +HDfprintf(stderr, "%s: hdr->heap_addr = %a\n", FUNC, hdr->heap_addr); +#endif /* QAK */ + if(NULL == (tmp_hdr = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_HDR, hdr->heap_addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") + HDassert(hdr == tmp_hdr); + } /* end if */ + + /* Set the dirty flags for the heap header */ + hdr->dirty = TRUE; + + /* Release the heap header (marked as dirty) */ + if(!is_protected) { + if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_HDR, hdr->heap_addr, tmp_hdr, H5AC__DIRTIED_FLAG) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_dirty() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_extend_heap + * + * Purpose: Extend heap to cover more space + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Apr 10 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_extend_heap(H5HF_t *hdr, hsize_t new_size, hsize_t extra_free) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_hdr_extend_heap) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(new_size >= hdr->total_size); + + /* Set the total space in heap */ + hdr->total_size = new_size; + hdr->man_size = new_size; + + /* Increment the free space in direct blocks */ + hdr->total_man_free += extra_free; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_hdr_extend_heap() */ + diff --git a/src/H5HFiblock.c b/src/H5HFiblock.c new file mode 100644 index 0000000..1ecaa9a --- /dev/null +++ b/src/H5HFiblock.c @@ -0,0 +1,1410 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5HFiblock.c + * Apr 10 2006 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Indirect block routines for fractal heaps. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5HF_PACKAGE /*suppress error about including H5HFpkg */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5HFpkg.h" /* Fractal heaps */ +#include "H5MFprivate.h" /* File memory management */ +#include "H5Vprivate.h" /* Vectors and arrays */ + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + +/* Indirect block routines */ +static herr_t H5HF_man_iblock_inc_loc(H5HF_indirect_t *iblock); +static herr_t H5HF_man_iblock_skip_blocks(H5HF_t *hdr, + H5HF_indirect_t *iblock, haddr_t iblock_addr, + unsigned start_entry, unsigned nentries); +static herr_t H5HF_man_iblock_skip_ranges(H5HF_t *hdr, + H5HF_indirect_t *iblock, haddr_t iblock_addr, + unsigned start_entry, unsigned nentries); +static herr_t H5HF_man_iblock_create(H5HF_t *fh, hid_t dxpl_id, + hsize_t block_off, unsigned nrows, unsigned max_rows, haddr_t *addr_p); + +/*********************/ +/* Package Variables */ +/*********************/ + +/* 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_ent_t sequence information */ +H5FL_SEQ_DEFINE(H5HF_indirect_ent_t); + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5HF_man_iblock_inc_loc + * + * Purpose: Increment location of next direct block in indirect block + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 14 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_man_iblock_inc_loc(H5HF_indirect_t *iblock) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_inc_loc) + + /* + * Check arguments. + */ + HDassert(iblock); + + /* Increment block entry */ + iblock->next_entry++; + + /* Increment column */ + iblock->next_col++; + + /* Check for walking off end of column */ + if(iblock->next_col == iblock->shared->man_dtable.cparam.width) { + /* Reset column */ + iblock->next_col = 0; + + /* Increment row & block size */ + iblock->next_row++; + if(iblock->next_row > 1) + iblock->next_size *= 2; + + /* 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 */ + if(H5HF_man_iblock_inc_loc(iblock->parent) < 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_row = %u\n", FUNC, iblock->next_row); +HDfprintf(stderr, "%s: iblock->next_col = %u\n", FUNC, iblock->next_col); +HDfprintf(stderr, "%s: iblock->next_entry = %u\n", FUNC, iblock->next_entry); +HDfprintf(stderr, "%s: iblock->next_size = %Zu\n", FUNC, iblock->next_size); +#endif /* QAK */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_man_iblock_inc_loc() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_iblock_incr + * + * Purpose: Increment reference count on shared indirect block + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 27 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_iblock_incr(H5HF_indirect_t *iblock) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_iblock_incr) + + /* Sanity check */ + HDassert(iblock); + +/* XXX: When "un-evictable" feature is finished, mark the block as + * unevictable on the first block to share it. - QAK + */ + + /* Increment reference count on shared indirect block */ + iblock->rc++; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_iblock_incr() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_iblock_decr + * + * Purpose: Decrement reference count on shared indirect block + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 27 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_iblock_decr(H5HF_indirect_t *iblock) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_iblock_decr) + + /* Sanity check */ + HDassert(iblock); + + /* Decrement reference count on shared indirect block */ + iblock->rc--; + +/* XXX: When "un-evictable" feature is finished, mark the block as + * evictable when the ref. count drops to zero. - QAK + */ +/* XXX: Take this call out after "un-evictable" flag is working */ + H5HF_cache_iblock_dest_real(iblock); + + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_iblock_decr() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_iblock_dirty + * + * Purpose: Mark indirect block as dirty + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 21 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_iblock_dirty(hid_t dxpl_id, H5HF_indirect_t *iblock) +{ + H5HF_indirect_t *tmp_iblock; /* Temporary pointer to indirect block */ + hbool_t is_protected; /* Whether the indirect block is protected */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_iblock_dirty) +#ifdef QAK +HDfprintf(stderr, "%s: Marking indirect block as dirty\n", FUNC); +#endif /* QAK */ + + /* Sanity check */ + HDassert(iblock); + +/* XXX: When "un-evictable" feature is finished, just mark the block as dirty + * in the cache, instead of this protect -> unprotect kludge - QAK + */ + /* Protect the indirect block */ + is_protected = iblock->cache_info.is_protected; + if(!is_protected) { +#ifdef QAK +HDfprintf(stderr, "%s: iblock->addr = %a\n", FUNC, iblock->addr); +#endif /* QAK */ + if(NULL == (tmp_iblock = H5AC_protect(iblock->shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, &iblock->nrows, iblock->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") + HDassert(iblock == tmp_iblock); + } /* end if */ + + /* Set the dirty flags for the indirect block */ + iblock->dirty = TRUE; + + /* Release the indirect block (marked as dirty) */ + if(!is_protected) { + if(H5AC_unprotect(iblock->shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, tmp_iblock, H5AC__DIRTIED_FLAG) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_iblock_dirty() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_man_iblock_skip_blocks + * + * Purpose: Add skipped direct blocks to free space for heap + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Apr 3 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_man_iblock_skip_blocks(H5HF_t *hdr, H5HF_indirect_t *iblock, + haddr_t iblock_addr, unsigned start_entry, unsigned nentries) +{ + H5HF_free_section_t *sec_node; /* Pointer to free list section for range */ + hsize_t sect_off; /* Offset of free section in heap */ + unsigned curr_row; /* Current row in indirect block */ + unsigned curr_col; /* Current column in indirect block */ + unsigned u; /* Local index variables */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_skip_blocks) +#ifdef QAK +HDfprintf(stderr, "%s: start_entry = %u, nentries = %u\n", FUNC, start_entry, nentries); +#endif /* QAK */ + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(iblock); + HDassert(H5F_addr_defined(iblock_addr)); + + /* Compute starting column & row */ + curr_row = start_entry / hdr->man_dtable.cparam.width; + curr_col = start_entry % hdr->man_dtable.cparam.width; + + /* Initialize information for rows skipped over */ + sect_off = iblock->block_off; + for(u = 0; u < curr_row; u++) + sect_off += hdr->man_dtable.row_block_size[u] * hdr->man_dtable.cparam.width; + for(u = 0; u < curr_col; u++) + sect_off += hdr->man_dtable.row_block_size[curr_row]; +#ifdef QAK +HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off); +#endif /* QAK */ + + /* Loop over the blocks to skip */ + for(u = start_entry; u < (start_entry + nentries); /* u is advanced in loop */) { + unsigned row_entries; /* Number of entries in a particular row */ + + /* Compute number of entries in (possible partial) current row */ + row_entries = MIN(hdr->man_dtable.cparam.width - curr_col, (start_entry + nentries) - u); +#ifdef QAK +HDfprintf(stderr, "%s: u = %u\n", FUNC, u); +HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row); +HDfprintf(stderr, "%s: row_entries = %u, hdr->man_dtable.row_dblock_free[%u] = %Hu\n", FUNC, row_entries, curr_row, hdr->man_dtable.row_dblock_free[curr_row]); +#endif /* QAK */ + + /* Add free space section for blocks in this row */ + + /* Create free list section node for blocks skipped over */ + if(NULL == (sec_node = H5FL_MALLOC(H5HF_free_section_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") + + /* Set section's information */ + sec_node->sect_addr = sect_off; + sec_node->sect_size = hdr->man_dtable.row_dblock_free[curr_row]; + sec_node->type = H5HF_SECT_RANGE; + sec_node->u.range.iblock_addr = iblock_addr; + sec_node->u.range.iblock_nrows = iblock->nrows; + sec_node->u.range.row = curr_row; + sec_node->u.range.col = curr_col; + sec_node->u.range.num_entries = row_entries; + + /* Add new free space to the global list of space */ + if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list") + + /* Advance row & column position */ + sect_off += row_entries * hdr->man_dtable.row_block_size[curr_row]; + curr_row++; + curr_col = 0; /* (first partial row aligns this) */ + u += row_entries; + } /* end for */ + + /* Re-compute row information for next empty block */ +#ifdef QAK +HDfprintf(stderr, "%s: u = %u\n", FUNC, u); +#endif /* QAK */ + curr_row = u / hdr->man_dtable.cparam.width; +#ifdef QAK +HDfprintf(stderr, "%s: curr_row = %u\n", FUNC, curr_row); +#endif /* QAK */ + + /* Set indirect block's "next entry" information */ + iblock->next_col = 0; + iblock->next_row = curr_row; + iblock->next_size = hdr->man_dtable.row_block_size[curr_row]; + iblock->next_entry = u; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_man_iblock_skip_blocks() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_man_iblock_skip_ranges + * + * Purpose: Add skipped indirect ranges to free space for heap + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Apr 4 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_man_iblock_skip_ranges(H5HF_t *hdr, H5HF_indirect_t *iblock, + haddr_t iblock_addr, unsigned start_entry, unsigned nentries) +{ + H5HF_free_section_t *sec_node; /* Pointer to free list section for range */ + hsize_t sect_off; /* Offset of free section in heap */ + size_t row_dblock_free_space; /* Size of free space for row of direct blocks in a row */ + size_t acc_row_dblock_free_space; /* Accumulated size of free space for row of direct blocks in a row */ + unsigned curr_row; /* Current row in indirect block */ + unsigned curr_col; /* Current column in indirect block */ + unsigned u, w; /* Local index variables */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_skip_ranges) +#ifdef QAK +HDfprintf(stderr, "%s: start_entry = %u, nentries = %u\n", FUNC, start_entry, nentries); +#endif /* QAK */ + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(iblock); + HDassert(H5F_addr_defined(iblock_addr)); + + /* Compute starting column & row */ + curr_row = start_entry / hdr->man_dtable.cparam.width; + curr_col = start_entry % hdr->man_dtable.cparam.width; + + /* Initialize information for rows skipped over */ + sect_off = iblock->block_off; + for(u = 0; u < curr_row; u++) + sect_off += hdr->man_dtable.row_block_size[u] * hdr->man_dtable.cparam.width; + for(u = 0; u < curr_col; u++) + sect_off += hdr->man_dtable.row_block_size[curr_row]; +#ifdef QAK +HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off); +#endif /* QAK */ + + /* Loop over the blocks to skip */ + for(u = start_entry; u < (start_entry + nentries); /* u is advanced in inner loop */) { + unsigned row_entries; /* Number of entries in a particular row */ + unsigned num_rows; /* Number of rows in indirect blocks referenced */ + + /* Compute number of rows in indirect blocks covered by entry */ + num_rows = (H5V_log2_of2((uint32_t)hdr->man_dtable.row_block_size[curr_row]) - + H5V_log2_of2(hdr->man_dtable.cparam.start_block_size)) - 1; + + /* Compute number of entries in (possible partial) current row */ + row_entries = MIN(hdr->man_dtable.cparam.width - curr_col, (start_entry + nentries) - u); +#ifdef QAK +HDfprintf(stderr, "%s: u = %u\n", FUNC, u); +HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row); +HDfprintf(stderr, "%s: row_entries = %u, num_rows = %u\n", FUNC, row_entries, num_rows); +#endif /* QAK */ + + /* Loop over rows in indirect blocks covered */ + acc_row_dblock_free_space = 0; + for(w = 0; w < num_rows; w++) { + + /* Compute free space in direct blocks for this row */ + row_dblock_free_space = hdr->man_dtable.cparam.width * hdr->man_dtable.row_dblock_free[w]; + acc_row_dblock_free_space += row_dblock_free_space; +#ifdef QAK +HDfprintf(stderr, "%s: w = %u\n", FUNC, w); +HDfprintf(stderr, "%s: hdr->man_dtable.row_dblock_free[%u] = %Zu\n", FUNC, w, hdr->man_dtable.row_dblock_free[w]); +#endif /* QAK */ + + /* Add "indirect" free space section for blocks in this row */ + + /* Create free list section node for blocks skipped over */ + if(NULL == (sec_node = H5FL_MALLOC(H5HF_free_section_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") + + /* Set section's information */ + sec_node->sect_addr = sect_off + hdr->man_dtable.row_block_off[w]; +#ifdef QAK +HDfprintf(stderr, "%s: sec_node->sect_addr = %a\n", FUNC, sec_node->sect_addr); +#endif /* QAK */ + sec_node->sect_size = hdr->man_dtable.row_dblock_free[w]; + sec_node->type = H5HF_SECT_INDIRECT; + sec_node->u.indirect.iblock_addr = iblock_addr; + sec_node->u.indirect.iblock_nrows = iblock->nrows; + sec_node->u.indirect.row = curr_row; + sec_node->u.indirect.col = curr_col; + sec_node->u.indirect.num_entries = row_entries; + sec_node->u.indirect.indir_row = w; + sec_node->u.indirect.indir_nrows = num_rows; + + /* Add new free space to the global list of space */ + if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list") + } /* end for */ +#ifdef QAK +HDfprintf(stderr, "%s: acc_row_dblock_free_space = %Zu\n", FUNC, acc_row_dblock_free_space); +#endif /* QAK */ + + /* Advance row & column position */ + sect_off += row_entries * hdr->man_dtable.row_block_size[curr_row]; + curr_row++; + curr_col = 0; /* (first partial row aligns this) */ + u += row_entries; + } /* end for */ + + /* Re-compute row information for next empty block */ +#ifdef QAK +HDfprintf(stderr, "%s: u = %u\n", FUNC, u); +#endif /* QAK */ + curr_row = u / hdr->man_dtable.cparam.width; +#ifdef QAK +HDfprintf(stderr, "%s: curr_row = %u\n", FUNC, curr_row); +#endif /* QAK */ + + /* Set indirect block's "next entry" information */ + iblock->next_col = 0; + iblock->next_row = curr_row; + iblock->next_size = hdr->man_dtable.row_block_size[curr_row]; + iblock->next_entry = u; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_man_iblock_skip_ranges() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_man_iblock_place_dblock + * + * Purpose: Find indirect block with location for placing a direct block + * + * Note: Creates necessary indirect blocks + * + * Return: Pointer to indirect block on success, NULL on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 14 2006 + * + *------------------------------------------------------------------------- + */ +H5HF_indirect_t * +H5HF_man_iblock_place_dblock(H5HF_t *hdr, hid_t dxpl_id, size_t min_dblock_size, + haddr_t *addr_p, size_t *entry_p, size_t *dblock_size) +{ + 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) +#ifdef QAK +HDfprintf(stderr, "%s: min_dblock_size = %Zu\n", FUNC, min_dblock_size); +#endif /* QAK */ + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(min_dblock_size > 0); + HDassert(addr_p); + + /* Check for creating first indirect block */ + if(hdr->man_dtable.curr_root_rows == 0) { + H5HF_direct_t *dblock; /* Pointer to direct block to query */ + hsize_t acc_dblock_free; /* Accumulated free space in direct blocks */ + hbool_t have_direct_block; /* Flag to indicate a direct block already exists */ + unsigned nrows; /* Number of rows for root indirect block */ + unsigned u; /* Local index variable */ + +#ifdef QAK +HDfprintf(stderr, "%s: creating first indirect block\n", FUNC); +#endif /* QAK */ + /* Check for allocating entire root indirect block initially */ + if(hdr->man_dtable.cparam.start_root_rows == 0) + nrows = hdr->man_dtable.max_root_rows; + else { + unsigned rows_needed; /* Number of rows needed to get to direct block size */ + unsigned block_row_off; /* Row offset from larger block sizes */ + + nrows = hdr->man_dtable.cparam.start_root_rows; + + block_row_off = H5V_log2_of2(min_dblock_size) - H5V_log2_of2(hdr->man_dtable.cparam.start_block_size); + if(block_row_off > 0) + block_row_off++; /* Account for the pair of initial rows of the initial block size */ + rows_needed = 1 + block_row_off; + if(nrows < rows_needed) + nrows = rows_needed; + } /* end else */ +#ifdef QAK +HDfprintf(stderr, "%s: nrows = %u\n", FUNC, nrows); +#endif /* QAK */ + + /* Allocate root indirect block */ + if(H5HF_man_iblock_create(hdr, dxpl_id, (hsize_t)0, nrows, hdr->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: iblock_addr = %a\n", FUNC, iblock_addr); +#endif /* QAK */ + + /* Move current direct block (used as root) into new indirect block */ + + /* Lock new indirect block */ + if(NULL == (iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &nrows, hdr, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") + + /* Check if there's already a direct block as root) */ + have_direct_block = H5F_addr_defined(hdr->man_dtable.table_addr); +#ifdef QAK +HDfprintf(stderr, "%s: have_direct_block = %u\n", FUNC, (unsigned)have_direct_block); +#endif /* QAK */ + if(have_direct_block) { + /* Lock first (root) direct block */ + if(NULL == (dblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, hdr->man_dtable.table_addr, &hdr->man_dtable.cparam.start_block_size, hdr, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap direct block") + + /* Point indirect block at direct block to add */ + iblock->child_free_space += (hssize_t)(dblock->blk_free_space - iblock->ents[0].free_space); + iblock->ents[0].addr = hdr->man_dtable.table_addr; + iblock->ents[0].free_space = dblock->blk_free_space; + + /* Make direct block share parent indirect block */ + dblock->parent = iblock; + dblock->par_entry = 0; + dblock->par_addr = iblock->addr; + dblock->par_nrows = iblock->nrows; + if(H5HF_iblock_incr(iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block") + + /* Unlock first (root) direct block */ + if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, hdr->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; + + /* Increment size of next block from this indirect block */ + /* (account for the already existing direct block */ + if(H5HF_man_iblock_inc_loc(iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't advance fractal heap block location") + } /* end if */ + + /* Check for skipping over direct blocks, in order to get to large enough block */ + if(min_dblock_size > iblock->next_size) { + /* Add skipped blocks to heap's free space */ + if(H5HF_man_iblock_skip_blocks(hdr, iblock, iblock_addr, + have_direct_block, ((nrows - 1) * hdr->man_dtable.cparam.width) - have_direct_block) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, NULL, "can't add skipped blocks to heap's free space") + HDassert(iblock->next_size == min_dblock_size); + } /* end if */ + + /* Mark indirect block as modified */ + if(H5HF_iblock_dirty(dxpl_id, iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, NULL, "can't mark indirect block as dirty") + + /* Point heap header at new indirect block */ + hdr->man_dtable.curr_root_rows = nrows; + hdr->man_dtable.table_addr = iblock_addr; + + /* Compute free space in direct blocks referenced from entries in root indirect block */ + acc_dblock_free = 0; + for(u = 0; u < nrows; u++) + acc_dblock_free += hdr->man_dtable.row_dblock_free[u] * hdr->man_dtable.cparam.width; + + /* Account for potential initial direct block */ + if(have_direct_block) + acc_dblock_free -= hdr->man_dtable.row_dblock_free[0]; + + /* Extend heap to cover new root indirect block */ + if(H5HF_hdr_extend_heap(hdr, hdr->man_dtable.row_block_off[nrows], acc_dblock_free) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, NULL, "can't increase space to cover root direct block") + + /* Mark heap header as modified */ + hdr->dirty = TRUE; + } /* end if */ + else { +#ifdef QAK +HDfprintf(stderr, "%s: searching root indirect block\n", FUNC); +#endif /* QAK */ + + /* Lock root indirect block */ + iblock_addr = hdr->man_dtable.table_addr; + if(NULL == (iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &hdr->man_dtable.curr_root_rows, hdr, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") + +#ifdef QAK +HDfprintf(stderr, "%s: iblock->next_row = %u, iblock->nrows = %u\n", FUNC, iblock->next_row, iblock->nrows); +HDfprintf(stderr, "%s: iblock->next_size = %Zu\n", FUNC, iblock->next_size); +#endif /* QAK */ + /* Check if we need a block past current allocation */ + /* (i.e. extend the root indirect block) */ + if(iblock->next_row == iblock->nrows || + /* Don't try to extend the root indirect block if the requested + * direct block is too large, but the + * next direct block is in a child indirect block. + */ + (iblock->nrows < hdr->man_dtable.max_direct_rows && + min_dblock_size > iblock->next_size)) { + haddr_t new_addr; /* New address of indirect block */ + hsize_t acc_dblock_free; /* Accumulated free space in direct blocks */ + unsigned old_next_entry; /* The previous value of the "next entry" for the indirect block */ + unsigned min_nrows = 0; /* Min. # of direct rows */ + unsigned old_nrows; /* Old # of rows */ + unsigned new_nrows; /* New # of rows */ + size_t u; /* Local index variable */ + +#ifdef QAK +HDfprintf(stderr, "%s: Extending root indirect block\n", FUNC); +#endif /* QAK */ + + /* Keep this for later */ + old_next_entry = iblock->next_entry; + old_nrows = iblock->nrows; + + /* Check for skipping over rows */ + if(iblock->nrows < hdr->man_dtable.max_direct_rows && min_dblock_size > iblock->next_size) { + /* Sanity check */ + HDassert(min_dblock_size > hdr->man_dtable.cparam.start_block_size); + + /* Make certain we allocate at least the required row for the block requested */ + min_nrows = 2 + (H5V_log2_of2(min_dblock_size) - H5V_log2_of2(hdr->man_dtable.cparam.start_block_size)); + + /* Set the information for the next block, of the appropriate size */ + iblock->next_entry = (min_nrows - 1) * hdr->man_dtable.cparam.width; + } /* end if */ + /* Check for special case of second row, which has blocks the same size as first row */ + else if(iblock->next_row == 1) + iblock->next_size = hdr->man_dtable.cparam.start_block_size; + + /* Compute new # of rows in indirect block */ + new_nrows = MAX(min_nrows, MIN(2 * iblock->nrows, iblock->max_rows)); +#ifdef QAK +HDfprintf(stderr, "%s: min_nrows = %u, new_nrows = %u\n", FUNC, min_nrows, new_nrows); +HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows); +HDfprintf(stderr, "%s: old_next_entry = %u, iblock->next_entry = %u\n", FUNC, old_next_entry, iblock->next_entry); +#endif /* QAK */ + +/* Currently, the old block 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 also keeps the file smaller, 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 */ + if(H5MF_xfree(hdr->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->nrows = new_nrows; + iblock->size = H5HF_MAN_INDIRECT_SIZE(hdr, iblock); + + /* Allocate space for the new indirect block on disk */ + if(HADDR_UNDEF == (new_addr = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, (hsize_t)iblock->size))) + HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, NULL, "file allocation failed for fractal heap indirect block") +#ifdef QAK +HDfprintf(stderr, "%s: new_addr = %a\n", FUNC, new_addr); +#endif /* QAK */ + + /* Re-allocate direct block entry table */ + if(NULL == (iblock->ents = H5FL_SEQ_REALLOC(H5HF_indirect_ent_t, iblock->ents, (iblock->nrows * hdr->man_dtable.cparam.width)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for direct entries") + + /* Check for skipping over rows and add free section for skipped rows */ + if(iblock->nrows < hdr->man_dtable.max_direct_rows && min_dblock_size > iblock->next_size) { + /* Add skipped blocks to heap's free space */ + if(H5HF_man_iblock_skip_blocks(hdr, iblock, new_addr, + old_next_entry, (iblock->next_entry - old_next_entry)) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, NULL, "can't add skipped blocks to heap's free space") + HDassert(iblock->next_size == min_dblock_size); + } /* end if */ + + /* Initialize new direct block entries in rows added */ + acc_dblock_free = 0; + for(u = (old_nrows * hdr->man_dtable.cparam.width); u < (iblock->nrows * hdr->man_dtable.cparam.width); u++) { + unsigned row = u / hdr->man_dtable.cparam.width; /* Row for current entry */ + + iblock->ents[u].addr = HADDR_UNDEF; + iblock->ents[u].free_space = hdr->man_dtable.row_dblock_free[row]; + iblock->child_free_space += iblock->ents[u].free_space; + acc_dblock_free += iblock->ents[u].free_space; + } /* end for */ + + /* Mark indirect block as dirty */ + if(H5HF_iblock_dirty(dxpl_id, iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, NULL, "can't mark indirect block as dirty") + + /* Release the indirect block (marked as dirty) */ + if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, H5AC__DIRTIED_FLAG) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release fractal heap indirect block") + iblock = NULL; + + /* Move object in cache */ + if(H5AC_rename(hdr->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 */ + hdr->man_dtable.curr_root_rows = new_nrows; + hdr->man_dtable.table_addr = iblock_addr = new_addr; + + /* Extend heap to cover new root indirect block */ +#ifdef QAK +HDfprintf(stderr, "%s: hdr->man_dtable.row_block_off[new_nrows - 1] = %Hu\n", FUNC, hdr->man_dtable.row_block_off[new_nrows - 1]); +HDfprintf(stderr, "%s: hdr->man_dtable.row_block_off[new_nrows] = %Hu\n", FUNC, hdr->man_dtable.row_block_off[new_nrows]); +HDfprintf(stderr, "%s: acc_dblock_free = %Hu\n", FUNC, acc_dblock_free); +#endif /* QAK */ + if(H5HF_hdr_extend_heap(hdr, 2 * hdr->man_dtable.row_block_off[new_nrows - 1], acc_dblock_free) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, NULL, "can't increase space to cover root direct block") + + /* Mark heap header as modified */ + hdr->dirty = TRUE; + + /* Lock root indirect block (again) */ + if(NULL == (iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &hdr->man_dtable.curr_root_rows, hdr, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") + iblock->addr = iblock_addr; + } /* end if */ + +#ifdef QAK +HDfprintf(stderr, "%s: Check 1.0\n", FUNC); +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 >= hdr->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 indirect block */ + unsigned nrows; /* Number of rows in new indirect block */ + + /* Compute # of rows in child indirect block */ + nrows = (H5V_log2_of2((uint32_t)iblock->next_size) - hdr->man_dtable.first_row_bits) + 1; +#ifdef QAK +HDfprintf(stderr, "%s: Check 2.0\n", FUNC); +HDfprintf(stderr, "%s: iblock->next_size = %Hu, nrows = %u\n", FUNC, iblock->next_size, nrows); +HDfprintf(stderr, "%s: iblock->next_entry = %u\n", FUNC, iblock->next_entry); +HDfprintf(stderr, "%s: iblock->next_row = %u\n", FUNC, iblock->next_row); +HDfprintf(stderr, "%s: iblock->max_rows = %u\n", FUNC, iblock->max_rows); +#endif /* QAK */ + + /* Check for skipping over indirect block rows */ + if(hdr->man_dtable.row_block_size[nrows - 1] < min_dblock_size) { + unsigned child_rows_needed; /* Number of rows needed to hold direct block */ + + /* Compute # of rows needed in child indirect block */ + child_rows_needed = (H5V_log2_of2(min_dblock_size) - H5V_log2_of2(hdr->man_dtable.cparam.start_block_size)) + 2; + HDassert(child_rows_needed > nrows); +#ifdef QAK +HDfprintf(stderr, "%s: child_rows_needed = %u\n", FUNC, child_rows_needed); +#endif /* QAK */ + + /* Add skipped indirect ranges to heap's free space */ + if(H5HF_man_iblock_skip_ranges(hdr, iblock, iblock->addr, iblock->next_entry, (child_rows_needed - nrows) * hdr->man_dtable.cparam.width) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, NULL, "can't add skipped blocks to heap's free space") + + /* Update the number of rows in requested child indirect block */ + nrows = child_rows_needed; +#ifdef QAK +HDfprintf(stderr, "%s: (new) nrows = %u\n", FUNC, nrows); +#endif /* QAK */ + } /* end if */ +#ifdef QAK +HDfprintf(stderr, "%s: iblock->next_size = %Hu, nrows = %u\n", FUNC, iblock->next_size, nrows); +HDfprintf(stderr, "%s: iblock->next_entry = %u\n", FUNC, iblock->next_entry); +HDfprintf(stderr, "%s: iblock->next_row = %u\n", FUNC, iblock->next_row); +HDfprintf(stderr, "%s: iblock->max_rows = %u\n", FUNC, iblock->max_rows); +#endif /* QAK */ + + /* Check for walking off indirect block rows */ + if(iblock->next_row >= iblock->max_rows) { +#ifdef QAK +HDfprintf(stderr, "%s: iblock->parent->nrows = %u\n", FUNC, iblock->parent->nrows); +HDfprintf(stderr, "%s: iblock->parent->next_entry = %u\n", FUNC, iblock->parent->next_entry); +HDfprintf(stderr, "%s: iblock->parent->next_size = %Hu\n", FUNC, iblock->parent->next_size); +HDfprintf(stderr, "%s: iblock->parent->next_row = %u\n", FUNC, iblock->parent->next_row); +HDfprintf(stderr, "%s: iblock->parent->next_col = %u\n", FUNC, iblock->parent->next_col); +#endif /* QAK */ + /* Locate parent indirect block */ + new_iblock_addr = iblock->parent->addr; + nrows = iblock->parent->nrows; + + /* Lock parent indirect block */ + if(NULL == (new_iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, new_iblock_addr, &nrows, hdr, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") + + /* Advance location in parent lock */ + if(H5HF_man_iblock_inc_loc(new_iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't advance fractal heap block location") + } /* end if */ + else { + /* Check for allocating new indirect block */ + if(!H5F_addr_defined(iblock->ents[iblock->next_entry].addr)) { + hsize_t new_iblock_off; /* Direct block offset in heap address space */ +#ifdef QAK + HDfprintf(stderr, "%s: Allocating new indirect block\n", FUNC); +#endif /* QAK */ + /* Compute the direct block's offset in the heap's address space */ + new_iblock_off = iblock->block_off; + new_iblock_off += hdr->man_dtable.row_block_off[iblock->next_entry / hdr->man_dtable.cparam.width]; + new_iblock_off += hdr->man_dtable.row_block_size[iblock->next_entry / hdr->man_dtable.cparam.width] * (iblock->next_entry % hdr->man_dtable.cparam.width); + + /* Allocate new indirect block */ + if(H5HF_man_iblock_create(hdr, dxpl_id, new_iblock_off, nrows, nrows, &new_iblock_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate fractal heap indirect block") + + /* Lock new indirect block */ + if(NULL == (new_iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, new_iblock_addr, &nrows, hdr, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") + + /* Set parent information */ + HDassert(new_iblock->parent == NULL); + new_iblock->parent = iblock; + new_iblock->par_entry = iblock->next_entry; + new_iblock->par_nrows = iblock->nrows; + new_iblock->par_addr = iblock->addr; + if(H5HF_iblock_incr(iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block") + + /* Point current indirect block at new indirect block */ + iblock->ents[iblock->next_entry].addr = new_iblock_addr; +#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 */ + + /* Check for skipping over rows and add free section for skipped rows */ + if(min_dblock_size > new_iblock->next_size) { + unsigned new_entry; /* Entry of direct block which is large enough */ + + /* Compute entry for direct block size requested */ + new_entry = hdr->man_dtable.cparam.width * + (1 + (H5V_log2_of2(min_dblock_size) - H5V_log2_of2(hdr->man_dtable.cparam.start_block_size))); +#ifdef QAK + HDfprintf(stderr, "%s: new_entry = %u\n", FUNC, new_entry); +#endif /* QAK */ + + /* Add skipped blocks to heap's free space */ + if(H5HF_man_iblock_skip_blocks(hdr, new_iblock, new_iblock->addr, 0, new_entry) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, NULL, "can't add skipped blocks to heap's free space") + HDassert(new_iblock->next_size == min_dblock_size); + } /* end if */ + + /* Mark current indirect block as modified */ + if(H5HF_iblock_dirty(dxpl_id, iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, NULL, "can't mark indirect block as dirty") + + /* Set dirty flag for the current indirect block */ + 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 */ + if(NULL == (new_iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, new_iblock_addr, &nrows, hdr, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") + } /* end else */ + } /* end else */ +#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 */ + + /* Release the current indirect block (possibly marked as dirty) */ + if(H5AC_unprotect(hdr->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, iblock->next_size = %Zu\n", FUNC, iblock->next_size); +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; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_man_iblock_place_dblock() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_man_iblock_alloc_range + * + * Purpose: Allocate a "single" section for an object, out of a "range" + * section + * + * Note: Creates necessary direct & indirect blocks + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 28 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_man_iblock_alloc_range(H5HF_t *hdr, hid_t dxpl_id, + H5HF_free_section_t **sec_node, size_t obj_size) +{ + H5HF_indirect_t *iblock; /* Pointer to indirect block */ + haddr_t iblock_addr; /* Indirect block's address */ + haddr_t dblock_addr; /* Direct block's address */ + unsigned iblock_nrows; /* Indirect block's number of rows */ + H5HF_free_section_t *dblock_sec_node = NULL; /* Pointer to direct block's section node */ + H5HF_free_section_t *old_sec_node = *sec_node; /* Pointer to old section node */ + size_t full_obj_size; /* Size of object including metadata */ + unsigned cur_entry; /* Current entry in indirect block */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_alloc_range) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(sec_node && *sec_node); + HDassert(obj_size > 0); + + /* Compute info about range */ + cur_entry = (old_sec_node->u.range.row * hdr->man_dtable.cparam.width) + old_sec_node->u.range.col; + + /* Check for range covering indirect blocks */ + if(old_sec_node->u.range.row >= hdr->man_dtable.max_direct_rows) { +HDfprintf(stderr, "%s: Can't handle range sections over indirect blocks yet\n", FUNC); +HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'range' free space sections over indirect blocks not supported yet") + } /* end if */ + + /* Get information about indirect block covering section */ + /* (Allow for root indirect block being resized) */ + iblock_addr = old_sec_node->u.range.iblock_addr; + if(H5F_addr_eq(iblock_addr, hdr->man_dtable.table_addr)) + iblock_nrows = hdr->man_dtable.curr_root_rows; + else + iblock_nrows = old_sec_node->u.range.iblock_nrows; + + /* Get a pointer to the indirect block covering the range */ + if(NULL == (iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &iblock_nrows, hdr, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") + + /* Compute size of object, with metadata overhead */ + full_obj_size = obj_size + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr); + +#ifdef QAK +HDfprintf(stderr, "%s: cur_entry = %u\n", FUNC, cur_entry); +HDfprintf(stderr, "%s: old_sec_node->u.range.num_entries = %u\n", FUNC, old_sec_node->u.range.num_entries); +#endif /* QAK */ +#ifdef QAK +HDfprintf(stderr, "%s: hdr->man_dtable.row_block_size[old_sec_node->u.range.row] = %Hu\n", FUNC, hdr->man_dtable.row_block_size[old_sec_node->u.range.row]); +HDfprintf(stderr, "%s: old_sec_node->sect_addr = %a\n", FUNC, old_sec_node->sect_addr); +#endif /* QAK */ + /* Create direct block of appropriate size */ + if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, cur_entry, (size_t)hdr->man_dtable.row_block_size[old_sec_node->u.range.row], (hsize_t)old_sec_node->sect_addr, &dblock_addr, &dblock_sec_node) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block") + + /* Hook direct block up to indirect block */ + iblock->ents[cur_entry].addr = dblock_addr; + + /* Check for only single block covered in range section */ + if(old_sec_node->u.range.num_entries == 1) + H5FL_FREE(H5HF_free_section_t, old_sec_node); + else { + /* Adjust section information */ + old_sec_node->sect_addr += hdr->man_dtable.row_block_size[old_sec_node->u.range.row]; + + /* Adjust range information */ + old_sec_node->u.range.col++; + old_sec_node->u.range.num_entries--; + + /* Add section back to free space list */ + if(H5HF_flist_add(hdr->flist, old_sec_node, &old_sec_node->sect_size, &old_sec_node->sect_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list") + } /* end else */ + + /* Release the indirect block (marked as dirty) */ + if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, H5AC__DIRTIED_FLAG) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + + /* Point 'sec_node' at new direct block section node */ + *sec_node = dblock_sec_node; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_man_iblock_alloc_range() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_man_iblock_alloc_indirect + * + * Purpose: Allocate a "single" section for an object, out of an + * "indirect" section, possibly creating "range" section as a + * byproduct. + * + * Note: Creates necessary direct & indirect blocks + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Apr 4 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_man_iblock_alloc_indirect(H5HF_t *hdr, hid_t dxpl_id, + H5HF_free_section_t **sec_node, size_t obj_size) +{ + H5HF_indirect_t *iblock; /* Pointer to indirect block */ + H5HF_indirect_t *child_iblock; /* Pointer to child indirect block */ + unsigned iblock_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for parent indirect block */ + haddr_t iblock_addr; /* Indirect block's address */ + haddr_t child_iblock_addr; /* Address of child indirect block */ + haddr_t dblock_addr; /* New direct block's address */ + unsigned iblock_nrows; /* Indirect block's number of rows */ + H5HF_free_section_t *dblock_sec_node = NULL; /* Pointer to direct block's section node */ + H5HF_free_section_t *range_sec_node = NULL; /* Pointer to new range section node */ + H5HF_free_section_t *old_sec_node = *sec_node; /* Pointer to old indirect section node */ + unsigned curr_entry; /* Current entry in indirect block */ + unsigned dblock_entry; /* Entry of direct block in child indirect block */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_alloc_indirect) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(sec_node && *sec_node); + HDassert(obj_size > 0); + + /* Compute info about range */ + curr_entry = (old_sec_node->u.indirect.row * hdr->man_dtable.cparam.width) + old_sec_node->u.indirect.col; + + /* Get information about indirect block covering section */ + /* (Allow for root indirect block being resized) */ + iblock_addr = old_sec_node->u.indirect.iblock_addr; + if(H5F_addr_eq(iblock_addr, hdr->man_dtable.table_addr)) + iblock_nrows = hdr->man_dtable.curr_root_rows; + else + iblock_nrows = old_sec_node->u.indirect.iblock_nrows; + + /* Get a pointer to the indirect block covering the range */ + if(NULL == (iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &iblock_nrows, hdr, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") + +#ifdef QAK +HDfprintf(stderr, "%s: curr_entry = %u\n", FUNC, curr_entry); +HDfprintf(stderr, "%s: iblock->ents[curr_entry].addr = %a\n", FUNC, iblock->ents[curr_entry].addr); +HDfprintf(stderr, "%s: iblock->ents[curr_entry].free_space = %Hu\n", FUNC, iblock->ents[curr_entry].free_space); +HDfprintf(stderr, "%s: old_sec_node->u.indirect.indir_nrows = %u\n", FUNC, old_sec_node->u.indirect.indir_nrows); +HDfprintf(stderr, "%s: old_sec_node->u.indirect.num_entries = %u\n", FUNC, old_sec_node->u.indirect.num_entries); +#endif /* QAK */ + + /* Check if indirect block for this indirect section has already been created */ + if(H5F_addr_defined(iblock->ents[curr_entry].addr)) { + /* Look up existing child indirect block */ + child_iblock_addr = iblock->ents[curr_entry].addr; + if(NULL == (child_iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, child_iblock_addr, &old_sec_node->u.indirect.indir_nrows, hdr, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") + } /* end if */ + else { + hsize_t new_iblock_off; /* Offset of new indirect block */ + + /* Compute heap offset of new indirect block */ + new_iblock_off = iblock->block_off + + hdr->man_dtable.row_block_off[old_sec_node->u.indirect.row] + + (old_sec_node->u.indirect.col * + hdr->man_dtable.row_block_size[old_sec_node->u.indirect.row]); +#ifdef QAK +HDfprintf(stderr, "%s: iblock->block_off = %Hu\n", FUNC, iblock->block_off); +HDfprintf(stderr, "%s: new_iblock_off = %Hu\n", FUNC, new_iblock_off); +#endif /* QAK */ + + /* Create child indirect block */ + if(H5HF_man_iblock_create(hdr, dxpl_id, new_iblock_off, old_sec_node->u.indirect.indir_nrows, old_sec_node->u.indirect.indir_nrows, &child_iblock_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap indirect block") + + /* Lock new child indirect block */ + if(NULL == (child_iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, child_iblock_addr, &old_sec_node->u.indirect.indir_nrows, hdr, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") + + /* Set parent information */ + HDassert(child_iblock->parent == NULL); + child_iblock->parent = iblock; + child_iblock->par_entry = curr_entry; + child_iblock->par_nrows = iblock->nrows; + child_iblock->par_addr = iblock->addr; + if(H5HF_iblock_incr(iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") +#ifdef QAK +HDfprintf(stderr, "%s: child_iblock->child_free_space = %Hu\n", FUNC, child_iblock->child_free_space); +#endif /* QAK */ + + /* Hook child up to parent indirect block */ + iblock->ents[curr_entry].addr = child_iblock_addr; + HDassert(iblock->ents[curr_entry].free_space == child_iblock->child_free_space); + + /* Mark parent indirect block as modified */ + if(H5HF_iblock_dirty(dxpl_id, iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") + + /* Set dirty flag for the parent indirect block */ + iblock_flags |= H5AC__DIRTIED_FLAG; + } /* end else */ + + /* Compute entry for new direct block in child indirect block */ + dblock_entry = old_sec_node->u.indirect.indir_row * hdr->man_dtable.cparam.width; + + /* Create direct block of correct size */ +#ifdef QAK +HDfprintf(stderr, "%s: old_sec_node->u.indirect.indir_row = %u\n", FUNC, old_sec_node->u.indirect.indir_row); +HDfprintf(stderr, "%s: hdr->man_dtable.row_block_size[old_sec_node->u.indirect.indir_row] = %Hu\n", FUNC, hdr->man_dtable.row_block_size[old_sec_node->u.indirect.indir_row]); +HDfprintf(stderr, "%s: old_sec_node->sect_addr = %a\n", FUNC, old_sec_node->sect_addr); +#endif /* QAK */ + if(H5HF_man_dblock_create(dxpl_id, hdr, child_iblock, dblock_entry, (size_t)hdr->man_dtable.row_block_size[old_sec_node->u.indirect.indir_row], (hsize_t)old_sec_node->sect_addr, &dblock_addr, &dblock_sec_node) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block") + + /* Hook direct block up to child indirect block */ + child_iblock->ents[dblock_entry].addr = dblock_addr; + + + /* Create "range" section for other direct blocks in row of child indirect block */ + + /* Create free list section node for blocks skipped over */ + if(NULL == (range_sec_node = H5FL_MALLOC(H5HF_free_section_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") + + /* Set section's information */ + range_sec_node->sect_addr = child_iblock->block_off + hdr->man_dtable.row_block_off[old_sec_node->u.indirect.indir_row] + + hdr->man_dtable.row_block_size[old_sec_node->u.indirect.indir_row]; + range_sec_node->sect_size = old_sec_node->sect_size; + range_sec_node->type = H5HF_SECT_RANGE; + range_sec_node->u.range.iblock_addr = child_iblock_addr; + range_sec_node->u.range.iblock_nrows = child_iblock->nrows; + range_sec_node->u.range.row = old_sec_node->u.indirect.indir_row; + range_sec_node->u.range.col = 1; + range_sec_node->u.range.num_entries = hdr->man_dtable.cparam.width - 1; + + /* Add new free space to the global list of space */ + if(H5HF_flist_add(hdr->flist, range_sec_node, &range_sec_node->sect_size, &range_sec_node->sect_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list") + + + /* Reduce "indirect" section */ + + /* Check for only single block covered in range section */ + if(old_sec_node->u.indirect.num_entries == 1) + H5FL_FREE(H5HF_free_section_t, old_sec_node); + else { + /* Adjust section information */ + old_sec_node->sect_addr += hdr->man_dtable.row_block_size[old_sec_node->u.indirect.row]; + + /* Adjust range information */ + old_sec_node->u.indirect.col++; + old_sec_node->u.indirect.num_entries--; + + /* Add section back to free space list */ + if(H5HF_flist_add(hdr->flist, old_sec_node, &old_sec_node->sect_size, &old_sec_node->sect_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list") + } /* end else */ + + /* Release the child indirect block (marked as dirty) */ + if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, child_iblock_addr, child_iblock, H5AC__DIRTIED_FLAG) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + + /* Release the parent indirect block (possibly dirty) */ + if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, iblock_flags) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + + /* Point 'sec_node' at new direct block section node */ + *sec_node = dblock_sec_node; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_man_iblock_alloc_indirect() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_man_iblock_create + * + * Purpose: Allocate & initialize a managed indirect block + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 6 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_man_iblock_create(H5HF_t *hdr, hid_t dxpl_id, + hsize_t block_off, unsigned nrows, unsigned max_rows, haddr_t *addr_p) +{ + H5HF_indirect_t *iblock = NULL; /* Pointer to indirect block */ + size_t curr_row; /* Current row within indirect block */ + size_t u, v; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_create) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(nrows > 0); + HDassert(addr_p); + + /* + * Allocate file and memory data structures. + */ + if(NULL == (iblock = H5FL_MALLOC(H5HF_indirect_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fractal heap indirect block") + + /* Reset the metadata cache info for the heap header */ + HDmemset(&iblock->cache_info, 0, sizeof(H5AC_info_t)); + + /* Share common heap information */ + iblock->shared = hdr; + if(H5HF_hdr_incr(hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared heap header") + +#ifdef QAK +HDfprintf(stderr, "%s: nrows = %u, max_nrows = %u\n", FUNC, nrows, max_nrows); +#endif /* QAK */ + /* Set info for direct block */ + iblock->rc = 0; + iblock->parent = NULL; /* Temporary, except for root indirect block */ + iblock->par_entry = 0; + iblock->par_nrows = 0; + iblock->par_addr = HADDR_UNDEF; + iblock->block_off = block_off; + iblock->nrows = nrows; + iblock->max_rows = max_rows; + iblock->next_col = 0; + iblock->next_row = 0; + iblock->next_entry = 0; + iblock->next_size = hdr->man_dtable.cparam.start_block_size; + iblock->dirty = TRUE; + iblock->evicted = FALSE; + + /* Compute size of buffer needed for indirect block */ + iblock->size = H5HF_MAN_INDIRECT_SIZE(hdr, iblock); + + /* Allocate indirect block entry tables */ + if(NULL == (iblock->ents = H5FL_SEQ_MALLOC(H5HF_indirect_ent_t, (iblock->nrows * hdr->man_dtable.cparam.width)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for block entries") + + /* Initialize indirect block entry tables */ + curr_row = 0; + iblock->child_free_space = 0; + for(u = 0; u < (iblock->nrows * hdr->man_dtable.cparam.width); /* u advanced in inner loop */) { + for(v = 0; v < hdr->man_dtable.cparam.width; v++, u++) { + iblock->ents[u].addr = HADDR_UNDEF; + iblock->ents[u].free_space = hdr->man_dtable.row_dblock_free[curr_row]; + iblock->child_free_space += iblock->ents[u].free_space; + } /* end for */ + curr_row++; + } /* end for */ + + /* Allocate space for the indirect block on disk */ + if(HADDR_UNDEF == (*addr_p = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, (hsize_t)iblock->size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap indirect block") + iblock->addr = *addr_p; + +/* XXX: Update indirect statistics when they are added */ + + /* Cache the new fractal heap header */ + if(H5AC_set(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, *addr_p, iblock, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add fractal heap indirect block to cache") + +done: + if(ret_value < 0) + if(iblock) + (void)H5HF_cache_iblock_dest(hdr->f, iblock); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_man_iblock_create() */ + diff --git a/src/H5HFint.c b/src/H5HFint.c index 421449c..64de9c4 100644 --- a/src/H5HFint.c +++ b/src/H5HFint.c @@ -43,12 +43,6 @@ /* Local Macros */ /****************/ -/* Limit on the size of the max. direct block size */ -/* (This is limited to 32-bits currently, because I think it's unlikely to - * need to be larger, the 32-bit limit for H5V_log2_of2(n), and - * some offsets/sizes are encoded with a maxiumum of 32-bits - QAK) - */ -#define H5HL_MAX_DIRECT_SIZE_LIMIT ((hsize_t)2 * 1024 * 1024 * 1024) /******************/ /* Local Typedefs */ @@ -59,87 +53,18 @@ /* Package Typedefs */ /********************/ -/* Direct block free list section node */ -struct H5HF_section_free_node_t { - haddr_t sect_addr; /* Address of free list section in the file */ - /* (Not actually used as address, used as unique ID for free list node) */ - size_t sect_size; /* Size of free space section */ - /* (section size is "object size", without the metadata overhead, since metadata overhead varies from block to block) */ - /* (for range sections, this is the largest single section within the range) */ - enum {H5HF_SECT_SINGLE, H5HF_SECT_RANGE} type; /* Type of free space section */ - union { - struct { - haddr_t dblock_addr; /* Address of direct block for free section */ - size_t dblock_size; /* Size of direct block */ - /* (Needed to retrieve direct block) */ - } single; - struct { - haddr_t iblock_addr; /* Address of indirect block for free section */ - unsigned iblock_nrows; /* Number of rows in indirect block */ - /* (Needed to retrieve indirect block) */ - unsigned entry; /* Starting entry in indirect block */ - unsigned num_entries; /* Number of entries covered */ - hsize_t range; /* Size of actual free section */ - } range; - } u; -}; - /********************/ /* Local Prototypes */ /********************/ -/* Doubling table routines */ -static herr_t H5HF_dtable_init(H5HF_dtable_t *dtable); -static herr_t H5HF_dtable_lookup(const H5HF_dtable_t *dtable, hsize_t off, - unsigned *row, unsigned *col); - -/* Shared heap header routines */ -static herr_t H5HF_hdr_dirty(hid_t dxpl_id, H5HF_t *hdr); - -/* Direct block routines */ -static herr_t H5HF_dblock_section_node_free_cb(void *item, void UNUSED *key, - void UNUSED *op_data); -static herr_t H5HF_man_dblock_create(hid_t dxpl_id, H5HF_t *hdr, - H5HF_indirect_t *par_iblock, unsigned par_entry, size_t block_size, - hsize_t block_off, haddr_t *addr_p, H5HF_section_free_node_t **ret_sec_node); -static herr_t H5HF_man_dblock_new(H5HF_t *fh, hid_t dxpl_id, - size_t request); -static herr_t H5HF_man_dblock_adj_free(hid_t dxpl_id, H5HF_direct_t *dblock, ssize_t amt); - -/* Indirect block routines */ -static herr_t H5HF_man_iblock_inc_loc(H5HF_indirect_t *iblock); -static herr_t H5HF_iblock_dirty(hid_t dxpl_id, H5HF_indirect_t *iblock); -static herr_t H5HF_man_iblock_adj_free(hid_t dxpl_id, H5HF_indirect_t *iblock, ssize_t amt); -static H5HF_indirect_t * H5HF_man_iblock_place_dblock(H5HF_t *fh, hid_t dxpl_id, - size_t min_dblock_size, haddr_t *addr_p, size_t *entry_p, - size_t *dblock_size); -static herr_t H5HF_man_iblock_alloc_range(H5HF_t *hdr, hid_t dxpl_id, - H5HF_section_free_node_t **sec_node, size_t obj_size); -static herr_t H5HF_man_iblock_create(H5HF_t *fh, hid_t dxpl_id, - hsize_t block_off, unsigned nrows, unsigned max_rows, haddr_t *addr_p); /*********************/ /* Package Variables */ /*********************/ -/* Declare a free list to manage the H5HF_direct_t struct */ -H5FL_DEFINE(H5HF_direct_t); - -/* Declare a free list to manage the H5HF_direct_free_head_t struct */ -H5FL_DEFINE(H5HF_direct_free_head_t); - -/* Declare a free list to manage the H5HF_direct_free_node_t struct */ -H5FL_DEFINE(H5HF_direct_free_node_t); - -/* Declare a free list to manage the H5HF_section_free_node_t struct */ -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_ent_t sequence information */ -H5FL_SEQ_DEFINE(H5HF_indirect_ent_t); +/* Declare a free list to manage the H5HF_free_section_t struct */ +H5FL_DEFINE(H5HF_free_section_t); /*****************************/ @@ -154,511 +79,9 @@ H5FL_SEQ_DEFINE(H5HF_indirect_ent_t); /*------------------------------------------------------------------------- - * Function: H5HF_dtable_init - * - * Purpose: Initialize values for doubling table - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 6 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HF_dtable_init(H5HF_dtable_t *dtable) -{ - hsize_t tmp_block_size; /* Temporary block size */ - hsize_t acc_block_off; /* Accumulated block offset */ - size_t u; /* Local index variable */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_dtable_init) - - /* - * Check arguments. - */ - HDassert(dtable); - - /* Compute/cache some values */ - dtable->first_row_bits = H5V_log2_of2(dtable->cparam.start_block_size) + - H5V_log2_of2(dtable->cparam.width); - dtable->max_root_rows = (dtable->cparam.max_index - dtable->first_row_bits) + 1; - dtable->max_direct_rows = (H5V_log2_of2(dtable->cparam.max_direct_size) - - H5V_log2_of2(dtable->cparam.start_block_size)) + 2; - dtable->num_id_first_row = dtable->cparam.start_block_size * dtable->cparam.width; - dtable->max_dir_blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dtable->cparam.max_direct_size); - - /* Build table of block sizes for each row */ - if(NULL == (dtable->row_block_size = H5MM_malloc(dtable->max_root_rows * sizeof(hsize_t)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create doubling table block size table") - if(NULL == (dtable->row_block_off = H5MM_malloc(dtable->max_root_rows * sizeof(hsize_t)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create doubling table block offset table") - tmp_block_size = dtable->cparam.start_block_size; - acc_block_off = dtable->cparam.start_block_size * dtable->cparam.width; - dtable->row_block_size[0] = dtable->cparam.start_block_size; - dtable->row_block_off[0] = 0; - for(u = 1; u < dtable->max_root_rows; u++) { - dtable->row_block_size[u] = tmp_block_size; - dtable->row_block_off[u] = acc_block_off; - tmp_block_size *= 2; - acc_block_off *= 2; - } /* end for */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_dtable_init() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_dtable_lookup - * - * Purpose: Compute the row & col of an offset in a doubling-table - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 6 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HF_dtable_lookup(const H5HF_dtable_t *dtable, hsize_t off, unsigned *row, unsigned *col) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_dtable_lookup) - - /* - * Check arguments. - */ - HDassert(dtable); - HDassert(row); - HDassert(col); - - /* Check for offset in first row */ - if(off < dtable->num_id_first_row) { - *row = 0; - *col = off / dtable->cparam.start_block_size; - } /* end if */ - else { - unsigned high_bit = H5V_log2_gen(off); /* Determine the high bit in the offset */ - hsize_t off_mask = 1 << high_bit; /* Compute mask for determining column */ - - *row = (high_bit - dtable->first_row_bits) + 1; - *col = (off - off_mask) / dtable->row_block_size[*row]; - } /* end else */ - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5HF_dtable_lookup() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_dtable_dest - * - * Purpose: Release information for doubling table - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 27 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5HF_dtable_dest(H5HF_dtable_t *dtable) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_dtable_dest) - - /* - * Check arguments. - */ - HDassert(dtable); - - /* Free the block size lookup table for the doubling table */ - H5MM_xfree(dtable->row_block_size); - - /* Free the block offset lookup table for the doubling table */ - H5MM_xfree(dtable->row_block_off); - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5HF_dtable_dest() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_alloc - * - * Purpose: Allocate shared fractal heap header - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 21 2006 - * - *------------------------------------------------------------------------- - */ -H5HF_t * -H5HF_alloc(H5F_t *f) -{ - H5HF_t *fh = NULL; /* Shared fractal heap header */ - H5HF_t *ret_value = NULL; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_alloc) - - /* - * Check arguments. - */ - HDassert(f); - - /* Allocate space for the shared information */ - if(NULL == (fh = H5FL_CALLOC(H5HF_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fractal heap shared header") - - /* Set the internal parameters for the heap */ - fh->f = f; - fh->sizeof_size = H5F_SIZEOF_SIZE(f); - fh->sizeof_addr = H5F_SIZEOF_ADDR(f); - - /* Set the return value */ - ret_value = fh; - -done: - if(!ret_value) - if(fh) - (void)H5HF_cache_hdr_dest(f, fh); - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_alloc() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_finish_init - * - * Purpose: Finish initializing info in shared heap header - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 21 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5HF_finish_init(H5HF_t *fh) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_finish_init) - - /* - * Check arguments. - */ - HDassert(fh); - - /* Compute/cache some values */ - fh->heap_off_size = H5HF_SIZEOF_OFFSET_BITS(fh->man_dtable.cparam.max_index); - if(H5HF_dtable_init(&fh->man_dtable) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize doubling table info") - - /* Create the free-list structure for the heap */ - if(NULL == (fh->flist = H5HF_flist_create(fh->man_dtable.cparam.max_direct_size, H5HF_dblock_section_node_free_cb))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize free list info") - - /* Set the size of heap IDs */ - fh->id_len = fh->heap_off_size + MIN(fh->man_dtable.max_dir_blk_off_size, - ((H5V_log2_gen((hsize_t)fh->standalone_size) + 7) / 8)); - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_finish_init() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_init - * - * Purpose: Initialize shared fractal heap header for new heap - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 21 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5HF_init(H5HF_t *fh, haddr_t fh_addr, H5HF_create_t *cparam) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_init) - - /* - * Check arguments. - */ - HDassert(fh); - HDassert(cparam); - -#ifndef NDEBUG - /* Check for valid parameters */ - if(!POWER_OF_TWO(cparam->managed.width) || cparam->managed.width == 0) - HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "width not power of two") - if(!POWER_OF_TWO(cparam->managed.start_block_size) || cparam->managed.start_block_size == 0) - HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "starting block size not power of two") - if(!POWER_OF_TWO(cparam->managed.max_direct_size) || - (cparam->managed.max_direct_size == 0 || cparam->managed.max_direct_size > H5HL_MAX_DIRECT_SIZE_LIMIT)) - HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. direct block size not power of two") - if(cparam->managed.max_direct_size < cparam->standalone_size) - HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. direct block size not large enough to hold all managed blocks") - if(cparam->managed.max_index > (8 * fh->sizeof_size) || cparam->managed.max_index == 0) - HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. direct block size not power of two") -#endif /* NDEBUG */ - - /* Set the creation parameters for the heap */ - fh->heap_addr = fh_addr; - fh->addrmap = cparam->addrmap; - fh->standalone_size = cparam->standalone_size; - HDmemcpy(&(fh->man_dtable.cparam), &(cparam->managed), sizeof(H5HF_dtable_cparam_t)); - - /* Set root table address */ - fh->man_dtable.table_addr = HADDR_UNDEF; - - /* Note that the shared info is dirty (it's not written to the file yet) */ - fh->dirty = TRUE; - - /* Make shared heap info reference counted */ - if(H5HF_finish_init(fh) < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for shared fractal heap header") - -done: - if(ret_value < 0) - if(fh) - (void)H5HF_cache_hdr_dest(NULL, fh); - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_init() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_man_iblock_inc_loc - * - * Purpose: Increment location of next direct block in indirect block - * - * Return: SUCCEED/FAIL - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 14 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HF_man_iblock_inc_loc(H5HF_indirect_t *iblock) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_inc_loc) - - /* - * Check arguments. - */ - HDassert(iblock); - - /* Increment block entry */ - iblock->next_entry++; - - /* Increment column */ - iblock->next_col++; - - /* Check for walking off end of column */ - if(iblock->next_col == iblock->shared->man_dtable.cparam.width) { - /* Reset column */ - iblock->next_col = 0; - - /* Increment row & block size */ - iblock->next_row++; - if(iblock->next_row > 1) - iblock->next_size *= 2; - - /* 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 */ - if(H5HF_man_iblock_inc_loc(iblock->parent) < 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_row = %u\n", FUNC, iblock->next_row); -HDfprintf(stderr, "%s: iblock->next_col = %u\n", FUNC, iblock->next_col); -HDfprintf(stderr, "%s: iblock->next_entry = %u\n", FUNC, iblock->next_entry); -HDfprintf(stderr, "%s: iblock->next_size = %Zu\n", FUNC, iblock->next_size); -#endif /* QAK */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_iblock_inc_loc() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_man_dblock_create - * - * Purpose: Allocate & initialize a managed direct block - * - * Return: Pointer to new direct block on success, NULL on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 27 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HF_man_dblock_create(hid_t dxpl_id, H5HF_t *hdr, H5HF_indirect_t *par_iblock, - unsigned par_entry, size_t block_size, hsize_t block_off, haddr_t *addr_p, - H5HF_section_free_node_t **ret_sec_node) -{ - H5HF_direct_free_node_t *node; /* Pointer to free list node for block */ - H5HF_section_free_node_t *sec_node; /* Pointer to free list section for block */ - H5HF_direct_t *dblock = NULL; /* Pointer to direct block */ - size_t free_space; /* Free space in new block */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_create) - - /* - * Check arguments. - */ - HDassert(hdr); - HDassert(block_size > 0); - HDassert(addr_p); - - /* - * Allocate file and memory data structures. - */ - if(NULL == (dblock = H5FL_MALLOC(H5HF_direct_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fractal heap direct block") - - /* Reset the metadata cache info for the heap header */ - HDmemset(&dblock->cache_info, 0, sizeof(H5AC_info_t)); - - /* Share common heap information */ - dblock->shared = hdr; - if(H5HF_hdr_incr(hdr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared heap header") - - /* Set info for direct block */ -#ifdef QAK -HDfprintf(stderr, "%s: size = %Zu, block_off = %Hu\n", FUNC, block_size, block_off); -#endif /* QAK */ - dblock->parent = par_iblock; - if(dblock->parent) { - if(H5HF_iblock_incr(par_iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") - dblock->par_addr = par_iblock->addr; - dblock->par_nrows = par_iblock->nrows; - } /* end if */ - else { - dblock->par_addr = HADDR_UNDEF; - dblock->par_nrows = 0; - } /* end else */ - dblock->par_entry = par_entry; - dblock->size = block_size; - dblock->block_off = block_off; - dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(block_size); - dblock->free_list_head = H5HF_MAN_ABS_DIRECT_OVERHEAD_DBLOCK(hdr, dblock); - dblock->blk_free_space = 0; /* temporarily, this is modified later */ - free_space = block_size - dblock->free_list_head; - - /* Allocate buffer for block */ -/* XXX: Change to using free-list factories */ - if((dblock->blk = H5FL_BLK_MALLOC(direct_block, block_size)) == NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") -#ifdef H5_USING_PURIFY -HDmemset(dblock->blk, 0, dblock->size); -#endif /* H5_USING_PURIFY */ - - /* Set up free list head */ - if(NULL == (dblock->free_list = H5FL_MALLOC(H5HF_direct_free_head_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list head") - dblock->free_list->dirty = TRUE; - - /* Set up free list node for all unused space in block */ - if(NULL == (node = H5FL_MALLOC(H5HF_direct_free_node_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list node") - - /* Set node's information */ - node->size = free_space; - node->my_offset = dblock->free_list_head; - node->next_offset = 0; - node->prev = node->next = NULL; - - /* Attach to free list head */ -/* XXX: Convert this list to a skip list? */ - dblock->free_list->first = node; - - /* Allocate space for the header on disk */ - if(HADDR_UNDEF == (*addr_p = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)block_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block") - - /* Create free list section node */ - if(NULL == (sec_node = H5FL_MALLOC(H5HF_section_free_node_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") - - /* Set section's information */ - sec_node->sect_addr = block_off + node->my_offset; - /* (section size is "object size", without the metadata overhead) */ - sec_node->sect_size = node->size - H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr); - sec_node->type = H5HF_SECT_SINGLE; - sec_node->u.single.dblock_addr = *addr_p; - sec_node->u.single.dblock_size = block_size; - - /* Check what to do with section node */ - if(ret_sec_node) - /* Pass back the pointer to the section instead of adding it to the free list */ - *ret_sec_node = sec_node; - else { - /* Add new free space to the global list of space */ - if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list") - } /* end else */ - - /* Adjust free space to include new block's space */ - if(H5HF_man_dblock_adj_free(dxpl_id, dblock, (ssize_t)sec_node->sect_size) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't adjust free space for direct block & parents") - - /* Update shared heap header */ - hdr->total_size += dblock->size; - hdr->man_size += dblock->size; - - /* Mark heap header as modified */ - if(H5HF_hdr_dirty(dxpl_id, hdr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty") - - /* Cache the new fractal heap direct block */ - if(H5AC_set(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, *addr_p, dblock, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add fractal heap direct block to cache") - -done: - if(ret_value < 0) - if(dblock) - (void)H5HF_cache_dblock_dest(hdr->f, dblock); - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_dblock_create() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_dblock_section_node_free_cb + * Function: H5HF_free_section_free_cb * - * Purpose: Free a section node for a block + * Purpose: Free a free section node * * Return: Success: non-negative * @@ -669,375 +92,18 @@ done: * *------------------------------------------------------------------------- */ -static herr_t -H5HF_dblock_section_node_free_cb(void *item, void UNUSED *key, void UNUSED *op_data) +herr_t +H5HF_free_section_free_cb(void *item, void UNUSED *key, void UNUSED *op_data) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_dblock_section_node_free_cb) + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_free_section_free_cb) HDassert(item); /* Release the sections */ - H5FL_FREE(H5HF_section_free_node_t, item); + H5FL_FREE(H5HF_free_section_t, item); FUNC_LEAVE_NOAPI(0) -} /* H5HF_dblock_section_node_free_cb() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_man_dblock_build_freelist - * - * Purpose: Parse the free list information for a direct block and build - * block's free list - * - * Return: SUCCEED/FAIL - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 28 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5HF_man_dblock_build_freelist(H5HF_direct_t *dblock, haddr_t dblock_addr) -{ - H5HF_direct_free_head_t *head = NULL; /* Pointer to free list head for block */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_build_freelist) - - /* - * Check arguments. - */ - HDassert(dblock); - - /* Allocate head of list */ - if(NULL == (head = H5FL_MALLOC(H5HF_direct_free_head_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list head") - head->dirty = FALSE; - - /* Check for any nodes on free list */ - if(dblock->free_list_head == 0) - head->first = NULL; - else { - H5HF_t *hdr; /* Pointer to shared heap header */ - H5HF_section_free_node_t *sec_node; /* Pointer to free list section for block */ - H5HF_direct_free_node_t *node = NULL; /* Pointer to free list node for block */ - H5HF_direct_free_node_t *prev_node; /* Pointer to previous free list node for block */ - hsize_t free_len; /* Length of free list info */ - hsize_t next_off; /* Next node offset in block */ - hsize_t prev_off; /* Prev node offset in block */ - uint8_t *p; /* Temporary pointer to free node info */ - - /* Get the pointer to the shared heap info */ - hdr = dblock->shared; - - /* Point to first node in free list */ - p = dblock->blk + dblock->free_list_head; - - /* Decode information for first node on free list */ - UINT64DECODE_VAR(p, free_len, dblock->blk_off_size); - UINT64DECODE_VAR(p, next_off, dblock->blk_off_size); - - /* Allocate node on list */ - if(NULL == (node = H5FL_MALLOC(H5HF_direct_free_node_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list node") - - /* Set node's information */ - node->size = free_len; - node->my_offset = dblock->free_list_head; - node->next_offset = next_off; - node->prev = node->next = NULL; - - /* Attach to free list head */ - head->first = node; - - /* Set block's free space */ - dblock->blk_free_space = free_len; - - /* Create free list section node */ - if(NULL == (sec_node = H5FL_MALLOC(H5HF_section_free_node_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") - - /* Set section's information */ - sec_node->sect_addr = dblock->block_off + node->my_offset; - /* (section size is "object size", without the metadata overhead) */ - sec_node->sect_size = node->size - H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr); - sec_node->type = H5HF_SECT_SINGLE; - sec_node->u.single.dblock_addr = dblock_addr; - sec_node->u.single.dblock_size = dblock->size; - - /* Add new free space to the global list of space */ - if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list") - - /* Set up trailing node pointer */ - prev_node = node; - prev_off = next_off; - - /* Bring in rest of node on free list */ - while(next_off != 0) { - /* Point to first node in free list */ - p = dblock->blk + next_off; - - /* Decode information for first node on free list */ - UINT64DECODE_VAR(p, free_len, dblock->blk_off_size); - UINT64DECODE_VAR(p, next_off, dblock->blk_off_size); - - /* Allocate node on list */ - if(NULL == (node = H5FL_MALLOC(H5HF_direct_free_node_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list node") - - /* Set node's information */ - node->size = free_len; - node->my_offset = prev_off; - node->next_offset = next_off; - node->prev = prev_node; - node->next = NULL; - - /* Adjust block's free space */ - dblock->blk_free_space += free_len; - - /* Create free list section node */ - if(NULL == (sec_node = H5FL_MALLOC(H5HF_section_free_node_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") - - /* Set section's information */ - sec_node->sect_addr = dblock->block_off + node->my_offset; - /* (section size is "object size", without the metadata overhead) */ - sec_node->sect_size = node->size - H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr); - sec_node->type = H5HF_SECT_SINGLE; - sec_node->u.single.dblock_addr = dblock_addr; - sec_node->u.single.dblock_size = dblock->size; - - /* Add new free space to the global list of space */ - if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list") - - /* Update trailing info */ - prev_node->next = node; - prev_off = next_off; - - /* Advance to next node */ - prev_node = node; - } /* end while */ - } /* end else */ - - /* Assign free list head to block */ - dblock->free_list = head; - -done: -/* XXX: cleanup on failure? */ - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_dblock_build_freelist() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_man_dblock_adj_free - * - * Purpose: Adjust the free space for a direct block, and it's parents - * - * Return: SUCCEED/FAIL - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 14 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HF_man_dblock_adj_free(hid_t dxpl_id, H5HF_direct_t *dblock, ssize_t amt) -{ - H5HF_t *hdr; /* Shared heap information */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_adj_free) -#ifdef QAK -HDfprintf(stderr, "%s: amt = %Zd\n", FUNC, amt); -#endif /* QAK */ - - /* - * Check arguments. - */ - HDassert(dblock); - - /* Get the pointer to the shared heap header */ - hdr = dblock->shared; - - /* Adjust space available in block */ - HDassert(amt > 0 || dblock->blk_free_space >= (size_t)-amt); - dblock->blk_free_space += amt; - - /* Check if the parent info is set */ - if(dblock->parent) { - H5HF_indirect_t *iblock; /* Block's parent */ - - /* Get the pointer to the shared parent indirect block */ - iblock = dblock->parent; - - /* Adjust this indirect block's child free space */ -#ifdef QAK -HDfprintf(stderr, "%s: iblock->child_free_space = %Hu\n", FUNC, iblock->child_free_space); -#endif /* QAK */ - HDassert(amt > 0 || iblock->ents[dblock->par_entry].free_space >= (hsize_t)-amt); - iblock->ents[dblock->par_entry].free_space += amt; - HDassert(amt > 0 || iblock->child_free_space >= (hsize_t)-amt); - iblock->child_free_space += amt; - - /* Mark indirect block as dirty */ - if(H5HF_iblock_dirty(dxpl_id, iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") - - /* Modify the free space in parent block(s) */ - while(iblock->parent) { - size_t par_entry; /* Entry in parent */ - - /* Get the pointer to the shared parent indirect block */ - par_entry = iblock->par_entry; - iblock = iblock->parent; - HDassert(iblock); - - /* Adjust this indirect block's child free space */ - HDassert(amt > 0 || iblock->ents[par_entry].free_space >= (hsize_t)-amt); - iblock->ents[par_entry].free_space += amt; - HDassert(amt > 0 || iblock->child_free_space >= (hsize_t)-amt); - iblock->child_free_space += amt; - - /* Mark indirect block as dirty */ - if(H5HF_iblock_dirty(dxpl_id, iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") - } /* end while */ - } /* end if */ - - /* Update shared heap free space header */ - HDassert(amt > 0 || hdr->total_man_free >= (hsize_t)-amt); - hdr->total_man_free += amt; -#ifdef QAK -HDfprintf(stderr, "%s: hdr->total_man_free = %Hu\n", FUNC, hdr->total_man_free); -#endif /* QAK */ - - /* Mark heap header as modified */ - if(H5HF_hdr_dirty(dxpl_id, hdr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_dblock_adj_free() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_man_dblock_new - * - * Purpose: Create a direct block large enough to hold an object of - * the requested size - * - * Return: SUCCEED/FAIL - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 13 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HF_man_dblock_new(H5HF_t *hdr, hid_t dxpl_id, size_t request) -{ - haddr_t dblock_addr; /* Address of new direct block */ - size_t dblock_size; /* Size of new direct block */ - size_t min_dblock_size; /* Min. size of direct block to allocate */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_new) -#ifdef QAK -HDfprintf(stderr, "%s: request = %Zu\n", FUNC, request); -#endif /* QAK */ - - /* - * Check arguments. - */ - HDassert(hdr); - HDassert(request > 0); - - /* Compute the min. size of the direct block needed to fulfill the request */ - if(request < hdr->man_dtable.cparam.start_block_size) - min_dblock_size = hdr->man_dtable.cparam.start_block_size; - else { - min_dblock_size = 1 << (1 + H5V_log2_gen((hsize_t)request)); - HDassert(min_dblock_size <= hdr->man_dtable.cparam.max_direct_size); - } /* end else */ - - /* Adjust the size of block needed to fulfill request, with overhead */ -#ifdef QAK -HDfprintf(stderr, "%s: Check 1 - min_dblock_size = %Zu\n", FUNC, min_dblock_size); -HDfprintf(stderr, "%s: H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE = %u\n", FUNC, H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, hdr->man_dtable.cparam.start_block_size)); -HDfprintf(stderr, "%s: H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN = %u\n", FUNC, H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr)); -#endif /* QAK */ - if((min_dblock_size - request) < (H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, min_dblock_size) - + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr))) - min_dblock_size *= 2; -#ifdef QAK -HDfprintf(stderr, "%s: Check 2 - min_dblock_size = %Zu\n", FUNC, min_dblock_size); -#endif /* QAK */ - - /* Check if this is the first block in the heap */ - if(!H5F_addr_defined(hdr->man_dtable.table_addr) && - min_dblock_size == hdr->man_dtable.cparam.start_block_size) { - /* Create new direct block at starting offset */ - dblock_size = hdr->man_dtable.cparam.start_block_size; - if(H5HF_man_dblock_create(dxpl_id, hdr, NULL, 0, dblock_size, (hsize_t)0, &dblock_addr, NULL) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block") - -#ifdef QAK -HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr); -#endif /* QAK */ - - /* Point root at new direct block */ - hdr->man_dtable.curr_root_rows = 0; - hdr->man_dtable.table_addr = dblock_addr; - } /* end if */ - /* Root entry already exists, go get indirect block for new direct block */ - else { - H5HF_indirect_t *iblock; /* Pointer to indirect block to create */ - haddr_t iblock_addr; /* Indirect block's address */ - size_t dblock_entry; /* Direct entry for new direct block */ - hsize_t dblock_off; /* Direct block offset in heap address space */ - - /* Find indirect block with room for block of correct size */ - if(NULL == (iblock = H5HF_man_iblock_place_dblock(hdr, dxpl_id, min_dblock_size, &iblock_addr, &dblock_entry, &dblock_size))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to locate indirect block with space for direct block") -#ifdef QAK -HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr); -HDfprintf(stderr, "%s: dblock_entry = %Zu\n", FUNC, dblock_entry); -HDfprintf(stderr, "%s: dblock_size = %Zu\n", FUNC, dblock_size); -#endif /* QAK */ - - /* Compute the direct block's offset in the heap's address space */ - dblock_off = iblock->block_off; - dblock_off += hdr->man_dtable.row_block_off[dblock_entry / hdr->man_dtable.cparam.width]; - dblock_off += hdr->man_dtable.row_block_size[dblock_entry / hdr->man_dtable.cparam.width] * (dblock_entry % hdr->man_dtable.cparam.width); - - /* Create new direct block at current location*/ - if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, dblock_entry, dblock_size, dblock_off, &dblock_addr, NULL) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block") - -#ifdef QAK -HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr); -#endif /* QAK */ - - /* Point indirect block at new direct block */ - iblock->ents[dblock_entry].addr = dblock_addr; - - /* Mark indirect block as modified */ - if(H5HF_iblock_dirty(dxpl_id, iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") - - /* Release the indirect block (marked as dirty) */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, H5AC__DIRTIED_FLAG) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") - } /* end else */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_dblock_new() */ +} /* H5HF_free_section_free_cb() */ /*------------------------------------------------------------------------- @@ -1055,8 +121,8 @@ done: *------------------------------------------------------------------------- */ herr_t -H5HF_man_find(H5HF_t *fh, hid_t dxpl_id, size_t request, - H5HF_section_free_node_t **sec_node/*out*/) +H5HF_man_find(H5HF_t *hdr, hid_t dxpl_id, size_t request, + H5HF_free_section_t **sec_node/*out*/) { htri_t node_found; /* Whether an existing free list node was found */ herr_t ret_value = SUCCEED; /* Return value */ @@ -1069,12 +135,12 @@ HDfprintf(stderr, "%s: request = %Zu\n", FUNC, request); /* * Check arguments. */ - HDassert(fh); + HDassert(hdr); HDassert(request > 0); HDassert(sec_node); /* Look for free space in global free list */ - if((node_found = H5HF_flist_find(fh->flist, request, (void **)sec_node)) < 0) + if((node_found = H5HF_flist_find(hdr->flist, request, (void **)sec_node)) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't locate free space in fractal heap direct block") /* XXX: Make certain we've loaded all the direct blocks in the heap */ @@ -1082,12 +148,12 @@ HDfprintf(stderr, "%s: request = %Zu\n", FUNC, request); /* If we didn't find a node, go make one big enough to hold the requested block */ if(!node_found) { /* Allocate direct block big enough to hold requested size */ - if(H5HF_man_dblock_new(fh, dxpl_id, request) < 0) + if(H5HF_man_dblock_new(hdr, dxpl_id, request) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "can't create fractal heap direct block") /* Request space from the free list */ /* (Ought to be able to be filled, now) */ - if(H5HF_flist_find(fh->flist, request, (void **)sec_node) <= 0) + if(H5HF_flist_find(hdr->flist, request, (void **)sec_node) <= 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't locate free space in fractal heap direct block") } /* end if */ HDassert(*sec_node); @@ -1117,7 +183,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5HF_man_insert(H5HF_t *hdr, hid_t dxpl_id, H5HF_section_free_node_t *sec_node, +H5HF_man_insert(H5HF_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sec_node, size_t obj_size, const void *obj, void *id) { H5HF_direct_t *dblock = NULL; /* Pointer to direct block to modify */ @@ -1134,18 +200,36 @@ H5HF_man_insert(H5HF_t *hdr, hid_t dxpl_id, H5HF_section_free_node_t *sec_node, HDassert(obj); HDassert(id); + /* Check for indirect section */ + if(sec_node->type == H5HF_SECT_INDIRECT) { +#ifdef QAK +HDfprintf(stderr, "%s: sec_node->sect_addr = %a\n", FUNC, sec_node->sect_addr); +HDfprintf(stderr, "%s: sec_node->sect_size = %Zu\n", FUNC, sec_node->sect_size); +HDfprintf(stderr, "%s: sec_node->u.indirect.iblock_addr = %a\n", FUNC, sec_node->u.indirect.iblock_addr); +HDfprintf(stderr, "%s: sec_node->u.indirect.iblock_nrows = %u\n", FUNC, sec_node->u.indirect.iblock_nrows); +HDfprintf(stderr, "%s: sec_node->u.indirect.row = %u\n", FUNC, sec_node->u.indirect.row); +HDfprintf(stderr, "%s: sec_node->u.indirect.col = %u\n", FUNC, sec_node->u.indirect.col); +HDfprintf(stderr, "%s: sec_node->u.indirect.num_entries = %u\n", FUNC, sec_node->u.indirect.num_entries); +HDfprintf(stderr, "%s: sec_node->u.indirect.indir_row = %u\n", FUNC, sec_node->u.indirect.indir_row); +HDfprintf(stderr, "%s: sec_node->u.indirect.indir_nrows = %u\n", FUNC, sec_node->u.indirect.indir_nrows); +#endif /* QAK */ + + /* Allocate 'single' selection out of 'indirect' selection */ + if(H5HF_man_iblock_alloc_indirect(hdr, dxpl_id, &sec_node, obj_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't break up indirect free section") + } /* end if */ /* Check for range section */ - if(sec_node->type == H5HF_SECT_RANGE) { + else if(sec_node->type == H5HF_SECT_RANGE) { #ifdef QAK HDfprintf(stderr, "%s: sec_node->sect_addr = %a\n", FUNC, sec_node->sect_addr); HDfprintf(stderr, "%s: sec_node->sect_size = %Zu\n", FUNC, sec_node->sect_size); HDfprintf(stderr, "%s: sec_node->u.range.iblock_addr = %a\n", FUNC, sec_node->u.range.iblock_addr); HDfprintf(stderr, "%s: sec_node->u.range.iblock_nrows = %u\n", FUNC, sec_node->u.range.iblock_nrows); -HDfprintf(stderr, "%s: sec_node->u.range.entry = %u\n", FUNC, sec_node->u.range.entry); +HDfprintf(stderr, "%s: sec_node->u.range.row = %u\n", FUNC, sec_node->u.range.row); +HDfprintf(stderr, "%s: sec_node->u.range.col = %u\n", FUNC, sec_node->u.range.col); HDfprintf(stderr, "%s: sec_node->u.range.num_entries = %u\n", FUNC, sec_node->u.range.num_entries); -HDfprintf(stderr, "%s: sec_node->u.range.range = %Hu\n", FUNC, sec_node->u.range.range); #endif /* QAK */ - /* Allocate 'single' selection out of range selection */ + /* Allocate 'single' selection out of 'range' selection */ if(H5HF_man_iblock_alloc_range(hdr, dxpl_id, &sec_node, obj_size) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't break up range free section") } /* end if */ @@ -1175,7 +259,7 @@ HDfprintf(stderr, "%s: sec_node->u.single.dblock_size = %Zu\n", FUNC, sec_node-> unsigned char free_frag_size; /* Size of free space fragment */ /* Locate "local" free list node for section */ -/* XXX: Change to using skip list */ +/* XXX: Change to using skip list? */ obj_off = sec_node->sect_addr - dblock->block_off; node = dblock->free_list->first; while(node->my_offset != obj_off) @@ -1185,6 +269,11 @@ HDfprintf(stderr, "%s: sec_node->u.single.dblock_size = %Zu\n", FUNC, sec_node-> full_obj_size = obj_size + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr); /* Sanity checks */ +#ifdef QAK +HDfprintf(stderr, "%s: hdr->total_man_free = %Hu\n", FUNC, hdr->total_man_free); +HDfprintf(stderr, "%s: dblock->blk_free_space = %Zu\n", FUNC, dblock->blk_free_space); +HDfprintf(stderr, "%s: dblock->block_off = %Hu\n", FUNC, dblock->block_off); +#endif /* QAK */ HDassert(dblock->blk_free_space >= obj_size); HDassert(dblock->free_list); HDassert(node->size >= full_obj_size); @@ -1227,7 +316,7 @@ HDfprintf(stderr, "%s: node->size = %Zu\n", FUNC, node->size); /* Release the memory for the free list node & section */ H5FL_FREE(H5HF_direct_free_node_t, node); - H5FL_FREE(H5HF_section_free_node_t, sec_node); + H5FL_FREE(H5HF_free_section_t, sec_node); } /* end if */ else { /* Allocate object from end of free space node */ @@ -1338,6 +427,9 @@ H5HF_man_read(H5HF_t *hdr, hid_t dxpl_id, hsize_t obj_off, size_t obj_len, void herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_read) +#ifdef QAK +HDfprintf(stderr, "%s: obj_off = %Hu, obj_len = %Zu\n", FUNC, obj_off, obj_len); +#endif /* QAK */ /* * Check arguments. @@ -1371,6 +463,9 @@ HDfprintf(stderr, "%s: row = %u, col = %u\n", FUNC, row, col); /* Set initial indirect block info */ iblock_addr = hdr->man_dtable.table_addr; +#ifdef QAK +HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr); +#endif /* QAK */ /* Lock indirect block */ if(NULL == (iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &hdr->man_dtable.curr_root_rows, hdr, H5AC_READ))) @@ -1387,6 +482,9 @@ HDfprintf(stderr, "%s: row = %u, col = %u\n", FUNC, row, col); /* Compute indirect block's entry */ entry = (row * hdr->man_dtable.cparam.width) + col; +#ifdef QAK +HDfprintf(stderr, "%s: entry = %Zu\n", FUNC, entry); +#endif /* QAK */ /* Locate child indirect block */ new_iblock_addr = iblock->ents[entry].addr; @@ -1395,13 +493,17 @@ HDfprintf(stderr, "%s: row = %u, col = %u\n", FUNC, row, col); if(NULL == (new_iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, new_iblock_addr, &nrows, hdr, 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) */ + /* Release the current indirect block */ if(H5AC_unprotect(hdr->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; +#ifdef QAK +HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr); +HDfprintf(stderr, "%s: iblock->block_off = %Hu\n", FUNC, iblock->block_off); +#endif /* QAK */ /* Look up row & column in new indirect block for object */ if(H5HF_dtable_lookup(&hdr->man_dtable, (obj_off - iblock->block_off), &row, &col) < 0) @@ -1431,6 +533,9 @@ HDfprintf(stderr, "%s: entry address = %a\n", FUNC, iblock->ents[entry].addr); HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") iblock = NULL; } /* end else */ +#ifdef QAK +HDfprintf(stderr, "%s: dblock_addr = %a, dblock_size = %Zu\n", FUNC, dblock_addr, dblock_size); +#endif /* QAK */ /* Compute offset of object within block */ HDassert((obj_off - dblock->block_off) < (hsize_t)dblock_size); @@ -1454,1021 +559,3 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_man_read() */ - -/*------------------------------------------------------------------------- - * Function: H5HF_hdr_incr - * - * Purpose: Increment reference count on shared heap header - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 27 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5HF_hdr_incr(H5HF_t *hdr) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_hdr_incr) - - /* Sanity check */ - HDassert(hdr); - -/* XXX: When "un-evictable" feature is finished, mark the header as - * unevictable on the first block to share it. - QAK - */ - - /* Increment reference count on shared header */ - hdr->rc++; - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5HF_hdr_incr() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_hdr_decr - * - * Purpose: Decrement reference count on shared heap header - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 27 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5HF_hdr_decr(H5HF_t *hdr) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_hdr_decr) - - /* Sanity check */ - HDassert(hdr); - - /* Decrement reference count on shared header */ - hdr->rc--; - -/* XXX: When "un-evictable" feature is finished, mark the header as - * evictable when the ref. count drops to zero. - QAK - */ -/* XXX: Take this call out after "un-evictable" flag is working */ - H5HF_cache_hdr_dest_real(hdr); - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5HF_hdr_decr() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_hdr_dirty - * - * Purpose: Mark heap header as dirty - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 27 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HF_hdr_dirty(hid_t dxpl_id, H5HF_t *hdr) -{ - H5HF_t *tmp_hdr; /* Temporary pointer to heap header */ - hbool_t is_protected; /* Whether the indirect block is protected */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_dirty) -#ifdef QAK -HDfprintf(stderr, "%s: Marking heap header as dirty\n", FUNC); -#endif /* QAK */ - - /* Sanity check */ - HDassert(hdr); - -/* XXX: When "un-evictable" feature is finished, just mark the header as dirty - * in the cache, instead of this protect -> unprotect kludge - QAK - */ - /* Protect the header */ - is_protected = hdr->cache_info.is_protected; - if(!is_protected) { -#ifdef QAK -HDfprintf(stderr, "%s: hdr->heap_addr = %a\n", FUNC, hdr->heap_addr); -#endif /* QAK */ - if(NULL == (tmp_hdr = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_HDR, hdr->heap_addr, NULL, NULL, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") - HDassert(hdr == tmp_hdr); - } /* end if */ - - /* Set the dirty flags for the heap header */ - hdr->dirty = TRUE; - - /* Release the heap header (marked as dirty) */ - if(!is_protected) { - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_HDR, hdr->heap_addr, tmp_hdr, H5AC__DIRTIED_FLAG) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") - } /* end if */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_hdr_dirty() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_iblock_incr - * - * Purpose: Increment reference count on shared indirect block - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 27 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5HF_iblock_incr(H5HF_indirect_t *iblock) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_iblock_incr) - - /* Sanity check */ - HDassert(iblock); - -/* XXX: When "un-evictable" feature is finished, mark the block as - * unevictable on the first block to share it. - QAK - */ - - /* Increment reference count on shared indirect block */ - iblock->rc++; - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5HF_iblock_incr() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_iblock_decr - * - * Purpose: Decrement reference count on shared indirect block - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 27 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5HF_iblock_decr(H5HF_indirect_t *iblock) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_iblock_decr) - - /* Sanity check */ - HDassert(iblock); - - /* Decrement reference count on shared indirect block */ - iblock->rc--; - -/* XXX: When "un-evictable" feature is finished, mark the block as - * evictable when the ref. count drops to zero. - QAK - */ -/* XXX: Take this call out after "un-evictable" flag is working */ - H5HF_cache_iblock_dest_real(iblock); - - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5HF_iblock_decr() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_iblock_dirty - * - * Purpose: Mark indirect block as dirty - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 21 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HF_iblock_dirty(hid_t dxpl_id, H5HF_indirect_t *iblock) -{ - H5HF_indirect_t *tmp_iblock; /* Temporary pointer to indirect block */ - hbool_t is_protected; /* Whether the indirect block is protected */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_iblock_dirty) -#ifdef QAK -HDfprintf(stderr, "%s: Marking indirect block as dirty\n", FUNC); -#endif /* QAK */ - - /* Sanity check */ - HDassert(iblock); - -/* XXX: When "un-evictable" feature is finished, just mark the block as dirty - * in the cache, instead of this protect -> unprotect kludge - QAK - */ - /* Protect the indirect block */ - is_protected = iblock->cache_info.is_protected; - if(!is_protected) { -#ifdef QAK -HDfprintf(stderr, "%s: iblock->addr = %a\n", FUNC, iblock->addr); -#endif /* QAK */ - if(NULL == (tmp_iblock = H5AC_protect(iblock->shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, &iblock->nrows, iblock->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") - HDassert(iblock == tmp_iblock); - } /* end if */ - - /* Set the dirty flags for the indirect block */ - iblock->dirty = TRUE; - - /* Release the indirect block (marked as dirty) */ - if(!is_protected) { - if(H5AC_unprotect(iblock->shared->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, tmp_iblock, H5AC__DIRTIED_FLAG) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") - } /* end if */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_iblock_dirty() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_man_iblock_adj_free - * - * Purpose: Adjust the free space for an indirect block, and it's parents - * - * Return: SUCCEED/FAIL - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 28 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HF_man_iblock_adj_free(hid_t dxpl_id, H5HF_indirect_t *iblock, ssize_t amt) -{ - H5HF_t *hdr; /* Shared heap information */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_adj_free) -#ifdef QAK -HDfprintf(stderr, "%s: amt = %Zd\n", FUNC, amt); -#endif /* QAK */ - - /* - * Check arguments. - */ - HDassert(iblock); - - /* Get the pointer to the shared heap header */ - hdr = iblock->shared; - - /* Adjust space available in block */ - HDassert(amt > 0 || iblock->child_free_space >= (hsize_t)-amt); - iblock->child_free_space += amt; - - /* Check if the parent info is set */ - while(iblock->parent) { - size_t par_entry; /* Entry in parent */ - - /* Get the pointer to the shared parent indirect block */ - par_entry = iblock->par_entry; - iblock = iblock->parent; - HDassert(iblock); - - /* Adjust this indirect block's child free space */ -#ifdef QAK -HDfprintf(stderr, "%s: iblock->child_free_space = %Hu\n", FUNC, iblock->child_free_space); -#endif /* QAK */ - HDassert(amt > 0 || iblock->ents[par_entry].free_space >= (hsize_t)-amt); - iblock->ents[par_entry].free_space += amt; - HDassert(amt > 0 || iblock->child_free_space >= (hsize_t)-amt); - iblock->child_free_space += amt; - - /* Mark indirect block as dirty */ - if(H5HF_iblock_dirty(dxpl_id, iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") - } /* end if */ - - /* Update shared heap free space header */ - HDassert(amt > 0 || hdr->total_man_free >= (hsize_t)-amt); - hdr->total_man_free += amt; -#ifdef QAK -HDfprintf(stderr, "%s: hdr->total_man_free = %Hu\n", FUNC, hdr->total_man_free); -#endif /* QAK */ - - /* Mark heap header as modified */ - if(H5HF_hdr_dirty(dxpl_id, hdr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_iblock_adj_free() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_man_iblock_place_dblock - * - * Purpose: Find indirect block with location for placing a direct block - * - * Note: Creates necessary indirect blocks - * - * Return: Pointer to indirect block on success, NULL on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 14 2006 - * - *------------------------------------------------------------------------- - */ -static H5HF_indirect_t * -H5HF_man_iblock_place_dblock(H5HF_t *hdr, hid_t dxpl_id, size_t min_dblock_size, - haddr_t *addr_p, size_t *entry_p, size_t *dblock_size) -{ - 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) -#ifdef QAK -HDfprintf(stderr, "%s: min_dblock_size = %Zu\n", FUNC, min_dblock_size); -#endif /* QAK */ - - /* - * Check arguments. - */ - HDassert(hdr); - HDassert(min_dblock_size > 0); - HDassert(addr_p); - - /* Check for creating first indirect block */ - if(hdr->man_dtable.curr_root_rows == 0) { - H5HF_direct_t *dblock; /* Pointer to direct block to query */ - hbool_t have_direct_block; /* Flag to indicate a direct block already exists */ - unsigned nrows; /* Number of rows for root indirect block */ - -#ifdef QAK -HDfprintf(stderr, "%s: creating first indirect block\n", FUNC); -#endif /* QAK */ - /* Check for allocating entire root indirect block initially */ - if(hdr->man_dtable.cparam.start_root_rows == 0) - nrows = hdr->man_dtable.max_root_rows; - else { - unsigned rows_needed; /* Number of rows needed to get to direct block size */ - - nrows = hdr->man_dtable.cparam.start_root_rows; - rows_needed = 2 + (H5V_log2_of2(min_dblock_size) - H5V_log2_of2(hdr->man_dtable.cparam.start_block_size)); - if(nrows < rows_needed) - nrows = rows_needed; - } /* end else */ -#ifdef QAK -HDfprintf(stderr, "%s: nrows = %u\n", FUNC, nrows); -#endif /* QAK */ - - /* Allocate root indirect block */ - if(H5HF_man_iblock_create(hdr, dxpl_id, (hsize_t)0, nrows, hdr->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: iblock_addr = %a\n", FUNC, iblock_addr); -#endif /* QAK */ - - /* Move current direct block (used as root) into new indirect block */ - - /* Lock new indirect block */ - if(NULL == (iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &nrows, hdr, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") - - /* Check if there's already a direct block as root) */ - have_direct_block = H5F_addr_defined(hdr->man_dtable.table_addr); - if(have_direct_block) { - /* Lock first (root) direct block */ - if(NULL == (dblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, hdr->man_dtable.table_addr, &hdr->man_dtable.cparam.start_block_size, hdr, H5AC_READ))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap direct block") - - /* Point indirect block at direct block to add */ - iblock->ents[0].addr = hdr->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 */ - dblock->parent = iblock; - dblock->par_entry = 0; - dblock->par_addr = iblock->addr; - dblock->par_nrows = iblock->nrows; - if(H5HF_iblock_incr(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block") - - /* Unlock first (root) direct block */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, hdr->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; - - /* Increment size of next block from this indirect block */ - /* (account for the already existing direct block */ - if(H5HF_man_iblock_inc_loc(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't advance fractal heap block location") - } /* end if */ - - /* Check for skipping over direct blocks, in order to get to large enough block */ - if(min_dblock_size > iblock->next_size) { - H5HF_section_free_node_t *sec_node; /* Pointer to free list section for range */ - size_t dblock_free_space; /* Size of free space for direct block */ - hsize_t range; /* Size range skipped over */ - unsigned cur_entry; /* Current entry */ - unsigned u, v; /* Local index variables */ - - /* Initialize information for rows skipped over */ - cur_entry = (unsigned)have_direct_block; - range = 0; - for(u = 0; u < (nrows - 1); u++) { - /* Compute free space in direct blocks for this row */ - dblock_free_space = hdr->man_dtable.row_block_size[u] - - (H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, hdr->man_dtable.row_block_size[u]) - + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr)); - - /* Initialize information for this row */ - if(u == 0 && have_direct_block) - v = 1; - else - v = 0; - for(; v < hdr->man_dtable.cparam.width; v++) { - /* Initialize entry for this row */ - iblock->ents[cur_entry].addr = HADDR_UNDEF; - iblock->ents[cur_entry].free_space = dblock_free_space; - - /* Increment block and heap's free space */ - if(H5HF_man_iblock_adj_free(dxpl_id, iblock, (ssize_t)dblock_free_space) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, NULL, "can't adjust free space for indirect block & parents") - - /* Increment range skipped */ - range += hdr->man_dtable.row_block_size[u]; - - /* Move to next entry */ - cur_entry++; - } /* end for */ - } /* end for */ - - /* Set indirect block's "next entry" information */ - iblock->next_col = 0; - iblock->next_row = u; - iblock->next_size = hdr->man_dtable.row_block_size[u]; - iblock->next_entry = cur_entry; - HDassert(iblock->next_size == min_dblock_size); - - /* Create free space section for blocks skipped over */ - - /* Create free list section node for blocks skipped over */ - if(NULL == (sec_node = H5FL_MALLOC(H5HF_section_free_node_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for direct block free list section") - - /* Set section's information */ - sec_node->sect_addr = (hsize_t)have_direct_block * hdr->man_dtable.row_block_size[0]; /* Range starts at offset 0 in the heap */ - sec_node->sect_size = dblock_free_space; - sec_node->type = H5HF_SECT_RANGE; - sec_node->u.range.iblock_addr = iblock->addr; - sec_node->u.range.iblock_nrows = iblock->nrows; - sec_node->u.range.entry = (unsigned)have_direct_block; - sec_node->u.range.num_entries = cur_entry - (unsigned)have_direct_block; - sec_node->u.range.range = range; - - /* Add new free space to the global list of space */ - if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't add indirect block free space to global list") - } /* end else */ - - /* Mark indirect block as modified */ - if(H5HF_iblock_dirty(dxpl_id, iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, NULL, "can't mark indirect block as dirty") - - /* Point heap header at new indirect block */ - hdr->man_dtable.curr_root_rows = nrows; - hdr->man_dtable.table_addr = iblock_addr; - - /* Mark heap header as modified */ - hdr->dirty = TRUE; - } /* end if */ - else { -#ifdef QAK -HDfprintf(stderr, "%s: searching root indirect block\n", FUNC); -#endif /* QAK */ - - /* Lock root indirect block */ - iblock_addr = hdr->man_dtable.table_addr; - if(NULL == (iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &hdr->man_dtable.curr_root_rows, hdr, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") - -#ifdef QAK -HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows); -#endif /* QAK */ - /* 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_row == 1) - iblock->next_size = hdr->man_dtable.cparam.start_block_size; - - /* Compute new # of rows in indirect block */ - 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 -*/ - /* Free previous indirect block disk space */ - if(H5MF_xfree(hdr->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->nrows = new_nrows; - iblock->size = H5HF_MAN_INDIRECT_SIZE(hdr, iblock); - - /* Allocate space for the new indirect block on disk */ - if(HADDR_UNDEF == (new_addr = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, (hsize_t)iblock->size))) - HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, NULL, "file allocation failed for fractal heap indirect block") - - /* Re-allocate direct block entry table */ - if(NULL == (iblock->ents = H5FL_SEQ_REALLOC(H5HF_indirect_ent_t, iblock->ents, (iblock->nrows * hdr->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_row * hdr->man_dtable.cparam.width); - u < (iblock->nrows * hdr->man_dtable.cparam.width); - u++) { - iblock->ents[u].addr = HADDR_UNDEF; - iblock->ents[u].free_space = 0; - } /* end for */ - - /* Mark indirect block as dirty */ - if(H5HF_iblock_dirty(dxpl_id, iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, NULL, "can't mark indirect block as dirty") - - /* Release the indirect block (marked as dirty) */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, H5AC__DIRTIED_FLAG) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release fractal heap indirect block") - iblock = NULL; - - /* Move object in cache */ - if(H5AC_rename(hdr->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 */ - hdr->man_dtable.curr_root_rows = new_nrows; - hdr->man_dtable.table_addr = iblock_addr = new_addr; - - /* Mark heap header as modified */ - hdr->dirty = TRUE; - - /* Lock root indirect block (again) */ - if(NULL == (iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &hdr->man_dtable.curr_root_rows, hdr, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") - iblock->addr = iblock_addr; - } /* end if */ - -#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 >= hdr->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) - hdr->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)) { - hsize_t new_iblock_off; /* Direct block offset in heap address space */ -#ifdef QAK -HDfprintf(stderr, "%s: Allocating new indirect block\n", FUNC); -#endif /* QAK */ - /* Compute the direct block's offset in the heap's address space */ - new_iblock_off = iblock->block_off; - new_iblock_off += hdr->man_dtable.row_block_off[iblock->next_entry / hdr->man_dtable.cparam.width]; - new_iblock_off += hdr->man_dtable.row_block_size[iblock->next_entry / hdr->man_dtable.cparam.width] * (iblock->next_entry % hdr->man_dtable.cparam.width); - - /* Allocate new indirect block */ - if(H5HF_man_iblock_create(hdr, dxpl_id, new_iblock_off, nrows, nrows, &new_iblock_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate fractal heap indirect block") - - /* Lock new indirect block */ - if(NULL == (new_iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, new_iblock_addr, &nrows, hdr, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") - - /* Set parent information */ - HDassert(new_iblock->parent == NULL); - new_iblock->parent = iblock; - new_iblock->par_entry = iblock->next_entry; - new_iblock->par_nrows = iblock->nrows; - new_iblock->par_addr = iblock->addr; - if(H5HF_iblock_incr(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block") - - /* Point current indirect block at new indirect block */ - iblock->ents[iblock->next_entry].addr = new_iblock_addr; - - /* Mark current indirect block as modified */ - if(H5HF_iblock_dirty(dxpl_id, iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, NULL, "can't mark indirect block as dirty") - - /* 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 */ - if(NULL == (new_iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, new_iblock_addr, &nrows, hdr, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") - } /* end else */ -#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 */ - - /* Release the current indirect block (possibly marked as dirty) */ - if(H5AC_unprotect(hdr->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; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_iblock_place_dblock() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_man_iblock_alloc_range - * - * Purpose: Allocate a "single" section for an object, out of a "range" - * section - * - * Note: Creates necessary direct & indirect blocks - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 28 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HF_man_iblock_alloc_range(H5HF_t *hdr, hid_t dxpl_id, - H5HF_section_free_node_t **sec_node, size_t obj_size) -{ - H5HF_indirect_t *iblock; /* Pointer to indirect block */ - haddr_t iblock_addr; /* Indirect block's address */ - haddr_t dblock_addr; /* Direct block's address */ - unsigned iblock_nrows; /* Indirect block's number of rows */ - H5HF_section_free_node_t *dblock_sec_node = NULL; /* Pointer to direct block's section node */ - H5HF_section_free_node_t *old_sec_node = *sec_node; /* Pointer to old section node */ - size_t full_obj_size; /* Size of object including metadata */ - unsigned cur_entry; /* Current entry in indirect block */ - unsigned cur_row; /* Current row in indirect block */ - size_t row_size; /* Size of objects in current row */ - hsize_t range_covered; /* Range covered while searching for block to use */ - unsigned u; /* Local index variable */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_alloc_range) - - /* - * Check arguments. - */ - HDassert(hdr); - HDassert(sec_node && *sec_node); - HDassert(obj_size > 0); - - /* Compute info about range */ - cur_entry = old_sec_node->u.range.entry; - - /* Check for range covering indirect blocks */ - if((cur_entry / hdr->man_dtable.cparam.width) >= hdr->man_dtable.max_direct_rows || - ((cur_entry + old_sec_node->u.range.num_entries) / hdr->man_dtable.cparam.width) - >= hdr->man_dtable.max_direct_rows) { -HDfprintf(stderr, "%s: Can't handle range sections over indirect blocks yet\n", FUNC); -HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'range' free space sections over indirect blocks not supported yet") - } /* end if */ - - /* Get information about indirect block covering section */ - /* (Allow for root indirect block being resized) */ - iblock_addr = old_sec_node->u.range.iblock_addr; - if(H5F_addr_eq(iblock_addr, hdr->man_dtable.table_addr)) - iblock_nrows = hdr->man_dtable.curr_root_rows; - else - iblock_nrows = old_sec_node->u.range.iblock_nrows; - - /* Get a pointer to the indirect block covering the range */ - if(NULL == (iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &iblock_nrows, hdr, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") - - /* Compute size of object, with metadata overhead */ - full_obj_size = obj_size + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr); - - /* Look for first direct block that will fulfill request */ - range_covered = 0; - for(u = 0; u < old_sec_node->u.range.num_entries; ) { - unsigned skip_blocks; /* # of blocks to skip over to next row */ - - /* Compute informatio about current row */ - cur_row = cur_entry / hdr->man_dtable.cparam.width; - row_size = hdr->man_dtable.row_block_size[cur_row]; - - /* Check if first available block in this row will hold block */ - if((H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, row_size) + full_obj_size) <= row_size) - break; - - /* Compute number of blocks to skip in row */ - skip_blocks = ((cur_row + 1) * hdr->man_dtable.cparam.width) - cur_entry; - - /* Advance values to beginning of next row */ - range_covered += row_size * skip_blocks; - u += skip_blocks; - cur_entry += skip_blocks; - } /* end for */ -#ifdef QAK -HDfprintf(stderr, "%s: cur_entry = %u, cur_row = %u, row_size = %Zu\n", FUNC, cur_entry, cur_row, row_size); -HDfprintf(stderr, "%s: range_covered = %Hu, u = %u\n", FUNC, range_covered, u); -HDfprintf(stderr, "%s: old_sec_node->u.range.num_entries = %u\n", FUNC, old_sec_node->u.range.num_entries); -#endif /* QAK */ - /* Must find direct block of useful size */ - HDassert(u < old_sec_node->u.range.num_entries); - - /* Create direct block of appropriate size */ - if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, cur_entry, row_size, (hsize_t)(old_sec_node->sect_addr + range_covered), &dblock_addr, &dblock_sec_node) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block") - - /* Hook direct block up to indirect block */ - iblock->ents[cur_entry].addr = dblock_addr; - iblock->ents[cur_entry].free_space = dblock_sec_node->sect_size; - - /* Adjust free space in block & heap */ - if(H5HF_man_iblock_adj_free(dxpl_id, iblock, -(ssize_t)dblock_sec_node->sect_size) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't adjust free space for indirect block & parents") - - /* Break range section up into zero, one or two range sections and add them - * back to the free sections for the file - */ - - /* Check for only single block covered in range section */ - if(old_sec_node->u.range.num_entries == 1) - H5FL_FREE(H5HF_section_free_node_t, old_sec_node); - else { - size_t next_block_size; /* Next entry after block used */ - - /* Check for using first block in range section */ - if(u == 0) { -#ifdef QAK -HDfprintf(stderr, "%s: range type 1\n", FUNC); -#endif /* QAK */ - /* Adjust section information */ - old_sec_node->sect_addr += row_size; - /* Section size stays the same, since we just grabbed the smallest block in the range */ - - /* Adjust range information */ - old_sec_node->u.range.entry++; - old_sec_node->u.range.num_entries--; - old_sec_node->u.range.range -= row_size; - - /* Add section back to free space list */ - if(H5HF_flist_add(hdr->flist, old_sec_node, &old_sec_node->sect_size, &old_sec_node->sect_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list") - } /* end if */ - /* Check for using middle block from range section */ - else if(u < (old_sec_node->u.range.num_entries -1)) { - H5HF_section_free_node_t *new_sec_node; /* Pointer to new free list section for block */ -#ifdef QAK -HDfprintf(stderr, "%s: range type 2\n", FUNC); -#endif /* QAK */ - - /* Create new section node for space after block used */ - if(NULL == (new_sec_node = H5FL_MALLOC(H5HF_section_free_node_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for indirect block free list section") - - /* Set section information for new node */ - new_sec_node->sect_addr = old_sec_node->sect_addr + range_covered + row_size; - new_sec_node->sect_size = old_sec_node->sect_size; - - /* Set range information */ - new_sec_node->type = H5HF_SECT_RANGE; - new_sec_node->u.range.iblock_addr = old_sec_node->u.range.iblock_addr; - new_sec_node->u.range.iblock_nrows = old_sec_node->u.range.iblock_nrows; - new_sec_node->u.range.entry = cur_entry + 1; - new_sec_node->u.range.num_entries = old_sec_node->u.range.num_entries - (u + 1); - new_sec_node->u.range.range = old_sec_node->u.range.range - (range_covered + row_size); - - /* Add new section to free space list */ - if(H5HF_flist_add(hdr->flist, new_sec_node, &new_sec_node->sect_size, &new_sec_node->sect_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list") - - - /* Compute size of block before the one used */ - next_block_size = hdr->man_dtable.row_block_size[(cur_entry - 1) / - hdr->man_dtable.cparam.width]; - - /* Adjust current section information */ - old_sec_node->sect_size = next_block_size - - (H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, row_size) + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr)); - - /* Adjust range information */ - old_sec_node->u.range.num_entries = u; - old_sec_node->u.range.range = range_covered; - - /* Add section back to free space list */ - if(H5HF_flist_add(hdr->flist, old_sec_node, &old_sec_node->sect_size, &old_sec_node->sect_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list") - } /* end if */ - /* Must be using last block in range section */ - else { -#ifdef QAK -HDfprintf(stderr, "%s: range type 3\n", FUNC); -#endif /* QAK */ - /* Compute size of next block after the one used */ - next_block_size = hdr->man_dtable.row_block_size[(cur_entry - 1) / - hdr->man_dtable.cparam.width]; - - /* Adjust section information */ - old_sec_node->sect_size = next_block_size - - (H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, row_size) + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr)); - - /* Adjust range information */ - old_sec_node->u.range.num_entries--; - old_sec_node->u.range.range -= row_size; - - /* Add section back to free space list */ - if(H5HF_flist_add(hdr->flist, old_sec_node, &old_sec_node->sect_size, &old_sec_node->sect_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list") - } /* end else */ - } /* end if */ - - /* Release the indirect block (marked as dirty) */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, H5AC__DIRTIED_FLAG) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") - - /* Point 'sec_node' at new direct block section node */ - *sec_node = dblock_sec_node; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_iblock_alloc_range() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_man_iblock_create - * - * Purpose: Allocate & initialize a managed indirect block - * - * Return: SUCCEED/FAIL - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 6 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HF_man_iblock_create(H5HF_t *hdr, hid_t dxpl_id, - hsize_t block_off, unsigned nrows, unsigned max_rows, haddr_t *addr_p) -{ - H5HF_indirect_t *iblock = NULL; /* Pointer to indirect block */ - size_t u; /* Local index variable */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_create) - - /* - * Check arguments. - */ - HDassert(hdr); - HDassert(nrows > 0); - HDassert(addr_p); - - /* - * Allocate file and memory data structures. - */ - if(NULL == (iblock = H5FL_MALLOC(H5HF_indirect_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fractal heap indirect block") - - /* Reset the metadata cache info for the heap header */ - HDmemset(&iblock->cache_info, 0, sizeof(H5AC_info_t)); - - /* Share common heap information */ - iblock->shared = hdr; - if(H5HF_hdr_incr(hdr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared heap header") - -#ifdef QAK -HDfprintf(stderr, "%s: nrows = %u, max_nrows = %u\n", FUNC, nrows, max_nrows); -#endif /* QAK */ - /* Set info for direct block */ - iblock->rc = 0; - iblock->parent = NULL; /* Temporary, except for root indirect block */ - iblock->par_entry = 0; - iblock->par_nrows = 0; - iblock->par_addr = HADDR_UNDEF; - iblock->block_off = block_off; - iblock->child_free_space = 0; - iblock->nrows = nrows; - iblock->max_rows = max_rows; - iblock->next_col = 0; - iblock->next_row = 0; - iblock->next_entry = 0; - iblock->next_size = hdr->man_dtable.cparam.start_block_size; - iblock->dirty = TRUE; - iblock->evicted = FALSE; - - /* Compute size of buffer needed for indirect block */ - iblock->size = H5HF_MAN_INDIRECT_SIZE(hdr, iblock); - - /* Allocate indirect block entry tables */ - if(NULL == (iblock->ents = H5FL_SEQ_MALLOC(H5HF_indirect_ent_t, (iblock->nrows * hdr->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->nrows * hdr->man_dtable.cparam.width); u++) { - iblock->ents[u].addr = HADDR_UNDEF; - iblock->ents[u].free_space = 0; - } /* end for */ - - /* Allocate space for the indirect block on disk */ - if(HADDR_UNDEF == (*addr_p = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, (hsize_t)iblock->size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap indirect block") - iblock->addr = *addr_p; - -/* XXX: Update indirect statistics when they are added */ - - /* Cache the new fractal heap header */ - if(H5AC_set(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, *addr_p, iblock, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add fractal heap indirect block to cache") - -done: - if(ret_value < 0) - if(iblock) - (void)H5HF_cache_iblock_dest(hdr->f, iblock); - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_iblock_create() */ - diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h index ab69207..1f1518b 100644 --- a/src/H5HFpkg.h +++ b/src/H5HFpkg.h @@ -93,7 +93,7 @@ ) /* Size of overhead for a direct block */ -#define H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(h, o) ( \ +#define H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(h, s) ( \ /* General metadata fields */ \ H5HF_METADATA_PREFIX_SIZE \ \ @@ -103,7 +103,7 @@ + 2 /* Entry within parent block */ \ + 2 /* # of rows for parent block */ \ + (h)->heap_off_size /* Offset of the block in the heap */ \ - + H5HF_SIZEOF_OFFSET_LEN(o) /* Offset of first descriptor in free list */ \ + + H5HF_SIZEOF_OFFSET_LEN(s) /* Offset of first descriptor in free list */ \ ) #define H5HF_MAN_ABS_DIRECT_OVERHEAD_DBLOCK(h, d) ( \ /* General metadata fields */ \ @@ -165,13 +165,50 @@ typedef struct H5HF_dtable_t { hsize_t num_id_first_row; /* Number of IDs in first row of table */ hsize_t *row_block_size; /* Block size per row of indirect block */ hsize_t *row_block_off; /* Cumulative offset per row of indirect block */ + hsize_t *row_dblock_free; /* Free space in dblocks for this row */ + /* (For indirect block rows, it's the total + * free space in all direct blocks referenced + * from the indirect block + */ } H5HF_dtable_t; /* Fractal heap free list info (forward decl - defined in H5HFflist.c) */ typedef struct H5HF_freelist_t H5HF_freelist_t; -/* Fractal heap free list section info (forward decl - defined in H5HFint.c) */ -typedef struct H5HF_section_free_node_t H5HF_section_free_node_t; +/* Fractal heap free list section info */ +typedef struct H5HF_free_section_t { + haddr_t sect_addr; /* Address of free list section in the file */ + /* (Not actually used as address, used as unique ID for free list node) */ + size_t sect_size; /* Size of free space section */ + /* (section size is "object size", without the metadata overhead, since metadata overhead varies from block to block) */ + /* (for range sections, this is the largest single section within the range) */ + enum {H5HF_SECT_SINGLE, H5HF_SECT_RANGE, H5HF_SECT_INDIRECT} type; /* Type of free space section */ + union { + struct { + haddr_t dblock_addr; /* Address of direct block for free section */ + size_t dblock_size; /* Size of direct block */ + /* (Needed to retrieve direct block) */ + } single; + struct { + haddr_t iblock_addr; /* Address of indirect block for free section */ + unsigned iblock_nrows; /* Number of rows in indirect block */ + /* (Needed to retrieve indirect block) */ + unsigned row; /* Row for range of blocks */ + unsigned col; /* Column for range of blocks */ + unsigned num_entries; /* Number of entries covered */ + } range; + struct { + haddr_t iblock_addr; /* Address of indirect block for free section */ + unsigned iblock_nrows; /* Number of rows in indirect block */ + /* (Needed to retrieve indirect block) */ + unsigned row; /* Row for range of blocks */ + unsigned col; /* Column for range of blocks */ + unsigned num_entries; /* Number of entries covered */ + unsigned indir_row; /* Row for indirect range of blocks */ + unsigned indir_nrows; /* Number of rows in indirect blocks */ + } indirect; + } u; +} H5HF_free_section_t; /* The fractal heap header information */ /* (Each fractal heap header has certain information that is shared across all @@ -337,35 +374,60 @@ H5FL_EXTERN(H5HF_indirect_t); /* Declare a free list to manage the H5HF_indirect_ent_t sequence information */ H5FL_SEQ_EXTERN(H5HF_indirect_ent_t); +/* Declare a free list to manage the H5HF_free_section_t struct */ +H5FL_EXTERN(H5HF_free_section_t); + /******************************/ /* Package Private Prototypes */ /******************************/ /* Routines for managing shared fractal heap header */ -H5_DLL H5HF_t * H5HF_alloc(H5F_t *f); -H5_DLL herr_t H5HF_init(H5HF_t *fh, haddr_t heap_addr, H5HF_create_t *cparam); -H5_DLL herr_t H5HF_finish_init(H5HF_t *fh); +H5_DLL H5HF_t * H5HF_hdr_alloc(H5F_t *f); +H5_DLL herr_t H5HF_hdr_init(H5HF_t *hdr, haddr_t heap_addr, H5HF_create_t *cparam); +H5_DLL herr_t H5HF_hdr_finish_init(H5HF_t *hdr); /* Doubling table routines */ +H5_DLL herr_t H5HF_dtable_init(H5HF_dtable_t *dtable); H5_DLL herr_t H5HF_dtable_dest(H5HF_dtable_t *dtable); +H5_DLL herr_t H5HF_dtable_lookup(const H5HF_dtable_t *dtable, hsize_t off, + unsigned *row, unsigned *col); /* Heap header routines */ H5_DLL herr_t H5HF_cache_hdr_dest_real(H5HF_t *hdr); H5_DLL herr_t H5HF_hdr_incr(H5HF_t *hdr); H5_DLL herr_t H5HF_hdr_decr(H5HF_t *hdr); +H5_DLL herr_t H5HF_hdr_dirty(hid_t dxpl_id, H5HF_t *hdr); +H5_DLL herr_t H5HF_hdr_extend_heap(H5HF_t *hdr, hsize_t new_size, hsize_t extra_free); /* Indirect block routines */ H5_DLL herr_t H5HF_cache_iblock_dest_real(H5HF_indirect_t *iblock); H5_DLL herr_t H5HF_iblock_incr(H5HF_indirect_t *iblock); H5_DLL herr_t H5HF_iblock_decr(H5HF_indirect_t *iblock); - -/* Routines for allocating space */ +H5_DLL herr_t H5HF_iblock_dirty(hid_t dxpl_id, H5HF_indirect_t *iblock); +H5_DLL H5HF_indirect_t * H5HF_man_iblock_place_dblock(H5HF_t *fh, hid_t dxpl_id, + size_t min_dblock_size, haddr_t *addr_p, size_t *entry_p, + size_t *dblock_size); +H5_DLL herr_t H5HF_man_iblock_alloc_range(H5HF_t *hdr, hid_t dxpl_id, + H5HF_free_section_t **sec_node, size_t obj_size); +H5_DLL herr_t H5HF_man_iblock_alloc_indirect(H5HF_t *hdr, hid_t dxpl_id, + H5HF_free_section_t **sec_node, size_t obj_size); + +/* Direct block routines */ +H5_DLL herr_t H5HF_man_dblock_new(H5HF_t *fh, hid_t dxpl_id, size_t request); +H5_DLL herr_t H5HF_man_dblock_create(hid_t dxpl_id, H5HF_t *hdr, + H5HF_indirect_t *par_iblock, unsigned par_entry, size_t block_size, + hsize_t block_off, haddr_t *addr_p, H5HF_free_section_t **ret_sec_node); +H5_DLL herr_t H5HF_man_dblock_adj_free(hid_t dxpl_id, H5HF_direct_t *dblock, ssize_t amt); H5_DLL herr_t H5HF_man_dblock_build_freelist(H5HF_direct_t *dblock, haddr_t dblock_addr); + +/* Routines for internal operations */ +H5_DLL herr_t H5HF_free_section_free_cb(void *item, void UNUSED *key, + void UNUSED *op_data); H5_DLL herr_t H5HF_man_find(H5HF_t *fh, hid_t dxpl_id, size_t request, - H5HF_section_free_node_t **sec_node/*out*/); + H5HF_free_section_t **sec_node/*out*/); H5_DLL herr_t H5HF_man_insert(H5HF_t *fh, hid_t dxpl_id, - H5HF_section_free_node_t *sec_node, size_t obj_size, const void *obj, + H5HF_free_section_t *sec_node, size_t obj_size, const void *obj, void *id); H5_DLL herr_t H5HF_man_read(H5HF_t *fh, hid_t dxpl_id, hsize_t obj_off, size_t obj_len, void *obj); @@ -400,6 +462,8 @@ H5_DLL herr_t H5HF_flist_free(H5HF_freelist_t *flist); #ifdef H5HF_TESTING H5_DLL herr_t H5HF_get_cparam_test(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr, H5HF_create_t *cparam); +H5_DLL hsize_t H5HF_get_dblock_free_test(H5F_t *f, hid_t dxpl_id, + haddr_t fh_addr, unsigned row); #endif /* H5HF_TESTING */ #endif /* _H5HFpkg_H */ diff --git a/src/H5HFtest.c b/src/H5HFtest.c index 02024b9..c01475c 100644 --- a/src/H5HFtest.c +++ b/src/H5HFtest.c @@ -113,3 +113,46 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* H5HF_get_cparam_test() */ + +/*------------------------------------------------------------------------- + * Function: H5HF_get_dblock_free_test + * + * Purpose: Retrieve the size of direct block free space for a given + * direct or indirect block size + * + * Return: Success: Size of direct block free space + * + * Failure: 0 + * + * Programmer: Quincey Koziol + * Monday, April 10, 2006 + * + *------------------------------------------------------------------------- + */ +hsize_t +H5HF_get_dblock_free_test(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr, unsigned row) +{ + H5HF_t *hdr = NULL; /* Pointer to the fractal heap header */ + hsize_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_get_dblock_free_test) + + /* Check arguments. */ + HDassert(f); + HDassert(H5F_addr_defined(fh_addr)); + + /* Look up the fractal heap header */ + if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, 0, "unable to load fractal heap header") + + /* Return direct block free space */ + ret_value = hdr->man_dtable.row_dblock_free[row]; + +done: + /* Release fractal heap header node */ + if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, hdr, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, 0, "unable to release fractal heap header info") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_get_dblock_free_test() */ + diff --git a/src/H5err.txt b/src/H5err.txt index 58d6341..02a21d8 100644 --- a/src/H5err.txt +++ b/src/H5err.txt @@ -211,6 +211,7 @@ MINOR, MPI, H5E_MPIERRSTR, MPI Error String # Heap errors MINOR, HEAP, H5E_CANTRESTORE, Can't restore condition MINOR, HEAP, H5E_CANTCOMPUTE, Can't compute value +MINOR, HEAP, H5E_CANTEXTEND, Can't extend heap's space # FPHDF5 errors MINOR, FPH5, H5E_CANTRECV, Can't receive messages from processes diff --git a/src/Makefile.am b/src/Makefile.am index c590ee5..a67b5e2 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -55,7 +55,8 @@ libhdf5_la_SOURCES= H5.c H5dbg.c H5A.c H5AC.c H5B.c H5Bcache.c \ H5Gstab.c \ H5Gtest.c \ H5Gtraverse.c \ - H5HF.c H5HFcache.c H5HFdbg.c H5HFflist.c H5HFint.c H5HFstat.c H5HFtest.c \ + H5HF.c H5HFcache.c H5HFdbg.c H5HFdblock.c H5HDdtable.c H5HFflist.c \ + H5HFhdr.c H5HFiblock.c H5HFint.c H5HFstat.c H5HFtest.c \ H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5MF.c H5MM.c \ H5MP.c H5MPtest.c \ H5O.c \ diff --git a/src/Makefile.in b/src/Makefile.in index 0ac1a3c..7d5075a 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -94,6 +94,10 @@ am_libhdf5_la_OBJECTS = H5.lo H5dbg.lo H5A.lo H5AC.lo H5B.lo \ H5FPserver.lo H5FS.lo H5G.lo H5Gent.lo H5Glink.lo H5Gloc.lo \ H5Gname.lo H5Gnode.lo H5Gobj.lo H5Goh.lo H5Gstab.lo H5Gtest.lo \ H5Gtraverse.lo H5HF.lo H5HFcache.lo H5HFdbg.lo H5HFflist.lo \ + H5HFdblock.lo \ + H5HFdtable.lo \ + H5HFhdr.lo \ + H5HFiblock.lo \ H5HFint.lo H5HFstat.lo H5HFtest.lo H5HG.lo H5HGdbg.lo H5HL.lo \ H5HLdbg.lo H5HP.lo H5I.lo H5MF.lo H5MM.lo H5MP.lo H5MPtest.lo \ H5O.lo H5Oattr.lo H5Obogus.lo H5Ocache.lo H5Ocont.lo \ @@ -410,7 +414,12 @@ libhdf5_la_SOURCES = H5.c H5dbg.c H5A.c H5AC.c H5B.c H5Bcache.c \ H5Gstab.c \ H5Gtest.c \ H5Gtraverse.c \ - H5HF.c H5HFcache.c H5HFdbg.c H5HFflist.c H5HFint.c H5HFstat.c H5HFtest.c \ + H5HF.c H5HFcache.c H5HFdbg.c H5HFflist.c \ + H5HFdblock.c \ + H5HFdtable.c \ + H5HFhdr.c \ + H5HFiblock.c \ + H5HFint.c H5HFstat.c H5HFtest.c \ H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5MF.c H5MM.c \ H5MP.c H5MPtest.c \ H5O.c \ @@ -624,6 +633,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFcache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFdbg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFflist.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFdblock.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFdtable.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFhdr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFiblock.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFstat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFtest.Plo@am__quote@ diff --git a/test/fheap.c b/test/fheap.c index 8f2bbc7..489913f 100644 --- a/test/fheap.c +++ b/test/fheap.c @@ -30,76 +30,38 @@ #include "H5MMprivate.h" /* Memory management */ #include "H5Vprivate.h" /* Vectors and arrays */ +/* Object size macros */ +#define SMALL_OBJ_SIZE1 10 +#define SMALL_OBJ_SIZE2 20 + /* "Small" heap creation parameters */ #define SMALL_ADDRMAP H5HF_ABSOLUTE /* Heap address mapping */ -#define SMALL_STAND_SIZE (8 * 1024) /* Standalone obj. min. size */ +#define SMALL_STAND_SIZE (32 * 1024) /* Standalone obj. min. size */ #define SMALL_MAN_WIDTH 4 /* Managed obj. table width */ #define SMALL_MAN_START_BLOCK_SIZE 512 /* Managed obj. starting block size */ #define SMALL_MAN_MAX_DIRECT_SIZE (64 * 1024) /* Managed obj. max. direct block size */ #define SMALL_MAN_MAX_INDEX 32 /* Managed obj. # of bits for total heap size */ #define SMALL_MAN_START_ROOT_ROWS 1 /* Managed obj. starting # of root indirect block rows */ -/* "Standard" heap creation parameters */ -#define STD_ADDRMAP H5HF_ABSOLUTE /* Heap address mapping */ -#define STD_STAND_SIZE (64 * 1024) /* Standalone obj. min. size */ -#define STD_MAN_WIDTH 32 /* Managed obj. table width */ -#define STD_MAN_START_BLOCK_SIZE 1024 /* Managed obj. starting block size */ -#define STD_MAN_MAX_DIRECT_SIZE (1024 * 1024) /* Managed obj. max. direct block size */ -#define STD_MAN_MAX_INDEX 64 /* Managed obj. # of bits for total heap size */ -#define STD_MAN_START_ROOT_ROWS 1 /* Managed obj. starting # of root indirect block rows */ +/* Define this macro to enable all insertion tests */ +/* #define ALL_INSERT_TESTS */ -/* Heap metadata */ +/* Heap metadata macros */ #define DBLOCK_OVERHEAD 32 /* # of bytes in direct block overhead */ #define OBJ_PREFIX_LEN 1 /* # of bytes in object prefix overhead */ #define HEAP_ID_LEN 12 /* # of bytes to use for heap ID */ +#define DBLOCK_FREE(f, dxpl, a, r) H5HF_get_dblock_free_test(f, dxpl, a, r) const char *FILENAME[] = { "fheap", NULL }; -static int init_std_cparam(H5HF_create_t *cparam); static int check_stats(H5F_t *f, hid_t dxpl, haddr_t fh_addr, hsize_t total_size, hsize_t man_size, hsize_t std_size, hsize_t man_free_space, hsize_t nobjs); /*------------------------------------------------------------------------- - * Function: init_std_cparam - * - * Purpose: Initialize heap creation parameter structure with standard - * settings - * - * Return: Success: 0 - * - * Failure: 1 - * - * Programmer: Quincey Koziol - * Monday, February 27, 2006 - * - *------------------------------------------------------------------------- - */ -static int -init_std_cparam(H5HF_create_t *cparam) -{ - /* Wipe out background */ - HDmemset(cparam, 0, sizeof(H5HF_create_t)); - - /* General parameters */ - cparam->addrmap = STD_ADDRMAP; - cparam->standalone_size = STD_STAND_SIZE; - - /* Managed object doubling-table parameters */ - cparam->managed.width = STD_MAN_WIDTH; - cparam->managed.start_block_size = STD_MAN_START_BLOCK_SIZE; - cparam->managed.max_direct_size = STD_MAN_MAX_DIRECT_SIZE; - cparam->managed.max_index = STD_MAN_MAX_INDEX; - cparam->managed.start_root_rows = STD_MAN_START_ROOT_ROWS; - - return(0); -} /* init_std_cparam() */ - - -/*------------------------------------------------------------------------- * Function: init_small_cparam * * Purpose: Initialize heap creation parameter structure with small @@ -188,9 +150,74 @@ error: /*------------------------------------------------------------------------- + * Function: add_obj + * + * Purpose: Add an object to heap + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, April 10, 2006 + * + *------------------------------------------------------------------------- + */ +static int +add_obj(H5F_t *f, hid_t dxpl, haddr_t fh_addr, + hsize_t heap_size, hsize_t *free_space, unsigned *nobjs_ptr, + unsigned obj_init, size_t obj_size, hbool_t will_fill_heap) +{ + unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object inserted */ + unsigned char *obj = NULL; /* Buffer for object to insert */ + unsigned char *robj = NULL; /* Buffer for reading object */ + size_t u; /* Local counting variable */ + + /* Sanity check */ + HDassert(nobjs_ptr); + HDassert(free_space); + + /* Initialize object buffer */ + obj = H5MM_malloc(obj_size); + for(u = 0; u < obj_size; u++) + obj[u] = u + obj_init; + + /* Insert object */ + HDmemset(heap_id, 0, sizeof(heap_id)); + if(H5HF_insert(f, dxpl, fh_addr, obj_size, obj, heap_id) < 0) + FAIL_STACK_ERROR + + /* Increment the number of objects */ + (*nobjs_ptr)++; + + /* Check free space left in heap */ + *free_space -= obj_size + (will_fill_heap ? 0 : OBJ_PREFIX_LEN); + if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, heap_size, heap_size, (hsize_t)0, *free_space, (hsize_t)*nobjs_ptr)) + FAIL_STACK_ERROR + + /* Read in object */ + robj = H5MM_malloc(obj_size); + if(H5HF_read(f, dxpl, fh_addr, heap_id, robj) < 0) + FAIL_STACK_ERROR + if(HDmemcmp(obj, robj, obj_size)) + FAIL_STACK_ERROR + + /* Operations succeeded */ + H5MM_xfree(obj); + H5MM_xfree(robj); + return(0); + +error: + H5MM_xfree(obj); + H5MM_xfree(robj); + return(1); +} /* add_obj() */ + + +/*------------------------------------------------------------------------- * Function: fill_heap * - * Purpose: Insert (small) objects to fill up the free space in a heap + * Purpose: Insert (small) objects to fill up the free space in a heap block * (Generally used to create & fill up a new direct block) * * Return: Success: 0 @@ -205,15 +232,14 @@ error: static int fill_heap(H5F_t *f, hid_t dxpl, haddr_t fh_addr, const H5HF_create_t *cparam, hsize_t heap_size, size_t block_size, - hsize_t extra_free, - unsigned start_nobjs, unsigned *nobjs_ptr) + hsize_t extra_free, unsigned *nobjs_ptr) { H5HF_stat_t heap_stats; /* Statistics about the heap */ unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object inserted */ hsize_t free_space; /* Size of free space in heap */ - 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 char obj[SMALL_OBJ_SIZE1]; /* Buffer for object to insert */ + unsigned char robj[SMALL_OBJ_SIZE1]; /* Buffer for reading object */ + size_t num_ids = 0; /* # of heap IDs in array */ size_t alloc_ids = 0; /* # of heap IDs allocated in array */ unsigned char *ids = NULL; /* Array of heap IDs */ size_t data_size; /* Size of data portion of heap block */ @@ -222,15 +248,12 @@ fill_heap(H5F_t *f, hid_t dxpl, haddr_t fh_addr, const H5HF_create_t *cparam, size_t last_obj_len; /* Size of last object inserted into heap */ unsigned u, v; /* Local index variable */ + /* Sanity check */ + HDassert(nobjs_ptr); + /* Initialize variables */ - if(block_size <= (64 * 1024)) { - data_size = block_size - (OBJ_PREFIX_LEN + DBLOCK_OVERHEAD + cparam->managed.max_index / 8); /* '28' is the size of the direct block's overhead */ - free_overhead = 4; - } /* end if */ - else { - data_size = block_size - (OBJ_PREFIX_LEN + DBLOCK_OVERHEAD + 1 + cparam->managed.max_index / 8); /* '29' is the size of the direct block's overhead */ - free_overhead = 6; - } /* end else */ + data_size = block_size - (OBJ_PREFIX_LEN + DBLOCK_OVERHEAD + cparam->managed.max_index / 8); /* the size of the direct block's overhead */ + free_overhead = 4; /* Initialize object buffer */ for(u = 0; u < sizeof(obj); u++) @@ -242,22 +265,22 @@ fill_heap(H5F_t *f, hid_t dxpl, haddr_t fh_addr, const H5HF_create_t *cparam, FAIL_STACK_ERROR /* Increment object count */ - nobjs++; + num_ids++; /* Check for needing to increase size of heap ID array */ - if(nobjs > alloc_ids) { + if(num_ids > alloc_ids) { alloc_ids = MAX(1024, (alloc_ids * 2)); if(NULL == (ids = H5MM_realloc(ids, HEAP_ID_LEN * alloc_ids))) FAIL_STACK_ERROR } /* end if */ - HDmemcpy(&ids[(nobjs - 1) * HEAP_ID_LEN], heap_id, HEAP_ID_LEN); + HDmemcpy(&ids[(num_ids - 1) * HEAP_ID_LEN], heap_id, HEAP_ID_LEN); - free_space = extra_free + (data_size - (nobjs * (sizeof(obj) + OBJ_PREFIX_LEN))); + free_space = extra_free + (data_size - (num_ids * (sizeof(obj) + OBJ_PREFIX_LEN))); #ifdef QAK HDfprintf(stderr, "extra_free = %Hu\n", extra_free); HDfprintf(stderr, "free_space = %Hu\n", free_space); #endif /* QAK */ - if(check_stats(f, dxpl, fh_addr, heap_size, heap_size, (hsize_t)0, free_space, (hsize_t)(start_nobjs + nobjs))) + if(check_stats(f, dxpl, fh_addr, heap_size, heap_size, (hsize_t)0, free_space, (hsize_t)(*nobjs_ptr + num_ids))) FAIL_STACK_ERROR /* Get statistics for heap */ @@ -269,22 +292,22 @@ HDfprintf(stderr, "free_space = %Hu\n", free_space); while((heap_stats.man_free_space - extra_free) > (sizeof(obj) + OBJ_PREFIX_LEN)) { /* Initialize object buffer */ for(u = 0; u < sizeof(obj); u++) - obj[u] = u + nobjs; + obj[u] = u + num_ids; HDmemset(heap_id, 0, sizeof(heap_id)); if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj), obj, heap_id) < 0) FAIL_STACK_ERROR /* Increment object count */ - nobjs++; + num_ids++; /* Check for needing to increase size of heap ID array */ - if(nobjs > alloc_ids) { + if(num_ids > alloc_ids) { alloc_ids = MAX(1024, (alloc_ids * 2)); if(NULL == (ids = H5MM_realloc(ids, HEAP_ID_LEN * alloc_ids))) FAIL_STACK_ERROR } /* end if */ - HDmemcpy(&ids[(nobjs - 1) * HEAP_ID_LEN], heap_id, HEAP_ID_LEN); + HDmemcpy(&ids[(num_ids - 1) * HEAP_ID_LEN], heap_id, HEAP_ID_LEN); /* Check stats for heap */ if(((heap_stats.man_free_space - extra_free) - sizeof(obj)) <= free_overhead) @@ -292,11 +315,11 @@ HDfprintf(stderr, "free_space = %Hu\n", free_space); #ifdef QAK HDfprintf(stderr, "free_frag_size = %u\n", free_frag_size); #endif /* QAK */ - free_space = extra_free + (data_size - ((nobjs * (sizeof(obj) + OBJ_PREFIX_LEN)) + free_frag_size)); + free_space = extra_free + (data_size - ((num_ids * (sizeof(obj) + OBJ_PREFIX_LEN)) + free_frag_size)); #ifdef QAK HDfprintf(stderr, "free_space = %Hu\n", free_space); #endif /* QAK */ - if(check_stats(f, dxpl, fh_addr, heap_size, heap_size, (hsize_t)0, free_space, (hsize_t)(start_nobjs + nobjs))) + if(check_stats(f, dxpl, fh_addr, heap_size, heap_size, (hsize_t)0, free_space, (hsize_t)(num_ids + *nobjs_ptr))) FAIL_STACK_ERROR /* Get statistics for heap */ @@ -310,7 +333,7 @@ HDfprintf(stderr, "free_space = %Hu\n", free_space); /* Initialize object buffer */ for(u = 0; u < sizeof(obj); u++) - obj[u] = u + nobjs; + obj[u] = u + num_ids; /* Insert last object into the heap, using the remaining free space */ HDmemset(heap_id, 0, sizeof(heap_id)); @@ -318,25 +341,25 @@ HDfprintf(stderr, "free_space = %Hu\n", free_space); FAIL_STACK_ERROR /* Increment object count */ - nobjs++; + num_ids++; /* Check for needing to increase size of heap ID array */ - if(nobjs > alloc_ids) { + if(num_ids > alloc_ids) { alloc_ids = MAX(1024, (alloc_ids * 2)); if(NULL == (ids = H5MM_realloc(ids, HEAP_ID_LEN * alloc_ids))) FAIL_STACK_ERROR } /* end if */ - HDmemcpy(&ids[(nobjs - 1) * HEAP_ID_LEN], heap_id, HEAP_ID_LEN); + HDmemcpy(&ids[(num_ids - 1) * HEAP_ID_LEN], heap_id, HEAP_ID_LEN); /* Verify that the heap is full */ - if(check_stats(f, dxpl, fh_addr, heap_size, heap_size, (hsize_t)0, extra_free, (hsize_t)(start_nobjs + nobjs))) + if(check_stats(f, dxpl, fh_addr, heap_size, heap_size, (hsize_t)0, extra_free, (hsize_t)(num_ids + *nobjs_ptr))) 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++) { + for(v = 0; v < num_ids; v++) { /* Initialize object buffer */ for(u = 0; u < sizeof(obj); u++) obj[u] = u + v; @@ -344,13 +367,12 @@ HDfprintf(stderr, "free_space = %Hu\n", free_space); /* Read in object */ if(H5HF_read(f, dxpl, fh_addr, &ids[v * HEAP_ID_LEN], robj) < 0) FAIL_STACK_ERROR - if(HDmemcmp(obj, robj, (v == (nobjs - 1) ? last_obj_len : sizeof(obj)))) + if(HDmemcmp(obj, robj, (v == (num_ids - 1) ? last_obj_len : sizeof(obj)))) FAIL_STACK_ERROR } /* end for */ - /* Set the number of objects, if requested */ - if(nobjs_ptr) - *nobjs_ptr = nobjs; + /* Set the number of objects inserted */ + *nobjs_ptr += num_ids; /* Operations succeeded */ H5MM_xfree(ids); @@ -363,6 +385,571 @@ error: /*------------------------------------------------------------------------- + * Function: fill_root_row + * + * Purpose: Fill up a row of direct blocks in the root indirect block + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, April 10, 2006 + * + *------------------------------------------------------------------------- + */ +static int +fill_root_row(H5F_t *f, hid_t dxpl, haddr_t fh_addr, const H5HF_create_t *cparam, + hsize_t *base_heap_size, hsize_t *base_free_space, unsigned row, + unsigned *nobjs_ptr) +{ + hsize_t first_free_space; /* Size of free space in heap after the first block */ + hsize_t all_free_space; /* Size of free space in heap after all blocks */ + hsize_t free_space; /* Size of free space in heap */ + hsize_t first_heap_size; /* Total size of the heap after the first block */ + hsize_t all_heap_size; /* Total size of the heap after all blocks */ + hsize_t heap_size; /* Total size of the heap */ + size_t block_size; /* Block size for row */ + unsigned expand_rows; /* # of rows to expand heap by */ + unsigned u; /* Local index variable */ + + /* Sanity check */ + HDassert(nobjs_ptr); + HDassert(base_heap_size); + HDassert(base_free_space); + + /* Get the correct size for blocks in this row */ + if(row == 0) + block_size = cparam->managed.start_block_size; + else + block_size = cparam->managed.start_block_size * (1 << (row - 1)); + + /* Compute the number of rows to expand heap by */ + if(row < 2) + expand_rows = 1; + else if(POWER_OF_TWO(row)) + expand_rows = row; + else + expand_rows = 0; + + /* Compute first block & all blocks heap size & free space */ + if(*base_heap_size == 0) { + first_heap_size = block_size; + first_free_space = DBLOCK_FREE(f, dxpl, fh_addr, row); + all_heap_size = cparam->managed.width * block_size; + all_free_space = (cparam->managed.width - 1) * DBLOCK_FREE(f, dxpl, fh_addr, row); + } /* end if */ + else if(expand_rows ==0) { + all_heap_size = *base_heap_size; + all_free_space = *base_free_space; + first_heap_size = all_heap_size; + first_free_space = all_free_space; + all_free_space -= DBLOCK_FREE(f, dxpl, fh_addr, row); /* Account for shift from first free space */ + } /* end if */ + else { + hsize_t block_mult; /* Base block size multiplier */ + + all_heap_size = *base_heap_size; + all_free_space = 0; + block_mult = 1; + for(u = 0; u < expand_rows; u++) { + all_heap_size += cparam->managed.width * block_size * block_mult; + all_free_space += cparam->managed.width * DBLOCK_FREE(f, dxpl, fh_addr, row + u); + block_mult *= 2; + } /* end for */ + first_heap_size = all_heap_size; + first_free_space = all_free_space; + all_free_space -= DBLOCK_FREE(f, dxpl, fh_addr, row); /* Account for shift from first free space */ + } /* end else */ + + /* Loop over filling direct blocks, until first root indirect row is full */ + heap_size = first_heap_size; + free_space = first_free_space; + for(u = 0; u < cparam->managed.width; u++) { + /* Set heap's size & free space correctly */ + if(u == 1) { + heap_size = all_heap_size; + free_space = all_free_space; + } /* end if */ + free_space -= DBLOCK_FREE(f, dxpl, fh_addr, row); + + /* Fill a direct heap block up */ + if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, free_space, nobjs_ptr)) + FAIL_STACK_ERROR + } /* end for */ + + /* Update heap size & free space */ + *base_heap_size = heap_size; + *base_free_space = free_space; + + /* Operations succeeded */ + return(0); + +error: + return(1); +} /* fill_root_row() */ + + +/*------------------------------------------------------------------------- + * Function: fill_row + * + * Purpose: Fill up a row of direct blocks in an non-root indirect block + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, April 10, 2006 + * + *------------------------------------------------------------------------- + */ +static int +fill_row(H5F_t *f, hid_t dxpl, haddr_t fh_addr, const H5HF_create_t *cparam, + hsize_t *heap_size, hsize_t *free_space, unsigned row, + unsigned *nobjs_ptr) +{ + size_t block_size; /* Block size for row */ + unsigned u; /* Local index variable */ + + /* Sanity check */ + HDassert(nobjs_ptr); + HDassert(heap_size); + HDassert(free_space); + + /* Get the correct size for blocks in this row */ + if(row == 0) + block_size = cparam->managed.start_block_size; + else + block_size = cparam->managed.start_block_size * (1 << (row - 1)); + + /* Loop over filling direct blocks, until indirect row is full */ + for(u = 0; u < cparam->managed.width; u++) { + /* Fill a direct heap block up */ + *free_space -= DBLOCK_FREE(f, dxpl, fh_addr, row); + if(fill_heap(f, dxpl, fh_addr, cparam, *heap_size, block_size, *free_space, nobjs_ptr)) + FAIL_STACK_ERROR + } /* end for */ + + /* Operations succeeded */ + return(0); + +error: + return(1); +} /* fill_row() */ + + +/*------------------------------------------------------------------------- + * Function: fill_root_direct + * + * Purpose: Insert (small) objects to fill up the free space in all direct + * heap blocks in the root indirect block + * (Generally used to create & fill up direct blocks in a new + * indirect block) + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, April 3, 2006 + * + *------------------------------------------------------------------------- + */ +static int +fill_root_direct(H5F_t *f, hid_t dxpl, haddr_t fh_addr, const H5HF_create_t *cparam, + hsize_t *heap_size, hsize_t *free_space, unsigned *nobjs) +{ + size_t block_size; /* Size of block added */ + unsigned nrows; /* Number of rows inserted */ + + /* Loop over rows */ + block_size = cparam->managed.start_block_size; + nrows = 0; + while(block_size <= cparam->managed.max_direct_size) { + if(fill_root_row(f, dxpl, fh_addr, cparam, heap_size, free_space, nrows, nobjs)) + FAIL_STACK_ERROR + + /* Adjust block size for row */ + if(nrows > 0) + block_size *= 2; + + /* Increment row count */ + nrows++; + } /* end for */ + + /* Operations succeeded */ + return(0); + +error: + return(1); +} /* fill_root_direct() */ + + +/*------------------------------------------------------------------------- + * Function: fill_2nd_indirect + * + * Purpose: Insert (small) objects to fill up the free space in all direct + * heap blocks in a second-level indirect block (which only has + * direct blocks) + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, April 10, 2006 + * + *------------------------------------------------------------------------- + */ +static int +fill_2nd_indirect(H5F_t *f, hid_t dxpl, haddr_t fh_addr, const H5HF_create_t *cparam, + hsize_t *heap_size, hsize_t *free_space, unsigned *nobjs, + size_t iblock_size) +{ + size_t max_dblock_size; /* Max. size of direct block to add */ + size_t dblock_size; /* Size of direct block added */ + unsigned nrows; /* Number of rows inserted */ + + /* Loop over rows */ + nrows = 0; + dblock_size = cparam->managed.start_block_size; + max_dblock_size = dblock_size * (1 << ((H5V_log2_of2(iblock_size / cparam->managed.width) - + (H5V_log2_of2(cparam->managed.start_block_size) + + H5V_log2_of2(cparam->managed.width))) + 1)); + while(dblock_size <= max_dblock_size) { + if(fill_row(f, dxpl, fh_addr, cparam, heap_size, free_space, nrows, nobjs)) + FAIL_STACK_ERROR + + /* Adjust block size for row */ + if(nrows > 0) + dblock_size *= 2; + + /* Increment row count */ + nrows++; + } /* end for */ + + /* Operations succeeded */ + return(0); + +error: + return(1); +} /* fill_2nd_direct() */ + + +/*------------------------------------------------------------------------- + * Function: fill_all_direct + * + * Purpose: Insert (small) objects to fill up the free space in all direct + * heap blocks up to the maximum direct block size + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, April 10, 2006 + * + *------------------------------------------------------------------------- + */ +static int +fill_all_direct(H5F_t *f, hid_t dxpl, haddr_t fh_addr, const H5HF_create_t *cparam, + hsize_t *heap_size, hsize_t *free_space, unsigned *nobjs) +{ + size_t dblock_size; /* Size of direct block added */ + unsigned nrows; /* Number of rows inserted */ + + /* Loop over rows */ + nrows = 0; + dblock_size = cparam->managed.start_block_size; + while(dblock_size <= cparam->managed.max_direct_size) { + if(fill_row(f, dxpl, fh_addr, cparam, heap_size, free_space, nrows, nobjs)) + FAIL_STACK_ERROR + + /* Adjust block size for row */ + if(nrows > 0) + dblock_size *= 2; + + /* Increment row count */ + nrows++; + } /* end for */ + + /* Operations succeeded */ + return(0); + +error: + return(1); +} /* fill_all_direct() */ + + +/*------------------------------------------------------------------------- + * Function: fill_2nd_indirect_row + * + * Purpose: Insert (small) objects to fill up the free space in all direct + * heap blocks in a row of second-level indirect block (which only + * have direct blocks) + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, April 10, 2006 + * + *------------------------------------------------------------------------- + */ +static int +fill_2nd_indirect_row(H5F_t *f, hid_t dxpl, haddr_t fh_addr, const H5HF_create_t *cparam, + hsize_t *heap_size, hsize_t *free_space, unsigned *nobjs, + size_t iblock_size) +{ + unsigned u; /* Local index variable */ + + /* Loop over row of indirect blocks */ + for(u = 0; u < cparam->managed.width; u++) + if(fill_2nd_indirect(f, dxpl, fh_addr, cparam, heap_size, free_space, nobjs, iblock_size)) + FAIL_STACK_ERROR + + /* Operations succeeded */ + return(0); + +error: + return(1); +} /* fill_2nd_direct_row() */ + + +/*------------------------------------------------------------------------- + * Function: fill_all_2nd_indirect_rows + * + * Purpose: Insert (small) objects to fill up the free space in all direct + * heap blocks in all rows of second-level indirect blocks (which only + * have direct blocks) + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, April 10, 2006 + * + *------------------------------------------------------------------------- + */ +static int +fill_all_2nd_indirect_rows(H5F_t *f, hid_t dxpl, haddr_t fh_addr, const H5HF_create_t *cparam, + hsize_t *heap_size, hsize_t *free_space, unsigned *nobjs) +{ + size_t iblock_size; /* Size of indirect block for row */ + unsigned u; /* Local index variable */ + + /* Loop over rows of 2nd level deep indirect blocks */ + iblock_size = 2 * cparam->managed.max_direct_size; + for(u = 0; u < (H5V_log2_of2(cparam->managed.width) + 1); u++) { + if(fill_2nd_indirect_row(f, dxpl, fh_addr, cparam, heap_size, free_space, nobjs, iblock_size)) + FAIL_STACK_ERROR + iblock_size *= 2; + } /* end for */ + + /* Operations succeeded */ + return(0); + +error: + return(1); +} /* fill_2nd_direct_row() */ + + +/*------------------------------------------------------------------------- + * Function: fill_3rd_indirect_row + * + * Purpose: Insert (small) objects to fill up the free space in all direct + * heap blocks in a row of third-level indirect block (which + * have one more level of indirect blocks) + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, April 10, 2006 + * + *------------------------------------------------------------------------- + */ +static int +fill_3rd_indirect_row(H5F_t *f, hid_t dxpl, haddr_t fh_addr, const H5HF_create_t *cparam, + hsize_t *heap_size, hsize_t *free_space, unsigned *nobjs, + unsigned pos) +{ + size_t iblock_size; /* Indirect block's size */ + unsigned u, v; /* Local index variable */ + + /* Loop over row of 3rd level indirect blocks */ + for(u = 0; u < cparam->managed.width; u++) { + /* Fill all direct block rows in third level indirect block */ + if(fill_all_direct(f, dxpl, fh_addr, cparam, heap_size, free_space, nobjs)) + FAIL_STACK_ERROR + + /* Fill rows of recursive indirect blocks in third level indirect block */ + iblock_size = 2 * cparam->managed.max_direct_size; + for(v = 0; v < pos; v++) { + if(fill_2nd_indirect_row(f, dxpl, fh_addr, cparam, heap_size, free_space, nobjs, iblock_size)) + FAIL_STACK_ERROR + iblock_size *= 2; + } /* end for */ + } /* end for */ + + /* Operations succeeded */ + return(0); + +error: + return(1); +} /* fill_3rd_direct_row() */ + + +/*------------------------------------------------------------------------- + * Function: fill_all_3rd_indirect_rows + * + * Purpose: Insert (small) objects to fill up the free space in all direct + * heap blocks in all rows of third-level indirect blocks (which + * have one more level of indirect blocks) + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, April 10, 2006 + * + *------------------------------------------------------------------------- + */ +static int +fill_all_3rd_indirect_rows(H5F_t *f, hid_t dxpl, haddr_t fh_addr, const H5HF_create_t *cparam, + hsize_t *heap_size, hsize_t *free_space, unsigned *nobjs) +{ + unsigned u; /* Local index variable */ + + /* Loop over rows of 3rd level deep indirect blocks */ + for(u = 0; u < (H5V_log2_of2(cparam->managed.width) + 1); u++) { + /* Fill row of 3rd level indirect blocks */ + if(fill_3rd_indirect_row(f, dxpl, fh_addr, cparam, heap_size, free_space, nobjs, u + 1)) + FAIL_STACK_ERROR + } /* end for */ + + /* Operations succeeded */ + return(0); + +error: + return(1); +} /* fill_all_3rd_direct_rows() */ + + +/*------------------------------------------------------------------------- + * Function: fill_4th_indirect_row + * + * Purpose: Insert (small) objects to fill up the free space in all direct + * heap blocks in a row of fourth-level indirect blocks (which + * have two more levels of indirect blocks) + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, April 10, 2006 + * + *------------------------------------------------------------------------- + */ +static int +fill_4th_indirect_row(H5F_t *f, hid_t dxpl, haddr_t fh_addr, const H5HF_create_t *cparam, + hsize_t *heap_size, hsize_t *free_space, unsigned *nobjs, + unsigned pos) +{ + unsigned u, v; /* Local index variables */ + + /* Loop over row of 4th level indirect blocks */ + for(u = 0; u < cparam->managed.width; u++) { + /* Fill all direct block rows in fourth level indirect block */ + if(fill_all_direct(f, dxpl, fh_addr, cparam, heap_size, free_space, nobjs)) + FAIL_STACK_ERROR + + /* Fill all rows of 2nd level deep indirect blocks in fourth level indirect block */ + if(fill_all_2nd_indirect_rows(f, dxpl, fh_addr, cparam, heap_size, free_space, nobjs)) + FAIL_STACK_ERROR + + /* Fill rows of third level indirect blocks in fourth level indirect block */ + for(v = 0; v < pos; v++) + if(fill_3rd_indirect_row(f, dxpl, fh_addr, cparam, heap_size, free_space, nobjs, (v + 1))) + FAIL_STACK_ERROR + } /* end for */ + + /* Operations succeeded */ + return(0); + +error: + return(1); +} /* fill_4th_direct_row() */ + + +/*------------------------------------------------------------------------- + * Function: fill_all_4th_indirect_rows + * + * Purpose: Insert (small) objects to fill up the free space in all direct + * heap blocks in all rows of fourth-level indirect blocks (which + * have two more levels of indirect blocks) + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, April 10, 2006 + * + *------------------------------------------------------------------------- + */ +static int +fill_all_4th_indirect_rows(H5F_t *f, hid_t dxpl, haddr_t fh_addr, const H5HF_create_t *cparam, + hsize_t *heap_size, hsize_t *free_space, unsigned *nobjs) +{ + unsigned u; /* Local index variable */ + + /* Loop over rows of 4th level deep indirect blocks */ + for(u = 0; u < (H5V_log2_of2(cparam->managed.width) + 1); u++) { + /* Fill row of 4th level indirect blocks */ + if(fill_4th_indirect_row(f, dxpl, fh_addr, cparam, heap_size, free_space, nobjs, (u + 1))) + FAIL_STACK_ERROR + + /* Account for root indirect block doubling # of rows again */ + /* (From 16 rows to the max. # of rows: 22) */ + if(u == 0) { + hsize_t block_size; /* Current block size */ + hsize_t max_block_size; /* Maximum size of blocks in heap */ + unsigned row; /* Row in heap */ + + /* Compute current & maximum block size in heap */ + block_size = cparam->managed.start_block_size * ((hsize_t)1 << 15); + max_block_size = (((hsize_t)1 << cparam->managed.max_index) / 2) / + cparam->managed.width; + + /* Increase heap size & free space */ + row = 16; + while(block_size <= max_block_size) { + *heap_size += cparam->managed.width * block_size; + *free_space += cparam->managed.width * DBLOCK_FREE(f, dxpl, fh_addr, row); + + /* Advance to next row */ + block_size *= 2; + row++; + } /* end while */ + } /* end if */ + } /* end for */ + + /* Operations succeeded */ + return(0); + +error: + return(1); +} /* fill_all_4th_direct_rows() */ + + +/*------------------------------------------------------------------------- * Function: test_create * * Purpose: Create fractal heap @@ -434,6 +1021,7 @@ error: return(1); } /* test_create() */ +#ifdef ALL_INSERT_TESTS /*------------------------------------------------------------------------- * Function: test_abs_insert_first @@ -458,11 +1046,8 @@ test_abs_insert_first(hid_t fapl, H5HF_create_t *cparam) H5F_t *f = NULL; /* Internal file object pointer */ haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ - unsigned char obj[10]; /* Buffer for object to insert */ - unsigned char robj[10]; /* Buffer for object to read */ - unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object inserted */ hsize_t free_space; /* Size of free space in heap */ - unsigned u; /* Local index variable */ + unsigned nobjs = 0; /* Total number of objects inserted */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -485,25 +1070,12 @@ test_abs_insert_first(hid_t fapl, H5HF_create_t *cparam) if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0)) FAIL_STACK_ERROR - /* Initialize object buffer */ - for(u = 0; u < sizeof(obj); u++) - obj[u] = u; - /* * Test inserting first (small) object into absolute heap */ TESTING("inserting first (small) object into absolute heap"); - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj), obj, heap_id) < 0) - FAIL_STACK_ERROR - free_space = cparam->managed.start_block_size - ((sizeof(obj) + OBJ_PREFIX_LEN) + OBJ_PREFIX_LEN +DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)cparam->managed.start_block_size, (hsize_t)cparam->managed.start_block_size, (hsize_t)0, free_space, (hsize_t)1)) - FAIL_STACK_ERROR - - /* Check reading back in the object */ - if(H5HF_read(f, dxpl, fh_addr, heap_id, robj) < 0) - FAIL_STACK_ERROR - if(HDmemcmp(obj, robj, sizeof(obj))) + free_space = DBLOCK_FREE(f, dxpl, fh_addr, 0); + if(add_obj(f, dxpl, fh_addr, (hsize_t)cparam->managed.start_block_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1, FALSE)) FAIL_STACK_ERROR PASSED() @@ -546,13 +1118,8 @@ test_abs_insert_second(hid_t fapl, H5HF_create_t *cparam) H5F_t *f = NULL; /* Internal file object pointer */ haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ - 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 */ - unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object inserted */ hsize_t free_space; /* Size of free space in heap */ - unsigned u; /* Local index variable */ + unsigned nobjs = 0; /* Total number of objects inserted */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -573,41 +1140,16 @@ test_abs_insert_second(hid_t fapl, H5HF_create_t *cparam) if(id_len > HEAP_ID_LEN) FAIL_STACK_ERROR - /* Initialize object buffers */ - for(u = 0; u < sizeof(obj); u++) - obj[u] = u; - for(u = 0; u < sizeof(obj2); u++) - obj2[u] = u + 10; - /* * Test inserting first (small) object into absolute heap */ TESTING("inserting two (small) objects into absolute heap"); - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj), obj, heap_id) < 0) - FAIL_STACK_ERROR - free_space = cparam->managed.start_block_size - ((sizeof(obj) + OBJ_PREFIX_LEN) + OBJ_PREFIX_LEN +DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)cparam->managed.start_block_size, (hsize_t)cparam->managed.start_block_size, (hsize_t)0, free_space, (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))) + free_space = DBLOCK_FREE(f, dxpl, fh_addr, 0); + if(add_obj(f, dxpl, fh_addr, (hsize_t)cparam->managed.start_block_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1, FALSE)) FAIL_STACK_ERROR /* Insert second object */ - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj2), obj2, heap_id) < 0) - FAIL_STACK_ERROR - free_space = cparam->managed.start_block_size - ((sizeof(obj) + OBJ_PREFIX_LEN) + (sizeof(obj2) + OBJ_PREFIX_LEN) + OBJ_PREFIX_LEN +DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)cparam->managed.start_block_size, (hsize_t)cparam->managed.start_block_size, (hsize_t)0, free_space, (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))) + if(add_obj(f, dxpl, fh_addr, (hsize_t)cparam->managed.start_block_size, &free_space, &nobjs, 20, SMALL_OBJ_SIZE2, FALSE)) FAIL_STACK_ERROR PASSED() @@ -651,6 +1193,7 @@ test_abs_insert_root_mult(hid_t fapl, H5HF_create_t *cparam) H5F_t *f = NULL; /* Internal file object pointer */ haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ + unsigned nobjs = 0; /* Number of objects inserted */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -677,7 +1220,7 @@ test_abs_insert_root_mult(hid_t fapl, H5HF_create_t *cparam) TESTING("inserting objects to fill absolute heap's root direct block"); /* Fill the heap up */ - if(fill_heap(f, dxpl, fh_addr, cparam, (hsize_t)cparam->managed.start_block_size, cparam->managed.start_block_size, (hsize_t)0, 0, NULL)) + if(fill_heap(f, dxpl, fh_addr, cparam, (hsize_t)cparam->managed.start_block_size, cparam->managed.start_block_size, (hsize_t)0, &nobjs)) FAIL_STACK_ERROR PASSED() @@ -722,11 +1265,9 @@ test_abs_insert_force_indirect(hid_t fapl, H5HF_create_t *cparam) H5F_t *f = NULL; /* Internal file object pointer */ haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ - unsigned char obj[10]; /* Buffer for first object to insert */ - unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object inserted */ hsize_t free_space; /* Size of free space in heap */ + hsize_t heap_size; /* Total size of the heap */ unsigned nobjs = 0; /* Number of objects 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)); @@ -753,25 +1294,13 @@ test_abs_insert_force_indirect(hid_t fapl, H5HF_create_t *cparam) TESTING("inserting objects to create root indirect block"); /* Fill the heap up */ - if(fill_heap(f, dxpl, fh_addr, cparam, (hsize_t)cparam->managed.start_block_size, cparam->managed.start_block_size, (hsize_t)0, 0, &nobjs)) + if(fill_heap(f, dxpl, fh_addr, cparam, (hsize_t)cparam->managed.start_block_size, cparam->managed.start_block_size, (hsize_t)0, &nobjs)) FAIL_STACK_ERROR /* Insert one more object, to force root indirect block creation */ - - /* Initialize object buffer */ - for(u = 0; u < sizeof(obj); u++) - obj[u] = u + nobjs; - - /* Insert another object, forcing the creation of an indirect block for the root block */ - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj), obj, heap_id) < 0) - FAIL_STACK_ERROR - - /* Increment object count */ - nobjs++; - - free_space = cparam->managed.start_block_size - ((sizeof(obj) + OBJ_PREFIX_LEN) + OBJ_PREFIX_LEN +DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)(2 * cparam->managed.start_block_size), (hsize_t)(2 * cparam->managed.start_block_size), (hsize_t)0, free_space, (hsize_t)nobjs)) + free_space = (cparam->managed.width - 1) * DBLOCK_FREE(f, dxpl, fh_addr, 0); + heap_size = cparam->managed.width * cparam->managed.start_block_size; + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1, FALSE)) FAIL_STACK_ERROR PASSED() @@ -816,8 +1345,9 @@ test_abs_insert_fill_second(hid_t fapl, H5HF_create_t *cparam) H5F_t *f = NULL; /* Internal file object pointer */ haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ + hsize_t free_space; /* Size of free space in heap */ + hsize_t heap_size; /* Total size of the heap */ unsigned nobjs = 0; /* Number of objects inserted */ - unsigned tot_nobjs = 0; /* Total number of objects inserted */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -844,12 +1374,13 @@ test_abs_insert_fill_second(hid_t fapl, H5HF_create_t *cparam) TESTING("inserting objects to fill second direct block"); /* Fill the first direct block heap up */ - if(fill_heap(f, dxpl, fh_addr, cparam, (hsize_t)cparam->managed.start_block_size, cparam->managed.start_block_size, (hsize_t)0, tot_nobjs, &nobjs)) + if(fill_heap(f, dxpl, fh_addr, cparam, (hsize_t)cparam->managed.start_block_size, cparam->managed.start_block_size, (hsize_t)0, &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, cparam, (hsize_t)(2 * cparam->managed.start_block_size), cparam->managed.start_block_size, (hsize_t)0, tot_nobjs, &nobjs)) + free_space = (cparam->managed.width - 2) * DBLOCK_FREE(f, dxpl, fh_addr, 0); + heap_size = cparam->managed.width * cparam->managed.start_block_size; + if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, cparam->managed.start_block_size, free_space, &nobjs)) FAIL_STACK_ERROR PASSED() @@ -895,13 +1426,9 @@ test_abs_insert_third_direct(hid_t fapl, H5HF_create_t *cparam) H5F_t *f = NULL; /* Internal file object pointer */ haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ - unsigned char obj[10]; /* Buffer for first object to insert */ - unsigned char robj[10]; /* Buffer for reading object */ - unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object inserted */ hsize_t free_space; /* Size of free space in heap */ + hsize_t heap_size; /* Total size of the heap */ unsigned nobjs = 0; /* Number of objects inserted */ - unsigned tot_nobjs = 0; /* Total number of objects 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)); @@ -928,37 +1455,17 @@ test_abs_insert_third_direct(hid_t fapl, H5HF_create_t *cparam) TESTING("inserting objects to create third direct block"); /* Fill the first direct block up */ - if(fill_heap(f, dxpl, fh_addr, cparam, (hsize_t)cparam->managed.start_block_size, cparam->managed.start_block_size, (hsize_t)0, tot_nobjs, &nobjs)) + if(fill_heap(f, dxpl, fh_addr, cparam, (hsize_t)cparam->managed.start_block_size, cparam->managed.start_block_size, (hsize_t)0, &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, cparam, (hsize_t)(2 * cparam->managed.start_block_size), cparam->managed.start_block_size, (hsize_t)0, tot_nobjs, &nobjs)) + free_space = (cparam->managed.width - 2) * DBLOCK_FREE(f, dxpl, fh_addr, 0); + heap_size = cparam->managed.width * cparam->managed.start_block_size; + if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, cparam->managed.start_block_size, free_space, &nobjs)) FAIL_STACK_ERROR - tot_nobjs += nobjs; /* Insert one more object, to force creation of third direct block */ - - /* Initialize object buffer */ - for(u = 0; u < sizeof(obj); u++) - obj[u] = u + nobjs; - - /* Insert another object, forcing the creation of the third direct block */ - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj), obj, heap_id) < 0) - FAIL_STACK_ERROR - - /* Increment object count */ - tot_nobjs++; - - free_space = cparam->managed.start_block_size - ((sizeof(obj) + OBJ_PREFIX_LEN) + OBJ_PREFIX_LEN +DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)(3 * cparam->managed.start_block_size), (hsize_t)(3 * cparam->managed.start_block_size), (hsize_t)0, free_space, (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))) + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1, FALSE)) FAIL_STACK_ERROR PASSED() @@ -1003,9 +1510,9 @@ test_abs_fill_first_row(hid_t fapl, H5HF_create_t *cparam) H5F_t *f = NULL; /* Internal file object pointer */ haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ - unsigned tot_nobjs = 0; /* Total number of objects inserted */ - unsigned u; /* Local index variable */ + hsize_t free_space; /* Size of free space in heap */ + hsize_t heap_size; /* Total size of heap */ + unsigned nobjs = 0; /* Total number of objects inserted */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -1031,13 +1538,11 @@ test_abs_fill_first_row(hid_t fapl, H5HF_create_t *cparam) */ 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 < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - if(fill_heap(f, dxpl, fh_addr, cparam, (hsize_t)(u + 1) * cparam->managed.start_block_size, cparam->managed.start_block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ + /* Fill first row of [root] indirect block */ + heap_size = 0; + free_space = 0; + if(fill_root_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, 0, &nobjs)) + FAIL_STACK_ERROR PASSED() @@ -1081,13 +1586,9 @@ test_abs_start_second_row(hid_t fapl, H5HF_create_t *cparam) H5F_t *f = NULL; /* Internal file object pointer */ haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ - unsigned char obj[10]; /* Buffer for object to insert */ - unsigned char robj[10]; /* Buffer for reading object */ - unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object inserted */ hsize_t free_space; /* Size of free space in heap */ + hsize_t heap_size; /* Total size of the heap */ unsigned nobjs = 0; /* Number of objects inserted */ - unsigned tot_nobjs = 0; /* Total number of objects 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)); @@ -1113,36 +1614,16 @@ test_abs_start_second_row(hid_t fapl, H5HF_create_t *cparam) */ 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 < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - if(fill_heap(f, dxpl, fh_addr, cparam, (hsize_t)(u + 1) * cparam->managed.start_block_size, cparam->managed.start_block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Insert one more object, to force expanding root indirect block to two rows */ - - /* Initialize object buffer */ - for(u = 0; u < sizeof(obj); u++) - obj[u] = u + tot_nobjs; - - /* Insert another object, forcing the creation of an indirect block for the root block */ - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj), obj, heap_id) < 0) - FAIL_STACK_ERROR - - /* Increment object count */ - tot_nobjs++; - - free_space = cparam->managed.start_block_size - ((sizeof(obj) + OBJ_PREFIX_LEN) + OBJ_PREFIX_LEN +DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)((cparam->managed.width + 1) * cparam->managed.start_block_size), (hsize_t)((cparam->managed.width + 1) * cparam->managed.start_block_size), (hsize_t)0, free_space, (hsize_t)tot_nobjs)) + /* Fill first root indirect row */ + heap_size = 0; + free_space = 0; + if(fill_root_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, 0, &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))) + /* Insert one more object, to force expanding root indirect block to two rows */ + heap_size += cparam->managed.width * cparam->managed.start_block_size; + free_space += cparam->managed.width * DBLOCK_FREE(f, dxpl, fh_addr, 1); + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1, FALSE)) FAIL_STACK_ERROR PASSED() @@ -1187,9 +1668,9 @@ test_abs_fill_second_row(hid_t fapl, H5HF_create_t *cparam) H5F_t *f = NULL; /* Internal file object pointer */ haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ + hsize_t free_space; /* Size of free space in heap */ + hsize_t heap_size; /* Total size of the heap */ unsigned nobjs = 0; /* Number of objects inserted */ - unsigned tot_nobjs = 0; /* Total number of objects 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)); @@ -1215,21 +1696,15 @@ test_abs_fill_second_row(hid_t fapl, H5HF_create_t *cparam) */ 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 < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - if(fill_heap(f, dxpl, fh_addr, cparam, (hsize_t)(u + 1) * cparam->managed.start_block_size, cparam->managed.start_block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ + /* Fill first root indirect row */ + heap_size = 0; + free_space = 0; + if(fill_root_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, 0, &nobjs)) + FAIL_STACK_ERROR - /* Loop over filling direct blocks, until second root indirect row is full */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - if(fill_heap(f, dxpl, fh_addr, cparam, (hsize_t)((cparam->managed.width * cparam->managed.start_block_size) + (u + 1) * cparam->managed.start_block_size), cparam->managed.start_block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ + /* Fill second root indirect row */ + if(fill_root_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, 1, &nobjs)) + FAIL_STACK_ERROR PASSED() @@ -1274,14 +1749,9 @@ test_abs_start_third_row(hid_t fapl, H5HF_create_t *cparam) H5F_t *f = NULL; /* Internal file object pointer */ haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ - unsigned char obj[10]; /* Buffer for object to insert */ - unsigned char robj[10]; /* Buffer for reading object */ - unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object inserted */ hsize_t free_space; /* Size of free space in heap */ - 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 */ + unsigned nobjs = 0; /* Number of objects inserted */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -1307,46 +1777,23 @@ test_abs_start_third_row(hid_t fapl, H5HF_create_t *cparam) */ 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 < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - if(fill_heap(f, dxpl, fh_addr, cparam, (hsize_t)(u + 1) * cparam->managed.start_block_size, cparam->managed.start_block_size, (hsize_t)0, 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 < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - if(fill_heap(f, dxpl, fh_addr, cparam, (hsize_t)((cparam->managed.width * cparam->managed.start_block_size) + (u + 1) * cparam->managed.start_block_size), cparam->managed.start_block_size, (hsize_t)0, 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 */ - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj), obj, heap_id) < 0) + /* Fill first root indirect row */ + heap_size = 0; + free_space = 0; + if(fill_root_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, 0, &nobjs)) FAIL_STACK_ERROR - /* Increment object count */ - tot_nobjs++; - - heap_size = (2 * cparam->managed.width) * cparam->managed.start_block_size + - (2 * cparam->managed.start_block_size); - free_space = (2 * cparam->managed.start_block_size) - ((sizeof(obj) + OBJ_PREFIX_LEN) + OBJ_PREFIX_LEN +DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, heap_size, heap_size, (hsize_t)0, free_space, (hsize_t)tot_nobjs)) + /* Fill second root indirect row */ + if(fill_root_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, 1, &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))) + /* Insert one more object, to force expanding root indirect block to four rows */ + /* (Goes to four rows because it's doubling) */ + heap_size += cparam->managed.width * cparam->managed.start_block_size * 2; + heap_size += cparam->managed.width * cparam->managed.start_block_size * 4; + free_space += cparam->managed.width * DBLOCK_FREE(f, dxpl, fh_addr, 2); + free_space += cparam->managed.width * DBLOCK_FREE(f, dxpl, fh_addr, 3); + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1, FALSE)) FAIL_STACK_ERROR PASSED() @@ -1392,10 +1839,9 @@ test_abs_fill_fourth_row(hid_t fapl, H5HF_create_t *cparam) haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ 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 free_space; /* Size of free space in heap */ hsize_t heap_size; /* Total size of heap */ - unsigned u, v; /* Local index variables */ + unsigned u; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -1422,22 +1868,11 @@ test_abs_fill_fourth_row(hid_t fapl, H5HF_create_t *cparam) TESTING("inserting objects to fill four rows of root indirect block"); /* Loop over rows */ - block_size = cparam->managed.start_block_size; heap_size = 0; - for(v = 0; v < 4; v++) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(v > 0) - block_size *= 2; - } /* end for */ + free_space = 0; + for(u = 0; u < 4; u++) + if(fill_root_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, u, &nobjs)) + FAIL_STACK_ERROR PASSED() @@ -1482,11 +1917,8 @@ test_abs_fill_all_root_direct(hid_t fapl, H5HF_create_t *cparam) haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ 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 free_space; /* Size of free space in heap */ 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)); @@ -1512,27 +1944,11 @@ test_abs_fill_all_root_direct(hid_t fapl, H5HF_create_t *cparam) */ TESTING("inserting objects to fill all direct rows of root indirect block"); - /* Loop over rows */ - block_size = cparam->managed.start_block_size; + /* Fill all direct blocks in root indirect block */ heap_size = 0; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR PASSED() @@ -1576,16 +1992,9 @@ test_abs_first_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) H5F_t *f = NULL; /* Internal file object pointer */ haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ - unsigned char obj[10]; /* Buffer for object to insert */ - unsigned char robj[10]; /* Buffer for reading object */ - unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object inserted */ - hsize_t free_space; /* Size of free space in heap */ 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 free_space; /* Size of free space in heap */ 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)); @@ -1611,51 +2020,14 @@ test_abs_first_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) */ TESTING("inserting objects to create first recursive indirect block"); - /* Loop over rows */ - block_size = cparam->managed.start_block_size; + /* Fill direct blocks up */ heap_size = 0; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* 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 */ - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj), obj, heap_id) < 0) - FAIL_STACK_ERROR - - /* Increment object count */ - tot_nobjs++; - - heap_size += cparam->managed.start_block_size; - free_space = cparam->managed.start_block_size - ((sizeof(obj) + OBJ_PREFIX_LEN) + OBJ_PREFIX_LEN +DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, heap_size, heap_size, (hsize_t)0, free_space, (hsize_t)tot_nobjs)) + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &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))) + /* Insert one more object, to force creation of first recursive indirect block */ + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1, FALSE)) FAIL_STACK_ERROR PASSED() @@ -1701,16 +2073,9 @@ test_abs_second_direct_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) H5F_t *f = NULL; /* Internal file object pointer */ haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ - unsigned char obj[10]; /* Buffer for object to insert */ - unsigned char robj[10]; /* Buffer for reading object */ - unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object inserted */ - hsize_t free_space; /* Size of free space in heap */ 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 free_space; /* Size of free space in heap */ 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)); @@ -1737,59 +2102,21 @@ test_abs_second_direct_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) */ TESTING("inserting objects to create second direct block in first recursive indirect block"); - /* Loop over rows */ - block_size = cparam->managed.start_block_size; + /* Fill direct blocks up */ heap_size = 0; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR /* Fill the first direct block in the recursive indirect block up */ - heap_size += cparam->managed.start_block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, cparam->managed.start_block_size, (hsize_t)0, tot_nobjs, &nobjs)) + free_space -= DBLOCK_FREE(f, dxpl, fh_addr, 0); + if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, cparam->managed.start_block_size, free_space, &nobjs)) FAIL_STACK_ERROR - tot_nobjs += nobjs; /* Insert one more object, to force creation of second direct block in * first recursive indirect block */ - - /* Initialize object buffer */ - for(u = 0; u < sizeof(obj); u++) - obj[u] = u + tot_nobjs; - - /* Insert object */ - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj), obj, heap_id) < 0) - FAIL_STACK_ERROR - - /* Increment object count */ - tot_nobjs++; - - heap_size += cparam->managed.start_block_size; - free_space = cparam->managed.start_block_size - ((sizeof(obj) + OBJ_PREFIX_LEN) + OBJ_PREFIX_LEN +DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, heap_size, heap_size, (hsize_t)0, free_space, (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))) + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1, FALSE)) FAIL_STACK_ERROR PASSED() @@ -1836,12 +2163,8 @@ test_abs_fill_first_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ unsigned nobjs = 0; /* Number of objects inserted */ - unsigned tot_nobjs = 0; /* Total number of objects inserted */ - size_t block_size; /* Size of block added */ - size_t max_block_size; /* Max. size of block to add */ + hsize_t free_space; /* Size of free space in heap */ 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)); @@ -1868,51 +2191,15 @@ test_abs_fill_first_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) */ TESTING("inserting objects to fill all direct blocks in first recursive indirect block"); - /* Loop over direct block rows in root indirect block */ - block_size = cparam->managed.start_block_size; + /* Fill direct blocks up in root indirect block */ heap_size = 0; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2((2 * cparam->managed.max_direct_size) / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Increment row count */ - nrows++; - } /* end for */ + /* Fill first recursive indirect block */ + if(fill_2nd_indirect(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs, 2 * cparam->managed.max_direct_size)) + FAIL_STACK_ERROR PASSED() @@ -1958,17 +2245,9 @@ test_abs_second_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) H5F_t *f = NULL; /* Internal file object pointer */ haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ - unsigned char obj[10]; /* Buffer for object to insert */ - unsigned char robj[10]; /* Buffer for reading object */ - unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object inserted */ - hsize_t free_space; /* Size of free space in heap */ unsigned nobjs = 0; /* Number of objects inserted */ - unsigned tot_nobjs = 0; /* Total number of objects inserted */ - size_t block_size; /* Size of block added */ - size_t max_block_size; /* Max. size of block to add */ + hsize_t free_space; /* Size of free space in heap */ 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)); @@ -1995,77 +2274,20 @@ test_abs_second_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) */ TESTING("inserting objects to start second recursive indirect block"); - /* Loop over direct block rows in root indirect block */ - block_size = cparam->managed.start_block_size; + /* Fill direct blocks up in root indirect block */ heap_size = 0; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2((2 * cparam->managed.max_direct_size) / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Increment row count */ - nrows++; - } /* end for */ + /* Fill first recursive indirect block */ + if(fill_2nd_indirect(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs, 2 * cparam->managed.max_direct_size)) + FAIL_STACK_ERROR /* Insert one more object, to force creation of second * recursive indirect block */ - - /* Initialize object buffer */ - for(u = 0; u < sizeof(obj); u++) - obj[u] = u + tot_nobjs; - - /* Insert object */ - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj), obj, heap_id) < 0) - FAIL_STACK_ERROR - - /* Increment object count */ - tot_nobjs++; - - heap_size += cparam->managed.start_block_size; - free_space = cparam->managed.start_block_size - ((sizeof(obj) + OBJ_PREFIX_LEN) + OBJ_PREFIX_LEN +DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, heap_size, heap_size, (hsize_t)0, free_space, (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))) + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1, FALSE)) FAIL_STACK_ERROR PASSED() @@ -2114,12 +2336,8 @@ test_abs_fill_second_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ unsigned nobjs = 0; /* Number of objects inserted */ - unsigned tot_nobjs = 0; /* Total number of objects inserted */ - size_t block_size; /* Size of block added */ - size_t max_block_size; /* Max. size of block to add */ + hsize_t free_space; /* Size of free space in heap */ 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)); @@ -2146,75 +2364,19 @@ test_abs_fill_second_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) */ TESTING("inserting objects to fill all direct blocks in second recursive indirect block"); - /* Loop over direct block rows in root indirect block */ - block_size = cparam->managed.start_block_size; + /* Fill direct blocks up in root indirect block */ heap_size = 0; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2((2 * cparam->managed.max_direct_size) / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - - /* Loop over direct block rows in second recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2((2 * cparam->managed.max_direct_size) / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; + /* Fill first recursive indirect block */ + if(fill_2nd_indirect(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs, 2 * cparam->managed.max_direct_size)) + FAIL_STACK_ERROR - /* Increment row count */ - nrows++; - } /* end for */ + /* Fill 2nd recursive indirect block */ + if(fill_2nd_indirect(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs, 2 * cparam->managed.max_direct_size)) + FAIL_STACK_ERROR PASSED() @@ -2262,12 +2424,8 @@ test_abs_fill_recursive_indirect_row(hid_t fapl, H5HF_create_t *cparam) haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ unsigned nobjs = 0; /* Number of objects inserted */ - unsigned tot_nobjs = 0; /* Total number of objects inserted */ - size_t block_size; /* Size of block added */ - size_t max_block_size; /* Max. size of block to add */ + hsize_t free_space; /* Size of free space in heap */ hsize_t heap_size; /* Total size of heap */ - unsigned nrows; /* Number of rows inserted */ - 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)); @@ -2294,54 +2452,15 @@ test_abs_fill_recursive_indirect_row(hid_t fapl, H5HF_create_t *cparam) */ TESTING("inserting objects to fill all direct blocks in first row of recursive indirect block"); - /* Loop over direct block rows in root indirect block */ - block_size = cparam->managed.start_block_size; + /* Fill direct blocks in root indirect block up */ heap_size = 0; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - - /* Loop over row of indirect blocks */ - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2((2 * cparam->managed.max_direct_size) / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ + /* Fill row of recursive indirect blocks */ + if(fill_2nd_indirect_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs, 2 * cparam->managed.max_direct_size)) + FAIL_STACK_ERROR PASSED() @@ -2386,17 +2505,9 @@ test_abs_start_2nd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) H5F_t *f = NULL; /* Internal file object pointer */ haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ - unsigned char obj[10]; /* Buffer for object to insert */ - unsigned char robj[10]; /* Buffer for reading object */ - unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object inserted */ - hsize_t free_space; /* Size of free space in heap */ unsigned nobjs = 0; /* Number of objects inserted */ - unsigned tot_nobjs = 0; /* Total number of objects inserted */ - size_t block_size; /* Size of block added */ - size_t max_block_size; /* Max. size of block to add */ + hsize_t free_space; /* Size of free space in heap */ hsize_t heap_size; /* Total size of heap */ - unsigned nrows; /* Number of rows inserted */ - 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)); @@ -2423,80 +2534,20 @@ test_abs_start_2nd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) */ TESTING("inserting objects to start second row of recursive indirect blocks"); - /* Loop over direct block rows in root indirect block */ - block_size = cparam->managed.start_block_size; + /* Fill direct blocks in root indirect block up */ heap_size = 0; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - - /* Loop over row of indirect blocks */ - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2((2 * cparam->managed.max_direct_size) / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ + /* Fill row of recursive indirect blocks */ + if(fill_2nd_indirect_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs, 2 * cparam->managed.max_direct_size)) + FAIL_STACK_ERROR /* Insert one more object, to force creation of second * recursive indirect block */ - - /* Initialize object buffer */ - for(u = 0; u < sizeof(obj); u++) - obj[u] = u + tot_nobjs; - - /* Insert object */ - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj), obj, heap_id) < 0) - FAIL_STACK_ERROR - - /* Increment object count */ - tot_nobjs++; - - heap_size += cparam->managed.start_block_size; - free_space = cparam->managed.start_block_size - ((sizeof(obj) + OBJ_PREFIX_LEN) + OBJ_PREFIX_LEN +DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, heap_size, heap_size, (hsize_t)0, free_space, (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))) + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1, FALSE)) FAIL_STACK_ERROR PASSED() @@ -2543,12 +2594,8 @@ test_abs_recursive_indirect_two_deep(hid_t fapl, H5HF_create_t *cparam) haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ unsigned nobjs = 0; /* Number of objects inserted */ - unsigned tot_nobjs = 0; /* Total number of objects inserted */ - size_t block_size; /* Size of block added */ - size_t max_block_size; /* Max. size of block to add */ + hsize_t free_space; /* Size of free space in heap */ hsize_t heap_size; /* Total size of heap */ - unsigned nrows; /* Number of rows inserted */ - unsigned u, v, w; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -2575,56 +2622,15 @@ test_abs_recursive_indirect_two_deep(hid_t fapl, H5HF_create_t *cparam) */ TESTING("inserting objects to fill recursive indirect blocks two levels deep"); - /* Loop over direct block rows in root indirect block */ - block_size = cparam->managed.start_block_size; + /* Fill direct blocks up in root indirect block */ heap_size = 0; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (H5V_log2_of2(cparam->managed.width) + 1); w++) { - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ + /* Fill all rows of 2nd level indirect blocks */ + if(fill_all_2nd_indirect_rows(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR PASSED() @@ -2670,17 +2676,9 @@ test_abs_start_3rd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) H5F_t *f = NULL; /* Internal file object pointer */ haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ - unsigned char obj[10]; /* Buffer for object to insert */ - unsigned char robj[10]; /* Buffer for reading object */ - unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object inserted */ - hsize_t free_space; /* Size of free space in heap */ unsigned nobjs = 0; /* Number of objects inserted */ - unsigned tot_nobjs = 0; /* Total number of objects inserted */ - size_t block_size; /* Size of block added */ - size_t max_block_size; /* Max. size of block to add */ + hsize_t free_space; /* Size of free space in heap */ hsize_t heap_size; /* Total size of heap */ - unsigned nrows; /* Number of rows inserted */ - unsigned u, v, w; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -2707,82 +2705,20 @@ test_abs_start_3rd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) */ TESTING("inserting objects to start recursive indirect blocks three levels deep"); - /* Loop over direct block rows in root indirect block */ - block_size = cparam->managed.start_block_size; + /* Fill direct blocks up in root indirect block */ heap_size = 0; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (H5V_log2_of2(cparam->managed.width) + 1); w++) { - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ + /* Fill all rows of 2nd level indirect blocks */ + if(fill_all_2nd_indirect_rows(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR /* Insert one more object, to force creation of third level deep * recursive indirect block */ - - /* Initialize object buffer */ - for(u = 0; u < sizeof(obj); u++) - obj[u] = u + tot_nobjs; - - /* Insert object */ - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj), obj, heap_id) < 0) - FAIL_STACK_ERROR - - /* Increment object count */ - tot_nobjs++; - - heap_size += cparam->managed.start_block_size; - free_space = cparam->managed.start_block_size - ((sizeof(obj) + OBJ_PREFIX_LEN) + OBJ_PREFIX_LEN +DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, heap_size, heap_size, (hsize_t)0, free_space, (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))) + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1, FALSE)) FAIL_STACK_ERROR PASSED() @@ -2830,12 +2766,8 @@ test_abs_fill_first_3rd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ unsigned nobjs = 0; /* Number of objects inserted */ - unsigned tot_nobjs = 0; /* Total number of objects inserted */ - size_t block_size; /* Size of block added */ - size_t max_block_size; /* Max. size of block to add */ + hsize_t free_space; /* Size of free space in heap */ hsize_t heap_size; /* Total size of heap */ - unsigned nrows; /* Number of rows inserted */ - unsigned u, v, w; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -2862,104 +2794,23 @@ test_abs_fill_first_3rd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) */ TESTING("inserting objects to fill first indirect block of recursive indirect blocks three levels deep"); - /* Loop over direct block rows in root indirect block */ - block_size = cparam->managed.start_block_size; + /* Fill direct blocks up in root indirect block */ heap_size = 0; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (H5V_log2_of2(cparam->managed.width) + 1); w++) { - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ - - /* Loop over direct block rows in third level indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Increment row count */ - nrows++; - } /* end for */ + /* Fill all rows of 2nd level indirect blocks */ + if(fill_all_2nd_indirect_rows(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Loop over row of indirect blocks */ - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2((2 * cparam->managed.max_direct_size) / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; + /* Fill all direct block rows in third level indirect block */ + if(fill_all_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ + /* Fill row of recursive indirect blocks in third level indirect block */ + if(fill_2nd_indirect_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs, 2 * cparam->managed.max_direct_size)) + FAIL_STACK_ERROR PASSED() @@ -3006,12 +2857,8 @@ test_abs_fill_3rd_recursive_indirect_row(hid_t fapl, H5HF_create_t *cparam) haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ unsigned nobjs = 0; /* Number of objects inserted */ - unsigned tot_nobjs = 0; /* Total number of objects inserted */ - size_t block_size; /* Size of block added */ - size_t max_block_size; /* Max. size of block to add */ + hsize_t free_space; /* Size of free space in heap */ hsize_t heap_size; /* Total size of heap */ - unsigned nrows; /* Number of rows inserted */ - unsigned u, v, w; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -3038,107 +2885,19 @@ test_abs_fill_3rd_recursive_indirect_row(hid_t fapl, H5HF_create_t *cparam) */ TESTING("inserting objects to fill row of indirect blocks in recursive indirect blocks three levels deep"); - /* Loop over direct block rows in root indirect block */ - block_size = cparam->managed.start_block_size; + /* Fill direct blocks up in root indirect block */ heap_size = 0; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (H5V_log2_of2(cparam->managed.width) + 1); w++) { - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ - - /* Loop over row of 3rd level deep indirect blocks */ - for(w = 0; w < cparam->managed.width; w++) { - /* Loop over direct block rows in third level indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Increment row count */ - nrows++; - } /* end for */ + /* Fill all rows of 2nd level indirect blocks */ + if(fill_all_2nd_indirect_rows(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Loop over row of indirect blocks */ - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2((2 * cparam->managed.max_direct_size) / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ + /* Fill 1st row of 3rd level indirect blocks */ + if(fill_3rd_indirect_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs, 1)) + FAIL_STACK_ERROR PASSED() @@ -3185,12 +2944,8 @@ test_abs_fill_all_3rd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ unsigned nobjs = 0; /* Number of objects inserted */ - unsigned tot_nobjs = 0; /* Total number of objects inserted */ - size_t block_size; /* Size of block added */ - size_t max_block_size; /* Max. size of block to add */ + hsize_t free_space; /* Size of free space in heap */ hsize_t heap_size; /* Total size of heap */ - unsigned nrows; /* Number of rows inserted */ - unsigned u, v, w, x, y; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -3217,116 +2972,19 @@ test_abs_fill_all_3rd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) */ TESTING("inserting objects to fill row of indirect blocks in recursive indirect blocks three levels deep"); - /* Loop over direct block rows in root indirect block */ - block_size = cparam->managed.start_block_size; + /* Fill direct blocks up in root indirect block */ heap_size = 0; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (H5V_log2_of2(cparam->managed.width) + 1); w++) { - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ + /* Fill all rows of 2nd level indirect blocks */ + if(fill_all_2nd_indirect_rows(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Loop over rows of 3rd level deep indirect blocks */ - for(y = 0; y < (H5V_log2_of2(cparam->managed.width) + 1); y++) { - - /* Loop over row of 3rd level deep indirect blocks */ - for(x = 0; x < cparam->managed.width; x++) { - - /* Loop over direct block rows in third level indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (y + 1); w++) { - - /* Loop over row of indirect blocks */ - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ + /* Fill all rows of 3rd level indirect blocks */ + if(fill_all_3rd_indirect_rows(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR PASSED() @@ -3373,17 +3031,9 @@ test_abs_start_4th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) H5F_t *f = NULL; /* Internal file object pointer */ haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ - unsigned char obj[10]; /* Buffer for object to insert */ - unsigned char robj[10]; /* Buffer for reading object */ - unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object inserted */ - hsize_t free_space; /* Size of free space in heap */ unsigned nobjs = 0; /* Number of objects inserted */ - unsigned tot_nobjs = 0; /* Total number of objects inserted */ - size_t block_size; /* Size of block added */ - size_t max_block_size; /* Max. size of block to add */ + hsize_t free_space; /* Size of free space in heap */ hsize_t heap_size; /* Total size of heap */ - unsigned nrows; /* Number of rows inserted */ - unsigned u, v, w, x, y; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -3410,142 +3060,24 @@ test_abs_start_4th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) */ TESTING("inserting objects to start first direct block in recursive indirect blocks four levels deep"); - /* Loop over direct block rows in root indirect block */ - block_size = cparam->managed.start_block_size; + /* Fill direct blocks up in root indirect block */ heap_size = 0; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (H5V_log2_of2(cparam->managed.width) + 1); w++) { - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ + /* Fill all rows of 2nd level indirect blocks */ + if(fill_all_2nd_indirect_rows(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Loop over rows of 3rd level deep indirect blocks */ - for(y = 0; y < (H5V_log2_of2(cparam->managed.width) + 1); y++) { - - /* Loop over row of 3rd level deep indirect blocks */ - for(x = 0; x < cparam->managed.width; x++) { - - /* Loop over direct block rows in third level indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (y + 1); w++) { - - /* Loop over row of indirect blocks */ - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ + /* Fill all rows of 3rd level indirect blocks */ + if(fill_all_3rd_indirect_rows(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR /* Insert one more object, to force creation of four level deep * recursive indirect block */ - - /* Initialize object buffer */ - for(u = 0; u < sizeof(obj); u++) - obj[u] = u + tot_nobjs; - - /* Insert object */ - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj), obj, heap_id) < 0) - FAIL_STACK_ERROR - - /* Increment object count */ - tot_nobjs++; - - heap_size += cparam->managed.start_block_size; - free_space = cparam->managed.start_block_size - ((sizeof(obj) + OBJ_PREFIX_LEN) + OBJ_PREFIX_LEN +DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, heap_size, heap_size, (hsize_t)0, free_space, (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))) + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1, FALSE)) FAIL_STACK_ERROR PASSED() @@ -3594,12 +3126,8 @@ test_abs_fill_first_4th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ unsigned nobjs = 0; /* Number of objects inserted */ - unsigned tot_nobjs = 0; /* Total number of objects inserted */ - size_t block_size; /* Size of block added */ - size_t max_block_size; /* Max. size of block to add */ + hsize_t free_space; /* Size of free space in heap */ hsize_t heap_size; /* Total size of heap */ - unsigned nrows; /* Number of rows inserted */ - unsigned u, v, w, x, y; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -3626,224 +3154,31 @@ test_abs_fill_first_4th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) */ TESTING("inserting objects to fill first (3rd level) indirect block in recursive indirect block four levels deep"); - /* Loop over direct block rows in root indirect block */ - block_size = cparam->managed.start_block_size; + /* Fill direct blocks up in root indirect block */ heap_size = 0; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (H5V_log2_of2(cparam->managed.width) + 1); w++) { - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ - - /* Loop over rows of 3rd level deep indirect blocks */ - for(y = 0; y < (H5V_log2_of2(cparam->managed.width) + 1); y++) { - - /* Loop over row of 3rd level deep indirect blocks */ - for(x = 0; x < cparam->managed.width; x++) { - - /* Loop over direct block rows in third level indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (y + 1); w++) { - - /* Loop over row of indirect blocks */ - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ - - /* Loop over direct block rows in fourth level indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (H5V_log2_of2(cparam->managed.width) + 1); w++) { - - /* Loop over row of indirect blocks */ - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ + /* Fill all rows of 2nd level indirect blocks */ + if(fill_all_2nd_indirect_rows(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Loop over row of 3rd level deep indirect blocks */ - for(x = 0; x < cparam->managed.width; x++) { + /* Fill all rows of 3rd level indirect blocks */ + if(fill_all_3rd_indirect_rows(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Loop over direct block rows in third level indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; + /* Fill direct block rows in fourth level indirect block */ + if(fill_all_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Increment row count */ - nrows++; - } /* end for */ + /* Fill all rows of 2nd level deep indirect blocks in fourth level indirect block */ + if(fill_all_2nd_indirect_rows(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < 1; w++) { - - /* Loop over row of indirect blocks */ - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ + /* Fill first row of 3rd level deep indirect blocks in fourth level indirect block */ + if(fill_3rd_indirect_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs, 1)) + FAIL_STACK_ERROR PASSED() @@ -3891,12 +3226,8 @@ test_abs_fill_4th_recursive_indirect_row(hid_t fapl, H5HF_create_t *cparam) haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ unsigned nobjs = 0; /* Number of objects inserted */ - unsigned tot_nobjs = 0; /* Total number of objects inserted */ - size_t block_size; /* Size of block added */ - size_t max_block_size; /* Max. size of block to add */ + hsize_t free_space; /* Size of free space in heap */ hsize_t heap_size; /* Total size of heap */ - unsigned nrows; /* Number of rows inserted */ - unsigned u, v, w, x, y, z; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -3923,232 +3254,23 @@ test_abs_fill_4th_recursive_indirect_row(hid_t fapl, H5HF_create_t *cparam) */ TESTING("inserting objects to fill first row of recursive indirect blocks four levels deep"); - /* Loop over direct block rows in root indirect block */ - block_size = cparam->managed.start_block_size; + /* Fill direct blocks up in root indirect block */ heap_size = 0; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (H5V_log2_of2(cparam->managed.width) + 1); w++) { - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ - - /* Loop over rows of 3rd level deep indirect blocks */ - for(y = 0; y < (H5V_log2_of2(cparam->managed.width) + 1); y++) { - - /* Loop over row of 3rd level deep indirect blocks */ - for(x = 0; x < cparam->managed.width; x++) { - - /* Loop over direct block rows in third level indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (y + 1); w++) { - - /* Loop over row of indirect blocks */ - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ - - /* Loop over row of 4th level indirect blocks */ - for(z = 0; z < cparam->managed.width; z++) { - - /* Loop over direct block rows in fourth level indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Increment row count */ - nrows++; - } /* end for */ + /* Fill all rows of 2nd level indirect blocks */ + if(fill_all_2nd_indirect_rows(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (H5V_log2_of2(cparam->managed.width) + 1); w++) { - - /* Loop over row of indirect blocks */ - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ + /* Fill all rows of 3rd level indirect blocks */ + if(fill_all_3rd_indirect_rows(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Loop over rows of 3rd level deep indirect blocks */ - for(y = 0; y < 1; y++) { - - /* Loop over row of 3rd level deep indirect blocks */ - for(x = 0; x < cparam->managed.width; x++) { - - /* Loop over direct block rows in third level indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (y + 1); w++) { - - /* Loop over row of indirect blocks */ - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ + /* Fill 1st row of 4th level indirect blocks */ + if(fill_4th_indirect_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs, 1)) + FAIL_STACK_ERROR PASSED() @@ -4196,12 +3318,8 @@ test_abs_fill_all_4th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ unsigned nobjs = 0; /* Number of objects inserted */ - unsigned tot_nobjs = 0; /* Total number of objects inserted */ - size_t block_size; /* Size of block added */ - size_t max_block_size; /* Max. size of block to add */ + hsize_t free_space; /* Size of free space in heap */ hsize_t heap_size; /* Total size of heap */ - unsigned nrows; /* Number of rows inserted */ - unsigned u, v, w, x, y, z, uu; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -4228,236 +3346,23 @@ test_abs_fill_all_4th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) */ TESTING("inserting objects to fill all rows of recursive indirect blocks four levels deep"); - /* Loop over direct block rows in root indirect block */ - block_size = cparam->managed.start_block_size; + /* Fill direct blocks up in root indirect block */ heap_size = 0; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (H5V_log2_of2(cparam->managed.width) + 1); w++) { - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ + /* Fill all rows of 2nd level indirect blocks */ + if(fill_all_2nd_indirect_rows(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Loop over rows of 3rd level deep indirect blocks */ - for(y = 0; y < (H5V_log2_of2(cparam->managed.width) + 1); y++) { - - /* Loop over row of 3rd level deep indirect blocks */ - for(x = 0; x < cparam->managed.width; x++) { - - /* Loop over direct block rows in third level indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (y + 1); w++) { - - /* Loop over row of indirect blocks */ - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ + /* Fill all rows of 3rd level indirect blocks */ + if(fill_all_3rd_indirect_rows(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Loop over rows of 2nd level deep indirect blocks */ - for(uu = 0; uu < (H5V_log2_of2(cparam->managed.width) + 1); uu++) { - - /* Loop over row of 4th level indirect blocks */ - for(z = 0; z < cparam->managed.width; z++) { - - /* Loop over direct block rows in fourth level indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (H5V_log2_of2(cparam->managed.width) + 1); w++) { - - /* Loop over row of indirect blocks */ - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ - - /* Loop over rows of 3rd level deep indirect blocks */ - for(y = 0; y < (uu + 1); y++) { - - /* Loop over row of 3rd level deep indirect blocks */ - for(x = 0; x < cparam->managed.width; x++) { - - /* Loop over direct block rows in third level indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (y + 1); w++) { - - /* Loop over row of indirect blocks */ - for(v = 0; v < cparam->managed.width; v++) { - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); - while(block_size <= max_block_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ + /* Fill all rows of 4th level indirect blocks */ + if(fill_all_4th_indirect_rows(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR PASSED() @@ -4474,6 +3379,7 @@ error: } H5E_END_TRY; return(1); } /* test_abs_fill_all_4th_recursive_indirect() */ +#endif /* ALL_INSERT_TESTS */ /*------------------------------------------------------------------------- @@ -4505,17 +3411,9 @@ test_abs_start_5th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam) H5F_t *f = NULL; /* Internal file object pointer */ haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ - unsigned char obj[10]; /* Buffer for object to insert */ - unsigned char robj[10]; /* Buffer for reading object */ - unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object inserted */ - hsize_t free_space; /* Size of free space in heap */ unsigned nobjs = 0; /* Number of objects inserted */ - unsigned tot_nobjs = 0; /* Total number of objects inserted */ - size_t block_size; /* Size of block added */ - size_t max_block_size; /* Max. size of block to add */ + hsize_t free_space; /* Size of free space in heap */ hsize_t heap_size; /* Total size of heap */ - unsigned nrows; /* Number of rows inserted */ - unsigned u, v, w, x, y, z, uu; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -4541,380 +3439,208 @@ HDfprintf(stderr, "Fractal heap header address = %a\n", fh_addr); /* * Test inserting mult. (small) objects to fill all direct - * blocks in recursive indirect blocks four levels deep + * blocks in recursive indirect blocks four levels deep and add one more + * block, to make a five level deep structure */ TESTING("inserting objects to create first direct block in recursive indirect blocks five levels deep"); - /* Loop over direct block rows in root indirect block */ - block_size = cparam->managed.start_block_size; + /* Fill direct blocks up in root indirect block */ heap_size = 0; - nrows = 0; - while(block_size <= cparam->managed.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 < cparam->managed.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, cparam, heap_size, block_size, (hsize_t)0, 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; + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Increment row count */ - nrows++; - } /* end for */ + /* Fill all rows of 2nd level indirect blocks */ + if(fill_all_2nd_indirect_rows(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (H5V_log2_of2(cparam->managed.width) + 1); w++) { -#ifdef QAK -HDfprintf(stderr, "indirect row # = %u\n", w); -#endif /* QAK */ - for(v = 0; v < cparam->managed.width; v++) { -#ifdef QAK -HDfprintf(stderr, "indirect block # = %u\n", v); -#endif /* QAK */ - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); -#ifdef QAK -HDfprintf(stderr, "max_block_size = %Zu\n", max_block_size); -#endif /* QAK */ - while(block_size <= max_block_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 < cparam->managed.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, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ -#ifdef QAK -HDfprintf(stderr, "\n"); -#endif /* QAK */ + /* Fill all rows of 3rd level indirect blocks */ + if(fill_all_3rd_indirect_rows(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; + /* Fill all rows of 4th level indirect blocks */ + if(fill_all_4th_indirect_rows(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ + /* Insert one more object, to force creation of five level deep + * recursive indirect block + */ + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1, FALSE)) + FAIL_STACK_ERROR - /* Loop over rows of 3rd level deep indirect blocks */ - for(y = 0; y < (H5V_log2_of2(cparam->managed.width) + 1); y++) { -#ifdef QAK -HDfprintf(stderr, "3rd indirect row # = %u\n", y); -#endif /* QAK */ + PASSED() - /* Loop over row of 3rd level deep indirect blocks */ - for(x = 0; x < cparam->managed.width; x++) { -#ifdef QAK -HDfprintf(stderr, "3rd indirect block # = %u\n", x); -#endif /* QAK */ + /* Close the file */ + if(H5Fclose(file) < 0) + TEST_ERROR - /* Loop over direct block rows in third level indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (y + 1); w++) { -#ifdef QAK -HDfprintf(stderr, "indirect row # = %u\n", w); -#endif /* QAK */ + /* All tests passed */ + return(0); - /* Loop over row of indirect blocks */ - for(v = 0; v < cparam->managed.width; v++) { -#ifdef QAK -HDfprintf(stderr, "indirect block # = %u\n", v); -#endif /* QAK */ - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); -#ifdef QAK -HDfprintf(stderr, "max_block_size = %Zu\n", max_block_size); -#endif /* QAK */ - while(block_size <= max_block_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 < cparam->managed.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, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ -#ifdef QAK -HDfprintf(stderr, "\n"); -#endif /* QAK */ +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_abs_start_5th_recursive_indirect() */ - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; +#ifndef QAK + +/*------------------------------------------------------------------------- + * Function: test_abs_skip_start_block + * + * Purpose: Test inserting object into absolute heap which is too large + * for starting block size, which forces root indirect block + * creation + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, March 27, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_skip_start_block(hid_t fapl, H5HF_create_t *cparam) +{ + 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 */ + haddr_t fh_addr; /* Address of fractal heap created */ + size_t id_len; /* Size of fractal heap IDs */ + unsigned nobjs = 0; /* Number of objects inserted */ + size_t obj_size; /* Size of object */ + hsize_t free_space; /* Size of free space in heap */ + hsize_t heap_size; /* Total size of heap */ - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); - /* Loop over rows of 2nd level deep indirect blocks */ - for(uu = 0; uu < (H5V_log2_of2(cparam->managed.width) + 1); uu++) { -#ifdef QAK -HDfprintf(stderr, "4th indirect row # = %u\n", uu); -#endif /* QAK */ + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR - /* Loop over row of 4th level indirect blocks */ - for(z = 0; z < cparam->managed.width; z++) { -#ifdef QAK -HDfprintf(stderr, "4th indirect block # = %u\n", z); -#endif /* QAK */ + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR - /* Loop over direct block rows in fourth level indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (H5V_log2_of2(cparam->managed.width) + 1); w++) { -#ifdef QAK -HDfprintf(stderr, "indirect row # = %u\n", w); -#endif /* QAK */ + /* Create absolute heap */ + if(H5HF_create(f, dxpl, cparam, &fh_addr/*out*/, &id_len/*out*/) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + if(id_len > HEAP_ID_LEN) + FAIL_STACK_ERROR + if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0)) + FAIL_STACK_ERROR - /* Loop over row of indirect blocks */ - for(v = 0; v < cparam->managed.width; v++) { -#ifdef QAK -HDfprintf(stderr, "indirect block # = %u\n", v); -#endif /* QAK */ - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); -#ifdef QAK -HDfprintf(stderr, "max_block_size = %Zu\n", max_block_size); -#endif /* QAK */ - while(block_size <= max_block_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 < cparam->managed.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, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ -#ifdef QAK -HDfprintf(stderr, "\n"); -#endif /* QAK */ + /* + * Test inserting object into absolute heap which doesn't fit into starting + * block size + */ + TESTING("inserting object that is too large for starting block"); - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; + obj_size = cparam->managed.start_block_size + 1; + free_space = 2 * cparam->managed.width * DBLOCK_FREE(f, dxpl, fh_addr, 0); + free_space += cparam->managed.width * DBLOCK_FREE(f, dxpl, fh_addr, 2); + heap_size = 2 * cparam->managed.width * cparam->managed.start_block_size; + heap_size += cparam->managed.width * (cparam->managed.start_block_size * 2); + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, obj_size, FALSE)) + FAIL_STACK_ERROR - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ + PASSED() - /* Loop over rows of 3rd level deep indirect blocks */ - for(y = 0; y < (uu + 1); y++) { -#ifdef QAK -HDfprintf(stderr, "3rd indirect row # = %u\n", y); -#endif /* QAK */ + /* Close the file */ + if(H5Fclose(file) < 0) + TEST_ERROR - /* Loop over row of 3rd level deep indirect blocks */ - for(x = 0; x < cparam->managed.width; x++) { -#ifdef QAK -HDfprintf(stderr, "3rd indirect block # = %u\n", x); -#endif /* QAK */ + /* All tests passed */ + return(0); - /* Loop over direct block rows in third level indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - /* Loop over filling direct blocks for a row */ - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ - heap_size += block_size; - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ - - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - - /* Loop over rows of 2nd level deep indirect blocks */ - for(w = 0; w < (y + 1); w++) { -#ifdef QAK -HDfprintf(stderr, "indirect row # = %u\n", w); -#endif /* QAK */ +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_abs_skip_start_block() */ - /* Loop over row of indirect blocks */ - for(v = 0; v < cparam->managed.width; v++) { -#ifdef QAK -HDfprintf(stderr, "indirect block # = %u\n", v); -#endif /* QAK */ - /* Loop over direct block rows in first recursive indirect block */ - block_size = cparam->managed.start_block_size; - nrows = 0; - max_block_size = block_size * (1 << ((H5V_log2_of2(cparam->managed.max_direct_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + (w + 1) + 1)); -#ifdef QAK -HDfprintf(stderr, "max_block_size = %Zu\n", max_block_size); -#endif /* QAK */ - while(block_size <= max_block_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 < cparam->managed.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, cparam, heap_size, block_size, (hsize_t)0, tot_nobjs, &nobjs)) - FAIL_STACK_ERROR - tot_nobjs += nobjs; - } /* end for */ -#ifdef QAK -HDfprintf(stderr, "\n"); -#endif /* QAK */ + +/*------------------------------------------------------------------------- + * Function: test_abs_skip_start_block_add_back + * + * Purpose: Test inserting object into absolute heap which is too large + * for starting block size, which forces root indirect block + * creation, then add object which fits in skipped direct block + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Tuesday, March 28, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_skip_start_block_add_back(hid_t fapl, H5HF_create_t *cparam) +{ + 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 */ + haddr_t fh_addr; /* Address of fractal heap created */ + size_t id_len; /* Size of fractal heap IDs */ + unsigned nobjs = 0; /* Number of objects inserted */ + size_t obj_size; /* Size of object */ + hsize_t free_space; /* Size of free space in heap */ + hsize_t heap_size; /* Total size of heap */ - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ - } /* end for */ + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); - /* Insert one more object, to force creation of five level deep - * recursive indirect block - */ + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR - /* Initialize object buffer */ - for(u = 0; u < sizeof(obj); u++) - obj[u] = u + tot_nobjs; + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR - /* Insert object */ - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj), obj, heap_id) < 0) + /* Create absolute heap */ + if(H5HF_create(f, dxpl, cparam, &fh_addr/*out*/, &id_len/*out*/) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + if(id_len > HEAP_ID_LEN) + FAIL_STACK_ERROR + if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0)) FAIL_STACK_ERROR - /* Increment object count */ - tot_nobjs++; + /* + * Test inserting object into absolute heap which doesn't fit into starting + * block size + */ + TESTING("skipping starting block, then adding object back to first block"); - heap_size += cparam->managed.start_block_size; - free_space = cparam->managed.start_block_size - ((sizeof(obj) + OBJ_PREFIX_LEN) + OBJ_PREFIX_LEN + DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, heap_size, heap_size, (hsize_t)0, free_space, (hsize_t)tot_nobjs)) + /* Insert object too large for starting block size */ + obj_size = cparam->managed.start_block_size + 1; + free_space = 2 * cparam->managed.width * DBLOCK_FREE(f, dxpl, fh_addr, 0); + free_space += cparam->managed.width * DBLOCK_FREE(f, dxpl, fh_addr, 2); + heap_size = 2 * cparam->managed.width * cparam->managed.start_block_size; + heap_size += cparam->managed.width * (cparam->managed.start_block_size * 2); + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, obj_size, FALSE)) FAIL_STACK_ERROR - /* Read in object */ - if(H5HF_read(f, dxpl, fh_addr, heap_id, robj) < 0) + /* Insert an object to fill up the heap block just created */ + obj_size = DBLOCK_FREE(f, dxpl, fh_addr, 2) - (obj_size + OBJ_PREFIX_LEN); + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, obj_size, TRUE)) FAIL_STACK_ERROR - if(HDmemcmp(obj, robj, sizeof(obj))) + + /* Insert second "real" object, which should go in earlier direct block */ + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 20, SMALL_OBJ_SIZE2, FALSE)) FAIL_STACK_ERROR PASSED() @@ -4931,27 +3657,28 @@ error: H5Fclose(file); } H5E_END_TRY; return(1); -} /* test_abs_start_5th_recursive_indirect() */ +} /* test_abs_skip_start_block_add_back() */ /*------------------------------------------------------------------------- - * Function: test_abs_skip_start_block + * Function: test_abs_skip_start_block_add_skipped * * Purpose: Test inserting object into absolute heap which is too large * for starting block size, which forces root indirect block - * creation + * creation, then add objects to fill skipped direct blocks + * and add another object to start on next "normal" block * * Return: Success: 0 * * Failure: 1 * * Programmer: Quincey Koziol - * Monday, March 27, 2006 + * Tuesday, March 28, 2006 * *------------------------------------------------------------------------- */ static int -test_abs_skip_start_block(hid_t fapl, H5HF_create_t *cparam) +test_abs_skip_start_block_add_skipped(hid_t fapl, H5HF_create_t *cparam) { hid_t file = -1; /* File ID */ hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ @@ -4959,11 +3686,10 @@ test_abs_skip_start_block(hid_t fapl, H5HF_create_t *cparam) H5F_t *f = NULL; /* Internal file object pointer */ haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ - unsigned char *obj = NULL; /* Buffer for object to insert */ - unsigned char *robj = NULL; /* Buffer for object to read */ - unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object inserted */ + unsigned nobjs = 0; /* Number of objects inserted */ + size_t obj_size; /* Size of object */ hsize_t free_space; /* Size of free space in heap */ - unsigned u; /* Local index variable */ + hsize_t heap_size; /* Total size of heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -4986,28 +3712,34 @@ test_abs_skip_start_block(hid_t fapl, H5HF_create_t *cparam) if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0)) FAIL_STACK_ERROR - /* Initialize object buffer */ - obj = H5MM_malloc(cparam->managed.start_block_size + 1); - for(u = 0; u < (cparam->managed.start_block_size + 1); u++) - obj[u] = u; - /* * Test inserting object into absolute heap which doesn't fit into starting * block size */ - TESTING("inserting object that is too large for starting block"); - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, (cparam->managed.start_block_size + 1), obj, heap_id) < 0) + TESTING("skipping starting block, then adding objects to backfill and extend"); + + /* Insert object too large for starting block size */ + obj_size = cparam->managed.start_block_size + 1; + free_space = 2 * cparam->managed.width * DBLOCK_FREE(f, dxpl, fh_addr, 0); + free_space += cparam->managed.width * DBLOCK_FREE(f, dxpl, fh_addr, 2); + heap_size = 2 * cparam->managed.width * cparam->managed.start_block_size; + heap_size += cparam->managed.width * (cparam->managed.start_block_size * 2); + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, obj_size, FALSE)) FAIL_STACK_ERROR - free_space = (2 * cparam->managed.width * (cparam->managed.start_block_size - (OBJ_PREFIX_LEN + DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)))) + (2 * cparam->managed.start_block_size) - (((cparam->managed.start_block_size + 1) + OBJ_PREFIX_LEN) + OBJ_PREFIX_LEN + DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)(2 * cparam->managed.start_block_size), (hsize_t)(2 * cparam->managed.start_block_size), (hsize_t)0, free_space, (hsize_t)1)) + + /* Insert an object to fill up the heap block just created */ + obj_size = DBLOCK_FREE(f, dxpl, fh_addr, 2) - (cparam->managed.start_block_size + 1 + OBJ_PREFIX_LEN); + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, obj_size, TRUE)) FAIL_STACK_ERROR - /* Check reading back in the object */ - robj = H5MM_malloc(cparam->managed.start_block_size + 1); - if(H5HF_read(f, dxpl, fh_addr, heap_id, robj) < 0) + /* Add rows of blocks to "backfill" direct blocks that were skipped */ + if(fill_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, 0, &nobjs)) + FAIL_STACK_ERROR + if(fill_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, 1, &nobjs)) FAIL_STACK_ERROR - if(HDmemcmp(obj, robj, (cparam->managed.start_block_size + 1))) + + /* Insert another object, which should go extend direct blocks, instead of backfill */ + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 20, SMALL_OBJ_SIZE2, FALSE)) FAIL_STACK_ERROR PASSED() @@ -5017,38 +3749,35 @@ test_abs_skip_start_block(hid_t fapl, H5HF_create_t *cparam) TEST_ERROR /* All tests passed */ - H5MM_xfree(obj); - H5MM_xfree(robj); return(0); error: H5E_BEGIN_TRY { H5Fclose(file); - H5MM_xfree(obj); - H5MM_xfree(robj); } H5E_END_TRY; return(1); -} /* test_abs_skip_start_block() */ +} /* test_abs_skip_start_block_add_skipped() */ /*------------------------------------------------------------------------- - * Function: test_abs_skip_start_block_add_back + * Function: test_abs_skip_2nd_block * - * Purpose: Test inserting object into absolute heap which is too large - * for starting block size, which forces root indirect block - * creation, then add object which fits in skipped direct block + * Purpose: Test inserting object into absolute heap which is small + * enough for starting block size, then add object too large + * for any blocks in first row of direct blocks, to force + * early creation of indirect block (and range of skipped blocks) * * Return: Success: 0 * * Failure: 1 * * Programmer: Quincey Koziol - * Tuesday, March 28, 2006 + * Saturday, April 1, 2006 * *------------------------------------------------------------------------- */ static int -test_abs_skip_start_block_add_back(hid_t fapl, H5HF_create_t *cparam) +test_abs_skip_2nd_block(hid_t fapl, H5HF_create_t *cparam) { hid_t file = -1; /* File ID */ hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ @@ -5056,14 +3785,10 @@ test_abs_skip_start_block_add_back(hid_t fapl, H5HF_create_t *cparam) H5F_t *f = NULL; /* Internal file object pointer */ haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ - unsigned char *obj = NULL; /* Buffer for object to insert */ - unsigned char *robj = NULL; /* Buffer for object to read */ - unsigned char obj2[20]; /* Buffer for second object to insert */ - unsigned char robj2[20]; /* Buffer for reading second object */ - unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object inserted */ + unsigned nobjs = 0; /* Number of objects inserted */ + size_t obj_size; /* Size of object */ hsize_t free_space; /* Size of free space in heap */ - size_t obj_size; /* Size of object to add */ - unsigned u; /* Local index variable */ + hsize_t heap_size; /* Total size of heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -5083,70 +3808,286 @@ test_abs_skip_start_block_add_back(hid_t fapl, H5HF_create_t *cparam) FAIL_STACK_ERROR if(id_len > HEAP_ID_LEN) FAIL_STACK_ERROR - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0)) + + /* + * Test inserting first (small) object into absolute heap + */ + TESTING("insert object to initial block, then add object too large for starting direct blocks"); + + /* Insert small object, to create root direct block */ + obj_size = SMALL_OBJ_SIZE1; + free_space = DBLOCK_FREE(f, dxpl, fh_addr, 0); + heap_size = cparam->managed.start_block_size; + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, obj_size, FALSE)) FAIL_STACK_ERROR - /* Initialize object buffer */ + /* Insert large object, to force creation of indirect block and + * range of skipped blocks that are too small to hold the second object + */ obj_size = cparam->managed.start_block_size + 1; - obj = H5MM_malloc(obj_size); - for(u = 0; u < obj_size; u++) - obj[u] = u; + free_space += (cparam->managed.width - 1 )* DBLOCK_FREE(f, dxpl, fh_addr, 0); + free_space += cparam->managed.width * DBLOCK_FREE(f, dxpl, fh_addr, 1); + free_space += cparam->managed.width * DBLOCK_FREE(f, dxpl, fh_addr, 2); + heap_size += (cparam->managed.width - 1) * cparam->managed.start_block_size; + heap_size += cparam->managed.width * cparam->managed.start_block_size; + heap_size += cparam->managed.width * cparam->managed.start_block_size * 2; + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 20, obj_size, FALSE)) + 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_skip_2nd_block() */ + + +/*------------------------------------------------------------------------- + * Function: test_abs_skip_2nd_block_add_skipped + * + * Purpose: Test inserting object into absolute heap which is small + * enough for starting block size, then add object too large + * for any blocks in first row of direct blocks, to force + * early creation of indirect block (and range of skipped blocks). + * Then add more objects to fill up remainder of initial direct + * block and all the skipped blocks, and one more object (to + * start next "normal" block). + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Saturday, April 1, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_skip_2nd_block_add_skipped(hid_t fapl, H5HF_create_t *cparam) +{ + 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 */ + haddr_t fh_addr; /* Address of fractal heap created */ + size_t id_len; /* Size of fractal heap IDs */ + unsigned nobjs = 0; /* Number of objects inserted */ + size_t obj_size; /* Size of object */ + hsize_t free_space; /* Size of free space in heap */ + 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 */ + if(H5HF_create(f, dxpl, cparam, &fh_addr/*out*/, &id_len/*out*/) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + if(id_len > HEAP_ID_LEN) + FAIL_STACK_ERROR /* - * Test inserting object into absolute heap which doesn't fit into starting - * block size + * Test inserting first (small) object into absolute heap */ - TESTING("skipping starting block, then adding object back to first block"); - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, obj_size, obj, heap_id) < 0) + TESTING("insert object to initial block, then add object too large for starting direct blocks, then backfill and extend"); + + /* Insert small object, to create root direct block */ + obj_size = SMALL_OBJ_SIZE1; + free_space = DBLOCK_FREE(f, dxpl, fh_addr, 0); + heap_size = cparam->managed.start_block_size; + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, obj_size, FALSE)) FAIL_STACK_ERROR - free_space = (2 * cparam->managed.width * (cparam->managed.start_block_size - (OBJ_PREFIX_LEN + DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)))) + (2 * cparam->managed.start_block_size) - ((obj_size + OBJ_PREFIX_LEN) + OBJ_PREFIX_LEN + DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)(2 * cparam->managed.start_block_size), (hsize_t)(2 * cparam->managed.start_block_size), (hsize_t)0, free_space, (hsize_t)1)) + + /* Insert large object, to force creation of indirect block and + * range of skipped blocks that are too small to hold the second object + */ + obj_size = cparam->managed.start_block_size + 1; + free_space += (cparam->managed.width - 1 )* DBLOCK_FREE(f, dxpl, fh_addr, 0); + free_space += cparam->managed.width * DBLOCK_FREE(f, dxpl, fh_addr, 1); + free_space += cparam->managed.width * DBLOCK_FREE(f, dxpl, fh_addr, 2); + heap_size += (cparam->managed.width - 1) * cparam->managed.start_block_size; + heap_size += cparam->managed.width * cparam->managed.start_block_size; + heap_size += cparam->managed.width * cparam->managed.start_block_size * 2; + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 20, obj_size, FALSE)) FAIL_STACK_ERROR - /* Check reading back in the object */ - robj = H5MM_malloc(obj_size); - if(H5HF_read(f, dxpl, fh_addr, heap_id, robj) < 0) + /* Insert an object to fill up the (smaller) heap block just created */ + obj_size = DBLOCK_FREE(f, dxpl, fh_addr, 0) - (SMALL_OBJ_SIZE1 + OBJ_PREFIX_LEN); + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, obj_size, TRUE)) FAIL_STACK_ERROR - if(HDmemcmp(obj, robj, obj_size)) + + /* Fill remainder of 2 * start size block */ + obj_size = DBLOCK_FREE(f, dxpl, fh_addr, 2) - ((cparam->managed.start_block_size + 1) + OBJ_PREFIX_LEN); + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 20, obj_size, TRUE)) FAIL_STACK_ERROR - /* Insert an object to fill up the heap block just created */ + /* Insert objects to fill remaining rows of the starting block size */ + for(u = 0; u < 2; u++) { + /* Fill a row of direct heap blocks up */ + for(v = 0; v < (cparam->managed.width - 1); v++) { + free_space -= DBLOCK_FREE(f, dxpl, fh_addr, u); + if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, cparam->managed.start_block_size, free_space, &nobjs)) + FAIL_STACK_ERROR + } /* end for */ + } /* end for */ - /* Initialize object buffer */ - H5MM_xfree(obj); - obj_size = (2 * cparam->managed.start_block_size) - (OBJ_PREFIX_LEN + (cparam->managed.start_block_size + 1 + OBJ_PREFIX_LEN) + DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - obj = H5MM_malloc(obj_size); - for(u = 0; u < obj_size; u++) - obj[u] = u; + /* Insert one more object, to create new 2 * start size direct block */ + obj_size = SMALL_OBJ_SIZE1; + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, obj_size, FALSE)) + FAIL_STACK_ERROR - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, obj_size, obj, heap_id) < 0) + 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_skip_2nd_block_add_skipped() */ + + +/*------------------------------------------------------------------------- + * Function: test_abs_fill_one_partial_skip_2nd_block_add_skipped + * + * Purpose: Test filling initial direct block, then add object small enough + * for initial block size (to create root indirect block), then + * add object too large for any blocks in first three rows of + * direct blocks, to force extension of indirect block (and range + * of skipped blocks). + * + * Then add more objects to fill up remainder of partial direct + * block and all the skipped blocks, and one more object (to + * start next "normal" block). + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, April 3, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_fill_one_partial_skip_2nd_block_add_skipped(hid_t fapl, H5HF_create_t *cparam) +{ + 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 */ + haddr_t fh_addr; /* Address of fractal heap created */ + size_t id_len; /* Size of fractal heap IDs */ + unsigned nobjs = 0; /* Number of objects inserted */ + size_t obj_size; /* Size of object */ + hsize_t free_space; /* Size of free space in heap */ + 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 */ + if(H5HF_create(f, dxpl, cparam, &fh_addr/*out*/, &id_len/*out*/) < 0) FAIL_STACK_ERROR - free_space -= obj_size; /* no object prefix, there's no more space in the node */ - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)(2 * cparam->managed.start_block_size), (hsize_t)(2 * cparam->managed.start_block_size), (hsize_t)0, free_space, (hsize_t)2)) + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + if(id_len > HEAP_ID_LEN) FAIL_STACK_ERROR - /* Check reading back in the object */ - H5MM_xfree(robj); - robj = H5MM_malloc(obj_size); - if(H5HF_read(f, dxpl, fh_addr, heap_id, robj) < 0) + /* + * Test absolute heap + */ + TESTING("skipping blocks with indirect root, then backfill and extend"); + + /* Fill initial direct block */ + heap_size = cparam->managed.start_block_size; + free_space = 0; + if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, cparam->managed.start_block_size, free_space, &nobjs)) FAIL_STACK_ERROR - if(HDmemcmp(obj, robj, obj_size)) + + /* Insert small object, to create root indirect block */ + obj_size = SMALL_OBJ_SIZE1; + heap_size += (cparam->managed.width - 1) * cparam->managed.start_block_size; + free_space += (cparam->managed.width - 1) * DBLOCK_FREE(f, dxpl, fh_addr, 0); + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, obj_size, FALSE)) FAIL_STACK_ERROR - /* Insert second "real" object, which should go in earlier direct block */ - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj2), obj2, heap_id) < 0) + /* Insert large object, to force creation of indirect block and + * range of skipped blocks that are too small to hold the large object + */ + obj_size = (2 * cparam->managed.start_block_size) + 1; + heap_size += cparam->managed.width * cparam->managed.start_block_size; + heap_size += cparam->managed.width * cparam->managed.start_block_size * 2; + heap_size += cparam->managed.width * cparam->managed.start_block_size * 4; + free_space += cparam->managed.width * DBLOCK_FREE(f, dxpl, fh_addr, 1); + free_space += cparam->managed.width * DBLOCK_FREE(f, dxpl, fh_addr, 2); + free_space += cparam->managed.width * DBLOCK_FREE(f, dxpl, fh_addr, 3); + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 20, obj_size, FALSE)) FAIL_STACK_ERROR - free_space -= (OBJ_PREFIX_LEN + sizeof(obj2)); - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)(3 * cparam->managed.start_block_size), (hsize_t)(3 * cparam->managed.start_block_size), (hsize_t)0, free_space, (hsize_t)3)) + + /* Insert an object to fill up the (smaller) heap block just created */ + obj_size = DBLOCK_FREE(f, dxpl, fh_addr, 0) - (SMALL_OBJ_SIZE1 + OBJ_PREFIX_LEN); + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, obj_size, TRUE)) FAIL_STACK_ERROR - /* Check reading back in the second object */ - if(H5HF_read(f, dxpl, fh_addr, heap_id, robj2) < 0) + /* Insert object to fill remainder of 4 * start size block */ + obj_size = DBLOCK_FREE(f, dxpl, fh_addr, 3) - (((2 * cparam->managed.start_block_size) + 1) + OBJ_PREFIX_LEN); + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 20, obj_size, TRUE)) FAIL_STACK_ERROR - if(HDmemcmp(obj2, robj2, sizeof(obj2))) + + /* Insert objects to fill remaining heaps in first row */ + for(u = 0; u < (cparam->managed.width - 2); u++) { + /* Fill a direct heap block up */ + free_space -= DBLOCK_FREE(f, dxpl, fh_addr, 0); + if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, cparam->managed.start_block_size, free_space, &nobjs)) + FAIL_STACK_ERROR + } /* end for */ + + /* Insert objects to fill remaining heaps in second row */ + if(fill_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, 1, &nobjs)) + FAIL_STACK_ERROR + + /* Insert objects to fill remaining heaps in third row */ + if(fill_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, 2, &nobjs)) + FAIL_STACK_ERROR + + /* Insert one more object, to create new 4 * start size direct block */ + obj_size = SMALL_OBJ_SIZE1; + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, obj_size, FALSE)) FAIL_STACK_ERROR PASSED() @@ -5156,39 +4097,35 @@ test_abs_skip_start_block_add_back(hid_t fapl, H5HF_create_t *cparam) TEST_ERROR /* All tests passed */ - H5MM_xfree(obj); - H5MM_xfree(robj); return(0); error: H5E_BEGIN_TRY { H5Fclose(file); - H5MM_xfree(obj); - H5MM_xfree(robj); } H5E_END_TRY; return(1); -} /* test_abs_skip_start_block_add_back() */ +} /* test_abs_fill_one_partial_skip_2nd_block_add_skipped() */ /*------------------------------------------------------------------------- - * Function: test_abs_skip_start_block_add_skipped + * Function: test_abs_fill_direct_skip_indirect_start_block_add_skipped * - * Purpose: Test inserting object into absolute heap which is too large - * for starting block size, which forces root indirect block - * creation, then add objects to fill skipped direct blocks - * and add another object to start on next "normal" block + * Purpose: Test filling all direct blocks in root indirect block, then + * add object too large for initial block in first row of direct + * blocks in indirect block, to force extension of non-root + * indirect block (and range of skipped blocks). * * Return: Success: 0 * * Failure: 1 * * Programmer: Quincey Koziol - * Tuesday, March 28, 2006 + * Monday, April 3, 2006 * *------------------------------------------------------------------------- */ static int -test_abs_skip_start_block_add_skipped(hid_t fapl, H5HF_create_t *cparam) +test_abs_fill_direct_skip_indirect_start_block_add_skipped(hid_t fapl, H5HF_create_t *cparam) { hid_t file = -1; /* File ID */ hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ @@ -5196,18 +4133,10 @@ test_abs_skip_start_block_add_skipped(hid_t fapl, H5HF_create_t *cparam) H5F_t *f = NULL; /* Internal file object pointer */ haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ - unsigned char *obj = NULL; /* Buffer for object to insert */ - unsigned char *robj = NULL; /* Buffer for object to read */ - unsigned char obj2[20]; /* Buffer for second object to insert */ - unsigned char robj2[20]; /* Buffer for reading second object */ - unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object inserted */ - hsize_t free_space; /* Size of free space in heap */ unsigned nobjs = 0; /* Number of objects inserted */ - unsigned tot_nobjs = 0; /* Total number of objects inserted */ - size_t obj_size; /* Size of object to add */ - size_t block_size; /* Size of block added */ + size_t obj_size; /* Size of object */ + hsize_t free_space; /* Size of free space in heap */ hsize_t heap_size; /* Total size of heap */ - unsigned u, v; /* Local index variable */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -5227,102 +4156,470 @@ test_abs_skip_start_block_add_skipped(hid_t fapl, H5HF_create_t *cparam) FAIL_STACK_ERROR if(id_len > HEAP_ID_LEN) FAIL_STACK_ERROR - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0)) + + /* + * Test absolute heap + */ + TESTING("filling direct blocks and skipping blocks in non-root indirect block, then backfill and extend"); + + /* Fill direct blocks in root indirect block */ + heap_size = 0; + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) FAIL_STACK_ERROR - /* Initialize object buffer */ - obj_size = cparam->managed.start_block_size + 1; - obj = H5MM_malloc(obj_size); - for(u = 0; u < obj_size; u++) - obj[u] = u; + /* Insert large object, to force creation of indirect block and + * range of skipped blocks that are too small to hold the large object + */ + obj_size = (2 * cparam->managed.start_block_size) + 1; + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 20, obj_size, FALSE)) + FAIL_STACK_ERROR + + /* Add rows of blocks to "backfill" direct blocks that were skipped */ + if(fill_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, 0, &nobjs)) + FAIL_STACK_ERROR + if(fill_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, 1, &nobjs)) + FAIL_STACK_ERROR + + /* Insert an object to fill up the (biggest) heap block created */ + obj_size = DBLOCK_FREE(f, dxpl, fh_addr, 3) - (((2 * cparam->managed.start_block_size) + 1) + OBJ_PREFIX_LEN); + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 20, obj_size, TRUE)) + FAIL_STACK_ERROR + + /* Fill direct block heaps with 2 * initial block size in nested indirect block */ + if(fill_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, 2, &nobjs)) + FAIL_STACK_ERROR + + /* Insert one more object, to create new 4 * start size direct block */ + obj_size = SMALL_OBJ_SIZE1; + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, obj_size, FALSE)) + 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_fill_direct_skip_indirect_start_block_add_skipped() */ + + +/*------------------------------------------------------------------------- + * Function: test_abs_fill_direct_skip_2nd_indirect_start_block_add_skipped + * + * Purpose: Test filling all direct blocks in root indirect block, then + * add object too large for all direct blocks in first row of + * indirect blocks, to force skipping a row of indirect blocks + * (and range of skipped blocks), then backfill all direct blocks + * skipped and extend to next "normal" direct block. + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, April 3, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_fill_direct_skip_2nd_indirect_start_block_add_skipped(hid_t fapl, H5HF_create_t *cparam) +{ + 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 */ + haddr_t fh_addr; /* Address of fractal heap created */ + size_t id_len; /* Size of fractal heap IDs */ + unsigned first_row_bits; /* Number of bits used bit addresses in first row */ + unsigned first_indirect_block_size; /* Range of addresses covered by each of the first indirect blocks */ + unsigned num_first_indirect_rows; /* Number of rows (of direct blocks) in each of the first indirect blocks */ + size_t obj_block_size; /* Size of block to hold large object added */ + size_t block_size; /* Size of block added */ + unsigned row; /* Current row in indirect block */ + unsigned nobjs = 0; /* Number of objects inserted */ + size_t obj_size; /* Size of object */ + hsize_t free_space; /* Size of free space in heap */ + 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 */ + if(H5HF_create(f, dxpl, cparam, &fh_addr/*out*/, &id_len/*out*/) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + if(id_len > HEAP_ID_LEN) + FAIL_STACK_ERROR +#ifdef QAK +HDfprintf(stderr, "Fractal heap header address = %a\n", fh_addr); +#endif /* QAK */ + + /* Compute # of bits used in first row */ + first_row_bits = H5V_log2_of2(cparam->managed.start_block_size) + + H5V_log2_of2(cparam->managed.width); + first_indirect_block_size = 2 * cparam->managed.max_direct_size; + num_first_indirect_rows = (H5V_log2_of2(first_indirect_block_size) - first_row_bits) + 1; + obj_block_size = 1 << ((num_first_indirect_rows + H5V_log2_of2(cparam->managed.start_block_size)) - 1); +#ifdef QAK +HDfprintf(stderr, "first_row_bits = %u\n", first_row_bits); +HDfprintf(stderr, "first_indirect_block_size = %u\n", first_indirect_block_size); +HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); +HDfprintf(stderr, "obj_block_size = %Zu\n", obj_block_size); +#endif /* QAK */ /* - * Test inserting object into absolute heap which doesn't fit into starting - * block size + * Test absolute heap */ - TESTING("skipping starting block, then adding objects to backfill and extend"); - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, obj_size, obj, heap_id) < 0) + TESTING("filling direct blocks and skipping row of non-root indirect blocks, then backfill and extend"); + + /* Fill direct blocks in root indirect block */ + heap_size = 0; + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) FAIL_STACK_ERROR - free_space = (2 * cparam->managed.width * (cparam->managed.start_block_size - (OBJ_PREFIX_LEN + DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)))) + (2 * cparam->managed.start_block_size) - ((obj_size + OBJ_PREFIX_LEN) + OBJ_PREFIX_LEN + DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)(2 * cparam->managed.start_block_size), (hsize_t)(2 * cparam->managed.start_block_size), (hsize_t)0, free_space, (hsize_t)1)) + + /* Insert large object, to force creation of indirect block and + * range of skipped (indirect) blocks that are too small to hold the large + * object + */ + obj_size = (1 << ((num_first_indirect_rows + H5V_log2_of2(cparam->managed.start_block_size)) - 2)) + 1; +#ifdef QAK +HDfprintf(stderr, "obj_size = %Zu\n", obj_size); +#endif /* QAK */ + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 20, obj_size, FALSE)) FAIL_STACK_ERROR - /* Check reading back in the object */ - robj = H5MM_malloc(obj_size); - if(H5HF_read(f, dxpl, fh_addr, heap_id, robj) < 0) + /* Insert object to fill space in (large) block created */ + obj_size = DBLOCK_FREE(f, dxpl, fh_addr, num_first_indirect_rows) - (obj_size + OBJ_PREFIX_LEN); + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 20, obj_size, TRUE)) FAIL_STACK_ERROR - if(HDmemcmp(obj, robj, obj_size)) + + /* Fill all rows of direct blocks that are smaller than large object's block size */ + block_size = cparam->managed.start_block_size; + row = 0; + while(block_size < obj_block_size) { + /* Fill rows of direct blocks in skipped indirect blocks */ + for(u = 0; u < cparam->managed.width; u++) + if(fill_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, row, &nobjs)) + FAIL_STACK_ERROR + + /* Fill row of direct blocks in largest (i.e. non-skipped) indirect block */ + if(fill_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, row, &nobjs)) + FAIL_STACK_ERROR + + /* Advance position in blocks */ + if(row > 0) + block_size *= 2; + row++; + } /* end while */ + + /* Add one more object, to create another "large" block */ + obj_size = SMALL_OBJ_SIZE1; + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, obj_size, FALSE)) FAIL_STACK_ERROR - /* Insert an object to fill up the heap block just created */ + PASSED() - /* Initialize object buffer */ - H5MM_xfree(obj); - obj_size = (2 * cparam->managed.start_block_size) - (OBJ_PREFIX_LEN + (cparam->managed.start_block_size + 1 + OBJ_PREFIX_LEN) + DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - obj = H5MM_malloc(obj_size); - for(u = 0; u < obj_size; u++) - obj[u] = u; + /* Close the file */ + if(H5Fclose(file) < 0) + TEST_ERROR - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, obj_size, obj, heap_id) < 0) + /* All tests passed */ + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_abs_fill_direct_skip_2nd_indirect_start_block_add_skipped() */ + + +/*------------------------------------------------------------------------- + * Function: test_abs_fill_direct_skip_2nd_indirect_skip_2nd_block_add_skipped + * + * Purpose: Test filling all direct blocks in root indirect block, then + * add object too large for all direct blocks in first row of + * indirect blocks, to force skipping a row of indirect blocks + * (and range of skipped blocks), then add object that is too + * large for initial block size in skipped indirect blocks, then + * backfill all direct blocks and extend to next "normal" direct + * block (but insert first block of backfilling with object + * too large for initial block size in skipped indirect block + * row's direct blocks). + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Tuesday, April 11, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_fill_direct_skip_2nd_indirect_skip_2nd_block_add_skipped(hid_t fapl, H5HF_create_t *cparam) +{ + 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 */ + haddr_t fh_addr; /* Address of fractal heap created */ + size_t id_len; /* Size of fractal heap IDs */ + unsigned first_row_bits; /* Number of bits used bit addresses in first row */ + unsigned first_indirect_block_size; /* Range of addresses covered by each of the first indirect blocks */ + unsigned num_first_indirect_rows; /* Number of rows (of direct blocks) in each of the first indirect blocks */ + size_t obj_block_size; /* Size of block to hold large object added */ + size_t block_size; /* Size of block added */ + unsigned row; /* Current row in indirect block */ + unsigned nobjs = 0; /* Number of objects inserted */ + size_t obj_size; /* Size of object */ + hsize_t free_space; /* Size of free space in heap */ + 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 */ + if(H5HF_create(f, dxpl, cparam, &fh_addr/*out*/, &id_len/*out*/) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + if(id_len > HEAP_ID_LEN) FAIL_STACK_ERROR - free_space -= obj_size; /* no object prefix, there's no more space in the node */ #ifdef QAK -HDfprintf(stderr, "free_space = %Hu\n", free_space); +HDfprintf(stderr, "Fractal heap header address = %a\n", fh_addr); +#endif /* QAK */ + + /* Compute # of bits used in first row */ + first_row_bits = H5V_log2_of2(cparam->managed.start_block_size) + + H5V_log2_of2(cparam->managed.width); + first_indirect_block_size = 2 * cparam->managed.max_direct_size; + num_first_indirect_rows = (H5V_log2_of2(first_indirect_block_size) - first_row_bits) + 1; + obj_block_size = 1 << ((num_first_indirect_rows + H5V_log2_of2(cparam->managed.start_block_size)) - 1); +#ifdef QAK +HDfprintf(stderr, "first_row_bits = %u\n", first_row_bits); +HDfprintf(stderr, "first_indirect_block_size = %u\n", first_indirect_block_size); +HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); +HDfprintf(stderr, "obj_block_size = %Zu\n", obj_block_size); #endif /* QAK */ - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)(2 * cparam->managed.start_block_size), (hsize_t)(2 * cparam->managed.start_block_size), (hsize_t)0, free_space, (hsize_t)2)) + + /* + * Test absolute heap + */ + TESTING("filling direct blocks and skipping row of non-root indirect blocks, then skip row of direct blocks, then backfill and extend"); + + /* Fill direct blocks in root indirect block */ + heap_size = 0; + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) FAIL_STACK_ERROR - /* Check reading back in the object */ - H5MM_xfree(robj); - robj = H5MM_malloc(obj_size); - if(H5HF_read(f, dxpl, fh_addr, heap_id, robj) < 0) + /* Insert large object, to force creation of indirect block and + * range of skipped (indirect) blocks that are too small to hold the large + * object + */ + obj_size = (1 << ((num_first_indirect_rows + H5V_log2_of2(cparam->managed.start_block_size)) - 2)) + 1; +#ifdef QAK +HDfprintf(stderr, "obj_size = %Zu\n", obj_size); +#endif /* QAK */ + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 20, obj_size, FALSE)) FAIL_STACK_ERROR - if(HDmemcmp(obj, robj, obj_size)) + + /* Insert object to fill space in (large) block created */ + obj_size = DBLOCK_FREE(f, dxpl, fh_addr, num_first_indirect_rows) - (obj_size + OBJ_PREFIX_LEN); + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 20, obj_size, TRUE)) FAIL_STACK_ERROR - /* Add row of blocks to "backfill" direct blocks that were skipped */ - heap_size = (2 * cparam->managed.start_block_size) + cparam->managed.start_block_size; - block_size = cparam->managed.start_block_size; - tot_nobjs = nobjs = 2; - free_space -= cparam->managed.start_block_size - (OBJ_PREFIX_LEN + DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); + /* Insert object too large for initial block size in skipped indirect blocks */ + obj_size = (cparam->managed.start_block_size * 4) + 1; #ifdef QAK -HDfprintf(stderr, "free_space = %Hu\n", free_space); +HDfprintf(stderr, "obj_size = %Zu\n", obj_size); #endif /* QAK */ - for(v = 0; v < 2; v++) { - for(u = 0; u < cparam->managed.width; u++) { - /* Fill a direct heap block up */ + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, obj_size, FALSE)) + FAIL_STACK_ERROR + + /* Insert object to fill space in (medium) block just created */ + obj_size = DBLOCK_FREE(f, dxpl, fh_addr, 4) - (obj_size + OBJ_PREFIX_LEN); #ifdef QAK -HDfprintf(stderr, "heap_size = %Hu\n", heap_size); +HDfprintf(stderr, "obj_size = %Zu\n", obj_size); #endif /* QAK */ - if(fill_heap(f, dxpl, fh_addr, cparam, heap_size, block_size, free_space, tot_nobjs, &nobjs)) + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 20, obj_size, TRUE)) + FAIL_STACK_ERROR + + /* Finish off blocks in row of medium block size (just to make row filling easier below) */ + obj_size = DBLOCK_FREE(f, dxpl, fh_addr, 4); + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 20, obj_size, TRUE)) + FAIL_STACK_ERROR + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 20, obj_size, TRUE)) + FAIL_STACK_ERROR + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 20, obj_size, TRUE)) + FAIL_STACK_ERROR + + /* Fill all rows of direct blocks that are smaller than large object's block size */ + block_size = cparam->managed.start_block_size; + row = 0; + while(block_size < obj_block_size) { + /* Fill rows of direct blocks in skipped indirect blocks */ + for(u = 0; u < cparam->managed.width; u++) + if(fill_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, row, &nobjs)) FAIL_STACK_ERROR - free_space -= cparam->managed.start_block_size - (OBJ_PREFIX_LEN + DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - heap_size += block_size; - tot_nobjs += nobjs; - } /* end for */ - } /* end for */ - /* Insert another object, which should go extend direct blocks, instead of backfill */ - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj2), obj2, heap_id) < 0) + /* Fill row of direct blocks in largest (i.e. non-skipped) indirect block */ + /* (Skip the row of blocks filled above) */ + if(row != 4) + if(fill_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, row, &nobjs)) + FAIL_STACK_ERROR + + /* Advance position in blocks */ + if(row > 0) + block_size *= 2; + row++; + } /* end while */ + + /* Add one more object, to create another "large" block */ + obj_size = SMALL_OBJ_SIZE1; + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, obj_size, FALSE)) + 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_fill_direct_skip_2nd_indirect_skip_2nd_block_add_skipped() */ + + +/*------------------------------------------------------------------------- + * Function: test_abs_fill_2nd_direct_skip_start_block_add_skipped + * + * Purpose: Test filling all direct blocks in root indirect block and all + * direct blocks in 2nd level indirect blocks, the insert object + * that is too large to hold in first row of direct blocks of + * 3rd level indirect block, then backfill & extend all skipped + * 3rd level indirect block's direct blocks. + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Tuesday, April 11, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_fill_2nd_direct_skip_start_block_add_skipped(hid_t fapl, H5HF_create_t *cparam) +{ + 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 */ + haddr_t fh_addr; /* Address of fractal heap created */ + size_t id_len; /* Size of fractal heap IDs */ + unsigned nobjs = 0; /* Number of objects inserted */ + size_t obj_size; /* Size of object */ + hsize_t free_space; /* Size of free space in heap */ + hsize_t heap_size; /* Total size of heap */ + + /* 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 */ + if(H5HF_create(f, dxpl, cparam, &fh_addr/*out*/, &id_len/*out*/) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + if(id_len > HEAP_ID_LEN) FAIL_STACK_ERROR - heap_size += cparam->managed.start_block_size; - free_space = (2 * cparam->managed.start_block_size) - (OBJ_PREFIX_LEN + DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - free_space -= (OBJ_PREFIX_LEN + sizeof(obj2)); #ifdef QAK -HDfprintf(stderr, "free_space = %Hu\n", free_space); -HDfprintf(stderr, "heap_size = %Hu\n", heap_size); +HDfprintf(stderr, "Fractal heap header address = %a\n", fh_addr); #endif /* QAK */ - tot_nobjs++; - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, heap_size, heap_size, (hsize_t)0, free_space, (hsize_t)tot_nobjs)) + + /* + * Test absolute heap + */ + TESTING("filling direct blocks, filling 2nd level indirect blocks, and skip first rows of direct blocks of 3rd level indirect block, then backfill and extend"); + + /* Fill direct blocks in root indirect block */ + heap_size = 0; + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR + + /* Fill all rows of 2nd level indirect blocks */ + if(fill_all_2nd_indirect_rows(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR + + /* Insert large object, to force creation of indirect block and + * range of skipped (indirect) blocks that are too small to hold the large + * object + */ + obj_size = (cparam->managed.start_block_size * 2) + 1; + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, obj_size, FALSE)) + FAIL_STACK_ERROR + + /* Insert object to fill space in (large) block created */ + obj_size = DBLOCK_FREE(f, dxpl, fh_addr, 3) - (obj_size + OBJ_PREFIX_LEN); + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 20, obj_size, TRUE)) FAIL_STACK_ERROR - /* Check reading back in the second object */ - if(H5HF_read(f, dxpl, fh_addr, heap_id, robj2) < 0) + /* Fill rows skipped over in 3rd level indirect block's direct blocks */ + if(fill_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, 0, &nobjs)) FAIL_STACK_ERROR - if(HDmemcmp(obj2, robj2, sizeof(obj2))) + if(fill_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, 1, &nobjs)) + FAIL_STACK_ERROR + if(fill_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, 2, &nobjs)) + FAIL_STACK_ERROR + + /* Add one more object, to create another "large" block */ + obj_size = SMALL_OBJ_SIZE1; + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, obj_size, FALSE)) FAIL_STACK_ERROR PASSED() @@ -5332,39 +4629,38 @@ HDfprintf(stderr, "heap_size = %Hu\n", heap_size); TEST_ERROR /* All tests passed */ - H5MM_xfree(obj); - H5MM_xfree(robj); return(0); error: H5E_BEGIN_TRY { H5Fclose(file); - H5MM_xfree(obj); - H5MM_xfree(robj); } H5E_END_TRY; return(1); -} /* test_abs_skip_start_block_add_skipped() */ +} /* test_abs_fill_2nd_direct_skip_start_block_add_skipped() */ /*------------------------------------------------------------------------- - * Function: test_abs_skip_2nd_block + * Function: test_abs_fill_2nd_direct_skip_2nd_indirect_start_block_add_skipped * - * Purpose: Test inserting object into absolute heap which is small - * enough for starting block size, then add object too large - * for any blocks in first row of direct blocks, to force - * early creation of indirect block (and range of skipped blocks) + * Purpose: Test filling all direct blocks in root indirect block and all + * direct blocks in 2nd level indirect blocks, fill all direct + * blocks in 3rd level indirect block, then insert object + * that is too large to hold in first row of direct blocks of + * 3rd level indirect block's first 2nd level indirect block, then + * backfill & extend all skipped 2nd level indirect block's direct + * blocks. * * Return: Success: 0 * * Failure: 1 * * Programmer: Quincey Koziol - * Saturday, April 1, 2006 + * Tuesday, April 11, 2006 * *------------------------------------------------------------------------- */ static int -test_abs_skip_2nd_block(hid_t fapl, H5HF_create_t *cparam) +test_abs_fill_2nd_direct_skip_2nd_indirect_start_block_add_skipped(hid_t fapl, H5HF_create_t *cparam) { hid_t file = -1; /* File ID */ hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ @@ -5372,15 +4668,10 @@ test_abs_skip_2nd_block(hid_t fapl, H5HF_create_t *cparam) H5F_t *f = NULL; /* Internal file object pointer */ haddr_t fh_addr; /* Address of fractal heap created */ size_t id_len; /* Size of fractal heap IDs */ - unsigned char obj[10]; /* Buffer for first object to insert */ - unsigned char robj[10]; /* Buffer for reading first object */ - unsigned char *obj2; /* Buffer for second object to insert */ - unsigned char *robj2; /* Buffer for reading second object */ - unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object inserted */ + unsigned nobjs = 0; /* Number of objects inserted */ + size_t obj_size; /* Size of object */ hsize_t free_space; /* Size of free space in heap */ - size_t obj2_size; /* Size of object to add */ 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)); @@ -5400,50 +4691,55 @@ test_abs_skip_2nd_block(hid_t fapl, H5HF_create_t *cparam) FAIL_STACK_ERROR if(id_len > HEAP_ID_LEN) FAIL_STACK_ERROR - - /* Initialize object buffers */ - for(u = 0; u < sizeof(obj); u++) - obj[u] = u; - obj2_size = cparam->managed.start_block_size + 1; - obj2 = H5MM_malloc(obj2_size); - for(u = 0; u < obj2_size; u++) - obj2[u] = u + 10; +#ifdef QAK +HDfprintf(stderr, "Fractal heap header address = %a\n", fh_addr); +#endif /* QAK */ /* - * Test inserting first (small) object into absolute heap + * Test absolute heap */ - TESTING("inserting two (small) objects into absolute heap"); - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, sizeof(obj), obj, heap_id) < 0) - FAIL_STACK_ERROR - free_space = cparam->managed.start_block_size - ((sizeof(obj) + OBJ_PREFIX_LEN) + OBJ_PREFIX_LEN + DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, (hsize_t)cparam->managed.start_block_size, (hsize_t)cparam->managed.start_block_size, (hsize_t)0, free_space, (hsize_t)1)) + TESTING("filling direct blocks, filling 2nd level indirect blocks, filling 3rd level indirect block's direct blocks, and skip first rows of direct blocks of 3rd level indirect block's 2nd level indirect block, then backfill and extend"); + + /* Fill direct blocks in root indirect block */ + heap_size = 0; + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) FAIL_STACK_ERROR - /* Check reading back in the first object */ - if(H5HF_read(f, dxpl, fh_addr, heap_id, robj) < 0) + /* Fill all rows of 2nd level indirect blocks */ + if(fill_all_2nd_indirect_rows(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) FAIL_STACK_ERROR - if(HDmemcmp(obj, robj, sizeof(obj))) + + /* Fill all direct block rows in third level indirect block */ + if(fill_all_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) FAIL_STACK_ERROR - /* Insert second object, to force creation of indirect block and - * range of skipped blocks that are too small to hold the second object + /* Insert large object, to force creation of indirect block and + * range of skipped (indirect) blocks that are too small to hold the large + * object */ - HDmemset(heap_id, 0, sizeof(heap_id)); - if(H5HF_insert(f, dxpl, fh_addr, obj2_size, obj2, heap_id) < 0) + obj_size = (cparam->managed.start_block_size * 2) + 1; + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, obj_size, FALSE)) FAIL_STACK_ERROR - free_space += (cparam->managed.start_block_size - (OBJ_PREFIX_LEN + DBLOCK_OVERHEAD + (cparam->managed.max_index / 8))) * (cparam->managed.width - 1); /* Rest of first row */ - free_space += (cparam->managed.start_block_size - (OBJ_PREFIX_LEN + DBLOCK_OVERHEAD + (cparam->managed.max_index / 8))) * cparam->managed.width; /* All of second row (blocks are same size as first row) */ - free_space += (2 * cparam->managed.start_block_size) - ((obj2_size + OBJ_PREFIX_LEN) + OBJ_PREFIX_LEN +DBLOCK_OVERHEAD + (cparam->managed.max_index / 8)); - heap_size = cparam->managed.start_block_size + (2 * cparam->managed.start_block_size); - if(check_stats(f, H5P_DATASET_XFER_DEFAULT, fh_addr, heap_size, heap_size, (hsize_t)0, free_space, (hsize_t)2)) + + /* Insert object to fill space in (large) block created */ + obj_size = DBLOCK_FREE(f, dxpl, fh_addr, 3) - (obj_size + OBJ_PREFIX_LEN); + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 20, obj_size, TRUE)) FAIL_STACK_ERROR - /* Check reading back in the second object */ - robj2 = H5MM_malloc(obj2_size); - if(H5HF_read(f, dxpl, fh_addr, heap_id, robj2) < 0) + /* Fill rows skipped over in (3rd level indirect block's) 2nd level + * indirect block's direct blocks + */ + if(fill_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, 0, &nobjs)) + FAIL_STACK_ERROR + if(fill_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, 1, &nobjs)) + FAIL_STACK_ERROR + if(fill_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, 2, &nobjs)) FAIL_STACK_ERROR - if(HDmemcmp(obj2, robj2, obj2_size)) + + /* Add one more object, to create another "large" block */ + obj_size = SMALL_OBJ_SIZE1; + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, obj_size, FALSE)) FAIL_STACK_ERROR PASSED() @@ -5453,94 +4749,160 @@ test_abs_skip_2nd_block(hid_t fapl, H5HF_create_t *cparam) TEST_ERROR /* All tests passed */ - H5MM_xfree(obj2); - H5MM_xfree(robj2); return(0); error: H5E_BEGIN_TRY { H5Fclose(file); } H5E_END_TRY; - H5MM_xfree(obj2); - H5MM_xfree(robj2); return(1); -} /* test_abs_skip_2nd_block() */ +} /* test_abs_fill_2nd_direct_skip_2nd_indirect_start_block_add_skipped() */ +#endif /* QAK */ /*------------------------------------------------------------------------- - * Function: run_tests + * Function: test_abs_fill_2nd_direct_fill_direct_skip_3rd_indirect_start_block_add_skipped * - * Purpose: Test the fractal heap code, with different file access property - * lists and heap creation parameters + * Purpose: Test filling all direct blocks in root indirect block and all + * direct blocks in 2nd level indirect blocks, fill all direct + * blocks in 3rd level indirect block, then insert object + * that is too large to hold in row of indirect blocks of + * 3rd level indirect block, then backfill & extend all skipped + * direct blocks. * - * Return: Success: + * Return: Success: 0 * - * Failure: + * Failure: 1 * * Programmer: Quincey Koziol - * Tuesday, March 21, 2006 + * Tuesday, April 11, 2006 * *------------------------------------------------------------------------- */ -static unsigned -run_tests(hid_t fapl, H5HF_create_t *cparam) +static int +test_abs_fill_2nd_direct_fill_direct_skip_3rd_indirect_start_block_add_skipped(hid_t fapl, H5HF_create_t *cparam) { - unsigned nerrors = 0; /* Cumulative error count */ + 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 */ + haddr_t fh_addr; /* Address of fractal heap created */ + size_t id_len; /* Size of fractal heap IDs */ + unsigned first_row_bits; /* Number of bits used bit addresses in first row */ + unsigned first_indirect_block_size; /* Range of addresses covered by each of the first indirect blocks */ + unsigned num_first_indirect_rows; /* Number of rows (of direct blocks) in each of the first indirect blocks */ + size_t obj_block_size; /* Size of block to hold large object added */ + unsigned nobjs = 0; /* Number of objects inserted */ + size_t obj_size; /* Size of object */ + hsize_t free_space; /* Size of free space in heap */ + hsize_t heap_size; /* Total size of heap */ + unsigned u, v; /* Local index variables */ - /* Test fractal heap creation */ - nerrors += test_create(fapl, cparam); + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); - /* Test fractal heap object insertion */ + /* 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 */ + if(H5HF_create(f, dxpl, cparam, &fh_addr/*out*/, &id_len/*out*/) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + if(id_len > HEAP_ID_LEN) + FAIL_STACK_ERROR #ifdef QAK - nerrors += test_abs_insert_first(fapl, cparam); - nerrors += test_abs_insert_second(fapl, cparam); - nerrors += test_abs_insert_root_mult(fapl, cparam); - nerrors += test_abs_insert_force_indirect(fapl, cparam); - nerrors += test_abs_insert_fill_second(fapl, cparam); - nerrors += test_abs_insert_third_direct(fapl, cparam); - nerrors += test_abs_fill_first_row(fapl, cparam); - nerrors += test_abs_start_second_row(fapl, cparam); - nerrors += test_abs_fill_second_row(fapl, cparam); - nerrors += test_abs_start_third_row(fapl, cparam); - nerrors += test_abs_fill_fourth_row(fapl, cparam); - nerrors += test_abs_fill_all_root_direct(fapl, cparam); - nerrors += test_abs_first_recursive_indirect(fapl, cparam); - nerrors += test_abs_second_direct_recursive_indirect(fapl, cparam); - nerrors += test_abs_fill_first_recursive_indirect(fapl, cparam); - nerrors += test_abs_second_recursive_indirect(fapl, cparam); - nerrors += test_abs_fill_second_recursive_indirect(fapl, cparam); - nerrors += test_abs_fill_recursive_indirect_row(fapl, cparam); - nerrors += test_abs_start_2nd_recursive_indirect(fapl, cparam); - nerrors += test_abs_recursive_indirect_two_deep(fapl, cparam); - nerrors += test_abs_start_3rd_recursive_indirect(fapl, cparam); - nerrors += test_abs_fill_first_3rd_recursive_indirect(fapl, cparam); - nerrors += test_abs_fill_3rd_recursive_indirect_row(fapl, cparam); - nerrors += test_abs_fill_all_3rd_recursive_indirect(fapl, cparam); - nerrors += test_abs_start_4th_recursive_indirect(fapl, cparam); - nerrors += test_abs_fill_first_4th_recursive_indirect(fapl, cparam); - nerrors += test_abs_fill_4th_recursive_indirect_row(fapl, cparam); - nerrors += test_abs_fill_all_4th_recursive_indirect(fapl, cparam); +HDfprintf(stderr, "Fractal heap header address = %a\n", fh_addr); #endif /* QAK */ - /* If this test fails, uncomment the tests above, which build up to this - * level of complexity gradually. -QAK - */ -#ifndef QAK - nerrors += test_abs_start_5th_recursive_indirect(fapl, cparam); -#else /* QAK */ -HDfprintf(stderr, "Uncomment tests!\n"); + + /* Compute # of bits used in first row */ + first_row_bits = H5V_log2_of2(cparam->managed.start_block_size) + + H5V_log2_of2(cparam->managed.width); + first_indirect_block_size = 2 * cparam->managed.max_direct_size; + num_first_indirect_rows = (H5V_log2_of2(first_indirect_block_size) - first_row_bits) + 1; + obj_block_size = 1 << ((num_first_indirect_rows + H5V_log2_of2(cparam->managed.start_block_size)) - 1); +#ifdef QAK +HDfprintf(stderr, "first_row_bits = %u\n", first_row_bits); +HDfprintf(stderr, "first_indirect_block_size = %u\n", first_indirect_block_size); +HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); +HDfprintf(stderr, "obj_block_size = %Zu\n", obj_block_size); #endif /* QAK */ -#ifndef QAK - nerrors += test_abs_skip_start_block(fapl, cparam); - nerrors += test_abs_skip_start_block_add_back(fapl, cparam); - nerrors += test_abs_skip_start_block_add_skipped(fapl, cparam); - nerrors += test_abs_skip_2nd_block(fapl, cparam); -#else /* QAK */ -HDfprintf(stderr, "Uncomment tests!\n"); + /* + * Test absolute heap + */ + TESTING("filling direct blocks, filling 2nd level indirect blocks, filling 3rd level indirect block's direct blocks, and skip first row of indirect blocks of 3rd level indirect block, then backfill and extend"); + + /* Fill direct blocks in root indirect block */ + heap_size = 0; + free_space = 0; + if(fill_root_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR + + /* Fill all rows of 2nd level indirect blocks */ + if(fill_all_2nd_indirect_rows(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR + + /* Fill all direct block rows in third level indirect block */ + if(fill_all_direct(f, dxpl, fh_addr, cparam, &heap_size, &free_space, &nobjs)) + FAIL_STACK_ERROR + + /* Insert large object, to force creation of indirect block and + * range of skipped (indirect) blocks that are too small to hold the large + * object + */ + obj_size = (1 << ((num_first_indirect_rows + H5V_log2_of2(cparam->managed.start_block_size)) - 2)) + 1; +#ifdef QAK +HDfprintf(stderr, "obj_size = %Zu\n", obj_size); #endif /* QAK */ + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 20, obj_size, FALSE)) + FAIL_STACK_ERROR + + /* Insert object to fill space in (large) block created */ + obj_size = DBLOCK_FREE(f, dxpl, fh_addr, num_first_indirect_rows) - (obj_size + OBJ_PREFIX_LEN); + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 20, obj_size, TRUE)) + FAIL_STACK_ERROR - return nerrors; -} /* end run_tests() */ + /* Fill rows skipped over in (first 3rd level indirect block's) 2nd level + * indirect block's direct blocks + * (and second 3rd level indirect block's direct blocks) + */ + for(u = 0; u < num_first_indirect_rows; u++) { + /* Direct block rows in 2nd level indirect blocks */ + for(v = 0; v < cparam->managed.width; v++) + if(fill_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, u, &nobjs)) + FAIL_STACK_ERROR + + /* Direct block row in 3rd level indirect block */ + if(fill_row(f, dxpl, fh_addr, cparam, &heap_size, &free_space, u, &nobjs)) + FAIL_STACK_ERROR + } /* end for */ + + /* Add one more object, to create another "large" block */ + obj_size = SMALL_OBJ_SIZE1; + if(add_obj(f, dxpl, fh_addr, heap_size, &free_space, &nobjs, 10, obj_size, FALSE)) + 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_fill_2nd_direct_fill_direct_skip_3rd_indirect_start_block_add_skipped() */ /*------------------------------------------------------------------------- @@ -5568,23 +4930,68 @@ main(void) h5_reset(); fapl = h5_fileaccess(); -#ifndef QAK /* Test fractal heap with small parameters */ init_small_cparam(&cparam); - puts("Testing with small heap creation parameters:"); - nerrors += run_tests(fapl, &cparam); + /* Test fractal heap creation */ + nerrors += test_create(fapl, &cparam); + + /* Test fractal heap object insertion */ +#ifdef ALL_INSERT_TESTS + nerrors += test_abs_insert_first(fapl, &cparam); + nerrors += test_abs_insert_second(fapl, &cparam); + nerrors += test_abs_insert_root_mult(fapl, &cparam); + nerrors += test_abs_insert_force_indirect(fapl, &cparam); + nerrors += test_abs_insert_fill_second(fapl, &cparam); + nerrors += test_abs_insert_third_direct(fapl, &cparam); + nerrors += test_abs_fill_first_row(fapl, &cparam); + nerrors += test_abs_start_second_row(fapl, &cparam); + nerrors += test_abs_fill_second_row(fapl, &cparam); + nerrors += test_abs_start_third_row(fapl, &cparam); + nerrors += test_abs_fill_fourth_row(fapl, &cparam); + nerrors += test_abs_fill_all_root_direct(fapl, &cparam); + nerrors += test_abs_first_recursive_indirect(fapl, &cparam); + nerrors += test_abs_second_direct_recursive_indirect(fapl, &cparam); + nerrors += test_abs_fill_first_recursive_indirect(fapl, &cparam); + nerrors += test_abs_second_recursive_indirect(fapl, &cparam); + nerrors += test_abs_fill_second_recursive_indirect(fapl, &cparam); + nerrors += test_abs_fill_recursive_indirect_row(fapl, &cparam); + nerrors += test_abs_start_2nd_recursive_indirect(fapl, &cparam); + nerrors += test_abs_recursive_indirect_two_deep(fapl, &cparam); + nerrors += test_abs_start_3rd_recursive_indirect(fapl, &cparam); + nerrors += test_abs_fill_first_3rd_recursive_indirect(fapl, &cparam); + nerrors += test_abs_fill_3rd_recursive_indirect_row(fapl, &cparam); + nerrors += test_abs_fill_all_3rd_recursive_indirect(fapl, &cparam); + nerrors += test_abs_start_4th_recursive_indirect(fapl, &cparam); + nerrors += test_abs_fill_first_4th_recursive_indirect(fapl, &cparam); + nerrors += test_abs_fill_4th_recursive_indirect_row(fapl, &cparam); + nerrors += test_abs_fill_all_4th_recursive_indirect(fapl, &cparam); +#endif /* ALL_INSERT_TESTS */ + /* If this test fails, uncomment the tests above, which build up to this + * level of complexity gradually. -QAK + */ +#ifndef QAK + nerrors += test_abs_start_5th_recursive_indirect(fapl, &cparam); #else /* QAK */ HDfprintf(stderr, "Uncomment tests!\n"); #endif /* QAK */ -#ifdef QAK - /* Test fractal heap with standard parameters */ - init_std_cparam(&cparam); - puts("Testing with standard heap creation parameters:"); - nerrors += run_tests(fapl, &cparam); + +#ifndef QAK + nerrors += test_abs_skip_start_block(fapl, &cparam); + nerrors += test_abs_skip_start_block_add_back(fapl, &cparam); + nerrors += test_abs_skip_start_block_add_skipped(fapl, &cparam); + nerrors += test_abs_skip_2nd_block(fapl, &cparam); + nerrors += test_abs_skip_2nd_block_add_skipped(fapl, &cparam); + nerrors += test_abs_fill_one_partial_skip_2nd_block_add_skipped(fapl, &cparam); + nerrors += test_abs_fill_direct_skip_indirect_start_block_add_skipped(fapl, &cparam); + nerrors += test_abs_fill_direct_skip_2nd_indirect_start_block_add_skipped(fapl, &cparam); + nerrors += test_abs_fill_direct_skip_2nd_indirect_skip_2nd_block_add_skipped(fapl, &cparam); + nerrors += test_abs_fill_2nd_direct_skip_start_block_add_skipped(fapl, &cparam); + nerrors += test_abs_fill_2nd_direct_skip_2nd_indirect_start_block_add_skipped(fapl, &cparam); #else /* QAK */ HDfprintf(stderr, "Uncomment tests!\n"); #endif /* QAK */ + nerrors += test_abs_fill_2nd_direct_fill_direct_skip_3rd_indirect_start_block_add_skipped(fapl, &cparam); if(nerrors) goto error; |