From 02bba16ee0b5c9da300608896d1ea9bc97c9ab1a Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Sat, 28 Oct 2006 21:17:07 -0500 Subject: [svn-r12823] Description: Add support for compress heap blocks in "managed" heaps. Also, fix bug when the first direct block moves between having a parent and not having one (and vice versa), which occurs when the heap moves between having a direct root block and having an indirect root block. Tested on: FreeBSD 4.11 (sleipnir) w/threadsafe Linux/32 2.4 (heping) w/C++ & FORTRAN Linux/64 2.4 (mir) w/build-all & 1.6 compat --- src/H5FSprivate.h | 2 +- src/H5HF.c | 18 ++- src/H5HFcache.c | 201 +++++++++++++++++++++-- src/H5HFdbg.c | 31 +++- src/H5HFdblock.c | 37 ++++- src/H5HFiblock.c | 34 +++- src/H5HFman.c | 30 ++-- src/H5HFpkg.h | 22 ++- src/H5HFsection.c | 233 +++++++++++++++++++++------ test/fheap.c | 468 +++++++++++++++++++++++++++++++++++++++++++++++++----- 10 files changed, 920 insertions(+), 156 deletions(-) diff --git a/src/H5FSprivate.h b/src/H5FSprivate.h index 0b3b84b..9a70c4c 100644 --- a/src/H5FSprivate.h +++ b/src/H5FSprivate.h @@ -113,7 +113,7 @@ typedef enum H5FS_section_state_t { /* Free space section info */ struct H5FS_section_info_t { - haddr_t addr; /* Address of free space section in the address space */ + haddr_t addr; /* Offset of free space section in the address space */ hsize_t size; /* Size of free space section */ unsigned type; /* Type of free space section (i.e. class) */ H5FS_section_state_t state; /* Whether the section is in "serialized" or "live" form */ diff --git a/src/H5HF.c b/src/H5HF.c index 29b2e4d..425fa85 100644 --- a/src/H5HF.c +++ b/src/H5HF.c @@ -781,8 +781,24 @@ HDfprintf(stderr, "%s: hdr->fs_addr = %a\n", FUNC, hdr->fs_addr); HDfprintf(stderr, "%s: hdr->man_dtable.table_addr = %a\n", FUNC, hdr->man_dtable.table_addr); #endif /* QAK */ if(hdr->man_dtable.curr_root_rows == 0) { + hsize_t dblock_size; /* Size of direct block */ + + /* Check for I/O filters on this heap */ + if(hdr->filter_len > 0) { + dblock_size = (hsize_t)hdr->pline_root_direct_size; +#ifdef QAK +HDfprintf(stderr, "%s: hdr->pline_root_direct_size = %Zu\n", FUNC, hdr->pline_root_direct_size); +#endif /* QAK */ + + /* Reset the header's pipeline information */ + hdr->pline_root_direct_size = 0; + hdr->pline_root_direct_filter_mask = 0; + } /* end else */ + else + dblock_size = (hsize_t)hdr->man_dtable.cparam.start_block_size; + /* Delete root direct block */ - if(H5HF_man_dblock_delete(f, dxpl_id, hdr->man_dtable.table_addr, (hsize_t)hdr->man_dtable.cparam.start_block_size) < 0) + if(H5HF_man_dblock_delete(f, dxpl_id, hdr->man_dtable.table_addr, dblock_size) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release fractal heap root direct block") } /* end if */ else { diff --git a/src/H5HFcache.c b/src/H5HFcache.c index 41e79e6..8661af7 100644 --- a/src/H5HFcache.c +++ b/src/H5HFcache.c @@ -35,6 +35,7 @@ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5HFpkg.h" /* Fractal heaps */ +#include "H5MFprivate.h" /* File memory management */ #include "H5MMprivate.h" /* Memory management */ #include "H5Vprivate.h" /* Vectors and arrays */ @@ -1199,14 +1200,6 @@ H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_size, if(H5HF_hdr_incr(hdr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared heap header") -#ifdef LATER - /* Check for I/O filters on this heap */ - if(hdr->filter_len > 0) { -HDfprintf(stderr, "%s: I/O filters not supported yet!\n", FUNC); -HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, NULL, "I/O filters not supported yet") - } /* end if */ -#endif /* LATER */ - /* Set block's internal information */ dblock->size = *size; dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dblock->size); @@ -1216,10 +1209,77 @@ HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, NULL, "I/O filters not supported yet") if((dblock->blk = H5FL_BLK_MALLOC(direct_block, (size_t)dblock->size)) == NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - /* Read direct block from disk */ - if(H5F_block_read(f, H5FD_MEM_FHEAP_DBLOCK, addr, (size_t)dblock->size, dxpl_id, dblock->blk) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "can't read fractal heap direct block") + /* Check for I/O filters on this heap */ + if(hdr->filter_len > 0) { + H5Z_cb_t filter_cb = {NULL, NULL}; /* Filter callback structure */ + size_t nbytes; /* Number of bytes used in buffer, after applying reverse filters */ + void *read_buf; /* Pointer to buffer to read in */ + size_t read_size; /* Size of filtered direct block to read */ + unsigned filter_mask; /* Excluded filters for direct block */ + + /* Check for root direct block */ + if(par_info->iblock == NULL) { +#ifdef QAK +HDfprintf(stderr, "%s: hdr->pline_root_direct_size = %Zu, hdr->pline_root_direct_filter_mask = %x\n", FUNC, hdr->pline_root_direct_size, hdr->pline_root_direct_filter_mask); +HDfprintf(stderr, "%s: hdr->man_dtable.table_addr = %a, addr = %a\n", FUNC, hdr->man_dtable.table_addr, addr); +#endif /* QAK */ + /* Sanity check */ + HDassert(H5F_addr_eq(hdr->man_dtable.table_addr, addr)); + + /* Set up parameters to read filtered direct block */ + read_size = hdr->pline_root_direct_size; + filter_mask = hdr->pline_root_direct_filter_mask; + } /* end if */ + else { +#ifdef QAK +HDfprintf(stderr, "%s: par_info->iblock = %p, par_info->entry = %u\n", FUNC, par_info->iblock, par_info->entry); +HDfprintf(stderr, "%s: par_info->iblock->filt_ents[%u].size = %Zu, par_info->iblock->filt_ents[%u].filter_mask = %x\n", FUNC, par_info->entry, par_info->iblock->filt_ents[par_info->entry].size, par_info->entry, par_info->iblock->filt_ents[par_info->entry].filter_mask); +HDfprintf(stderr, "%s: par_info->iblock->ents[%u].addr = %a, addr = %a\n", FUNC, par_info->entry, par_info->iblock->ents[par_info->entry].addr, addr); +#endif /* QAK */ + /* Sanity check */ + HDassert(H5F_addr_eq(par_info->iblock->ents[par_info->entry].addr, addr)); + + /* Set up parameters to read filtered direct block */ + read_size = par_info->iblock->filt_ents[par_info->entry].size; + filter_mask = par_info->iblock->filt_ents[par_info->entry].filter_mask; + } /* end else */ + + /* Allocate buffer to perform I/O filtering on */ + if(NULL == (read_buf = H5MM_malloc(read_size))) + HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "memory allocation failed for pipeline buffer") +#ifdef QAK +HDfprintf(stderr, "%s: read_size = %Zu, read_buf = %p\n", FUNC, read_size, read_buf); +#endif /* QAK */ + + /* Read filtered direct block from disk */ + if(H5F_block_read(f, H5FD_MEM_FHEAP_DBLOCK, addr, read_size, dxpl_id, read_buf) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "can't read fractal heap direct block") + + /* Push direct block data through I/O filter pipeline */ + nbytes = read_size; + if(H5Z_pipeline(&(hdr->pline), H5Z_FLAG_REVERSE, &filter_mask, H5Z_ENABLE_EDC, + filter_cb, &nbytes, &read_size, &read_buf) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFILTER, NULL, "output pipeline failed") +#ifdef QAK +HDfprintf(stderr, "%s: nbytes = %Zu, read_size = %Zu, read_buf = %p\n", FUNC, nbytes, read_size, read_buf); +#endif /* QAK */ + + /* Sanity check */ + HDassert(nbytes == dblock->size); + /* Copy un-filtered data into block's buffer */ + HDmemcpy(dblock->blk, read_buf, dblock->size); + + /* Release the read buffer */ + H5MM_xfree(read_buf); + } /* end if */ + else { + /* Read direct block from disk */ + if(H5F_block_read(f, H5FD_MEM_FHEAP_DBLOCK, addr, dblock->size, dxpl_id, dblock->blk) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "can't read fractal heap direct block") + } /* end else */ + + /* Start decoding direct block */ p = dblock->blk; /* Magic number */ @@ -1358,7 +1418,6 @@ H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, /* Sanity check */ HDassert((size_t)(p - dblock->blk) == H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr)); -#ifdef LATER /* Check for I/O filters on this heap */ if(hdr->filter_len > 0) { H5Z_cb_t filter_cb = {NULL, NULL}; /* Filter callback structure */ @@ -1376,21 +1435,129 @@ H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, if(H5Z_pipeline(&(hdr->pline), 0, &filter_mask, H5Z_ENABLE_EDC, filter_cb, &nbytes, &write_size, &write_buf) < 0) HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "output pipeline failed") +#ifdef QAK HDfprintf(stderr, "%s: nbytes = %Zu, write_size = %Zu, write_buf = %p\n", FUNC, nbytes, write_size, write_buf); +HDfprintf(stderr, "%s: dblock->block_off = %Hu\n", FUNC, dblock->block_off); HDfprintf(stderr, "%s: dblock->size = %Zu, dblock->blk = %p\n", FUNC, dblock->size, dblock->blk); +HDfprintf(stderr, "%s: dblock->parent = %p, dblock->par_entry = %u\n", FUNC, dblock->parent, dblock->par_entry); +#endif /* QAK */ + + /* Use the compressed number of bytes as the size to write */ + write_size = nbytes; -HDfprintf(stderr, "%s: I/O filters not supported yet!\n", FUNC); -HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "I/O filters not supported yet") + /* Check for root direct block */ + if(dblock->parent == NULL) { + hbool_t hdr_changed = FALSE; /* Whether the header information changed */ + +#ifdef QAK +HDfprintf(stderr, "%s: hdr->pline_root_direct_size = %Zu, hdr->pline_root_direct_filter_mask = %x\n", FUNC, hdr->pline_root_direct_size, hdr->pline_root_direct_filter_mask); +HDfprintf(stderr, "%s: hdr->man_dtable.table_addr = %a, addr = %a\n", FUNC, hdr->man_dtable.table_addr, addr); +#endif /* QAK */ + /* Sanity check */ + HDassert(H5F_addr_eq(hdr->man_dtable.table_addr, addr)); + HDassert(hdr->pline_root_direct_size > 0); + + /* Check if the filter mask changed */ + if(hdr->pline_root_direct_filter_mask != filter_mask) { + hdr->pline_root_direct_filter_mask = filter_mask; + hdr_changed = TRUE; + } /* end if */ + + /* Check if we need to re-size the block on disk */ + if(hdr->pline_root_direct_size != write_size) { +#ifdef QAK +HDfprintf(stderr, "%s: Need to re-allocate root direct block!\n", FUNC); +#endif /* QAK */ + /* Release direct block's current disk space */ + if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, addr, (hsize_t)hdr->pline_root_direct_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block") + + /* Allocate space for the compressed direct block */ + if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)write_size))) + HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block") + + /* Let the metadata cache know, if the block moved */ + if(!H5F_addr_eq(hdr->man_dtable.table_addr, addr)) + if(H5AC_rename(f, H5AC_FHEAP_DBLOCK, hdr->man_dtable.table_addr, addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRENAME, FAIL, "unable to move direct block") + + /* Update information about compressed direct block's location & size */ + hdr->man_dtable.table_addr = addr; + hdr->pline_root_direct_size = write_size; + + /* Note that heap header was modified */ + hdr_changed = TRUE; + } /* end if */ + + /* Check if heap header was modified */ + if(hdr_changed) + if(H5HF_hdr_dirty(hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty") + } /* end if */ + else { + hbool_t par_changed = FALSE; /* Whether the parent's information changed */ + H5HF_indirect_t *par_iblock; /* Parent indirect block */ + unsigned par_entry; /* Entry in parent indirect block */ + + /* Get parent information */ + par_iblock = dblock->parent; + par_entry = dblock->par_entry; + +#ifdef QAK +HDfprintf(stderr, "%s: par_iblock->filt_ents[%u].size = %Zu, par_iblock->filt_ents[%u].filter_mask = %x\n", FUNC, par_entry, par_iblock->filt_ents[par_entry].size, par_entry, par_iblock->filt_ents[par_entry].filter_mask); +HDfprintf(stderr, "%s: par_iblock->ents[%u].addr = %a, addr = %a\n", FUNC, par_entry, par_iblock->ents[par_entry].addr, addr); +#endif /* QAK */ + /* Sanity check */ + HDassert(H5F_addr_eq(par_iblock->ents[par_entry].addr, addr)); + HDassert(par_iblock->filt_ents[par_entry].size > 0); + + /* Check if the filter mask changed */ + if(par_iblock->filt_ents[par_entry].filter_mask != filter_mask) { + par_iblock->filt_ents[par_entry].filter_mask = filter_mask; + par_changed = TRUE; + } /* end if */ + + /* Check if we need to re-size the block on disk */ + if(par_iblock->filt_ents[par_entry].size != write_size) { +#ifdef QAK +HDfprintf(stderr, "%s: Need to re-allocate non-root direct block!\n", FUNC); +#endif /* QAK */ + /* Release direct block's current disk space */ + if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, addr, (hsize_t)par_iblock->filt_ents[par_entry].size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block") + + /* Allocate space for the compressed direct block */ + if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)write_size))) + HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block") + + /* Let the metadata cache know, if the block moved */ + if(!H5F_addr_eq(par_iblock->ents[par_entry].addr, addr)) + if(H5AC_rename(f, H5AC_FHEAP_DBLOCK, par_iblock->ents[par_entry].addr, addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRENAME, FAIL, "unable to move direct block") + + /* Update information about compressed direct block's location & size */ + par_iblock->ents[par_entry].addr = addr; + par_iblock->filt_ents[par_entry].size = write_size; + + /* Note that parent was modified */ + par_changed = TRUE; + } /* end if */ + + /* Check if parent was modified */ + if(par_changed) + if(H5HF_iblock_dirty(par_iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty") + } /* end else */ } /* end if */ else { -#endif /* LATER */ write_buf = dblock->blk; write_size = dblock->size; -#ifdef LATER } /* end else */ -#endif /* LATER */ /* Write the direct block */ +#ifdef QAK +HDfprintf(stderr, "%s: addr = %a, write_size = %Zu\n", FUNC, addr, write_size); +#endif /* QAK */ if(H5F_block_write(f, H5FD_MEM_FHEAP_DBLOCK, addr, write_size, dxpl_id, write_buf) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTFLUSH, FAIL, "unable to save fractal heap direct block to disk") diff --git a/src/H5HFdbg.c b/src/H5HFdbg.c index ce17e60..8553b15 100644 --- a/src/H5HFdbg.c +++ b/src/H5HFdbg.c @@ -212,6 +212,9 @@ H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, /* * Print the values. */ + HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, + "Heap is:", + hdr->man_dtable.curr_root_rows > 0 ? "Indirect" : "Direct"); HDfprintf(stream, "%*s%-*s %t\n", indent, "", fwidth, "Objects stored in 'debugging' format:", hdr->debug_objs); @@ -251,7 +254,7 @@ H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, "ID of next 'huge' object:", hdr->huge_next_id); - HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, + HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, "Address of v2 B-tree for 'huge' objects:", hdr->huge_bt2_addr); HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, @@ -267,6 +270,14 @@ H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, /* Print information about I/O filters */ if(hdr->filter_len > 0) { HDfprintf(stream, "%*sI/O filter Info...\n", indent, ""); + if(hdr->man_dtable.curr_root_rows == 0) { + HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", MAX(0, fwidth - 3), + "Compressed size of root direct block:", + hdr->pline_root_direct_size); + HDfprintf(stream, "%*s%-*s %x\n", indent + 3, "", MAX(0, fwidth - 3), + "Filter mask for root direct block:", + hdr->pline_root_direct_filter_mask); + } /* end if */ H5O_debug_id(H5O_PLINE_ID, f, dxpl_id, &(hdr->pline), stream, indent + 3, MAX(0, fwidth - 3)); } /* end if */ @@ -564,7 +575,10 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, hdr->man_dtable.max_direct_rows); /* Print the entry tables */ - HDfprintf(stream, "%*sDirect Block Entries: (address)\n", indent, ""); + if(hdr->filter_len > 0) + HDfprintf(stream, "%*sDirect Block Entries: (address/compressed size/filter mask)\n", indent, ""); + else + HDfprintf(stream, "%*sDirect Block Entries: (address)\n", indent, ""); for(u = 0; u < hdr->man_dtable.max_direct_rows && u < iblock->nrows; u++) { sprintf(temp_str, "Row #%u: (block size: %lu)", (unsigned)u, (unsigned long)hdr->man_dtable.row_block_size[u]); HDfprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(0, fwidth - 3), @@ -573,9 +587,16 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, size_t off = (u * hdr->man_dtable.cparam.width) + v; sprintf(temp_str, "Col #%u:", (unsigned)v); - HDfprintf(stream, "%*s%-*s %9a\n", indent + 6, "", MAX(0, fwidth - 6), - temp_str, - iblock->ents[off].addr); + if(hdr->filter_len > 0) + HDfprintf(stream, "%*s%-*s %9a/%6Zu/%x\n", indent + 6, "", MAX(0, fwidth - 6), + temp_str, + iblock->ents[off].addr, + iblock->filt_ents[off].size, + iblock->filt_ents[off].filter_mask); + else + HDfprintf(stream, "%*s%-*s %9a\n", indent + 6, "", MAX(0, fwidth - 6), + temp_str, + iblock->ents[off].addr); } /* end for */ } /* end for */ HDfprintf(stream, "%*sIndirect Block Entries:\n", indent, ""); diff --git a/src/H5HFdblock.c b/src/H5HFdblock.c index 6082d38..1007412 100644 --- a/src/H5HFdblock.c +++ b/src/H5HFdblock.c @@ -147,7 +147,7 @@ H5HF_man_dblock_create(hid_t dxpl_id, H5HF_hdr_t *hdr, H5HF_indirect_t *par_iblo HDmemset(dblock->blk, 0, dblock->size); #endif /* H5_USING_PURIFY */ - /* Allocate space for the header on disk */ + /* Allocate space for the direct block on disk */ if(HADDR_UNDEF == (dblock_addr = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)dblock->size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block") #ifdef QAK @@ -163,7 +163,7 @@ HDfprintf(stderr, "%s: direct block address = %a\n", FUNC, dblock_addr); /* Create a new 'single' section for the free space in the block */ if(NULL == (sec_node = H5HF_sect_single_new((dblock->block_off + H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr)), - free_space, dblock->parent, dblock->par_entry, dblock_addr, dblock->size))) + free_space, dblock->parent, dblock->par_entry))) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create section for new direct block's free space") /* Check what to do with section node */ @@ -218,6 +218,7 @@ herr_t H5HF_man_dblock_destroy(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_direct_t *dblock, haddr_t dblock_addr) { + hsize_t dblock_size; /* Size of direct block on disk */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_destroy) @@ -233,6 +234,27 @@ HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr); HDassert(hdr); HDassert(dblock); + /* Check for I/O filters on this heap */ + if(hdr->filter_len > 0) { + /* Check for root direct block */ + if(dblock->parent == NULL) + /* Get direct block's actual size */ + dblock_size = (hsize_t)hdr->pline_root_direct_size; + else { + H5HF_indirect_t *par_iblock; /* Parent indirect block */ + unsigned par_entry; /* Entry in parent indirect block */ + + /* Get parent information */ + par_iblock = dblock->parent; + par_entry = dblock->par_entry; + + /* Get direct block's actual size */ + dblock_size = (hsize_t)par_iblock->filt_ents[par_entry].size; + } /* end else */ + } /* end if */ + else + dblock_size = (hsize_t)dblock->size; + /* Check for root direct block */ if(hdr->man_dtable.curr_root_rows == 0) { #ifdef QAK @@ -298,11 +320,12 @@ HDfprintf(stderr, "%s: Reversing iterator\n", FUNC); dblock->par_entry = 0; } /* end else */ - /* Release direct block's disk space */ #ifdef QAK -HDfprintf(stderr, "%s: Before releasing direct block's space, dblock_addr = %a\n", FUNC, dblock_addr); +HDfprintf(stderr, "%s: Before releasing direct block's space, dblock_addr = %a, dblock_size = %Hu\n", FUNC, dblock_addr, dblock_size); #endif /* QAK */ - if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, dblock_addr, (hsize_t)dblock->size) < 0) + + /* Release direct block's disk space */ + if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, dblock_addr, dblock_size) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block") /* Remove direct block from metadata cache */ @@ -381,6 +404,10 @@ HDfprintf(stderr, "%s: root direct block, dblock_addr = %a\n", FUNC, dblock_addr /* Point root at new direct block */ hdr->man_dtable.curr_root_rows = 0; hdr->man_dtable.table_addr = dblock_addr; + if(hdr->filter_len > 0) { + hdr->pline_root_direct_size = hdr->man_dtable.cparam.start_block_size; + hdr->pline_root_direct_filter_mask = 0; + } /* end if */ /* Extend heap to cover new direct block */ if(H5HF_hdr_adjust_heap(hdr, (hsize_t)hdr->man_dtable.cparam.start_block_size, (hssize_t)hdr->man_dtable.row_tot_dblock_free[0]) < 0) diff --git a/src/H5HFiblock.c b/src/H5HFiblock.c index 503846b..ac31933 100644 --- a/src/H5HFiblock.c +++ b/src/H5HFiblock.c @@ -441,6 +441,17 @@ HDfprintf(stderr, "%s: have_direct_block = %u\n", FUNC, (unsigned)have_direct_bl if(H5HF_man_iblock_attach(iblock, 0, hdr->man_dtable.table_addr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTATTACH, FAIL, "can't attach root direct block to parent indirect block") + /* Check for I/O filters on this heap */ + if(hdr->filter_len > 0) { + /* Set the pipeline filter information from the header */ + iblock->filt_ents[0].size = hdr->pline_root_direct_size; + iblock->filt_ents[0].filter_mask = hdr->pline_root_direct_filter_mask; + + /* Reset the header's pipeline information */ + hdr->pline_root_direct_size = 0; + hdr->pline_root_direct_filter_mask = 0; + } /* end if */ + /* Unlock first (previously the root) direct block */ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, hdr->man_dtable.table_addr, dblock, H5AC__NO_FLAGS_SET) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block") @@ -862,9 +873,18 @@ HDfprintf(stderr, "%s: Reverting root indirect block\n", FUNC); /* Get pointer to last direct block */ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, root_iblock, 0, H5AC_WRITE))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block") + HDassert(dblock->parent == root_iblock); + HDassert(dblock->par_entry == 0); + + /* Check for I/O filters on this heap */ + if(hdr->filter_len > 0) { + /* Set the header's pipeline information from the indirect block */ + hdr->pline_root_direct_size = root_iblock->filt_ents[0].size; + hdr->pline_root_direct_filter_mask = root_iblock->filt_ents[0].filter_mask; + } /* end if */ /* Detach direct block from parent */ - if(H5HF_man_iblock_detach(dblock->parent, dxpl_id, dblock->par_entry) < 0) + if(H5HF_man_iblock_detach(dblock->parent, dxpl_id, 0) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTATTACH, FAIL, "can't detach direct block from parent indirect block") dblock->parent = NULL; dblock->par_entry = 0; @@ -1345,7 +1365,7 @@ HDfprintf(stderr, "%s: iblock->block_off = %Hu, iblock->nchildren = %u\n", FUNC, /* Compute row for entry */ row = entry / iblock->hdr->man_dtable.cparam.width; - /* If this is a direct block, set its initial size */ + /* If this is a direct block, reset its initial size */ if(row < iblock->hdr->man_dtable.max_direct_rows) { iblock->filt_ents[entry].size = 0; iblock->filt_ents[entry].filter_mask = 0; @@ -1503,8 +1523,16 @@ HDfprintf(stderr, "%s: iblock_addr = %a, iblock_nrows = %u\n", FUNC, iblock_addr /* Are we in a direct or indirect block row */ if(row < hdr->man_dtable.max_direct_rows) { + hsize_t dblock_size; /* Size of direct block on disk */ + + /* Check for I/O filters on this heap */ + if(hdr->filter_len > 0) + dblock_size = iblock->filt_ents[entry].size; + else + dblock_size = row_block_size; + /* Delete child direct block */ - if(H5HF_man_dblock_delete(hdr->f, dxpl_id, iblock->ents[entry].addr, row_block_size) < 0) + if(H5HF_man_dblock_delete(hdr->f, dxpl_id, iblock->ents[entry].addr, dblock_size) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release fractal heap child direct block") } /* end if */ else { diff --git a/src/H5HFman.c b/src/H5HFman.c index cc56759..56f24ca 100644 --- a/src/H5HFman.c +++ b/src/H5HFman.c @@ -96,6 +96,7 @@ H5HF_man_insert(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t obj_size, const void *obj H5HF_free_section_t *sec_node; /* Pointer to free space section */ H5HF_direct_t *dblock = NULL; /* Pointer to direct block to modify */ haddr_t dblock_addr = HADDR_UNDEF; /* Direct block address */ + size_t dblock_size; /* Direct block size */ uint8_t *id = (uint8_t *)_id; /* Pointer to ID buffer */ size_t blk_off; /* Offset of object within block */ htri_t node_found; /* Whether an existing free list node was found */ @@ -153,7 +154,9 @@ HDfprintf(stderr, "%s: sec_node->u.row.num_entries = %u\n", FUNC, sec_node->u.ro } /* end if */ HDassert(sec_node->sect_info.state == H5FS_SECT_LIVE); - /* Lock direct block */ + /* Retrieve direct block address from section */ + if(H5HF_sect_single_dblock_info(hdr, dxpl_id, sec_node, &dblock_addr, &dblock_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't retrieve direct block information") #ifdef QAK HDfprintf(stderr, "%s: sec_node->sect_info.addr = %a\n", FUNC, sec_node->sect_info.addr); HDfprintf(stderr, "%s: sec_node->sect_info.size = %Hu\n", FUNC, sec_node->sect_info.size); @@ -161,11 +164,10 @@ HDfprintf(stderr, "%s: sec_node->u.single.parent = %p\n", FUNC, sec_node->u.sing if(sec_node->u.single.parent) HDfprintf(stderr, "%s: sec_node->u.single.parent->addr = %a\n", FUNC, sec_node->u.single.parent->addr); HDfprintf(stderr, "%s: sec_node->u.single.par_entry = %u\n", FUNC, sec_node->u.single.par_entry); -HDfprintf(stderr, "%s: sec_node->u.single.dblock_addr = %a\n", FUNC, sec_node->u.single.dblock_addr); -HDfprintf(stderr, "%s: sec_node->u.single.dblock_size = %Zu\n", FUNC, sec_node->u.single.dblock_size); #endif /* QAK */ - dblock_addr = sec_node->u.single.dblock_addr; - if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, sec_node->u.single.dblock_size, sec_node->u.single.parent, sec_node->u.single.par_entry, H5AC_WRITE))) + + /* Lock direct block */ + if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, sec_node->u.single.parent, sec_node->u.single.par_entry, H5AC_WRITE))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block") /* Insert object into block */ @@ -470,7 +472,6 @@ H5HF_man_remove(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id) hbool_t did_protect; /* Whether we protected the indirect block or not */ hsize_t obj_off; /* Object's offset in heap */ size_t obj_len; /* Object's length in heap */ - haddr_t dblock_addr; /* Direct block address */ size_t dblock_size; /* Direct block size */ hsize_t dblock_block_off; /* Offset of the direct block within the heap's address space */ unsigned dblock_entry; /* Entry of direct block in parent indirect block */ @@ -516,7 +517,6 @@ HDfprintf(stderr, "%s: hdr->man_dtable.cparam.max_direct_size = %Zu\n", FUNC, hd HDfprintf(stderr, "%s: direct root block\n", FUNC); #endif /* QAK */ /* Set direct block info */ - dblock_addr = hdr->man_dtable.table_addr; dblock_size = hdr->man_dtable.cparam.start_block_size; dblock_block_off = 0; dblock_entry = 0; @@ -532,14 +532,13 @@ HDfprintf(stderr, "%s: indirect root block\n", FUNC); HDfprintf(stderr, "%s: entry address = %a\n", FUNC, iblock->ents[dblock_entry].addr); #endif /* QAK */ - /* Set direct block info */ - dblock_addr = iblock->ents[dblock_entry].addr; - dblock_size = hdr->man_dtable.row_block_size[dblock_entry / hdr->man_dtable.cparam.width]; - /* Check for offset of invalid direct block */ - if(!H5F_addr_defined(dblock_addr)) + if(!H5F_addr_defined(iblock->ents[dblock_entry].addr)) HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap ID not in allocated direct block") + /* Set direct block info */ + dblock_size = hdr->man_dtable.row_block_size[dblock_entry / hdr->man_dtable.cparam.width]; + /* Compute the direct block's offset in the heap's address space */ /* (based on parent indirect block's block offset) */ dblock_block_off = iblock->block_off; @@ -547,7 +546,7 @@ HDfprintf(stderr, "%s: entry address = %a\n", FUNC, iblock->ents[dblock_entry].a dblock_block_off += hdr->man_dtable.row_block_size[dblock_entry / hdr->man_dtable.cparam.width] * (dblock_entry % hdr->man_dtable.cparam.width); } /* end else */ #ifdef QAK -HDfprintf(stderr, "%s: dblock_addr = %a, dblock_size = %Zu\n", FUNC, dblock_addr, dblock_size); +HDfprintf(stderr, "%s: dblock_size = %Zu\n", FUNC, dblock_size); #endif /* QAK */ /* Compute offset of object within block */ @@ -566,8 +565,7 @@ HDfprintf(stderr, "%s: blk_off = %Zu\n", FUNC, blk_off); HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "object overruns end of direct block") /* Create free space section node */ - if(NULL == (sec_node = H5HF_sect_single_new(obj_off, obj_len, iblock, - dblock_entry, dblock_addr, dblock_size))) + if(NULL == (sec_node = H5HF_sect_single_new(obj_off, obj_len, iblock, dblock_entry))) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create section for direct block's free space") #ifdef QAK HDfprintf(stderr, "%s: sec_node->sect_info.addr = %a\n", FUNC, sec_node->sect_info.addr); @@ -576,8 +574,6 @@ HDfprintf(stderr, "%s: sec_node->u.single.parent = %p\n", FUNC, sec_node->u.sing if(sec_node->u.single.parent) HDfprintf(stderr, "%s: sec_node->u.single.parent->addr = %a\n", FUNC, sec_node->u.single.parent->addr); HDfprintf(stderr, "%s: sec_node->u.single.par_entry = %u\n", FUNC, sec_node->u.single.par_entry); -HDfprintf(stderr, "%s: sec_node->u.single.dblock_addr = %a\n", FUNC, sec_node->u.single.dblock_addr); -HDfprintf(stderr, "%s: sec_node->u.single.dblock_size = %Zu\n", FUNC, sec_node->u.single.dblock_size); #endif /* QAK */ /* Unlock indirect block */ diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h index 638d996..e927e4d 100644 --- a/src/H5HFpkg.h +++ b/src/H5HFpkg.h @@ -251,11 +251,6 @@ typedef struct H5HF_free_section_t { struct { H5HF_indirect_t *parent; /* Indirect block parent for free section's direct block */ unsigned par_entry; /* Entry of free section's direct block in parent indirect block */ - /* (Needed to retrieve direct block) */ - - haddr_t dblock_addr; /* Address of direct block for free section */ - size_t dblock_size; /* Size of direct block */ - /* (Needed to retrieve root direct block) */ } single; struct { struct H5HF_free_section_t *under; /* Pointer to indirect block underlying row section */ @@ -270,7 +265,7 @@ typedef struct H5HF_free_section_t { /* Holds either a pointer to an indirect block (if its "live") or * the block offset of it's indirect block (if its "serialized") * (This allows the indirect block that the section is within to - * be compared with other sections, whether its serialized + * be compared with other sections, whether it's serialized * or not) */ union { @@ -322,14 +317,14 @@ typedef struct H5HF_hdr_t { haddr_t fs_addr; /* Address of free space header on disk */ /* "Huge" object support (stored in header) */ - uint32_t max_man_size; /* Max. size of object to manage in doubling table */ - hsize_t huge_next_id; /* Next ID to use for indirectly tracked 'huge' object */ - haddr_t huge_bt2_addr; /* Address of v2 B-tree for tracking "huge" object info */ + uint32_t max_man_size; /* Max. size of object to manage in doubling table */ + hsize_t huge_next_id; /* Next ID to use for indirectly tracked 'huge' object */ + haddr_t huge_bt2_addr; /* Address of v2 B-tree for tracking "huge" object info */ /* I/O filter support (stored in header, if any are used) */ H5O_pline_t pline; /* I/O filter pipeline for heap objects */ - size_t pline_root_direct_size; /* Size of filtered root direct block */ - unsigned pline_root_direct_filter_mask; /* I/O filter mask for filtered root direct block */ + size_t pline_root_direct_size; /* Size of filtered root direct block */ + unsigned pline_root_direct_filter_mask; /* I/O filter mask for filtered root direct block */ /* Statistics for heap (stored in header) */ hsize_t man_size; /* Total amount of 'managed' space in heap */ @@ -698,10 +693,11 @@ H5_DLL herr_t H5HF_space_sect_change_class(H5HF_hdr_t *hdr, hid_t dxpl_id, /* Free space section routines */ H5_DLL H5HF_free_section_t *H5HF_sect_single_new(hsize_t sect_off, - size_t sect_size, H5HF_indirect_t *parent, unsigned par_entry, - haddr_t dblock_addr, size_t dblock_size); + size_t sect_size, H5HF_indirect_t *parent, unsigned par_entry); H5_DLL herr_t H5HF_sect_single_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect); +H5_DLL herr_t H5HF_sect_single_dblock_info(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *sect, haddr_t *dblock_addr, size_t *dblock_size); H5_DLL herr_t H5HF_sect_single_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect, size_t amt); H5_DLL herr_t H5HF_sect_row_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, diff --git a/src/H5HFsection.c b/src/H5HFsection.c index 717c7f8..807beb3 100644 --- a/src/H5HFsection.c +++ b/src/H5HFsection.c @@ -77,6 +77,8 @@ static herr_t H5HF_sect_node_free(H5HF_free_section_t *sect, H5HF_indirect_t *parent); /* 'single' section routines */ +static herr_t H5HF_sect_single_locate_parent(H5HF_hdr_t *hdr, hid_t dxpl_id, + hbool_t refresh, H5HF_free_section_t *sect); static herr_t H5HF_sect_single_full_dblock(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect); @@ -480,8 +482,7 @@ done: */ H5HF_free_section_t * H5HF_sect_single_new(hsize_t sect_off, size_t sect_size, - H5HF_indirect_t *parent, unsigned par_entry, - haddr_t dblock_addr, size_t dblock_size) + H5HF_indirect_t *parent, unsigned par_entry) { H5HF_free_section_t *sect = NULL; /* 'Single' free space section to add */ hbool_t par_incr = FALSE; /* Indicate that parent iblock has been incremented */ @@ -506,8 +507,6 @@ H5HF_sect_single_new(hsize_t sect_off, size_t sect_size, par_incr = TRUE; } /* end if */ sect->u.single.par_entry = par_entry; - sect->u.single.dblock_addr = dblock_addr; - sect->u.single.dblock_size = dblock_size; /* Set return value */ ret_value = sect; @@ -530,6 +529,70 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_sect_single_locate_parent + * + * Purpose: Locate the parent indirect block for a single section + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * October 24 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_single_locate_parent(H5HF_hdr_t *hdr, hid_t dxpl_id, hbool_t refresh, + H5HF_free_section_t *sect) +{ + H5HF_indirect_t *sec_iblock; /* Pointer to section indirect block */ + unsigned sec_entry; /* Entry within section indirect block */ + hbool_t did_protect; /* Whether we protected the indirect block or not */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_locate_parent) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(hdr->man_dtable.curr_root_rows > 0); + HDassert(sect); + + /* Look up indirect block containing direct blocks for range */ + if(H5HF_man_dblock_locate(hdr, dxpl_id, sect->sect_info.addr, &sec_iblock, &sec_entry, &did_protect, H5AC_READ) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section") + + /* Increment reference count on indirect block that free section is in */ + if(H5HF_iblock_incr(sec_iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") + + /* Check for refreshing existing parent information */ + if(refresh) { + if(sect->u.single.parent) { + /* Release hold on previous parent indirect block */ + if(H5HF_iblock_decr(sect->u.single.parent) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on section's indirect block") + } /* end if */ + } /* end if */ + else + HDassert(sect->u.single.parent == NULL); + + /* Set the information for the section */ + sect->u.single.parent = sec_iblock; + sect->u.single.par_entry = sec_entry; + + /* Unlock indirect block */ + if(H5HF_man_iblock_unprotect(sec_iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + sec_iblock = NULL; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_single_locate_parent() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_sect_single_revive * * Purpose: Update the memory information for a 'single' free section @@ -546,8 +609,6 @@ herr_t H5HF_sect_single_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect) { - H5HF_indirect_t *sec_iblock; /* Pointer to section indirect block */ - unsigned sec_entry; /* Entry within section indirect block */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_revive) @@ -562,45 +623,107 @@ H5HF_sect_single_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, /* Check for root direct block */ if(hdr->man_dtable.curr_root_rows == 0) { /* Set the information for the section */ + HDassert(H5F_addr_defined(hdr->man_dtable.table_addr)); sect->u.single.parent = NULL; sect->u.single.par_entry = 0; - - /* Set direct block info */ - HDassert(H5F_addr_defined(hdr->man_dtable.table_addr)); - sect->u.single.dblock_addr = hdr->man_dtable.table_addr; - sect->u.single.dblock_size = hdr->man_dtable.cparam.start_block_size; } /* end if */ else { - hbool_t did_protect; /* Whether we protected the indirect block or not */ + /* Look up indirect block information for section */ + if(H5HF_sect_single_locate_parent(hdr, dxpl_id, FALSE, sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get section's parent info") + } /* end else */ - /* Look up indirect block containing direct blocks for range */ - if(H5HF_man_dblock_locate(hdr, dxpl_id, sect->sect_info.addr, &sec_iblock, &sec_entry, &did_protect, H5AC_READ) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section") + /* Section is "live" now */ + sect->sect_info.state = H5FS_SECT_LIVE; - /* Increment reference count on indirect block that free section is in */ - if(H5HF_iblock_incr(sec_iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block") +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_single_revive() */ - /* Set the information for the section */ - sect->u.single.parent = sec_iblock; - sect->u.single.par_entry = sec_entry; + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_single_dblock_info + * + * Purpose: Retrieve the direct block information for a single section + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * October 24 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_sect_single_dblock_info(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *sect, haddr_t *dblock_addr, size_t *dblock_size) +{ + herr_t ret_value = SUCCEED; /* Return value */ - /* Set direct block info */ - sect->u.single.dblock_addr = sec_iblock->ents[sec_entry].addr; - sect->u.single.dblock_size = hdr->man_dtable.row_block_size[sec_entry / hdr->man_dtable.cparam.width]; + FUNC_ENTER_NOAPI(H5HF_sect_single_dblock_info, FAIL) - /* Unlock indirect block */ - if(H5HF_man_iblock_unprotect(sec_iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") - sec_iblock = NULL; - } /* end else */ + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(sect); + HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_SINGLE); + HDassert(sect->sect_info.state == H5FS_SECT_LIVE); + HDassert(dblock_addr); + HDassert(dblock_size); - /* Section is "live" now */ - sect->sect_info.state = H5FS_SECT_LIVE; + /* Check for section in first direct block of heap */ + if(sect->sect_info.addr < hdr->man_dtable.cparam.start_block_size) { + /* Check for heap changing from direct <-> indirect root (or vice versa) + * while section was live. + */ + if(sect->u.single.parent) { + /* Check for heap converting from indirect root to direct root while section was live */ + if(hdr->man_dtable.curr_root_rows == 0) { + /* Release hold on parent indirect block */ + if(H5HF_iblock_decr(sect->u.single.parent) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on section's indirect block") + + /* Reset parent information */ + sect->u.single.parent = NULL; + sect->u.single.par_entry = 0; + } /* end if */ + else { + /* Check for heap converting from indirect to direct and back + * to indirect again, which would indicate a different + * indirect root block would be used for the parent of + * this section and the actual root indirect block. + */ + if(H5HF_sect_single_locate_parent(hdr, dxpl_id, TRUE, sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get section's parent info") + } /* end else */ + } /* end if */ + else { + /* Check for heap converting from direct root to indirect root while section was live */ + if(hdr->man_dtable.curr_root_rows != 0) { + /* Look up indirect block information for section */ + if(H5HF_sect_single_locate_parent(hdr, dxpl_id, FALSE, sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get section's parent info") + } /* end if */ + } /* end else */ + } /* end if */ + + /* Check for root direct block */ + if(hdr->man_dtable.curr_root_rows == 0) { + /* Retrieve direct block info from heap header */ + HDassert(H5F_addr_defined(hdr->man_dtable.table_addr)); + *dblock_addr = hdr->man_dtable.table_addr; + *dblock_size = hdr->man_dtable.cparam.start_block_size; + } /* end if */ + else { + /* Retrieve direct block info from parent indirect block */ + *dblock_addr = sect->u.single.parent->ents[sect->u.single.par_entry].addr; + *dblock_size = hdr->man_dtable.row_block_size[sect->u.single.par_entry / hdr->man_dtable.cparam.width]; + } /* end else */ done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_sect_single_revive() */ +} /* end H5HF_sect_single_dblock_info() */ /*------------------------------------------------------------------------- @@ -676,6 +799,7 @@ static herr_t H5HF_sect_single_full_dblock(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect) { + haddr_t dblock_addr; /* Section's direct block's address */ size_t dblock_size; /* Section's direct block's size */ size_t dblock_overhead; /* Direct block's overhead */ herr_t ret_value = SUCCEED; /* Return value */ @@ -691,9 +815,12 @@ H5HF_sect_single_full_dblock(H5HF_hdr_t *hdr, hid_t dxpl_id, HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect->sect_info.addr, sect->sect_info.size, sect->sect_info.type, (sect->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED")); #endif /* QAK */ + /* Retrieve direct block address from section */ + if(H5HF_sect_single_dblock_info(hdr, dxpl_id, sect, &dblock_addr, &dblock_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't retrieve direct block information") + /* Check for section occupying entire direct block */ /* (and not the root direct block) */ - dblock_size = sect->u.single.dblock_size; dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); #ifdef QAK HDfprintf(stderr, "%s: dblock_size = %u\n", FUNC, dblock_size); @@ -703,10 +830,7 @@ HDfprintf(stderr, "%s: hdr->man_dtable.curr_root_rows = %u\n", FUNC, hdr->man_dt if((dblock_size - dblock_overhead) == sect->sect_info.size && hdr->man_dtable.curr_root_rows > 0) { H5HF_direct_t *dblock; /* Pointer to direct block for section */ - haddr_t dblock_addr; /* Section's direct block's address */ - /* Protect the direct block for the section */ - dblock_addr = sect->u.single.dblock_addr; #ifdef QAK HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr); #endif /* QAK */ @@ -1031,8 +1155,9 @@ H5HF_sect_single_shrink(H5FS_section_info_t **_sect, void UNUSED *_udata) H5HF_sect_add_ud1_t *udata = (H5HF_sect_add_ud1_t *)_udata; /* User callback data */ H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */ hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */ - H5HF_direct_t *dblock; /* Pointer to direct block for section */ - haddr_t dblock_addr; /* Section's direct block's address */ + H5HF_direct_t *dblock; /* Pointer to direct block for section */ + haddr_t dblock_addr; /* Section's direct block's address */ + size_t dblock_size; /* Section's direct block's size */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_shrink) @@ -1051,17 +1176,20 @@ HDfprintf(stderr, "%s: (*sect).sect_info = {%a, %Hu, %u}\n", FUNC, (*sect)->sect if(H5HF_sect_single_revive(hdr, dxpl_id, (*sect)) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section") + /* Retrieve direct block address from section */ + if(H5HF_sect_single_dblock_info(hdr, dxpl_id, (*sect), &dblock_addr, &dblock_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't retrieve direct block information") + /* Protect the direct block for the section */ /* (should be a root direct block) */ - dblock_addr = (*sect)->u.single.dblock_addr; HDassert(dblock_addr == hdr->man_dtable.table_addr); #ifdef QAK HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr); #endif /* QAK */ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, - (*sect)->u.single.dblock_size, (*sect)->u.single.parent, (*sect)->u.single.par_entry, H5AC_READ))) + dblock_size, (*sect)->u.single.parent, (*sect)->u.single.par_entry, H5AC_READ))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block") - HDassert(H5F_addr_eq(dblock->block_off + (*sect)->u.single.dblock_size, (*sect)->sect_info.addr + (*sect)->sect_info.size)); + HDassert(H5F_addr_eq(dblock->block_off + dblock_size, (*sect)->sect_info.addr + (*sect)->sect_info.size)); /* Destroy direct block */ if(H5HF_man_dblock_destroy(hdr, dxpl_id, dblock, dblock_addr) < 0) @@ -1153,28 +1281,34 @@ HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_single /* (not enough information to check on a single section in a root direct block) */ if(sect->u.single.parent != NULL) { H5HF_indirect_t *iblock; /* Indirect block that section's direct block resides in */ + haddr_t dblock_addr; /* Direct block address */ + size_t dblock_size; /* Direct block size */ size_t dblock_overhead; /* Direct block's overhead */ unsigned dblock_status = 0; /* Direct block's status in the metadata cache */ herr_t status; /* Generic status value */ #ifdef QAK -HDfprintf(stderr, "%s: sect->u.single = {%p, %u, %a, %Zu}\n", "H5HF_sect_single_valid", sect->u.single.parent, sect->u.single.par_entry, sect->u.single.dblock_addr, sect->u.single.dblock_size); +HDfprintf(stderr, "%s: sect->u.single = {%p, %u, %a, %Zu}\n", "H5HF_sect_single_valid", sect->u.single.parent, sect->u.single.par_entry); #endif /* QAK */ /* Sanity check settings for section's direct block's parent */ iblock = sect->u.single.parent; HDassert(H5F_addr_defined(iblock->ents[sect->u.single.par_entry].addr)); - HDassert(H5F_addr_eq(iblock->ents[sect->u.single.par_entry].addr, - sect->u.single.dblock_addr)); + + /* Retrieve direct block address from section */ + status = H5HF_sect_single_dblock_info(iblock->hdr, H5AC_dxpl_id, sect, &dblock_addr, &dblock_size); + HDassert(status >= 0); + HDassert(H5F_addr_eq(iblock->ents[sect->u.single.par_entry].addr, dblock_addr)); + HDassert(dblock_size > 0); /* Check if the section is actually within the heap */ HDassert(sect->sect_info.addr < iblock->hdr->man_iter_off); /* Check that the direct block has been merged correctly */ dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(iblock->hdr); - HDassert((sect->sect_info.size + dblock_overhead) < sect->u.single.dblock_size); + HDassert((sect->sect_info.size + dblock_overhead) < dblock_size); /* Check the direct block's status in the metadata cache */ - status = H5AC_get_entry_status(iblock->hdr->f, sect->u.single.dblock_addr, &dblock_status); + status = H5AC_get_entry_status(iblock->hdr->f, dblock_addr, &dblock_status); HDassert(status >= 0); /* If the direct block for the section isn't already protected, @@ -1185,19 +1319,18 @@ HDfprintf(stderr, "%s: sect->u.single = {%p, %u, %a, %Zu}\n", "H5HF_sect_single_ H5HF_direct_t *dblock; /* Direct block for section */ /* Protect the direct block for the section */ - dblock = H5HF_man_dblock_protect(iblock->hdr, H5AC_dxpl_id, sect->u.single.dblock_addr, sect->u.single.dblock_size, iblock, sect->u.single.par_entry, H5AC_READ); + dblock = H5HF_man_dblock_protect(iblock->hdr, H5AC_dxpl_id, dblock_addr, dblock_size, iblock, sect->u.single.par_entry, H5AC_READ); HDassert(dblock); /* Sanity check settings for section */ - HDassert(sect->u.single.dblock_size > 0); - HDassert(sect->u.single.dblock_size == dblock->size); + HDassert(dblock_size == dblock->size); HDassert(dblock->size > sect->sect_info.size); HDassert(H5F_addr_lt(dblock->block_off, sect->sect_info.addr)); HDassert(H5F_addr_ge((dblock->block_off + dblock->size), (sect->sect_info.addr + sect->sect_info.size))); /* Release direct block */ - status = H5AC_unprotect(iblock->hdr->f, H5AC_dxpl_id, H5AC_FHEAP_DBLOCK, sect->u.single.dblock_addr, dblock, H5AC__NO_FLAGS_SET); + status = H5AC_unprotect(iblock->hdr->f, H5AC_dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET); HDassert(status >= 0); } /* end if */ } /* end if */ diff --git a/test/fheap.c b/test/fheap.c index 1b701fd..d11208e 100644 --- a/test/fheap.c +++ b/test/fheap.c @@ -110,6 +110,13 @@ typedef enum { FHEAP_TEST_FILL_N /* The number of different ways to test filling heap blocks, must be last */ } fheap_test_fill_t; +/* Whether to compress blocks (during random tests) */ +typedef enum { + FHEAP_TEST_NO_COMPRESS, /* Don't compress direct blocks */ + FHEAP_TEST_COMPRESS, /* Compress direct blocks */ + FHEAP_TEST_COMP_N /* The number of different ways to test compressing heap blocks, must be last */ +} fheap_test_comp_t; + /* Testing parameters */ typedef struct fheap_test_param_t { fheap_test_type_t reopen_heap; /* Whether to re-open the heap during the test */ @@ -117,6 +124,7 @@ typedef struct fheap_test_param_t { fheap_test_del_drain_t drain_half; /* Whether to drain half of the objects & refill, when deleting objects */ fheap_test_fill_t fill; /* How to "bulk" fill heap blocks */ size_t actual_id_len; /* The actual length of heap IDs for a test */ + fheap_test_comp_t comp; /* Whether to compressed the blocks or not */ } fheap_test_param_t; /* Heap state information */ @@ -14082,10 +14090,9 @@ error: #endif /* QAK */ #endif /* QAK2 */ -#ifdef NOT_YET /*------------------------------------------------------------------------- - * Function: test_filtered_man_one + * Function: test_filtered_man_root_direct * * Purpose: Test storing one 'managed' object in a heap with I/O filters * @@ -14098,7 +14105,7 @@ error: *------------------------------------------------------------------------- */ static int -test_filtered_man_one(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tparam) +test_filtered_man_root_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tparam) { hid_t file = -1; /* File ID */ hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ @@ -14135,8 +14142,8 @@ test_filtered_man_one(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpa TEST_ERROR - /* Insert object small enough to fit into 'normal' heap blocks */ - obj_size = DBLOCK_SIZE(fh, 0) + 1; + /* Insert object small enough to fit into direct heap block */ + obj_size = DBLOCK_SIZE(fh, 0) / 2; if(H5HF_insert(fh, dxpl, obj_size, shared_wobj_g, heap_id) < 0) FAIL_STACK_ERROR if(H5HF_get_id_type_test(heap_id, &obj_type) < 0) @@ -14148,8 +14155,6 @@ test_filtered_man_one(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpa if(reopen_heap(f, dxpl, &fh, fh_addr, tparam) < 0) TEST_ERROR -/* QAK */ -#ifdef QAK /* Close the fractal heap */ if(H5HF_close(fh, dxpl) < 0) FAIL_STACK_ERROR @@ -14160,7 +14165,7 @@ test_filtered_man_one(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpa FAIL_STACK_ERROR /* Re-open the file */ - if((file = H5Fopen(filename, H5F_ACC_RDONLY, fapl)) < 0) + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) FAIL_STACK_ERROR /* Get a pointer to the internal file object */ @@ -14170,18 +14175,11 @@ test_filtered_man_one(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpa /* Re-open the heap */ if(NULL == (fh = H5HF_open(f, H5P_DATASET_XFER_DEFAULT, fh_addr))) FAIL_STACK_ERROR -#endif /* QAK */ -/* QAK */ /* Check up on heap... */ - state.man_size = tmp_cparam.managed.width * DBLOCK_SIZE(fh, 0); - state.man_size += tmp_cparam.managed.width * DBLOCK_SIZE(fh, 1); - state.man_size += tmp_cparam.managed.width * DBLOCK_SIZE(fh, 2); - state.man_alloc_size = DBLOCK_SIZE(fh, 2); - state.man_free_space = tmp_cparam.managed.width * DBLOCK_FREE(fh, 0); - state.man_free_space += tmp_cparam.managed.width * DBLOCK_FREE(fh, 1); - state.man_free_space += DBLOCK_FREE(fh, 2) - obj_size; - state.man_free_space += (tmp_cparam.managed.width - 1) * DBLOCK_FREE(fh, 2); + state.man_size = DBLOCK_SIZE(fh, 0); + state.man_alloc_size = DBLOCK_SIZE(fh, 0); + state.man_free_space = DBLOCK_FREE(fh, 0) - obj_size; state.man_nobjs++; if(check_stats(fh, &state)) TEST_ERROR @@ -14257,8 +14255,315 @@ error: H5Fclose(file); } H5E_END_TRY; return(1); -} /* test_filtered_man_one() */ +} /* test_filtered_man_root_direct() */ + + +/*------------------------------------------------------------------------- + * Function: test_filtered_man_root_indirect + * + * Purpose: Test storing several objects in a 'managed heap with I/O filters + * + * Return: Success: 0 + * Failure: 1 + * + * Programmer: Quincey Koziol + * Tuesday, October 24, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_filtered_man_root_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tparam) +{ + hid_t file = -1; /* File ID */ + hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ + char filename[FHEAP_FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5HF_t *fh = NULL; /* Fractal heap wrapper */ + haddr_t fh_addr; /* Address of fractal heap */ + H5HF_create_t tmp_cparam; /* Local heap creation parameters */ + fheap_heap_ids_t keep_ids; /* Structure to retain heap IDs */ + off_t empty_size; /* Size of a file with an empty heap */ +#ifdef NOT_YET + off_t file_size; /* Size of file currently */ #endif /* NOT_YET */ + unsigned char heap_id1[HEAP_ID_LEN]; /* Heap ID for object #1 */ + unsigned char heap_id2[HEAP_ID_LEN]; /* Heap ID for object #2 */ + size_t obj_size; /* Size of object */ + size_t robj_size; /* Size of object read */ + unsigned char obj_type; /* Type of storage for object */ + fheap_heap_state_t state; /* State of fractal heap */ + unsigned deflate_level; /* Deflation level */ + const char *base_desc = "insert two 'managed' objects into heap with I/O filters, then remove %s"; /* Test description */ + + /* Copy heap creation properties */ + HDmemcpy(&tmp_cparam, cparam, sizeof(H5HF_create_t)); + + /* Set an I/O filter for heap data */ + deflate_level = 6; + if(H5Z_append(&tmp_cparam.pline, H5Z_FILTER_DEFLATE, H5Z_FLAG_OPTIONAL, (size_t)1, &deflate_level) < 0) + FAIL_STACK_ERROR + + /* Perform common file & heap open operations */ + if(open_heap(filename, fapl, dxpl, &tmp_cparam, tparam, &file, &f, &fh, &fh_addr, &state, &empty_size) < 0) + TEST_ERROR + + /* Perform common test initialization operations */ + if(begin_test(tparam, base_desc, &keep_ids, NULL) < 0) + TEST_ERROR + + + /* Insert object #1, small enough to fit into direct heap block */ + obj_size = DBLOCK_SIZE(fh, 0) / 2; + if(H5HF_insert(fh, dxpl, obj_size, shared_wobj_g, heap_id1) < 0) + FAIL_STACK_ERROR + if(H5HF_get_id_type_test(heap_id1, &obj_type) < 0) + FAIL_STACK_ERROR + if(obj_type != H5HF_ID_TYPE_MAN) + TEST_ERROR + + /* Check for closing & re-opening the heap */ + if(reopen_heap(f, dxpl, &fh, fh_addr, tparam) < 0) + TEST_ERROR + + /* Insert object #2, small enough to fit into direct heap block */ + obj_size = DBLOCK_SIZE(fh, 0) / 2; + if(H5HF_insert(fh, dxpl, obj_size, shared_wobj_g, heap_id2) < 0) + FAIL_STACK_ERROR + if(H5HF_get_id_type_test(heap_id2, &obj_type) < 0) + FAIL_STACK_ERROR + if(obj_type != H5HF_ID_TYPE_MAN) + TEST_ERROR + + /* Close the fractal heap */ + if(H5HF_close(fh, dxpl) < 0) + FAIL_STACK_ERROR + fh = NULL; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* Re-open the heap */ + if(NULL == (fh = H5HF_open(f, H5P_DATASET_XFER_DEFAULT, fh_addr))) + FAIL_STACK_ERROR + + /* Check up on heap... */ + state.man_size = cparam->managed.width * DBLOCK_SIZE(fh, 0); + state.man_alloc_size = 2 * DBLOCK_SIZE(fh, 0); + state.man_free_space = (cparam->managed.width * DBLOCK_FREE(fh, 0)) - (obj_size * 2); + state.man_nobjs += 2; + if(check_stats(fh, &state)) + TEST_ERROR + + /* Read in ('normal') object #1 */ + if(H5HF_get_obj_len(fh, dxpl, heap_id1, &robj_size) < 0) + FAIL_STACK_ERROR + if(obj_size != robj_size) + TEST_ERROR + HDmemset(shared_robj_g, 0, obj_size); + if(H5HF_read(fh, dxpl, heap_id1, shared_robj_g) < 0) + FAIL_STACK_ERROR + if(HDmemcmp(shared_wobj_g, shared_robj_g, obj_size)) + TEST_ERROR + + /* Read in ('normal') object #2 */ + if(H5HF_get_obj_len(fh, dxpl, heap_id2, &robj_size) < 0) + FAIL_STACK_ERROR + if(obj_size != robj_size) + TEST_ERROR + HDmemset(shared_robj_g, 0, obj_size); + if(H5HF_read(fh, dxpl, heap_id2, shared_robj_g) < 0) + FAIL_STACK_ERROR + if(HDmemcmp(shared_wobj_g, shared_robj_g, obj_size)) + TEST_ERROR + + /* Delete individual objects, if we won't be deleting the entire heap later */ + if(tparam->del_dir != FHEAP_DEL_HEAP) { + if(tparam->del_dir == FHEAP_DEL_FORWARD) { + /* Remove object #1 from heap */ + if(H5HF_get_obj_len(fh, dxpl, heap_id1, &robj_size) < 0) + FAIL_STACK_ERROR + if(H5HF_remove(fh, dxpl, heap_id1) < 0) + FAIL_STACK_ERROR + + /* Close the fractal heap */ + if(H5HF_close(fh, dxpl) < 0) + FAIL_STACK_ERROR + fh = NULL; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* Re-open the heap */ + if(NULL == (fh = H5HF_open(f, H5P_DATASET_XFER_DEFAULT, fh_addr))) + FAIL_STACK_ERROR + + /* Remove object #2 from heap */ + if(H5HF_get_obj_len(fh, dxpl, heap_id2, &robj_size) < 0) + FAIL_STACK_ERROR + if(H5HF_remove(fh, dxpl, heap_id2) < 0) + FAIL_STACK_ERROR + + /* Check up on heap... */ + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) + TEST_ERROR + + /* Close the fractal heap */ + if(H5HF_close(fh, dxpl) < 0) + FAIL_STACK_ERROR + fh = NULL; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* Re-open the heap */ + if(NULL == (fh = H5HF_open(f, H5P_DATASET_XFER_DEFAULT, fh_addr))) + FAIL_STACK_ERROR + + /* Check up on heap... */ + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) + TEST_ERROR + } /* end if */ + else { + /* Remove object #2 from heap */ + if(H5HF_get_obj_len(fh, dxpl, heap_id2, &robj_size) < 0) + FAIL_STACK_ERROR + if(H5HF_remove(fh, dxpl, heap_id2) < 0) + FAIL_STACK_ERROR + + /* Close the fractal heap */ + if(H5HF_close(fh, dxpl) < 0) + FAIL_STACK_ERROR + fh = NULL; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* Re-open the heap */ + if(NULL == (fh = H5HF_open(f, H5P_DATASET_XFER_DEFAULT, fh_addr))) + FAIL_STACK_ERROR + + /* Remove object #1 from heap */ + if(H5HF_get_obj_len(fh, dxpl, heap_id1, &robj_size) < 0) + FAIL_STACK_ERROR + if(H5HF_remove(fh, dxpl, heap_id1) < 0) + FAIL_STACK_ERROR + + /* Check up on heap... */ + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) + TEST_ERROR + + /* Close the fractal heap */ + if(H5HF_close(fh, dxpl) < 0) + FAIL_STACK_ERROR + fh = NULL; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* Re-open the heap */ + if(NULL == (fh = H5HF_open(f, H5P_DATASET_XFER_DEFAULT, fh_addr))) + FAIL_STACK_ERROR + + /* Check up on heap... */ + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) + TEST_ERROR + } /* end else */ + } /* end if */ + + /* Close the fractal heap */ + if(H5HF_close(fh, H5P_DATASET_XFER_DEFAULT) < 0) + FAIL_STACK_ERROR + fh = NULL; + + /* Check for deleting the entire heap */ + if(tparam->del_dir == FHEAP_DEL_HEAP) { + /* Delete heap */ + if(H5HF_delete(f, dxpl, fh_addr) < 0) + FAIL_STACK_ERROR + } /* end if */ + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + +#ifdef NOT_YET + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR +#ifdef QAK +HDfprintf(stderr, "empty_size = %lu, file_size = %lu\n", (unsigned long)empty_size, (unsigned long)file_size); +#endif /* QAK */ + + /* Verify the file is correct size */ + if(file_size != empty_size) + TEST_ERROR +#endif /* NOT_YET */ + + /* Free resources */ + H5O_reset(H5O_PLINE_ID, &tmp_cparam.pline); /* Release the I/O pipeline filter information */ + + /* All tests passed */ + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + if(fh) + H5HF_close(fh, dxpl); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_filtered_man_root_indirect() */ #ifndef QAK @@ -14288,6 +14593,7 @@ test_random(hsize_t size_limit, hid_t fapl, H5HF_create_t *cparam, fheap_test_pa H5F_t *f = NULL; /* Internal file object pointer */ H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ + H5HF_create_t tmp_cparam; /* Local heap creation parameters */ size_t id_len; /* Size of fractal heap IDs */ fheap_heap_ids_t keep_ids; /* Structure to retain heap IDs */ unsigned long seed = 0; /* Random # seed */ @@ -14299,8 +14605,21 @@ test_random(hsize_t size_limit, hid_t fapl, H5HF_create_t *cparam, fheap_test_pa fheap_heap_state_t state; /* State of fractal heap */ size_t u; /* Local index variable */ + /* Copy heap creation properties */ + HDmemcpy(&tmp_cparam, cparam, sizeof(H5HF_create_t)); + + /* Check if we are compressing the blocks */ + if(tparam->comp == FHEAP_TEST_COMPRESS) { + unsigned deflate_level; /* Deflation level */ + + /* Set an I/O filter for heap data */ + deflate_level = 6; + if(H5Z_append(&tmp_cparam.pline, H5Z_FILTER_DEFLATE, H5Z_FLAG_OPTIONAL, (size_t)1, &deflate_level) < 0) + FAIL_STACK_ERROR + } /* end if */ + /* Perform common file & heap open operations */ - if(open_heap(filename, fapl, dxpl, cparam, tparam, &file, &f, &fh, &fh_addr, &state, &empty_size) < 0) + if(open_heap(filename, fapl, dxpl, &tmp_cparam, tparam, &file, &f, &fh, &fh_addr, &state, &empty_size) < 0) TEST_ERROR /* Get information about heap ID lengths */ @@ -14312,10 +14631,18 @@ test_random(hsize_t size_limit, hid_t fapl, H5HF_create_t *cparam, fheap_test_pa /* * Display testing message */ - if(tparam->del_dir == FHEAP_DEL_HEAP) - TESTING("inserting random-sized objects, then remove all objects (all - deleting heap)") - else - TESTING("inserting random-sized objects, then remove all objects (all - random)") + if(tparam->del_dir == FHEAP_DEL_HEAP) { + if(tparam->comp == FHEAP_TEST_COMPRESS) + TESTING("inserting random-sized objects in heap with compressed blocks, then remove all objects (all - deleting heap)") + else + TESTING("inserting random-sized objects, then remove all objects (all - deleting heap)") + } /* end if */ + else { + if(tparam->comp == FHEAP_TEST_COMPRESS) + TESTING("inserting random-sized objects in heap with compressed blocks, then remove all objects (all - random)") + else + TESTING("inserting random-sized objects, then remove all objects (all - random)") + } /* end else */ /* Initialize the heap ID structure */ HDmemset(&keep_ids, 0, sizeof(fheap_heap_ids_t)); @@ -14332,8 +14659,8 @@ HDfprintf(stderr, "Random # seed was: %lu\n", seed); total_obj_added = 0; while(total_obj_added < size_limit) { /* Choose a random size of object (from 1 up to above standalone block size limit) */ - obj_size = (HDrandom() % (cparam->max_man_size + 255)) + 1; - obj_loc = (cparam->max_man_size + 255) - obj_size; + obj_size = (HDrandom() % (tmp_cparam.max_man_size + 255)) + 1; + obj_loc = (tmp_cparam.max_man_size + 255) - obj_size; /* Insert object */ if(add_obj(fh, dxpl, obj_loc, obj_size, NULL, &keep_ids)) @@ -14416,6 +14743,10 @@ HDfprintf(stderr, "file_size = %lu\n", (unsigned long)file_size); TEST_ERROR /* Free resources */ + if(tparam->comp == FHEAP_TEST_COMPRESS) + H5O_reset(H5O_PLINE_ID, &tmp_cparam.pline); /* Release the I/O pipeline filter information */ + + /* Free resources */ H5MM_xfree(keep_ids.ids); H5MM_xfree(keep_ids.lens); H5MM_xfree(keep_ids.offs); @@ -14466,6 +14797,7 @@ test_random_pow2(hsize_t size_limit, hid_t fapl, H5HF_create_t *cparam, fheap_te H5F_t *f = NULL; /* Internal file object pointer */ H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ + H5HF_create_t tmp_cparam; /* Local heap creation parameters */ size_t id_len; /* Size of fractal heap IDs */ fheap_heap_ids_t keep_ids; /* Structure to retain heap IDs */ unsigned long seed = 0; /* Random # seed */ @@ -14477,8 +14809,21 @@ test_random_pow2(hsize_t size_limit, hid_t fapl, H5HF_create_t *cparam, fheap_te fheap_heap_state_t state; /* State of fractal heap */ size_t u; /* Local index variable */ + /* Copy heap creation properties */ + HDmemcpy(&tmp_cparam, cparam, sizeof(H5HF_create_t)); + + /* Check if we are compressing the blocks */ + if(tparam->comp == FHEAP_TEST_COMPRESS) { + unsigned deflate_level; /* Deflation level */ + + /* Set an I/O filter for heap data */ + deflate_level = 6; + if(H5Z_append(&tmp_cparam.pline, H5Z_FILTER_DEFLATE, H5Z_FLAG_OPTIONAL, (size_t)1, &deflate_level) < 0) + FAIL_STACK_ERROR + } /* end if */ + /* Perform common file & heap open operations */ - if(open_heap(filename, fapl, dxpl, cparam, tparam, &file, &f, &fh, &fh_addr, &state, &empty_size) < 0) + if(open_heap(filename, fapl, dxpl, &tmp_cparam, tparam, &file, &f, &fh, &fh_addr, &state, &empty_size) < 0) TEST_ERROR /* Get information about heap ID lengths */ @@ -14490,10 +14835,18 @@ test_random_pow2(hsize_t size_limit, hid_t fapl, H5HF_create_t *cparam, fheap_te /* * Display testing message */ - if(tparam->del_dir == FHEAP_DEL_HEAP) - TESTING("inserting random-sized objects with power of 2 distribution, then remove all objects (all - deleting heap)") - else - TESTING("inserting random-sized objects with power of 2 distribution, then remove all objects (all - random)") + if(tparam->del_dir == FHEAP_DEL_HEAP) { + if(tparam->comp == FHEAP_TEST_COMPRESS) + TESTING("inserting random-sized objects with power of 2 distribution in heap with compressed blocks, then remove all objects (all - deleting heap)") + else + TESTING("inserting random-sized objects with power of 2 distribution, then remove all objects (all - deleting heap)") + } /* end if */ + else { + if(tparam->comp == FHEAP_TEST_COMPRESS) + TESTING("inserting random-sized objects with power of 2 distribution in heap with compressed blocks, then remove all objects (all - random)") + else + TESTING("inserting random-sized objects with power of 2 distribution, then remove all objects (all - random)") + } /* end else */ /* Initialize the heap ID structure */ HDmemset(&keep_ids, 0, sizeof(fheap_heap_ids_t)); @@ -14509,21 +14862,21 @@ HDfprintf(stderr, "Random # seed was: %lu\n", seed); /* Loop over adding objects to the heap, until the size limit is reached */ total_obj_added = 0; while(total_obj_added < size_limit) { - unsigned size_range = (cparam->managed.start_block_size / 8); /* Object size range */ + unsigned size_range = (tmp_cparam.managed.start_block_size / 8); /* Object size range */ /* Determine the size of the range for this object */ /* (50% of the objects inserted will use the initial size range, * 25% of the objects will be twice as large, 12.5% will be * four times larger, etc.) */ - while(HDrandom() < (RAND_MAX / 2) && size_range < cparam->max_man_size) + while(HDrandom() < (RAND_MAX / 2) && size_range < tmp_cparam.max_man_size) size_range *= 2; - if(size_range > (cparam->max_man_size + 255)) - size_range = cparam->max_man_size + 255; + if(size_range > (tmp_cparam.max_man_size + 255)) + size_range = tmp_cparam.max_man_size + 255; /* Choose a random size of object (from 1 up to stand alone block size) */ obj_size = (HDrandom() % (size_range - 1)) + 1; - obj_loc = (cparam->max_man_size + 255) - obj_size; + obj_loc = (tmp_cparam.max_man_size + 255) - obj_size; /* Insert object */ if(add_obj(fh, dxpl, obj_loc, obj_size, NULL, &keep_ids)) @@ -14598,6 +14951,7 @@ HDfprintf(stderr, "keep_ids.num_ids = %Zu, total_obj_added = %Hu, size_limit = % if((file_size = h5_get_file_size(filename)) < 0) TEST_ERROR #ifdef QAK +HDfprintf(stderr, "empty_size = %lu\n", (unsigned long)empty_size); HDfprintf(stderr, "file_size = %lu\n", (unsigned long)file_size); #endif /* QAK */ @@ -14606,6 +14960,10 @@ HDfprintf(stderr, "file_size = %lu\n", (unsigned long)file_size); TEST_ERROR /* Free resources */ + if(tparam->comp == FHEAP_TEST_COMPRESS) + H5O_reset(H5O_PLINE_ID, &tmp_cparam.pline); /* Release the I/O pipeline filter information */ + + /* Free resources */ H5MM_xfree(keep_ids.ids); H5MM_xfree(keep_ids.lens); H5MM_xfree(keep_ids.offs); @@ -14688,8 +15046,8 @@ main(void) for(curr_test = FHEAP_TEST_NORMAL; curr_test < FHEAP_TEST_NTESTS; curr_test++) { #else /* QAK */ HDfprintf(stderr, "Uncomment test loop!\n"); -/* curr_test = FHEAP_TEST_NORMAL; */ -curr_test = FHEAP_TEST_REOPEN; +curr_test = FHEAP_TEST_NORMAL; +/* curr_test = FHEAP_TEST_REOPEN; */ #endif /* QAK */ /* Clear the testing parameters */ HDmemset(&tparam, 0, sizeof(fheap_test_param_t)); @@ -15002,10 +15360,28 @@ HDfprintf(stderr, "Uncomment tests!\n"); #endif /* QAK2 */ /* Test I/O filter support */ -#ifdef NOT_YET - /* This test isn't working properly yet */ - nerrors += test_filtered_man_one(fapl, &small_cparam, &tparam); -#endif /* NOT_YET */ + + /* Try several different methods of deleting objects */ + { + fheap_test_del_dir_t del_dir; /* Deletion direction */ + + for(del_dir = FHEAP_DEL_FORWARD; del_dir < FHEAP_DEL_NDIRS; del_dir++) { + tparam.del_dir = del_dir; + + /* Controlled tests */ + nerrors += test_filtered_man_root_direct(fapl, &small_cparam, &tparam); +/* XXX: Re-enable file size checks in this test, after the file has persistent free space tracking working */ + nerrors += test_filtered_man_root_indirect(fapl, &small_cparam, &tparam); + + /* Random tests, with compressed blocks */ + tparam.comp = FHEAP_TEST_COMPRESS; + nerrors += test_random((curr_test == FHEAP_TEST_NORMAL ? (hsize_t)(50*1000*1000) : (hsize_t)(25*1000*1000)), fapl, &small_cparam, &tparam); + nerrors += test_random_pow2((curr_test == FHEAP_TEST_NORMAL ? (hsize_t)(50*1000*1000) : (hsize_t)(2*1000*1000)), fapl, &small_cparam, &tparam); + + /* Reset block compression */ + tparam.comp = FHEAP_TEST_NO_COMPRESS; + } /* end for */ + } /* end block */ #ifndef QAK /* Random object insertion & deletion */ @@ -15017,7 +15393,7 @@ HDfprintf(stderr, "Uncomment tests!\n"); puts("Using 'small' heap creation parameters"); /* (reduce size of tests when re-opening each time) */ -/* XXX: Try to speed things up enough that these tests don't have to be reduced */ +/* XXX: Try to speed things up enough that these tests don't have to be reduced when re-opening */ tparam.del_dir = FHEAP_DEL_FORWARD; nerrors += test_random((curr_test == FHEAP_TEST_NORMAL ? (hsize_t)(100*1000*1000) : (hsize_t)(50*1000*1000)), fapl, &small_cparam, &tparam); nerrors += test_random_pow2((curr_test == FHEAP_TEST_NORMAL ? (hsize_t)(100*1000*1000) : (hsize_t)(4*1000*1000)), fapl, &small_cparam, &tparam); @@ -15029,12 +15405,13 @@ HDfprintf(stderr, "Uncomment tests!\n"); HDfprintf(stderr, "Uncomment tests!\n"); #endif /* QAK */ +#ifndef QAK /* Random tests using "large" heap creation parameters */ puts("Using 'large' heap creation parameters"); tparam.actual_id_len = LARGE_HEAP_ID_LEN; /* (reduce size of tests when re-opening each time) */ -/* XXX: Try to speed things up enough that these tests don't have to be reduced */ +/* XXX: Try to speed things up enough that these tests don't have to be reduced when re-opening */ tparam.del_dir = FHEAP_DEL_FORWARD; nerrors += test_random((curr_test == FHEAP_TEST_NORMAL ? (hsize_t)(100*1000*1000) : (hsize_t)(50*1000*1000)), fapl, &large_cparam, &tparam); nerrors += test_random_pow2((curr_test == FHEAP_TEST_NORMAL ? (hsize_t)(100*1000*1000) : (hsize_t)(4*1000*1000)), fapl, &large_cparam, &tparam); @@ -15042,6 +15419,9 @@ HDfprintf(stderr, "Uncomment tests!\n"); tparam.del_dir = FHEAP_DEL_HEAP; nerrors += test_random((curr_test == FHEAP_TEST_NORMAL ? (hsize_t)(100*1000*1000) : (hsize_t)(50*1000*1000)), fapl, &large_cparam, &tparam); nerrors += test_random_pow2((curr_test == FHEAP_TEST_NORMAL ? (hsize_t)(100*1000*1000) : (hsize_t)(4*1000*1000)), fapl, &large_cparam, &tparam); +#else /* QAK */ +HDfprintf(stderr, "Uncomment tests!\n"); +#endif /* QAK */ /* Reset the "normal" heap ID length */ tparam.actual_id_len = SMALL_HEAP_ID_LEN; -- cgit v0.12