diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2006-10-29 02:17:07 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2006-10-29 02:17:07 (GMT) |
commit | 02bba16ee0b5c9da300608896d1ea9bc97c9ab1a (patch) | |
tree | 63d98a79c1c5d01f786cfe078eec407719ff79fa /src/H5HFsection.c | |
parent | c6c63ab6c64f4a29b3f379673e5236b2d614b422 (diff) | |
download | hdf5-02bba16ee0b5c9da300608896d1ea9bc97c9ab1a.zip hdf5-02bba16ee0b5c9da300608896d1ea9bc97c9ab1a.tar.gz hdf5-02bba16ee0b5c9da300608896d1ea9bc97c9ab1a.tar.bz2 |
[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
Diffstat (limited to 'src/H5HFsection.c')
-rw-r--r-- | src/H5HFsection.c | 233 |
1 files changed, 183 insertions, 50 deletions
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 */ |