#include "H5HFmodule.h"
#include "H5private.h"
#include "H5Eprivate.h"
#include "H5HFpkg.h"
#include "H5MMprivate.h"
#include "H5VMprivate.h"
#define H5HF_SECT_INDIRECT_SERIAL_SIZE(h) ( \
(unsigned)(h)->heap_off_size \
+ (unsigned)2 \
+ (unsigned)2 \
+ (unsigned)2 \
)
typedef struct {
H5HF_hdr_t *hdr;
} H5HF_sect_private_t;
static herr_t H5HF_sect_init_cls(H5FS_section_class_t *cls,
H5HF_hdr_t *hdr);
static herr_t H5HF_sect_term_cls(H5FS_section_class_t *cls);
static H5HF_free_section_t *H5HF_sect_node_new(unsigned sect_type,
haddr_t sect_addr, hsize_t sect_size, H5FS_section_state_t state);
static herr_t H5HF_sect_node_free(H5HF_free_section_t *sect,
H5HF_indirect_t *parent);
static herr_t H5HF__sect_single_locate_parent(H5HF_hdr_t *hdr, hbool_t refresh,
H5HF_free_section_t *sect);
static herr_t H5HF__sect_single_full_dblock(H5HF_hdr_t *hdr, H5HF_free_section_t *sect);
static herr_t H5HF__sect_single_add(H5FS_section_info_t **sect, unsigned *flags,
void *udata);
static H5FS_section_info_t *H5HF__sect_single_deserialize(const H5FS_section_class_t *cls,
const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size,
unsigned *des_flags);
static htri_t H5HF__sect_single_can_merge(const H5FS_section_info_t *sect1,
const H5FS_section_info_t *sect2, void *udata);
static herr_t H5HF__sect_single_merge(H5FS_section_info_t **sect1,
H5FS_section_info_t *sect2, void *udata);
static htri_t H5HF__sect_single_can_shrink(const H5FS_section_info_t *sect,
void *udata);
static herr_t H5HF__sect_single_shrink(H5FS_section_info_t **_sect,
void *udata);
static herr_t H5HF__sect_single_valid(const H5FS_section_class_t *cls,
const H5FS_section_info_t *sect);
static H5HF_free_section_t *H5HF_sect_row_create(haddr_t sect_off,
hsize_t sect_size, hbool_t is_first, unsigned row, unsigned col,
unsigned nentries, H5HF_free_section_t *under_sect);
static herr_t H5HF__sect_row_first(H5HF_hdr_t *hdr, H5HF_free_section_t *sect);
static herr_t H5HF__sect_row_parent_removed(H5HF_free_section_t *sect);
static herr_t H5HF_sect_row_from_single(H5HF_hdr_t *hdr,
H5HF_free_section_t *sect, H5HF_direct_t *dblock);
static herr_t H5HF__sect_row_free_real(H5HF_free_section_t *sect);
static herr_t H5HF__sect_row_init_cls(H5FS_section_class_t *cls, void *udata);
static herr_t H5HF__sect_row_term_cls(H5FS_section_class_t *cls);
static herr_t H5HF__sect_row_serialize(const H5FS_section_class_t *cls,
const H5FS_section_info_t *sect, uint8_t *buf);
static H5FS_section_info_t *H5HF__sect_row_deserialize(const H5FS_section_class_t *cls,
const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size,
unsigned *des_flags);
static htri_t H5HF__sect_row_can_merge(const H5FS_section_info_t *sect1,
const H5FS_section_info_t *sect2, void *udata);
static herr_t H5HF__sect_row_merge(H5FS_section_info_t **sect1,
H5FS_section_info_t *sect2, void *udata);
static htri_t H5HF__sect_row_can_shrink(const H5FS_section_info_t *sect,
void *udata);
static herr_t H5HF__sect_row_shrink(H5FS_section_info_t **sect,
void *udata);
static herr_t H5HF__sect_row_free(H5FS_section_info_t *sect);
static herr_t H5HF__sect_row_valid(const H5FS_section_class_t *cls,
const H5FS_section_info_t *sect);
static herr_t H5HF__sect_row_debug(const H5FS_section_info_t *sect,
FILE *stream, int indent, int fwidth);
static H5HF_free_section_t *H5HF_sect_indirect_new(H5HF_hdr_t *hdr,
haddr_t sect_off, hsize_t sect_size,
H5HF_indirect_t *iblock, hsize_t iblock_off,
unsigned row, unsigned col, unsigned nentries);
static herr_t H5HF__sect_indirect_init_rows(H5HF_hdr_t *hdr, H5HF_free_section_t *sect,
hbool_t first_child, H5HF_free_section_t **first_row_sect,
unsigned space_flags, unsigned start_row, unsigned start_col,
unsigned end_row, unsigned end_col);
static H5HF_free_section_t *H5HF_sect_indirect_for_row(H5HF_hdr_t *hdr,
H5HF_indirect_t *iblock, H5HF_free_section_t *row_sect);
static herr_t H5HF_sect_indirect_decr(H5HF_free_section_t *sect);
static herr_t H5HF__sect_indirect_revive_row(H5HF_hdr_t *hdr,
H5HF_free_section_t *sect);
static herr_t H5HF__sect_indirect_revive(H5HF_hdr_t *hdr,
H5HF_free_section_t *sect, H5HF_indirect_t *sect_iblock);
static herr_t H5HF__sect_indirect_reduce_row(H5HF_hdr_t *hdr,
H5HF_free_section_t *row_sect, hbool_t *alloc_from_start);
static herr_t H5HF__sect_indirect_reduce(H5HF_hdr_t *hdr,
H5HF_free_section_t *sect, unsigned child_entry);
static herr_t H5HF__sect_indirect_first(H5HF_hdr_t *hdr,
H5HF_free_section_t *sect);
static hbool_t H5HF_sect_indirect_is_first(H5HF_free_section_t *sect);
static H5HF_indirect_t * H5HF_sect_indirect_get_iblock(H5HF_free_section_t *sect);
static hsize_t H5HF_sect_indirect_iblock_off(const H5HF_free_section_t *sect);
static H5HF_free_section_t * H5HF_sect_indirect_top(H5HF_free_section_t *sect);
static herr_t H5HF__sect_indirect_merge_row(H5HF_hdr_t *hdr,
H5HF_free_section_t *sect1, H5HF_free_section_t *sect2);
static herr_t H5HF__sect_indirect_build_parent(H5HF_hdr_t *hdr, H5HF_free_section_t *sect);
static herr_t H5HF__sect_indirect_shrink(H5HF_hdr_t *hdr,
H5HF_free_section_t *sect);
static herr_t H5HF_sect_indirect_serialize(H5HF_hdr_t *hdr,
const H5HF_free_section_t *sect, uint8_t *buf);
static H5FS_section_info_t *H5HF__sect_indirect_deserialize(H5HF_hdr_t *hdr,
const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size, unsigned *des_flags);
static herr_t H5HF_sect_indirect_free(H5HF_free_section_t *sect);
static herr_t H5HF_sect_indirect_valid(const H5HF_hdr_t *hdr,
const H5HF_free_section_t *sect);
static herr_t H5HF_sect_indirect_debug(const H5HF_free_section_t *sect,
FILE *stream, int indent, int fwidth);
static herr_t H5HF_sect_indirect_init_cls(H5FS_section_class_t *cls, void *udata);
static herr_t H5HF_sect_indirect_term_cls(H5FS_section_class_t *cls);
H5FS_section_class_t H5HF_FSPACE_SECT_CLS_SINGLE[1] = {{
H5HF_FSPACE_SECT_SINGLE,
0,
H5FS_CLS_MERGE_SYM,
NULL,
NULL,
NULL,
H5HF__sect_single_add,
NULL,
H5HF__sect_single_deserialize,
H5HF__sect_single_can_merge,
H5HF__sect_single_merge,
H5HF__sect_single_can_shrink,
H5HF__sect_single_shrink,
H5HF__sect_single_free,
H5HF__sect_single_valid,
NULL,
NULL,
}};
H5FS_section_class_t H5HF_FSPACE_SECT_CLS_FIRST_ROW[1] = {{
H5HF_FSPACE_SECT_FIRST_ROW,
0,
H5FS_CLS_MERGE_SYM,
NULL,
H5HF__sect_row_init_cls,
H5HF__sect_row_term_cls,
NULL,
H5HF__sect_row_serialize,
H5HF__sect_row_deserialize,
H5HF__sect_row_can_merge,
H5HF__sect_row_merge,
H5HF__sect_row_can_shrink,
H5HF__sect_row_shrink,
H5HF__sect_row_free,
H5HF__sect_row_valid,
NULL,
H5HF__sect_row_debug,
}};
H5FS_section_class_t H5HF_FSPACE_SECT_CLS_NORMAL_ROW[1] = {{
H5HF_FSPACE_SECT_NORMAL_ROW,
0,
H5FS_CLS_MERGE_SYM|H5FS_CLS_SEPAR_OBJ|H5FS_CLS_GHOST_OBJ,
NULL,
H5HF__sect_row_init_cls,
H5HF__sect_row_term_cls,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
H5HF__sect_row_free,
H5HF__sect_row_valid,
NULL,
H5HF__sect_row_debug,
}};
H5FS_section_class_t H5HF_FSPACE_SECT_CLS_INDIRECT[1] = {{
H5HF_FSPACE_SECT_INDIRECT,
0,
H5FS_CLS_MERGE_SYM|H5FS_CLS_GHOST_OBJ,
NULL,
H5HF_sect_indirect_init_cls,
H5HF_sect_indirect_term_cls,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
}};
H5FL_DEFINE(H5HF_free_section_t);
static herr_t
H5HF_sect_init_cls(H5FS_section_class_t *cls, H5HF_hdr_t *hdr)
{
H5HF_sect_private_t *cls_prvt;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
HDassert(cls);
HDassert(!cls->cls_private);
if(NULL == (cls_prvt = (H5HF_sect_private_t *)H5MM_malloc(sizeof(H5HF_sect_private_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
cls_prvt->hdr = hdr;
cls->cls_private = cls_prvt;
if(H5HF_hdr_incr(hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared heap header")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF_sect_term_cls(H5FS_section_class_t *cls)
{
H5HF_sect_private_t *cls_prvt;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
HDassert(cls);
cls_prvt = (H5HF_sect_private_t *)cls->cls_private;
if(H5HF_hdr_decr(cls_prvt->hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared heap header")
cls->cls_private = H5MM_xfree(cls_prvt);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static H5HF_free_section_t *
H5HF_sect_node_new(unsigned sect_type, haddr_t sect_addr, hsize_t sect_size,
H5FS_section_state_t sect_state)
{
H5HF_free_section_t *new_sect;
H5HF_free_section_t *ret_value = NULL;
FUNC_ENTER_NOAPI_NOINIT
HDassert(H5F_addr_defined(sect_addr));
if(NULL == (new_sect = H5FL_MALLOC(H5HF_free_section_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for direct block free list section")
new_sect->sect_info.addr = sect_addr;
new_sect->sect_info.size = sect_size;
new_sect->sect_info.type = sect_type;
new_sect->sect_info.state = sect_state;
ret_value = new_sect;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF_sect_node_free(H5HF_free_section_t *sect, H5HF_indirect_t *iblock)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
HDassert(sect);
if(iblock)
if(H5HF__iblock_decr(iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on section's indirect block")
sect = H5FL_FREE(H5HF_free_section_t, sect);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
H5HF_free_section_t *
H5HF_sect_single_new(hsize_t sect_off, size_t sect_size,
H5HF_indirect_t *parent, unsigned par_entry)
{
H5HF_free_section_t *sect = NULL;
H5HF_free_section_t *ret_value = NULL;
FUNC_ENTER_NOAPI_NOINIT
HDassert(sect_size);
if(NULL == (sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_SINGLE, sect_off, (hsize_t)sect_size, H5FS_SECT_LIVE)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for single section")
sect->u.single.parent = parent;
if(sect->u.single.parent) {
if(H5HF_iblock_incr(sect->u.single.parent) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block")
}
sect->u.single.par_entry = par_entry;
ret_value = sect;
done:
if(!ret_value && sect) {
sect = H5FL_FREE(H5HF_free_section_t, sect);
}
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_single_locate_parent(H5HF_hdr_t *hdr, hbool_t refresh,
H5HF_free_section_t *sect)
{
H5HF_indirect_t *sec_iblock;
unsigned sec_entry;
hbool_t did_protect;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(hdr);
HDassert(hdr->man_dtable.curr_root_rows > 0);
HDassert(sect);
if(H5HF__man_dblock_locate(hdr, sect->sect_info.addr, &sec_iblock, &sec_entry, &did_protect, H5AC__READ_ONLY_FLAG) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section")
if(H5HF_iblock_incr(sec_iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
if(refresh) {
if(sect->u.single.parent) {
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")
}
}
sect->u.single.parent = sec_iblock;
sect->u.single.par_entry = sec_entry;
if(H5HF__man_iblock_unprotect(sec_iblock, 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)
}
herr_t
H5HF__sect_single_revive(H5HF_hdr_t *hdr, H5HF_free_section_t *sect)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(hdr);
HDassert(sect);
HDassert(sect->sect_info.state == H5FS_SECT_SERIALIZED);
if(hdr->man_dtable.curr_root_rows == 0) {
HDassert(H5F_addr_defined(hdr->man_dtable.table_addr));
sect->u.single.parent = NULL;
sect->u.single.par_entry = 0;
}
else {
if(H5HF__sect_single_locate_parent(hdr, FALSE, sect) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get section's parent info")
}
sect->sect_info.state = H5FS_SECT_LIVE;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5HF_sect_single_dblock_info(H5HF_hdr_t *hdr, const H5HF_free_section_t *sect,
haddr_t *dblock_addr, size_t *dblock_size)
{
FUNC_ENTER_NOAPI_NOERR
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);
if(hdr->man_dtable.curr_root_rows == 0) {
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;
}
else {
*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];
}
FUNC_LEAVE_NOAPI(SUCCEED)
}
herr_t
H5HF__sect_single_reduce(H5HF_hdr_t *hdr, H5HF_free_section_t *sect, size_t amt)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(hdr);
HDassert(sect);
HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_SINGLE);
HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
if(sect->sect_info.size == amt) {
if(H5HF__sect_single_free((H5FS_section_info_t *)sect) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free single section node")
}
else {
sect->sect_info.addr += amt;
sect->sect_info.size -= amt;
if(H5HF__space_add(hdr, sect, 0) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't re-add single section to free space manager")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_single_full_dblock(H5HF_hdr_t *hdr, H5HF_free_section_t *sect)
{
haddr_t dblock_addr;
size_t dblock_size;
size_t dblock_overhead;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(sect);
HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
HDassert(hdr);
if(H5HF_sect_single_dblock_info(hdr, sect, &dblock_addr, &dblock_size) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't retrieve direct block information")
dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
if((dblock_size - dblock_overhead) == sect->sect_info.size &&
hdr->man_dtable.curr_root_rows > 0) {
H5HF_direct_t *dblock;
hbool_t parent_removed;
if(NULL == (dblock = H5HF__man_dblock_protect(hdr, dblock_addr, dblock_size, sect->u.single.parent, sect->u.single.par_entry, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block")
HDassert(H5F_addr_eq(dblock->block_off + dblock_overhead, sect->sect_info.addr));
if(H5HF_sect_row_from_single(hdr, sect, dblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't convert single section into row section")
if(H5HF__man_dblock_destroy(hdr, dblock, dblock_addr, &parent_removed) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release direct block")
dblock = NULL;
if(parent_removed && H5FS_SECT_LIVE == sect->u.row.under->sect_info.state)
if(H5HF__sect_row_parent_removed(sect) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTUPDATE, FAIL, "can't update section info")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_single_add(H5FS_section_info_t **_sect, unsigned *flags, void *_udata)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
if(!(*flags & H5FS_ADD_DESERIALIZING)) {
H5HF_free_section_t **sect = (H5HF_free_section_t **)_sect;
H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata;
H5HF_hdr_t *hdr = udata->hdr;
HDassert(sect);
HDassert(hdr);
if(H5HF__sect_single_full_dblock(hdr, (*sect)) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't check/convert single section")
if((*sect)->sect_info.type != H5HF_FSPACE_SECT_SINGLE)
*flags |= H5FS_ADD_RETURNED_SPACE;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static H5FS_section_info_t *
H5HF__sect_single_deserialize(const H5FS_section_class_t H5_ATTR_UNUSED *cls,
const uint8_t H5_ATTR_UNUSED *buf, haddr_t sect_addr,
hsize_t sect_size, unsigned H5_ATTR_UNUSED *des_flags)
{
H5HF_free_section_t *new_sect;
H5FS_section_info_t *ret_value = NULL;
FUNC_ENTER_STATIC
HDassert(H5F_addr_defined(sect_addr));
HDassert(sect_size);
if(NULL == (new_sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_SINGLE, sect_addr, sect_size, H5FS_SECT_SERIALIZED)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "allocation failed for direct block free list section")
ret_value = (H5FS_section_info_t *)new_sect;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static htri_t
H5HF__sect_single_can_merge(const H5FS_section_info_t *_sect1,
const H5FS_section_info_t *_sect2, void H5_ATTR_UNUSED *_udata)
{
const H5HF_free_section_t *sect1 = (const H5HF_free_section_t *)_sect1;
const H5HF_free_section_t *sect2 = (const H5HF_free_section_t *)_sect2;
htri_t ret_value = FALSE;
FUNC_ENTER_STATIC_NOERR
HDassert(sect1);
HDassert(sect2);
HDassert(sect1->sect_info.type == sect2->sect_info.type);
HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr));
if(H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr))
HGOTO_DONE(TRUE)
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_single_merge(H5FS_section_info_t **_sect1, H5FS_section_info_t *_sect2,
void *_udata)
{
H5HF_free_section_t **sect1 = (H5HF_free_section_t **)_sect1;
H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2;
H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata;
H5HF_hdr_t *hdr = udata->hdr;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(sect1);
HDassert((*sect1)->sect_info.type == H5HF_FSPACE_SECT_SINGLE);
HDassert(sect2);
HDassert(sect2->sect_info.type == H5HF_FSPACE_SECT_SINGLE);
HDassert(H5F_addr_eq((*sect1)->sect_info.addr + (*sect1)->sect_info.size, sect2->sect_info.addr));
(*sect1)->sect_info.size += sect2->sect_info.size;
if(H5HF__sect_single_free((H5FS_section_info_t *)sect2) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
if((*sect1)->sect_info.state != H5FS_SECT_LIVE)
if(H5HF__sect_single_revive(hdr, (*sect1)) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section")
if(H5HF__sect_single_full_dblock(hdr, (*sect1)) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't check/convert single section")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static htri_t
H5HF__sect_single_can_shrink(const H5FS_section_info_t *_sect, void *_udata)
{
const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect;
H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata;
H5HF_hdr_t *hdr = udata->hdr;
htri_t ret_value = FALSE;
FUNC_ENTER_STATIC_NOERR
HDassert(sect);
if(hdr->man_dtable.curr_root_rows == 0) {
size_t dblock_size;
size_t dblock_overhead;
dblock_size = hdr->man_dtable.cparam.start_block_size;
dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
if((dblock_size - dblock_overhead) == sect->sect_info.size)
HGOTO_DONE(TRUE)
}
else {
HDassert(hdr->man_iter_off > sect->sect_info.addr);
HGOTO_DONE(FALSE)
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_single_shrink(H5FS_section_info_t **_sect, void *_udata)
{
H5HF_free_section_t **sect = (H5HF_free_section_t **)_sect;
H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata;
H5HF_hdr_t *hdr = udata->hdr;
H5HF_direct_t *dblock;
haddr_t dblock_addr;
size_t dblock_size;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(sect);
HDassert(*sect);
HDassert((*sect)->sect_info.type == H5HF_FSPACE_SECT_SINGLE);
if((*sect)->sect_info.state != H5FS_SECT_LIVE)
if(H5HF__sect_single_revive(hdr, (*sect)) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section")
if(H5HF_sect_single_dblock_info(hdr, (*sect), &dblock_addr, &dblock_size) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't retrieve direct block information")
HDassert(dblock_addr == hdr->man_dtable.table_addr);
if(NULL == (dblock = H5HF__man_dblock_protect(hdr, dblock_addr, dblock_size, (*sect)->u.single.parent, (*sect)->u.single.par_entry, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block")
HDassert(H5F_addr_eq(dblock->block_off + dblock_size, (*sect)->sect_info.addr + (*sect)->sect_info.size));
if(H5HF__sect_single_free((H5FS_section_info_t *)*sect) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
if(H5HF__man_dblock_destroy(hdr, dblock, dblock_addr, NULL) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release direct block")
dblock = NULL;
*sect = NULL;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5HF__sect_single_free(H5FS_section_info_t *_sect)
{
H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect;
H5HF_indirect_t *parent = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(sect);
if(sect->sect_info.state == H5FS_SECT_LIVE)
if(sect->u.single.parent)
parent = sect->u.single.parent;
if(H5HF_sect_node_free(sect, parent) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_single_valid(const H5FS_section_class_t H5_ATTR_UNUSED *cls, const H5FS_section_info_t *_sect)
{
const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect;
FUNC_ENTER_STATIC_NOERR
HDassert(sect);
if(sect->sect_info.state == H5FS_SECT_LIVE) {
if(sect->u.single.parent != NULL) {
H5HF_indirect_t *iblock;
haddr_t dblock_addr;
size_t dblock_size;
unsigned dblock_status = 0;
size_t H5_ATTR_NDEBUG_UNUSED dblock_overhead;
herr_t H5_ATTR_NDEBUG_UNUSED status;
iblock = sect->u.single.parent;
HDassert(H5F_addr_defined(iblock->ents[sect->u.single.par_entry].addr));
status = H5HF_sect_single_dblock_info(iblock->hdr, (const H5HF_free_section_t *)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);
HDassert(sect->sect_info.addr < iblock->hdr->man_iter_off);
dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(iblock->hdr);
HDassert((sect->sect_info.size + dblock_overhead) < dblock_size);
status = H5AC_get_entry_status(iblock->hdr->f, dblock_addr, &dblock_status);
HDassert(status >= 0);
if(!(dblock_status & H5AC_ES__IS_PROTECTED)) {
H5HF_direct_t *dblock;
dblock = H5HF__man_dblock_protect(iblock->hdr, dblock_addr, dblock_size, iblock, sect->u.single.par_entry, H5AC__READ_ONLY_FLAG);
HDassert(dblock);
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)));
status = H5AC_unprotect(iblock->hdr->f, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET);
HDassert(status >= 0);
}
}
}
FUNC_LEAVE_NOAPI(SUCCEED)
}
static H5HF_free_section_t *
H5HF_sect_row_create(haddr_t sect_off, hsize_t sect_size, hbool_t is_first,
unsigned row, unsigned col, unsigned nentries, H5HF_free_section_t *under_sect)
{
H5HF_free_section_t *sect = NULL;
H5HF_free_section_t *ret_value = NULL;
FUNC_ENTER_NOAPI_NOINIT
HDassert(sect_size);
HDassert(nentries);
HDassert(under_sect);
if(NULL == (sect = H5HF_sect_node_new((unsigned)(is_first ? H5HF_FSPACE_SECT_FIRST_ROW : H5HF_FSPACE_SECT_NORMAL_ROW), sect_off, sect_size, under_sect->sect_info.state)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for row section")
sect->u.row.under = under_sect;
sect->u.row.row = row;
sect->u.row.col = col;
sect->u.row.num_entries = nentries;
sect->u.row.checked_out = FALSE;
ret_value = sect;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF_sect_row_from_single(H5HF_hdr_t *hdr, H5HF_free_section_t *sect,
H5HF_direct_t *dblock)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
HDassert(hdr);
HDassert(sect);
HDassert(dblock);
sect->sect_info.addr = dblock->block_off;
sect->sect_info.type = H5HF_FSPACE_SECT_FIRST_ROW;
sect->u.row.row = dblock->par_entry / hdr->man_dtable.cparam.width;
sect->u.row.col = dblock->par_entry % hdr->man_dtable.cparam.width;
sect->u.row.num_entries = 1;
sect->u.row.checked_out = FALSE;
if(NULL == (sect->u.row.under = H5HF_sect_indirect_for_row(hdr, dblock->parent, sect)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "serializing row section not supported yet")
if(H5HF__iblock_decr(dblock->parent) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5HF__sect_row_revive(H5HF_hdr_t *hdr, H5HF_free_section_t *sect)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(hdr);
HDassert(sect);
HDassert(sect->u.row.under);
if((H5FS_SECT_LIVE == sect->u.row.under->sect_info.state)
&& (TRUE == sect->u.row.under->u.indirect.u.iblock->removed_from_cache))
if(H5HF__sect_row_parent_removed(sect) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTUPDATE, FAIL, "can't update section info")
if(H5HF__sect_indirect_revive_row(hdr, sect->u.row.under) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTREVIVE, FAIL, "can't revive indirect section")
HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5HF__sect_row_reduce(H5HF_hdr_t *hdr, H5HF_free_section_t *sect,
unsigned *entry_p)
{
hbool_t alloc_from_start;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(hdr);
HDassert(sect);
HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ||
sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
HDassert(entry_p);
HDassert(sect->u.row.checked_out == FALSE);
sect->u.row.checked_out = TRUE;
alloc_from_start = FALSE;
if(H5HF__sect_indirect_reduce_row(hdr, sect, &alloc_from_start) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce underlying section")
*entry_p = (sect->u.row.row * hdr->man_dtable.cparam.width) + sect->u.row.col;
if(!alloc_from_start)
*entry_p += (sect->u.row.num_entries - 1);
if(sect->u.row.num_entries == 1) {
if(H5HF__sect_row_free((H5FS_section_info_t *)sect) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free row section node")
}
else {
if(alloc_from_start) {
sect->sect_info.addr += hdr->man_dtable.row_block_size[sect->u.row.row];
sect->u.row.col++;
}
sect->u.row.num_entries--;
sect->u.row.checked_out = FALSE;
if(H5HF__space_add(hdr, sect, 0) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't re-add indirect section to free space manager")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_row_first(H5HF_hdr_t *hdr, H5HF_free_section_t *sect)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(hdr);
HDassert(sect);
HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
if(sect->u.row.checked_out)
sect->sect_info.type = H5HF_FSPACE_SECT_FIRST_ROW;
else
if(H5HF__space_sect_change_class(hdr, sect, H5HF_FSPACE_SECT_FIRST_ROW) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "can't set row section to be first row")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
H5HF_indirect_t *
H5HF_sect_row_get_iblock(H5HF_free_section_t *sect)
{
H5HF_indirect_t *ret_value = NULL;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(sect);
HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ||
sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
ret_value = H5HF_sect_indirect_get_iblock(sect->u.row.under);
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_row_parent_removed(H5HF_free_section_t *sect)
{
hsize_t tmp_iblock_off;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(sect);
tmp_iblock_off = sect->u.row.under->u.indirect.u.iblock->block_off;
if(H5HF__iblock_decr(sect->u.row.under->u.indirect.u.iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
sect->u.row.under->u.indirect.u.iblock_off = tmp_iblock_off;
sect->u.row.under->u.indirect.iblock_entries = 0;
for(u = 0; u < sect->u.row.under->u.indirect.dir_nrows; u++)
sect->u.row.under->u.indirect.dir_rows[u]->sect_info.state = H5FS_SECT_SERIALIZED;
sect->u.row.under->sect_info.state = H5FS_SECT_SERIALIZED;
sect->sect_info.state = H5FS_SECT_SERIALIZED;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_row_init_cls(H5FS_section_class_t *cls, void *_udata)
{
H5HF_hdr_t *hdr = (H5HF_hdr_t *)_udata;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(cls);
HDassert(hdr);
if(H5HF_sect_init_cls(cls, hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize common section class")
if(cls->type == H5HF_FSPACE_SECT_FIRST_ROW)
cls->serial_size = H5HF_SECT_INDIRECT_SERIAL_SIZE(hdr);
else
cls->serial_size = 0;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_row_term_cls(H5FS_section_class_t *cls)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(cls);
if(H5HF_sect_term_cls(cls) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't terminate common section class")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_row_serialize(const H5FS_section_class_t *cls,
const H5FS_section_info_t *_sect, uint8_t *buf)
{
H5HF_hdr_t *hdr;
const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(cls);
HDassert(buf);
HDassert(sect);
HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
HDassert(sect->sect_info.addr == sect->u.row.under->sect_info.addr);
hdr = ((H5HF_sect_private_t *)(cls->cls_private))->hdr;
if(H5HF_sect_indirect_serialize(hdr, sect->u.row.under, buf) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTSERIALIZE, FAIL, "can't serialize row section's underlying indirect section")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static H5FS_section_info_t *
H5HF__sect_row_deserialize(const H5FS_section_class_t *cls, const uint8_t *buf,
haddr_t sect_addr, hsize_t sect_size, unsigned *des_flags)
{
H5HF_hdr_t *hdr;
H5FS_section_info_t *ret_value = NULL;
FUNC_ENTER_STATIC
HDassert(cls);
HDassert(buf);
HDassert(H5F_addr_defined(sect_addr));
HDassert(sect_size);
hdr = ((H5HF_sect_private_t *)(cls->cls_private))->hdr;
if(NULL == (ret_value = H5HF__sect_indirect_deserialize(hdr, buf, sect_addr, sect_size, des_flags)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTDECODE, NULL, "can't deserialize row section's underlying indirect section")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static htri_t
H5HF__sect_row_can_merge(const H5FS_section_info_t *_sect1,
const H5FS_section_info_t *_sect2, void H5_ATTR_UNUSED *_udata)
{
const H5HF_free_section_t *sect1 = (const H5HF_free_section_t *)_sect1;
const H5HF_free_section_t *sect2 = (const H5HF_free_section_t *)_sect2;
H5HF_free_section_t *top_indir_sect1, *top_indir_sect2;
htri_t ret_value = FALSE;
FUNC_ENTER_STATIC_NOERR
HDassert(sect1);
HDassert(sect1->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
HDassert(sect2);
HDassert(sect1->sect_info.type == sect2->sect_info.type);
HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr));
top_indir_sect1 = H5HF_sect_indirect_top(sect1->u.row.under);
HDassert(top_indir_sect1);
top_indir_sect2 = H5HF_sect_indirect_top(sect2->u.row.under);
HDassert(top_indir_sect2);
if(top_indir_sect1 != top_indir_sect2)
if(H5HF_sect_indirect_iblock_off(sect1->u.row.under) == H5HF_sect_indirect_iblock_off(sect2->u.row.under))
if(H5F_addr_eq((top_indir_sect1->sect_info.addr + top_indir_sect1->u.indirect.span_size), top_indir_sect2->sect_info.addr))
HGOTO_DONE(TRUE)
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_row_merge(H5FS_section_info_t **_sect1, H5FS_section_info_t *_sect2,
void *_udata)
{
H5HF_free_section_t **sect1 = (H5HF_free_section_t **)_sect1;
H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2;
H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata;
H5HF_hdr_t *hdr = udata->hdr;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(sect1);
HDassert((*sect1)->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
HDassert(sect2);
HDassert(sect2->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
if(sect2->sect_info.addr >= hdr->man_iter_off) {
H5HF_free_section_t *top_indir_sect;
top_indir_sect = H5HF_sect_indirect_top(sect2->u.row.under);
if(H5HF__sect_indirect_shrink(hdr, top_indir_sect) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't shrink underlying indirect section")
}
else
if(H5HF__sect_indirect_merge_row(hdr, (*sect1), sect2) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTMERGE, FAIL, "can't merge underlying indirect sections")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static htri_t
H5HF__sect_row_can_shrink(const H5FS_section_info_t *_sect, void H5_ATTR_UNUSED *_udata)
{
const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect;
H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata;
H5HF_hdr_t *hdr = udata->hdr;
htri_t ret_value = FALSE;
FUNC_ENTER_STATIC_NOERR
HDassert(sect);
HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
if(sect->sect_info.addr >= hdr->man_iter_off)
HGOTO_DONE(TRUE)
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_row_shrink(H5FS_section_info_t **_sect, void *_udata)
{
H5HF_free_section_t **sect = (H5HF_free_section_t **)_sect;
H5HF_free_section_t *top_indir_sect;
H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata;
H5HF_hdr_t *hdr = udata->hdr;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(sect);
HDassert(*sect);
HDassert((*sect)->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
top_indir_sect = H5HF_sect_indirect_top((*sect)->u.row.under);
if(H5HF__sect_indirect_shrink(hdr, top_indir_sect) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't shrink underlying indirect section")
*sect = NULL;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_row_free_real(H5HF_free_section_t *sect)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(sect);
if(H5HF_sect_node_free(sect, NULL) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_row_free(H5FS_section_info_t *_sect)
{
H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(sect);
HDassert(sect->u.row.under);
if(H5HF_sect_indirect_decr(sect->u.row.under) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't detach section node")
if(H5HF__sect_row_free_real(sect) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_row_valid(const H5FS_section_class_t *cls, const H5FS_section_info_t *_sect)
{
H5HF_sect_private_t *cls_prvt;
const H5HF_hdr_t *hdr;
const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect;
const H5HF_free_section_t *indir_sect;
unsigned H5_ATTR_NDEBUG_UNUSED indir_idx;
FUNC_ENTER_STATIC_NOERR
HDassert(cls);
HDassert(sect);
cls_prvt = (H5HF_sect_private_t *)cls->cls_private;
hdr = cls_prvt->hdr;
HDassert(sect->u.row.under);
HDassert(sect->u.row.num_entries);
HDassert(sect->u.row.checked_out == FALSE);
indir_sect = sect->u.row.under;
indir_idx = sect->u.row.row - indir_sect->u.indirect.row;
HDassert(indir_sect->u.indirect.dir_rows[indir_idx] == sect);
HDassert(sect->sect_info.addr < hdr->man_iter_off);
if(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW) {
H5HF_free_section_t *top_indir_sect;
HDassert(sect->u.row.row == indir_sect->u.indirect.row);
top_indir_sect = H5HF_sect_indirect_top(sect->u.row.under);
H5HF_sect_indirect_valid(hdr, top_indir_sect);
}
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5HF__sect_row_debug(const H5FS_section_info_t *_sect, FILE *stream, int indent, int fwidth)
{
const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect;
FUNC_ENTER_STATIC_NOERR
HDassert(sect);
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"Row:",
sect->u.row.row);
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"Column:",
sect->u.row.col);
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"Number of entries:",
sect->u.row.num_entries);
if(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW) {
HDfprintf(stream, "%*s%-*s\n", indent, "", fwidth,
"Underlying indirect section:");
H5HF_sect_indirect_debug(sect->u.row.under, stream, indent + 3, MAX(0, fwidth - 3));
}
FUNC_LEAVE_NOAPI(SUCCEED)
}
static hsize_t
H5HF_sect_indirect_iblock_off(const H5HF_free_section_t *sect)
{
hsize_t ret_value = 0;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(sect);
ret_value = sect->sect_info.state == H5FS_SECT_LIVE ? sect->u.indirect.u.iblock->block_off : sect->u.indirect.u.iblock_off;
FUNC_LEAVE_NOAPI(ret_value)
}
static H5HF_free_section_t *
H5HF_sect_indirect_top(H5HF_free_section_t *sect)
{
H5HF_free_section_t *ret_value = NULL;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(sect);
if(sect->u.indirect.parent)
ret_value = H5HF_sect_indirect_top(sect->u.indirect.parent);
else
ret_value = sect;
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF_sect_indirect_init_cls(H5FS_section_class_t *cls, void *_udata)
{
H5HF_hdr_t *hdr = (H5HF_hdr_t *)_udata;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
HDassert(cls);
HDassert(hdr);
if(H5HF_sect_init_cls(cls, hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize common section class")
cls->serial_size = H5HF_SECT_INDIRECT_SERIAL_SIZE(hdr);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF_sect_indirect_term_cls(H5FS_section_class_t *cls)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
HDassert(cls);
if(H5HF_sect_term_cls(cls) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't terminate common section class")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static H5HF_free_section_t *
H5HF_sect_indirect_new(H5HF_hdr_t *hdr, haddr_t sect_off, hsize_t sect_size,
H5HF_indirect_t *iblock, hsize_t iblock_off, unsigned row, unsigned col,
unsigned nentries)
{
H5HF_free_section_t *sect = NULL;
H5HF_free_section_t *ret_value = NULL;
FUNC_ENTER_NOAPI_NOINIT
HDassert(hdr);
HDassert(nentries);
if(NULL == (sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_INDIRECT, sect_off,
sect_size, (iblock ? H5FS_SECT_LIVE : H5FS_SECT_SERIALIZED))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for indirect section")
if(iblock) {
sect->u.indirect.u.iblock = iblock;
sect->u.indirect.iblock_entries = hdr->man_dtable.cparam.width *
sect->u.indirect.u.iblock->max_rows;
if(H5HF_iblock_incr(sect->u.indirect.u.iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block")
}
else {
sect->u.indirect.u.iblock_off = iblock_off;
sect->u.indirect.iblock_entries = 0;
}
sect->u.indirect.row = row;
sect->u.indirect.col = col;
sect->u.indirect.num_entries = nentries;
sect->u.indirect.span_size = H5HF_dtable_span_size(&hdr->man_dtable,
row, col, nentries);
HDassert(sect->u.indirect.span_size > 0);
sect->u.indirect.parent = NULL;
sect->u.indirect.par_entry = 0;
ret_value = sect;
done:
if(!ret_value && sect) {
sect = H5FL_FREE(H5HF_free_section_t, sect);
}
FUNC_LEAVE_NOAPI(ret_value)
}
static H5HF_free_section_t *
H5HF_sect_indirect_for_row(H5HF_hdr_t *hdr, H5HF_indirect_t *iblock,
H5HF_free_section_t *row_sect)
{
H5HF_free_section_t *sect = NULL;
H5HF_free_section_t *ret_value = NULL;
FUNC_ENTER_NOAPI_NOINIT
HDassert(hdr);
HDassert(iblock);
HDassert(row_sect);
HDassert(row_sect->u.row.row < hdr->man_dtable.max_direct_rows);
if(NULL == (sect = H5HF_sect_indirect_new(hdr, row_sect->sect_info.addr,
row_sect->sect_info.size, iblock, iblock->block_off,
row_sect->u.row.row, row_sect->u.row.col, row_sect->u.row.num_entries)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't create indirect section")
sect->u.indirect.dir_nrows = 1;
if(NULL == (sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *))))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "allocation failed for row section pointer array")
sect->u.indirect.dir_rows[0] = row_sect;
sect->u.indirect.rc = 1;
sect->u.indirect.indir_nents = 0;
sect->u.indirect.indir_ents = NULL;
ret_value = sect;
done:
if(!ret_value && sect)
if(H5HF_sect_indirect_free(sect) < 0)
HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, NULL, "can't free indirect section node")
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_indirect_init_rows(H5HF_hdr_t *hdr, H5HF_free_section_t *sect,
hbool_t first_child, H5HF_free_section_t **first_row_sect,
unsigned space_flags, unsigned start_row, unsigned start_col,
unsigned end_row, unsigned end_col)
{
hsize_t curr_off;
size_t dblock_overhead;
unsigned row_entries;
unsigned row_col;
unsigned curr_entry;
unsigned curr_indir_entry;
unsigned curr_row;
unsigned dir_nrows;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(sect);
HDassert(sect->u.indirect.span_size > 0);
sect->u.indirect.rc = 0;
sect->u.indirect.dir_rows = NULL;
sect->u.indirect.indir_ents = NULL;
if(start_row < hdr->man_dtable.max_direct_rows) {
unsigned max_direct_row;
max_direct_row = MIN(end_row, (hdr->man_dtable.max_direct_rows - 1));
dir_nrows = (max_direct_row - start_row) + 1;
sect->u.indirect.dir_nrows = 0;
if(NULL == (sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *) * dir_nrows)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for row section pointer array")
}
else {
dir_nrows = 0;
sect->u.indirect.dir_nrows = 0;
}
if(end_row >= hdr->man_dtable.max_direct_rows) {
unsigned indirect_start_row;
unsigned indirect_start_col;
unsigned indirect_start_entry;
unsigned indirect_end_entry;
if(start_row < hdr->man_dtable.max_direct_rows) {
indirect_start_row = hdr->man_dtable.max_direct_rows;
indirect_start_col = 0;
}
else {
indirect_start_row = start_row;
indirect_start_col = start_col;
}
indirect_start_entry = (indirect_start_row * hdr->man_dtable.cparam.width)
+ indirect_start_col;
indirect_end_entry = (end_row * hdr->man_dtable.cparam.width) + end_col;
sect->u.indirect.indir_nents = (indirect_end_entry - indirect_start_entry) + 1;
if(NULL == (sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *) * sect->u.indirect.indir_nents)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for indirect section pointer array")
}
else {
sect->u.indirect.indir_nents = 0;
}
if(start_row == end_row)
row_entries = (end_col - start_col) + 1;
else
row_entries = hdr->man_dtable.cparam.width - start_col;
row_col = start_col;
curr_off = sect->sect_info.addr;
curr_entry = (start_row * hdr->man_dtable.cparam.width) + start_col;
curr_row = 0;
curr_indir_entry = 0;
dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
for(u = start_row; u <= end_row; u++, curr_row++) {
if(u < hdr->man_dtable.max_direct_rows) {
H5HF_free_section_t *row_sect = NULL;
if(NULL == (row_sect = H5HF_sect_row_create(curr_off,
(hdr->man_dtable.row_block_size[u] - dblock_overhead), first_child, u, row_col,
row_entries, sect)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "creation failed for child row section")
sect->u.indirect.dir_rows[curr_row] = row_sect;
if(first_row_sect)
*first_row_sect = row_sect;
else
if(H5HF__space_add(hdr, row_sect, space_flags) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add row section to free space")
sect->u.indirect.rc++;
curr_off += row_entries * hdr->man_dtable.row_block_size[u];
curr_entry += row_entries;
first_child = FALSE;
first_row_sect = NULL;
}
else {
H5HF_indirect_t *child_iblock;
H5HF_free_section_t *child_sect;
unsigned child_nrows;
unsigned child_nentries;
unsigned v;
child_nrows = H5HF_dtable_size_to_rows(&hdr->man_dtable, hdr->man_dtable.row_block_size[u]);
child_nentries = child_nrows * hdr->man_dtable.cparam.width;
for(v = 0; v < row_entries; v++) {
hbool_t did_protect;
if(sect->sect_info.state == H5FS_SECT_LIVE) {
haddr_t child_iblock_addr;
if(H5HF_man_iblock_entry_addr(sect->u.indirect.u.iblock, curr_entry, &child_iblock_addr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve child indirect block's address")
if(H5F_addr_defined(child_iblock_addr)) {
if(NULL == (child_iblock = H5HF__man_iblock_protect(hdr, child_iblock_addr, child_nrows, sect->u.indirect.u.iblock, curr_entry, FALSE, H5AC__NO_FLAGS_SET, &did_protect)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
}
else
child_iblock = NULL;
}
else
child_iblock = NULL;
if(NULL == (child_sect = H5HF_sect_indirect_new(hdr, curr_off, (hsize_t)0,
child_iblock, curr_off, 0, 0, child_nentries)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section")
if(H5HF__sect_indirect_init_rows(hdr, child_sect,
first_child, first_row_sect, space_flags, 0, 0,
(child_nrows - 1), (hdr->man_dtable.cparam.width - 1)) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize indirect section")
if(child_iblock)
if(H5HF__man_iblock_unprotect(child_iblock, H5AC__NO_FLAGS_SET, did_protect) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
child_sect->u.indirect.parent = sect;
child_sect->u.indirect.par_entry = curr_entry;
sect->u.indirect.indir_ents[curr_indir_entry] = child_sect;
sect->u.indirect.rc++;
curr_off += hdr->man_dtable.row_block_size[u];
curr_entry++;
curr_indir_entry++;
first_child = FALSE;
first_row_sect = NULL;
}
}
if(u < (end_row - 1))
row_entries = hdr->man_dtable.cparam.width;
else
row_entries = end_col + 1;
row_col = 0;
}
sect->u.indirect.dir_nrows = dir_nrows;
HDassert(sect->u.indirect.rc ==
(sect->u.indirect.indir_nents + sect->u.indirect.dir_nrows));
done:
if(ret_value < 0) {
if(sect->u.indirect.indir_ents)
H5MM_xfree(sect->u.indirect.indir_ents);
if(sect->u.indirect.dir_rows)
H5MM_xfree(sect->u.indirect.dir_rows);
}
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5HF__sect_indirect_add(H5HF_hdr_t *hdr, H5HF_indirect_t *iblock, unsigned start_entry, unsigned nentries)
{
H5HF_free_section_t *sect = NULL;
H5HF_free_section_t *first_row_sect = NULL;
hsize_t sect_off;
unsigned start_row;
unsigned start_col;
unsigned end_entry;
unsigned end_row;
unsigned end_col;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(hdr);
HDassert(iblock);
HDassert(nentries);
start_row = start_entry / hdr->man_dtable.cparam.width;
start_col = start_entry % hdr->man_dtable.cparam.width;
end_entry = (start_entry + nentries) - 1;
end_row = end_entry / hdr->man_dtable.cparam.width;
end_col = end_entry % hdr->man_dtable.cparam.width;
sect_off = iblock->block_off;
for(u = 0; u < start_row; u++)
sect_off += hdr->man_dtable.row_block_size[u] * hdr->man_dtable.cparam.width;
sect_off += hdr->man_dtable.row_block_size[start_row] * start_col;
if(NULL == (sect = H5HF_sect_indirect_new(hdr, sect_off, (hsize_t)0, iblock,
iblock->block_off, start_row, start_col, nentries)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section")
if(H5HF__sect_indirect_init_rows(hdr, sect, TRUE, &first_row_sect,
H5FS_ADD_SKIP_VALID, start_row, start_col, end_row, end_col) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize indirect section")
HDassert(first_row_sect);
if(H5HF__space_add(hdr, first_row_sect, H5FS_ADD_RETURNED_SPACE) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add row section to free space")
done:
if(ret_value < 0 && sect)
if(H5HF_sect_indirect_free(sect) < 0)
HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF_sect_indirect_decr(H5HF_free_section_t *sect)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
HDassert(sect);
HDassert(sect->u.indirect.rc);
sect->u.indirect.rc--;
if(sect->u.indirect.rc == 0) {
H5HF_free_section_t *par_sect;
par_sect = sect->u.indirect.parent;
if(H5HF_sect_indirect_free(sect) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
if(par_sect)
if(H5HF_sect_indirect_decr(par_sect) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't decrement ref. count on parent indirect section")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_indirect_revive_row(H5HF_hdr_t *hdr, H5HF_free_section_t *sect)
{
H5HF_indirect_t *sec_iblock;
hbool_t did_protect;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(hdr);
HDassert(sect);
HDassert(sect->sect_info.state == H5FS_SECT_SERIALIZED);
if(H5HF__man_dblock_locate(hdr, sect->sect_info.addr, &sec_iblock, NULL, &did_protect, H5AC__READ_ONLY_FLAG) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section")
if(H5HF__sect_indirect_revive(hdr, sect, sec_iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTREVIVE, FAIL, "can't revive indirect section")
done:
if(sec_iblock && H5HF__man_iblock_unprotect(sec_iblock, H5AC__NO_FLAGS_SET, did_protect) < 0)
HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_indirect_revive(H5HF_hdr_t *hdr, H5HF_free_section_t *sect, H5HF_indirect_t *sect_iblock)
{
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(hdr);
HDassert(sect);
HDassert(sect->sect_info.state == H5FS_SECT_SERIALIZED);
HDassert(sect_iblock);
if(H5HF_iblock_incr(sect_iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
sect->u.indirect.u.iblock = sect_iblock;
sect->u.indirect.iblock_entries = hdr->man_dtable.cparam.width *
sect->u.indirect.u.iblock->max_rows;
sect->sect_info.state = H5FS_SECT_LIVE;
for(u = 0; u < sect->u.indirect.dir_nrows; u++)
sect->u.indirect.dir_rows[u]->sect_info.state = H5FS_SECT_LIVE;
if(sect->u.indirect.parent && sect->u.indirect.parent->sect_info.state == H5FS_SECT_SERIALIZED)
if(H5HF__sect_indirect_revive(hdr, sect->u.indirect.parent, sect->u.indirect.u.iblock->parent) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTREVIVE, FAIL, "can't revive indirect section")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_indirect_reduce_row(H5HF_hdr_t *hdr, H5HF_free_section_t *row_sect,
hbool_t *alloc_from_start)
{
H5HF_free_section_t *sect;
unsigned row_start_entry;
unsigned row_end_entry;
unsigned row_entry;
unsigned start_entry;
unsigned start_row;
unsigned start_col;
unsigned end_entry;
unsigned end_row;
H5HF_free_section_t *peer_sect = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(hdr);
HDassert(row_sect);
row_start_entry = (row_sect->u.row.row * hdr->man_dtable.cparam.width) + row_sect->u.row.col;
row_end_entry = (row_start_entry + row_sect->u.row.num_entries) - 1;
sect = row_sect->u.row.under;
start_row = sect->u.indirect.row;
start_col = sect->u.indirect.col;
start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col;
end_entry = (start_entry + sect->u.indirect.num_entries) - 1;
end_row = end_entry / hdr->man_dtable.cparam.width;
HDassert(sect->u.indirect.span_size > 0);
HDassert(sect->u.indirect.iblock_entries > 0);
HDassert(sect->u.indirect.dir_nrows > 0);
HDassert(sect->u.indirect.dir_rows);
HDassert(sect->u.indirect.dir_rows[(row_sect->u.row.row - start_row)] == row_sect);
if(row_end_entry == end_entry && start_row != end_row) {
*alloc_from_start = FALSE;
row_entry = row_end_entry;
}
else {
*alloc_from_start = TRUE;
row_entry = row_start_entry;
}
if(sect->u.indirect.parent) {
hbool_t is_first;
is_first = H5HF_sect_indirect_is_first(sect);
if(H5HF__sect_indirect_reduce(hdr, sect->u.indirect.parent, sect->u.indirect.par_entry) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce parent indirect section")
sect->u.indirect.parent = NULL;
sect->u.indirect.par_entry = 0;
if(!is_first)
if(H5HF__sect_indirect_first(hdr, sect) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for indirect section")
}
sect->u.indirect.span_size -= row_sect->sect_info.size;
if(sect->u.indirect.num_entries > 1) {
if(row_entry == start_entry) {
sect->sect_info.addr += hdr->man_dtable.row_block_size[sect->u.indirect.row];
sect->u.indirect.col++;
if(sect->u.indirect.col == hdr->man_dtable.cparam.width) {
HDassert(row_sect->u.row.num_entries == 1);
sect->u.indirect.row++;
sect->u.indirect.col = 0;
sect->u.indirect.dir_nrows--;
if(sect->u.indirect.dir_nrows > 0) {
HDassert(sect->u.indirect.dir_rows);
HDmemmove(§->u.indirect.dir_rows[0],
§->u.indirect.dir_rows[1],
sect->u.indirect.dir_nrows * sizeof(H5HF_free_section_t *));
HDassert(sect->u.indirect.dir_rows[0]);
if(row_sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW)
if(H5HF__sect_row_first(hdr, sect->u.indirect.dir_rows[0]) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for indirect section")
}
else {
HDassert(sect->u.indirect.indir_nents > 0);
HDassert(sect->u.indirect.indir_ents);
sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.dir_rows);
if(row_sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW)
if(H5HF__sect_indirect_first(hdr, sect->u.indirect.indir_ents[0]) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for child indirect section")
}
}
sect->u.indirect.num_entries--;
}
else if(row_entry == end_entry) {
unsigned new_end_row;
HDassert(sect->u.indirect.indir_nents == 0);
HDassert(sect->u.indirect.indir_ents == NULL);
sect->u.indirect.num_entries--;
new_end_row = ((start_entry + sect->u.indirect.num_entries) - 1) / hdr->man_dtable.cparam.width;
HDassert(new_end_row <= end_row);
if(new_end_row < end_row) {
HDassert(new_end_row == (end_row - 1));
sect->u.indirect.dir_nrows--;
}
}
else {
H5HF_indirect_t *iblock;
hsize_t iblock_off;
unsigned peer_nentries;
unsigned peer_dir_nrows;
unsigned new_start_row;
unsigned u;
HDassert(row_sect->u.row.col == 0);
HDassert(row_sect->u.row.row > 0);
HDassert(row_sect->u.row.row < hdr->man_dtable.max_direct_rows);
HDassert(row_sect->u.row.num_entries == hdr->man_dtable.cparam.width);
HDassert(row_sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
new_start_row = row_sect->u.row.row;
peer_nentries = row_entry - start_entry;
peer_dir_nrows = new_start_row - start_row;
if(sect->sect_info.state == H5FS_SECT_LIVE) {
iblock = sect->u.indirect.u.iblock;
iblock_off = sect->u.indirect.u.iblock->block_off;
}
else {
iblock = NULL;
iblock_off = sect->u.indirect.u.iblock_off;
}
if(NULL == (peer_sect = H5HF_sect_indirect_new(hdr, sect->sect_info.addr,
sect->sect_info.size, iblock, iblock_off, start_row, start_col,
peer_nentries)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section")
peer_sect->u.indirect.indir_nents = 0;
peer_sect->u.indirect.indir_ents = NULL;
peer_sect->u.indirect.dir_nrows = peer_dir_nrows;
if(NULL == (peer_sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *) * peer_dir_nrows)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "allocation failed for row section pointer array")
H5MM_memcpy(&peer_sect->u.indirect.dir_rows[0],
§->u.indirect.dir_rows[0],
(sizeof(H5HF_free_section_t *) * peer_dir_nrows));
HDmemmove(§->u.indirect.dir_rows[0],
§->u.indirect.dir_rows[peer_dir_nrows],
(sizeof(H5HF_free_section_t *) * (sect->u.indirect.dir_nrows - peer_dir_nrows)));
sect->u.indirect.dir_nrows -= peer_dir_nrows;
HDassert(row_sect == sect->u.indirect.dir_rows[0]);
for(u = 0; u < peer_dir_nrows; u++)
peer_sect->u.indirect.dir_rows[u]->u.row.under = peer_sect;
row_sect->sect_info.type = H5HF_FSPACE_SECT_FIRST_ROW;
peer_sect->u.indirect.rc = peer_dir_nrows;
sect->u.indirect.rc -= peer_dir_nrows;
peer_sect->u.indirect.iblock_entries = sect->u.indirect.iblock_entries;
peer_sect->u.indirect.span_size = row_sect->sect_info.addr - peer_sect->sect_info.addr;
sect->sect_info.addr = row_sect->sect_info.addr + hdr->man_dtable.row_block_size[new_start_row];
sect->u.indirect.span_size -= peer_sect->u.indirect.span_size;
sect->u.indirect.row = new_start_row;
sect->u.indirect.col = row_sect->u.row.col + 1;
sect->u.indirect.num_entries -= (peer_nentries + 1);
HDassert(sect->u.indirect.rc ==
(sect->u.indirect.indir_nents + sect->u.indirect.dir_nrows));
HDassert(peer_sect->u.indirect.rc ==
(peer_sect->u.indirect.indir_nents + peer_sect->u.indirect.dir_nrows));
peer_sect = NULL;
}
}
else {
sect->u.indirect.num_entries--;
sect->u.indirect.dir_nrows--;
HDassert(sect->u.indirect.dir_nrows == 0);
sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.dir_rows);
}
done:
if(peer_sect) {
HDassert(ret_value < 0);
if(H5HF_sect_indirect_free(peer_sect) < 0)
HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
}
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_indirect_reduce(H5HF_hdr_t *hdr, H5HF_free_section_t *sect,
unsigned child_entry)
{
unsigned start_entry;
unsigned start_row;
unsigned start_col;
unsigned end_entry;
unsigned end_row;
H5HF_free_section_t *peer_sect = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(hdr);
HDassert(sect);
HDassert(sect->u.indirect.span_size > 0);
HDassert(sect->u.indirect.iblock_entries > 0);
start_row = sect->u.indirect.row;
start_col = sect->u.indirect.col;
start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col;
end_entry = (start_entry + sect->u.indirect.num_entries) - 1;
end_row = end_entry / hdr->man_dtable.cparam.width;
if(sect->u.indirect.num_entries > 1) {
if(sect->u.indirect.parent) {
hbool_t is_first;
is_first = H5HF_sect_indirect_is_first(sect);
if(H5HF__sect_indirect_reduce(hdr, sect->u.indirect.parent, sect->u.indirect.par_entry) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce parent indirect section")
sect->u.indirect.parent = NULL;
sect->u.indirect.par_entry = 0;
if(!is_first)
if(H5HF__sect_indirect_first(hdr, sect) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for indirect section")
}
if(child_entry == start_entry) {
HDassert(sect->u.indirect.dir_nrows == 0);
HDassert(sect->u.indirect.dir_rows == NULL);
HDassert(sect->u.indirect.indir_nents > 0);
HDassert(sect->u.indirect.indir_ents);
sect->sect_info.addr += hdr->man_dtable.row_block_size[start_row];
sect->u.indirect.col++;
if(sect->u.indirect.col == hdr->man_dtable.cparam.width) {
sect->u.indirect.row++;
sect->u.indirect.col = 0;
}
sect->u.indirect.num_entries--;
sect->u.indirect.span_size -= hdr->man_dtable.row_block_size[start_row];
sect->u.indirect.indir_nents--;
HDmemmove(§->u.indirect.indir_ents[0],
§->u.indirect.indir_ents[1],
sect->u.indirect.indir_nents * sizeof(H5HF_free_section_t *));
HDassert(sect->u.indirect.indir_ents[0]);
if(H5HF__sect_indirect_first(hdr, sect->u.indirect.indir_ents[0]) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for child indirect section")
}
else if(child_entry == end_entry) {
HDassert(sect->u.indirect.indir_nents > 0);
HDassert(sect->u.indirect.indir_ents);
sect->u.indirect.num_entries--;
sect->u.indirect.span_size -= hdr->man_dtable.row_block_size[end_row];
sect->u.indirect.indir_nents--;
if(sect->u.indirect.indir_nents == 0)
sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.indir_ents);
}
else {
H5HF_indirect_t *iblock;
hsize_t iblock_off;
haddr_t peer_sect_addr;
unsigned peer_nentries;
unsigned peer_start_row;
unsigned peer_start_col;
unsigned child_row;
unsigned new_nentries;
unsigned u;
HDassert(sect->u.indirect.indir_nents > 0);
HDassert(sect->u.indirect.indir_ents);
peer_nentries = end_entry - child_entry;
peer_start_row = (child_entry + 1) / hdr->man_dtable.cparam.width;
peer_start_col = (child_entry + 1) % hdr->man_dtable.cparam.width;
child_row = child_entry / hdr->man_dtable.cparam.width;
new_nentries = sect->u.indirect.num_entries - (peer_nentries + 1);
HDassert(child_row >= hdr->man_dtable.max_direct_rows);
if(sect->sect_info.state == H5FS_SECT_LIVE) {
iblock = sect->u.indirect.u.iblock;
iblock_off = sect->u.indirect.u.iblock->block_off;
}
else {
iblock = NULL;
iblock_off = sect->u.indirect.u.iblock_off;
}
sect->u.indirect.num_entries = new_nentries;
sect->u.indirect.span_size = H5HF_dtable_span_size(&hdr->man_dtable,
sect->u.indirect.row, sect->u.indirect.col, new_nentries);
HDassert(sect->u.indirect.span_size > 0);
peer_sect_addr = sect->sect_info.addr;
peer_sect_addr += sect->u.indirect.span_size;
peer_sect_addr += hdr->man_dtable.row_block_size[child_row];
if(NULL == (peer_sect = H5HF_sect_indirect_new(hdr, peer_sect_addr,
sect->sect_info.size, iblock, iblock_off, peer_start_row,
peer_start_col, peer_nentries)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section")
peer_sect->u.indirect.dir_nrows = 0;
peer_sect->u.indirect.dir_rows = NULL;
peer_sect->u.indirect.indir_nents = peer_nentries;
if(NULL == (peer_sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *) * peer_nentries)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "allocation failed for indirect section pointer array")
H5MM_memcpy(&peer_sect->u.indirect.indir_ents[0],
§->u.indirect.indir_ents[sect->u.indirect.indir_nents - peer_nentries],
(sizeof(H5HF_free_section_t *) * peer_nentries));
sect->u.indirect.indir_nents -= (peer_nentries + 1);
if(sect->u.indirect.indir_nents == 0)
sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.indir_ents);
for(u = 0; u < peer_nentries; u++)
peer_sect->u.indirect.indir_ents[u]->u.indirect.parent = peer_sect;
peer_sect->u.indirect.rc = peer_nentries;
sect->u.indirect.rc -= peer_nentries;
peer_sect->u.indirect.iblock_entries = sect->u.indirect.iblock_entries;
HDassert((sect->u.indirect.rc - 1) ==
(sect->u.indirect.indir_nents + sect->u.indirect.dir_nrows));
HDassert(peer_sect->u.indirect.rc ==
(peer_sect->u.indirect.indir_nents + peer_sect->u.indirect.dir_nrows));
if(H5HF__sect_indirect_first(hdr, peer_sect->u.indirect.indir_ents[0]) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for peer indirect section")
peer_sect = NULL;
}
}
else {
sect->u.indirect.num_entries--;
sect->u.indirect.indir_nents--;
HDassert(sect->u.indirect.indir_nents == 0);
sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.indir_ents);
}
if(H5HF_sect_indirect_decr(sect) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't decrement section's ref. count ")
done:
if(peer_sect) {
HDassert(ret_value < 0);
if(H5HF_sect_indirect_free(peer_sect) < 0)
HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
}
FUNC_LEAVE_NOAPI(ret_value)
}
static hbool_t
H5HF_sect_indirect_is_first(H5HF_free_section_t *sect)
{
hbool_t ret_value = FALSE;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(sect);
if(sect->u.indirect.parent) {
if(sect->sect_info.addr == sect->u.indirect.parent->sect_info.addr)
ret_value = H5HF_sect_indirect_is_first(sect->u.indirect.parent);
}
else
ret_value = TRUE;
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_indirect_first(H5HF_hdr_t *hdr, H5HF_free_section_t *sect)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(hdr);
HDassert(sect);
if(sect->u.indirect.dir_nrows > 0) {
HDassert(sect->u.indirect.row == 0);
HDassert(sect->u.indirect.col == 0);
HDassert(sect->u.indirect.dir_rows);
HDassert(sect->u.indirect.dir_rows[0]);
if(H5HF__sect_row_first(hdr, sect->u.indirect.dir_rows[0]) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "can't set row section to be first row")
}
else {
HDassert(sect->u.indirect.indir_nents > 0);
HDassert(sect->u.indirect.indir_ents);
HDassert(sect->u.indirect.indir_ents[0]);
if(H5HF__sect_indirect_first(hdr, sect->u.indirect.indir_ents[0]) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "can't set child indirect section to be first row")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static H5HF_indirect_t *
H5HF_sect_indirect_get_iblock(H5HF_free_section_t *sect)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(sect);
HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_INDIRECT);
HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
FUNC_LEAVE_NOAPI(sect->u.indirect.u.iblock)
}
static herr_t
H5HF__sect_indirect_merge_row(H5HF_hdr_t *hdr, H5HF_free_section_t *row_sect1,
H5HF_free_section_t *row_sect2)
{
H5HF_free_section_t *sect1, *sect2;
unsigned start_entry1;
unsigned start_row1, start_col1;
unsigned end_entry1;
unsigned end_row1;
unsigned start_row2;
hbool_t merged_rows;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(hdr);
HDassert(row_sect1);
HDassert(row_sect1->u.row.under);
HDassert(row_sect2);
HDassert(row_sect2->u.row.under);
HDassert(row_sect2->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
sect1 = H5HF_sect_indirect_top(row_sect1->u.row.under);
HDassert(sect1);
sect2 = H5HF_sect_indirect_top(row_sect2->u.row.under);
HDassert(sect2);
HDassert(sect1->u.indirect.span_size > 0);
HDassert(sect2->u.indirect.span_size > 0);
start_row1 = sect1->u.indirect.row;
start_col1 = sect1->u.indirect.col;
start_entry1 = (start_row1 * hdr->man_dtable.cparam.width) + start_col1;
end_entry1 = (start_entry1 + sect1->u.indirect.num_entries) - 1;
end_row1 = end_entry1 / hdr->man_dtable.cparam.width;
start_row2 = sect2->u.indirect.row;
if(sect2->u.indirect.dir_nrows > 0) {
hsize_t sect1_iblock_off, sect2_iblock_off;
unsigned new_dir_nrows1;
unsigned src_row2;
unsigned nrows_moved2;
HDassert(sect1->u.indirect.dir_nrows > 0);
HDassert(sect1->u.indirect.dir_rows);
if(H5FS_SECT_LIVE == row_sect1->u.row.under->sect_info.state)
sect1_iblock_off = row_sect1->u.row.under->u.indirect.u.iblock->block_off;
else
sect1_iblock_off = row_sect1->u.row.under->u.indirect.u.iblock_off;
if(H5FS_SECT_LIVE == row_sect2->u.row.under->sect_info.state)
sect2_iblock_off = row_sect2->u.row.under->u.indirect.u.iblock->block_off;
else
sect2_iblock_off = row_sect2->u.row.under->u.indirect.u.iblock_off;
if(sect1_iblock_off == sect2_iblock_off && end_row1 == start_row2) {
H5HF_free_section_t *last_row_sect1;
if(row_sect1->u.row.row != end_row1)
last_row_sect1 = sect1->u.indirect.dir_rows[sect1->u.indirect.dir_nrows - 1];
else
last_row_sect1 = row_sect1;
HDassert(last_row_sect1);
HDassert(last_row_sect1->u.row.row == end_row1);
HDassert((last_row_sect1->u.row.col + last_row_sect1->u.row.num_entries) == row_sect2->u.row.col);
last_row_sect1->u.row.num_entries += row_sect2->u.row.num_entries;
src_row2 = 1;
nrows_moved2 = sect2->u.indirect.dir_nrows - 1;
new_dir_nrows1 = (sect1->u.indirect.dir_nrows + sect2->u.indirect.dir_nrows) - 1;
merged_rows = TRUE;
}
else {
src_row2 = 0;
nrows_moved2 = sect2->u.indirect.dir_nrows;
new_dir_nrows1 = sect1->u.indirect.dir_nrows + sect2->u.indirect.dir_nrows;
merged_rows = FALSE;
}
if(nrows_moved2 > 0) {
H5HF_free_section_t **new_dir_rows;
if(NULL == (new_dir_rows = (H5HF_free_section_t **)H5MM_realloc(sect1->u.indirect.dir_rows, sizeof(H5HF_free_section_t *) * new_dir_nrows1)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for row section pointer array")
sect1->u.indirect.dir_rows = new_dir_rows;
H5MM_memcpy(§1->u.indirect.dir_rows[sect1->u.indirect.dir_nrows],
§2->u.indirect.dir_rows[src_row2],
(sizeof(H5HF_free_section_t *) * nrows_moved2));
for(u = sect1->u.indirect.dir_nrows; u < new_dir_nrows1; u++)
sect1->u.indirect.dir_rows[u]->u.row.under = sect1;
sect1->u.indirect.rc += nrows_moved2;
sect2->u.indirect.rc -= nrows_moved2;
sect1->u.indirect.dir_nrows = new_dir_nrows1;
}
}
else
merged_rows = FALSE;
if(sect2->u.indirect.indir_nents > 0) {
unsigned new_indir_nents1;
HDassert(sect2->u.indirect.rc > 0);
HDassert(sect2->u.indirect.indir_nents > 0);
HDassert(sect2->u.indirect.indir_ents);
new_indir_nents1 = sect1->u.indirect.indir_nents + sect2->u.indirect.indir_nents;
if(sect1->u.indirect.indir_ents == NULL) {
sect1->u.indirect.indir_ents = sect2->u.indirect.indir_ents;
sect2->u.indirect.indir_ents = NULL;
}
else {
H5HF_free_section_t **new_indir_ents;
if(NULL == (new_indir_ents = (H5HF_free_section_t **)H5MM_realloc(sect1->u.indirect.indir_ents, sizeof(H5HF_free_section_t *) * new_indir_nents1)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for row section pointer array")
sect1->u.indirect.indir_ents = new_indir_ents;
H5MM_memcpy(§1->u.indirect.indir_ents[sect1->u.indirect.indir_nents],
§2->u.indirect.indir_ents[0],
(sizeof(H5HF_free_section_t *) * sect2->u.indirect.indir_nents));
}
for(u = sect1->u.indirect.indir_nents; u < new_indir_nents1; u++)
sect1->u.indirect.indir_ents[u]->u.indirect.parent = sect1;
sect1->u.indirect.rc += sect2->u.indirect.indir_nents;
sect2->u.indirect.rc -= sect2->u.indirect.indir_nents;
sect1->u.indirect.indir_nents = new_indir_nents1;
}
sect1->u.indirect.num_entries += sect2->u.indirect.num_entries;
sect1->u.indirect.span_size += sect2->u.indirect.span_size;
HDassert(sect1->u.indirect.rc ==
(sect1->u.indirect.indir_nents + sect1->u.indirect.dir_nrows));
if(merged_rows) {
HDassert(sect2->u.indirect.rc == 1);
if(H5HF__sect_row_free((H5FS_section_info_t *)row_sect2) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free row section")
}
else {
HDassert(sect2->u.indirect.rc == 0);
if(sect2->u.indirect.parent)
if(H5HF_sect_indirect_decr(sect2->u.indirect.parent) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't decrement ref. count on parent indirect section")
if(H5HF_sect_indirect_free(sect2) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
row_sect2->sect_info.type = H5HF_FSPACE_SECT_NORMAL_ROW;
if(H5HF__space_add(hdr, row_sect2, H5FS_ADD_SKIP_VALID) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't re-add second row section to free space")
}
if(sect1->u.indirect.iblock_entries == sect1->u.indirect.num_entries) {
HDassert(sect1->u.indirect.parent == NULL);
if(H5HF__sect_indirect_build_parent(hdr, sect1) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "can't create parent for full indirect section")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_indirect_build_parent(H5HF_hdr_t *hdr, H5HF_free_section_t *sect)
{
H5HF_indirect_t *par_iblock;
H5HF_free_section_t *par_sect = NULL;
hsize_t par_block_off;
unsigned par_row, par_col;
unsigned par_entry;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(hdr);
HDassert(sect);
HDassert(H5FS_SECT_LIVE == sect->sect_info.state);
HDassert(sect->u.indirect.span_size > 0);
HDassert(sect->u.indirect.iblock_entries > 0);
HDassert(sect->u.indirect.iblock_entries == sect->u.indirect.num_entries);
HDassert(sect->u.indirect.u.iblock);
HDassert(sect->u.indirect.parent == NULL);
if(sect->u.indirect.u.iblock->parent) {
par_entry = sect->u.indirect.u.iblock->par_entry;
par_iblock = sect->u.indirect.u.iblock->parent;
par_block_off = par_iblock->block_off;
}
else {
if(H5HF__man_iblock_parent_info(hdr, sect->sect_info.addr, &par_block_off, &par_entry) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get block entry")
par_iblock = NULL;
}
par_row = par_entry / hdr->man_dtable.cparam.width;
par_col = par_entry % hdr->man_dtable.cparam.width;
HDassert(par_row >= hdr->man_dtable.max_direct_rows);
if(NULL == (par_sect = H5HF_sect_indirect_new(hdr, sect->sect_info.addr,
sect->sect_info.size, par_iblock, par_block_off,
par_row, par_col, 1)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section")
par_sect->u.indirect.dir_nrows = 0;
par_sect->u.indirect.dir_rows = NULL;
par_sect->u.indirect.indir_nents = 1;
if(NULL == (par_sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *))))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for indirect section pointer array")
sect->u.indirect.parent = par_sect;
sect->u.indirect.par_entry = par_entry;
par_sect->u.indirect.indir_ents[0] = sect;
par_sect->u.indirect.rc = 1;
done:
if(ret_value < 0)
if(par_sect && H5HF_sect_indirect_free(par_sect) < 0)
HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF__sect_indirect_shrink(H5HF_hdr_t *hdr, H5HF_free_section_t *sect)
{
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(hdr);
HDassert(sect);
HDassert(sect->u.indirect.dir_nrows > 0 || sect->u.indirect.indir_nents > 0);
for(u = 0; u < sect->u.indirect.dir_nrows; u++) {
if(sect->u.indirect.dir_rows[u]->sect_info.type != H5HF_FSPACE_SECT_FIRST_ROW) {
HDassert(sect->u.indirect.dir_rows[u]->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
if(H5HF__space_remove(hdr, sect->u.indirect.dir_rows[u]) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove section from heap free space")
}
if(H5HF__sect_row_free_real(sect->u.indirect.dir_rows[u]) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free child section node")
}
for(u = 0; u < sect->u.indirect.indir_nents; u++)
if(H5HF__sect_indirect_shrink(hdr, sect->u.indirect.indir_ents[u]) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free child section node")
if(H5HF_sect_indirect_free(sect) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF_sect_indirect_serialize(H5HF_hdr_t *hdr, const H5HF_free_section_t *sect,
uint8_t *buf)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
HDassert(hdr);
HDassert(sect);
HDassert(buf);
if(sect->u.indirect.parent) {
if(sect->sect_info.addr == sect->u.indirect.parent->sect_info.addr)
if(H5HF_sect_indirect_serialize(hdr, sect->u.indirect.parent, buf) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTSERIALIZE, FAIL, "can't serialize indirect section's parent indirect section")
}
else {
if(sect->sect_info.state == H5FS_SECT_LIVE) {
HDassert(sect->u.indirect.u.iblock);
UINT64ENCODE_VAR(buf, sect->u.indirect.u.iblock->block_off, hdr->heap_off_size);
}
else
UINT64ENCODE_VAR(buf, sect->u.indirect.u.iblock_off, hdr->heap_off_size);
UINT16ENCODE(buf, sect->u.indirect.row);
UINT16ENCODE(buf, sect->u.indirect.col);
UINT16ENCODE(buf, sect->u.indirect.num_entries);
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static H5FS_section_info_t *
H5HF__sect_indirect_deserialize(H5HF_hdr_t *hdr, const uint8_t *buf,
haddr_t sect_addr, hsize_t sect_size, unsigned *des_flags)
{
H5HF_free_section_t *new_sect;
hsize_t iblock_off;
unsigned start_row;
unsigned start_col;
unsigned nentries;
unsigned start_entry;
unsigned end_entry;
unsigned end_row;
unsigned end_col;
H5FS_section_info_t *ret_value = NULL;
FUNC_ENTER_STATIC
HDassert(hdr);
HDassert(buf);
HDassert(H5F_addr_defined(sect_addr));
HDassert(sect_size);
UINT64DECODE_VAR(buf, iblock_off, hdr->heap_off_size);
UINT16DECODE(buf, start_row);
UINT16DECODE(buf, start_col);
UINT16DECODE(buf, nentries);
if(NULL == (new_sect = H5HF_sect_indirect_new(hdr, sect_addr, sect_size,
NULL, iblock_off, start_row, start_col, nentries)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't create indirect section")
start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col;
end_entry = (start_entry + nentries) - 1;
end_row = end_entry / hdr->man_dtable.cparam.width;
end_col = end_entry % hdr->man_dtable.cparam.width;
if(H5HF__sect_indirect_init_rows(hdr, new_sect, TRUE, NULL,
H5FS_ADD_DESERIALIZING, new_sect->u.indirect.row, new_sect->u.indirect.col,
end_row, end_col) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't initialize indirect section")
*des_flags |= H5FS_DESERIALIZE_NO_ADD;
ret_value = (H5FS_section_info_t *)new_sect;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF_sect_indirect_free(H5HF_free_section_t *sect)
{
H5HF_indirect_t *iblock = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
HDassert(sect);
sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.dir_rows);
sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.indir_ents);
if(sect->sect_info.state == H5FS_SECT_LIVE)
if(sect->u.indirect.u.iblock)
iblock = sect->u.indirect.u.iblock;
if(H5HF_sect_node_free(sect, iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5HF_sect_indirect_valid(const H5HF_hdr_t *hdr, const H5HF_free_section_t *sect)
{
unsigned start_row;
unsigned start_col;
unsigned start_entry;
unsigned end_row;
unsigned end_entry;
unsigned u;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(hdr);
HDassert(sect);
start_row = sect->u.indirect.row;
start_col = sect->u.indirect.col;
start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col;
end_entry = (start_entry + sect->u.indirect.num_entries) - 1;
end_row = end_entry / hdr->man_dtable.cparam.width;
if(sect->u.indirect.dir_nrows > 0) {
unsigned dir_nrows;
unsigned max_dir_row;
if(end_row >= hdr->man_dtable.max_direct_rows)
max_dir_row = hdr->man_dtable.max_direct_rows - 1;
else
max_dir_row = end_row;
dir_nrows = (max_dir_row - start_row) + 1;
HDassert(dir_nrows == sect->u.indirect.dir_nrows);
for(u = 0; u < dir_nrows; u++) {
const H5HF_free_section_t H5_ATTR_NDEBUG_UNUSED *tmp_row_sect;
tmp_row_sect = sect->u.indirect.dir_rows[u];
HDassert(tmp_row_sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW
|| tmp_row_sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
HDassert(tmp_row_sect->u.row.under == sect);
HDassert(tmp_row_sect->u.row.row == (start_row + u));
if(u > 0) {
const H5HF_free_section_t H5_ATTR_NDEBUG_UNUSED *tmp_row_sect2;
tmp_row_sect2 = sect->u.indirect.dir_rows[u - 1];
HDassert(tmp_row_sect2->u.row.row < tmp_row_sect->u.row.row);
HDassert(H5F_addr_lt(tmp_row_sect2->sect_info.addr, tmp_row_sect->sect_info.addr));
HDassert(tmp_row_sect2->sect_info.size <= tmp_row_sect->sect_info.size);
}
}
}
if(sect->u.indirect.indir_nents > 0) {
if(sect->sect_info.state == H5FS_SECT_LIVE) {
HDassert(sect->u.indirect.iblock_entries);
HDassert(sect->u.indirect.indir_nents <= sect->u.indirect.iblock_entries);
}
HDassert(sect->u.indirect.indir_ents);
for(u = 0; u < sect->u.indirect.indir_nents; u++) {
const H5HF_free_section_t *tmp_child_sect;
tmp_child_sect = sect->u.indirect.indir_ents[u];
HDassert(tmp_child_sect->sect_info.type == H5HF_FSPACE_SECT_INDIRECT);
HDassert(tmp_child_sect->u.indirect.parent == sect);
if(u > 0) {
const H5HF_free_section_t H5_ATTR_NDEBUG_UNUSED *tmp_child_sect2;
tmp_child_sect2 = sect->u.indirect.indir_ents[u - 1];
HDassert(H5F_addr_lt(tmp_child_sect2->sect_info.addr, tmp_child_sect->sect_info.addr));
}
H5HF_sect_indirect_valid(hdr, tmp_child_sect);
}
}
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5HF_sect_indirect_debug(const H5HF_free_section_t *sect,
FILE *stream, int indent, int fwidth)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(sect);
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"Row:",
sect->u.indirect.row);
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"Column:",
sect->u.indirect.col);
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"Number of entries:",
sect->u.indirect.num_entries);
FUNC_LEAVE_NOAPI(SUCCEED)
}