#include "H5Dmodule.h"
#include "H5private.h"
#include "H5Bprivate.h"
#include "H5Dpkg.h"
#include "H5Eprivate.h"
#include "H5Fprivate.h"
#include "H5FDprivate.h"
#include "H5FLprivate.h"
#include "H5Iprivate.h"
#include "H5MFprivate.h"
#include "H5MMprivate.h"
#include "H5Oprivate.h"
#include "H5Sprivate.h"
#include "H5VMprivate.h"
typedef struct H5D_btree_key_t {
hsize_t scaled[H5O_LAYOUT_NDIMS];
uint32_t nbytes;
unsigned filter_mask;
} H5D_btree_key_t;
typedef struct H5D_btree_it_ud_t {
H5D_chunk_common_ud_t common;
H5D_chunk_cb_func_t cb;
void *udata;
} H5D_btree_it_ud_t;
typedef struct H5D_btree_dbg_t {
H5D_chunk_common_ud_t common;
unsigned ndims;
} H5D_btree_dbg_t;
static herr_t H5D__btree_shared_free(void *_shared);
static herr_t H5D__btree_shared_create(const H5F_t *f, H5O_storage_chunk_t *store,
const H5O_layout_chunk_t *layout);
static int H5D__btree_idx_iterate_cb(H5F_t *f, const void *left_key,
haddr_t addr, const void *right_key, void *_udata);
static H5UC_t *H5D__btree_get_shared(const H5F_t *f, const void *_udata);
static herr_t H5D__btree_new_node(H5F_t *f, H5B_ins_t, void *_lt_key,
void *_udata, void *_rt_key, haddr_t *addr_p );
static int H5D__btree_cmp2(void *_lt_key, void *_udata, void *_rt_key);
static int H5D__btree_cmp3(void *_lt_key, void *_udata, void *_rt_key);
static htri_t H5D__btree_found(H5F_t *f, haddr_t addr,
const void *_lt_key, void *_udata);
static H5B_ins_t H5D__btree_insert(H5F_t *f, haddr_t addr,
void *_lt_key, hbool_t *lt_key_changed, void *_md_key, void *_udata,
void *_rt_key, hbool_t *rt_key_changed, haddr_t *new_node);
static H5B_ins_t H5D__btree_remove( H5F_t *f, haddr_t addr, void *_lt_key,
hbool_t *lt_key_changed, void *_udata, void *_rt_key, hbool_t *rt_key_changed);
static herr_t H5D__btree_decode_key(const H5B_shared_t *shared, const uint8_t *raw,
void *_key);
static herr_t H5D__btree_encode_key(const H5B_shared_t *shared, uint8_t *raw,
const void *_key);
static herr_t H5D__btree_debug_key(FILE *stream, int indent, int fwidth,
const void *key, const void *udata);
static herr_t H5D__btree_idx_init(const H5D_chk_idx_info_t *idx_info,
const H5S_t *space, haddr_t dset_ohdr_addr);
static herr_t H5D__btree_idx_create(const H5D_chk_idx_info_t *idx_info);
static hbool_t H5D__btree_idx_is_space_alloc(const H5O_storage_chunk_t *storage);
static herr_t H5D__btree_idx_insert(const H5D_chk_idx_info_t *idx_info,
H5D_chunk_ud_t *udata, const H5D_t *dset);
static herr_t H5D__btree_idx_get_addr(const H5D_chk_idx_info_t *idx_info,
H5D_chunk_ud_t *udata);
static int H5D__btree_idx_iterate(const H5D_chk_idx_info_t *idx_info,
H5D_chunk_cb_func_t chunk_cb, void *chunk_udata);
static herr_t H5D__btree_idx_remove(const H5D_chk_idx_info_t *idx_info,
H5D_chunk_common_ud_t *udata);
static herr_t H5D__btree_idx_delete(const H5D_chk_idx_info_t *idx_info);
static herr_t H5D__btree_idx_copy_setup(const H5D_chk_idx_info_t *idx_info_src,
const H5D_chk_idx_info_t *idx_info_dst);
static herr_t H5D__btree_idx_copy_shutdown(H5O_storage_chunk_t *storage_src,
H5O_storage_chunk_t *storage_dst);
static herr_t H5D__btree_idx_size(const H5D_chk_idx_info_t *idx_info,
hsize_t *size);
static herr_t H5D__btree_idx_reset(H5O_storage_chunk_t *storage, hbool_t reset_addr);
static herr_t H5D__btree_idx_dump(const H5O_storage_chunk_t *storage,
FILE *stream);
static herr_t H5D__btree_idx_dest(const H5D_chk_idx_info_t *idx_info);
const H5D_chunk_ops_t H5D_COPS_BTREE[1] = {{
FALSE,
H5D__btree_idx_init,
H5D__btree_idx_create,
H5D__btree_idx_is_space_alloc,
H5D__btree_idx_insert,
H5D__btree_idx_get_addr,
NULL,
H5D__btree_idx_iterate,
H5D__btree_idx_remove,
H5D__btree_idx_delete,
H5D__btree_idx_copy_setup,
H5D__btree_idx_copy_shutdown,
H5D__btree_idx_size,
H5D__btree_idx_reset,
H5D__btree_idx_dump,
H5D__btree_idx_dest
}};
H5B_class_t H5B_BTREE[1] = {{
H5B_CHUNK_ID,
sizeof(H5D_btree_key_t),
H5D__btree_get_shared,
H5D__btree_new_node,
H5D__btree_cmp2,
H5D__btree_cmp3,
H5D__btree_found,
H5D__btree_insert,
FALSE,
FALSE,
H5B_LEFT,
H5D__btree_remove,
H5D__btree_decode_key,
H5D__btree_encode_key,
H5D__btree_debug_key
}};
H5FL_DEFINE_STATIC(H5O_layout_chunk_t);
static H5UC_t *
H5D__btree_get_shared(const H5F_t H5_ATTR_UNUSED *f, const void *_udata)
{
const H5D_chunk_common_ud_t *udata = (const H5D_chunk_common_ud_t *) _udata;
FUNC_ENTER_STATIC_NOERR
HDassert(udata);
HDassert(udata->storage);
HDassert(udata->storage->idx_type == H5D_CHUNK_IDX_BTREE);
HDassert(udata->storage->u.btree.shared);
FUNC_LEAVE_NOAPI(udata->storage->u.btree.shared)
}
static herr_t
H5D__btree_new_node(H5F_t H5_ATTR_NDEBUG_UNUSED *f, H5B_ins_t op, void *_lt_key, void *_udata,
void *_rt_key, haddr_t *addr_p)
{
H5D_btree_key_t *lt_key = (H5D_btree_key_t *) _lt_key;
H5D_btree_key_t *rt_key = (H5D_btree_key_t *) _rt_key;
H5D_chunk_ud_t *udata = (H5D_chunk_ud_t *) _udata;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC_NOERR
HDassert(f);
HDassert(lt_key);
HDassert(rt_key);
HDassert(udata);
HDassert(udata->common.layout->ndims > 0 && udata->common.layout->ndims < H5O_LAYOUT_NDIMS);
HDassert(addr_p);
HDassert(H5F_addr_defined(udata->chunk_block.offset));
HDassert(udata->chunk_block.length > 0);
*addr_p = udata->chunk_block.offset;
H5_CHECKED_ASSIGN(lt_key->nbytes, uint32_t, udata->chunk_block.length, hsize_t);
lt_key->filter_mask = udata->filter_mask;
for(u = 0; u < udata->common.layout->ndims; u++)
lt_key->scaled[u] = udata->common.scaled[u];
if(H5B_INS_LEFT != op) {
rt_key->nbytes = 0;
rt_key->filter_mask = 0;
for(u = 0; u < udata->common.layout->ndims; u++) {
HDassert(udata->common.scaled[u] + 1 > udata->common.scaled[u]);
rt_key->scaled[u] = udata->common.scaled[u] + 1;
}
}
FUNC_LEAVE_NOAPI(ret_value)
}
static int
H5D__btree_cmp2(void *_lt_key, void *_udata, void *_rt_key)
{
H5D_btree_key_t *lt_key = (H5D_btree_key_t *) _lt_key;
H5D_btree_key_t *rt_key = (H5D_btree_key_t *) _rt_key;
H5D_chunk_common_ud_t *udata = (H5D_chunk_common_ud_t *) _udata;
int ret_value = -1;
FUNC_ENTER_STATIC_NOERR
HDassert(lt_key);
HDassert(rt_key);
HDassert(udata);
HDassert(udata->layout->ndims > 0 && udata->layout->ndims <= H5O_LAYOUT_NDIMS);
ret_value = H5VM_vector_cmp_u(udata->layout->ndims, lt_key->scaled, rt_key->scaled);
FUNC_LEAVE_NOAPI(ret_value)
}
static int
H5D__btree_cmp3(void *_lt_key, void *_udata, void *_rt_key)
{
H5D_btree_key_t *lt_key = (H5D_btree_key_t *) _lt_key;
H5D_btree_key_t *rt_key = (H5D_btree_key_t *) _rt_key;
H5D_chunk_common_ud_t *udata = (H5D_chunk_common_ud_t *) _udata;
int ret_value = 0;
FUNC_ENTER_STATIC_NOERR
HDassert(lt_key);
HDassert(rt_key);
HDassert(udata);
HDassert(udata->layout->ndims > 0 && udata->layout->ndims <= H5O_LAYOUT_NDIMS);
if(udata->layout->ndims == 2) {
if(udata->scaled[0] > rt_key->scaled[0])
ret_value = 1;
else if(udata->scaled[0] == rt_key->scaled[0] &&
udata->scaled[1] >= rt_key->scaled[1])
ret_value = 1;
else if(udata->scaled[0] < lt_key->scaled[0])
ret_value = (-1);
}
else {
if(H5VM_vector_ge_u(udata->layout->ndims, udata->scaled, rt_key->scaled))
ret_value = 1;
else if(H5VM_vector_lt_u(udata->layout->ndims, udata->scaled, lt_key->scaled))
ret_value = (-1);
}
FUNC_LEAVE_NOAPI(ret_value)
}
static htri_t
H5D__btree_found(H5F_t H5_ATTR_UNUSED *f, haddr_t addr, const void *_lt_key,
void *_udata)
{
H5D_chunk_ud_t *udata = (H5D_chunk_ud_t *) _udata;
const H5D_btree_key_t *lt_key = (const H5D_btree_key_t *) _lt_key;
unsigned u;
htri_t ret_value = TRUE;
FUNC_ENTER_STATIC_NOERR
HDassert(f);
HDassert(H5F_addr_defined(addr));
HDassert(udata);
HDassert(lt_key);
for(u = 0; u < udata->common.layout->ndims; u++)
if(udata->common.scaled[u] >= (lt_key->scaled[u] + 1))
HGOTO_DONE(FALSE)
HDassert(lt_key->nbytes > 0);
udata->chunk_block.offset = addr;
udata->chunk_block.length = lt_key->nbytes;
udata->filter_mask = lt_key->filter_mask;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static hbool_t
H5D__chunk_disjoint(unsigned n, const hsize_t *scaled1, const hsize_t *scaled2)
{
unsigned u;
hbool_t ret_value = FALSE;
FUNC_ENTER_STATIC_NOERR
HDassert(n);
HDassert(scaled1);
HDassert(scaled2);
for(u = 0; u < n; u++)
if((scaled1[u] + 1) <= scaled2[u] || (scaled2[u] + 1) <= scaled1[u])
HGOTO_DONE(TRUE)
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static H5B_ins_t
H5D__btree_insert(H5F_t H5_ATTR_NDEBUG_UNUSED *f, haddr_t H5_ATTR_NDEBUG_UNUSED addr, void *_lt_key, hbool_t *lt_key_changed,
void *_md_key, void *_udata, void *_rt_key, hbool_t H5_ATTR_UNUSED *rt_key_changed,
haddr_t *new_node_p)
{
H5D_btree_key_t *lt_key = (H5D_btree_key_t *) _lt_key;
H5D_btree_key_t *md_key = (H5D_btree_key_t *) _md_key;
H5D_btree_key_t *rt_key = (H5D_btree_key_t *) _rt_key;
H5D_chunk_ud_t *udata = (H5D_chunk_ud_t *) _udata;
int cmp;
unsigned u;
H5B_ins_t ret_value = H5B_INS_ERROR;
FUNC_ENTER_STATIC
HDassert(f);
HDassert(H5F_addr_defined(addr));
HDassert(lt_key);
HDassert(lt_key_changed);
HDassert(md_key);
HDassert(udata);
HDassert(rt_key);
HDassert(new_node_p);
cmp = H5D__btree_cmp3(lt_key, udata, rt_key);
HDassert(cmp <= 0);
if(cmp < 0) {
HGOTO_ERROR(H5E_STORAGE, H5E_UNSUPPORTED, H5B_INS_ERROR, "internal error")
} else if(H5VM_vector_eq_u(udata->common.layout->ndims,
udata->common.scaled, lt_key->scaled) && lt_key->nbytes > 0) {
if(lt_key->nbytes != udata->chunk_block.length) {
HDassert(H5F_addr_defined(udata->chunk_block.offset));
*new_node_p = udata->chunk_block.offset;
H5_CHECKED_ASSIGN(lt_key->nbytes, uint32_t, udata->chunk_block.length, hsize_t);
lt_key->filter_mask = udata->filter_mask;
*lt_key_changed = TRUE;
ret_value = H5B_INS_CHANGE;
} else {
HDassert(H5F_addr_defined(udata->chunk_block.offset));
ret_value = H5B_INS_NOOP;
}
} else if (H5D__chunk_disjoint(udata->common.layout->ndims,
lt_key->scaled, udata->common.scaled)) {
HDassert(H5D__chunk_disjoint(udata->common.layout->ndims,
rt_key->scaled, udata->common.scaled));
H5_CHECKED_ASSIGN(md_key->nbytes, uint32_t, udata->chunk_block.length, hsize_t);
md_key->filter_mask = udata->filter_mask;
for(u = 0; u < udata->common.layout->ndims; u++)
md_key->scaled[u] = udata->common.scaled[u];
HDassert(H5F_addr_defined(udata->chunk_block.offset));
*new_node_p = udata->chunk_block.offset;
ret_value = H5B_INS_RIGHT;
} else {
HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, H5B_INS_ERROR, "internal error")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static H5B_ins_t
H5D__btree_remove(H5F_t *f, haddr_t addr, void *_lt_key ,
hbool_t *lt_key_changed ,
void H5_ATTR_UNUSED * _udata ,
void H5_ATTR_UNUSED * _rt_key ,
hbool_t *rt_key_changed )
{
H5D_btree_key_t *lt_key = (H5D_btree_key_t *)_lt_key;
H5B_ins_t ret_value=H5B_INS_REMOVE;
FUNC_ENTER_STATIC
H5_CHECK_OVERFLOW(lt_key->nbytes, uint32_t, hsize_t);
if(H5MF_xfree(f, H5FD_MEM_DRAW, addr, (hsize_t)lt_key->nbytes) < 0)
HGOTO_ERROR(H5E_STORAGE, H5E_CANTFREE, H5B_INS_ERROR, "unable to free chunk")
*lt_key_changed = FALSE;
*rt_key_changed = FALSE;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__btree_decode_key(const H5B_shared_t *shared, const uint8_t *raw, void *_key)
{
const H5O_layout_chunk_t *layout;
H5D_btree_key_t *key = (H5D_btree_key_t *) _key;
hsize_t tmp_offset;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(shared);
HDassert(raw);
HDassert(key);
layout = (const H5O_layout_chunk_t *)shared->udata;
HDassert(layout);
HDassert(layout->ndims > 0 && layout->ndims <= H5O_LAYOUT_NDIMS);
UINT32DECODE(raw, key->nbytes);
UINT32DECODE(raw, key->filter_mask);
for(u = 0; u < layout->ndims; u++) {
if(layout->dim[u] == 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "chunk size must be > 0, dim = %u ", u)
UINT64DECODE(raw, tmp_offset);
HDassert(0 == (tmp_offset % layout->dim[u]));
key->scaled[u] = tmp_offset / layout->dim[u];
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__btree_encode_key(const H5B_shared_t *shared, uint8_t *raw, const void *_key)
{
const H5O_layout_chunk_t *layout;
const H5D_btree_key_t *key = (const H5D_btree_key_t *)_key;
hsize_t tmp_offset;
unsigned u;
FUNC_ENTER_STATIC_NOERR
HDassert(shared);
HDassert(raw);
HDassert(key);
layout = (const H5O_layout_chunk_t *)shared->udata;
HDassert(layout);
HDassert(layout->ndims > 0 && layout->ndims <= H5O_LAYOUT_NDIMS);
UINT32ENCODE(raw, key->nbytes);
UINT32ENCODE(raw, key->filter_mask);
for(u = 0; u < layout->ndims; u++) {
tmp_offset = key->scaled[u] * layout->dim[u];
UINT64ENCODE(raw, tmp_offset);
}
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__btree_debug_key(FILE *stream, int indent, int fwidth, const void *_key,
const void *_udata)
{
const H5D_btree_key_t *key = (const H5D_btree_key_t *)_key;
const H5D_btree_dbg_t *udata = (const H5D_btree_dbg_t *)_udata;
unsigned u;
FUNC_ENTER_STATIC_NOERR
HDassert(key);
HDfprintf(stream, "%*s%-*s %u bytes\n", indent, "", fwidth, "Chunk size:", (unsigned)key->nbytes);
HDfprintf(stream, "%*s%-*s 0x%08x\n", indent, "", fwidth, "Filter mask:", key->filter_mask);
HDfprintf(stream, "%*s%-*s {", indent, "", fwidth, "Logical offset:");
for(u = 0; u < udata->ndims; u++)
HDfprintf(stream, "%s%Hd", u?", ":"", (key->scaled[u] * udata->common.layout->dim[u]));
HDfputs("}\n", stream);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__btree_shared_free(void *_shared)
{
H5B_shared_t *shared = (H5B_shared_t *)_shared;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
shared->udata = H5FL_FREE(H5O_layout_chunk_t, shared->udata);
if(H5B_shared_free(shared) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "can't free shared B-tree info")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__btree_shared_create(const H5F_t *f, H5O_storage_chunk_t *store,
const H5O_layout_chunk_t *layout)
{
H5B_shared_t *shared;
H5O_layout_chunk_t *my_layout = NULL;
size_t sizeof_rkey;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
sizeof_rkey = 4 +
4 +
layout->ndims * 8;
if(NULL == (shared = H5B_shared_new(f, H5B_BTREE, sizeof_rkey)))
HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "memory allocation failed for shared B-tree info")
if(NULL == (my_layout = H5FL_MALLOC(H5O_layout_chunk_t)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate chunk layout")
H5MM_memcpy(my_layout, layout, sizeof(H5O_layout_chunk_t));
shared->udata = my_layout;
if(NULL == (store->u.btree.shared = H5UC_create(shared, H5D__btree_shared_free)))
HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for shared B-tree info")
done:
if(ret_value < 0)
if(my_layout)
my_layout = H5FL_FREE(H5O_layout_chunk_t, my_layout);
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__btree_idx_init(const H5D_chk_idx_info_t *idx_info, const H5S_t H5_ATTR_UNUSED *space,
haddr_t dset_ohdr_addr)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(idx_info);
HDassert(idx_info->f);
HDassert(idx_info->pline);
HDassert(idx_info->layout);
HDassert(idx_info->storage);
HDassert(H5F_addr_defined(dset_ohdr_addr));
idx_info->storage->u.btree.dset_ohdr_addr = dset_ohdr_addr;
if(H5D__btree_shared_create(idx_info->f, idx_info->storage, idx_info->layout) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create wrapper for shared B-tree info")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__btree_idx_create(const H5D_chk_idx_info_t *idx_info)
{
H5D_chunk_common_ud_t udata;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(idx_info);
HDassert(idx_info->f);
HDassert(idx_info->pline);
HDassert(idx_info->layout);
HDassert(idx_info->storage);
HDassert(!H5F_addr_defined(idx_info->storage->idx_addr));
udata.layout = idx_info->layout;
udata.storage = idx_info->storage;
if(H5B_create(idx_info->f, H5B_BTREE, &udata, &(idx_info->storage->idx_addr)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't create B-tree")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static hbool_t
H5D__btree_idx_is_space_alloc(const H5O_storage_chunk_t *storage)
{
FUNC_ENTER_STATIC_NOERR
HDassert(storage);
FUNC_LEAVE_NOAPI((hbool_t)H5F_addr_defined(storage->idx_addr))
}
static herr_t
H5D__btree_idx_insert(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata,
const H5D_t H5_ATTR_UNUSED *dset)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(idx_info);
HDassert(idx_info->f);
HDassert(idx_info->pline);
HDassert(idx_info->layout);
HDassert(idx_info->storage);
HDassert(H5F_addr_defined(idx_info->storage->idx_addr));
HDassert(udata);
if(H5B_insert(idx_info->f, H5B_BTREE, idx_info->storage->idx_addr, udata) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to allocate chunk")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__btree_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(idx_info);
HDassert(idx_info->f);
HDassert(idx_info->pline);
HDassert(idx_info->layout);
HDassert(idx_info->layout->ndims > 0);
HDassert(idx_info->storage);
HDassert(H5F_addr_defined(idx_info->storage->idx_addr));
HDassert(udata);
if(H5B_find(idx_info->f, H5B_BTREE, idx_info->storage->idx_addr, udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk info")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static int
H5D__btree_idx_iterate_cb(H5F_t H5_ATTR_UNUSED *f, const void *_lt_key,
haddr_t addr, const void H5_ATTR_UNUSED *_rt_key, void *_udata)
{
H5D_btree_it_ud_t *udata = (H5D_btree_it_ud_t *)_udata;
const H5D_btree_key_t *lt_key = (const H5D_btree_key_t *)_lt_key;
H5D_chunk_rec_t chunk_rec;
int ret_value = -1;
FUNC_ENTER_STATIC_NOERR
HDcompile_assert(offsetof(H5D_chunk_rec_t, nbytes) == offsetof(H5D_btree_key_t, nbytes));
HDcompile_assert(sizeof(chunk_rec.nbytes) == sizeof(lt_key->nbytes));
HDcompile_assert(offsetof(H5D_chunk_rec_t, scaled) == offsetof(H5D_btree_key_t, scaled));
HDcompile_assert(sizeof(chunk_rec.scaled) == sizeof(lt_key->scaled));
HDcompile_assert(offsetof(H5D_chunk_rec_t, filter_mask) == offsetof(H5D_btree_key_t, filter_mask));
HDcompile_assert(sizeof(chunk_rec.filter_mask) == sizeof(lt_key->filter_mask));
H5MM_memcpy(&chunk_rec, lt_key, sizeof(*lt_key));
chunk_rec.chunk_addr = addr;
if((ret_value = (udata->cb)(&chunk_rec, udata->udata)) < 0)
HERROR(H5E_DATASET, H5E_CALLBACK, "failure in generic chunk iterator callback");
FUNC_LEAVE_NOAPI(ret_value)
}
static int
H5D__btree_idx_iterate(const H5D_chk_idx_info_t *idx_info,
H5D_chunk_cb_func_t chunk_cb, void *chunk_udata)
{
H5D_btree_it_ud_t udata;
int ret_value = -1;
FUNC_ENTER_STATIC_NOERR
HDassert(idx_info);
HDassert(idx_info->f);
HDassert(idx_info->pline);
HDassert(idx_info->layout);
HDassert(idx_info->storage);
HDassert(H5F_addr_defined(idx_info->storage->idx_addr));
HDassert(chunk_cb);
HDassert(chunk_udata);
HDmemset(&udata, 0, sizeof udata);
udata.common.layout = idx_info->layout;
udata.common.storage = idx_info->storage;
udata.cb = chunk_cb;
udata.udata = chunk_udata;
if((ret_value = H5B_iterate(idx_info->f, H5B_BTREE, idx_info->storage->idx_addr, H5D__btree_idx_iterate_cb, &udata)) < 0)
HERROR(H5E_DATASET, H5E_BADITER, "unable to iterate over chunk B-tree");
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__btree_idx_remove(const H5D_chk_idx_info_t *idx_info, H5D_chunk_common_ud_t *udata)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(idx_info);
HDassert(idx_info->f);
HDassert(idx_info->pline);
HDassert(idx_info->layout);
HDassert(idx_info->storage);
HDassert(H5F_addr_defined(idx_info->storage->idx_addr));
HDassert(udata);
if(H5B_remove(idx_info->f, H5B_BTREE, idx_info->storage->idx_addr, udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTDELETE, FAIL, "unable to remove chunk entry")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__btree_idx_delete(const H5D_chk_idx_info_t *idx_info)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(idx_info);
HDassert(idx_info->f);
HDassert(idx_info->pline);
HDassert(idx_info->layout);
HDassert(idx_info->storage);
if(H5F_addr_defined(idx_info->storage->idx_addr)) {
H5O_storage_chunk_t tmp_storage;
H5D_chunk_common_ud_t udata;
tmp_storage = *idx_info->storage;
if(H5D__btree_shared_create(idx_info->f, &tmp_storage, idx_info->layout) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't create wrapper for shared B-tree info")
HDmemset(&udata, 0, sizeof udata);
udata.layout = idx_info->layout;
udata.storage = &tmp_storage;
if(H5B_delete(idx_info->f, H5B_BTREE, tmp_storage.idx_addr, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTDELETE, FAIL, "unable to delete chunk B-tree")
if(NULL == tmp_storage.u.btree.shared)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "ref-counted page nil")
if(H5UC_DEC(tmp_storage.u.btree.shared) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to decrement ref-counted page")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__btree_idx_copy_setup(const H5D_chk_idx_info_t *idx_info_src,
const H5D_chk_idx_info_t *idx_info_dst)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC_TAG(H5AC__COPIED_TAG)
HDassert(idx_info_src);
HDassert(idx_info_src->f);
HDassert(idx_info_src->pline);
HDassert(idx_info_src->layout);
HDassert(idx_info_src->storage);
HDassert(idx_info_dst);
HDassert(idx_info_dst->f);
HDassert(idx_info_dst->pline);
HDassert(idx_info_dst->layout);
HDassert(idx_info_dst->storage);
HDassert(!H5F_addr_defined(idx_info_dst->storage->idx_addr));
if(H5D__btree_shared_create(idx_info_src->f, idx_info_src->storage, idx_info_src->layout) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create wrapper for source shared B-tree info")
if(H5D__btree_shared_create(idx_info_dst->f, idx_info_dst->storage, idx_info_dst->layout) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create wrapper for destination shared B-tree info")
if(H5D__btree_idx_create(idx_info_dst) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to initialize chunked storage")
HDassert(H5F_addr_defined(idx_info_dst->storage->idx_addr));
done:
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
static herr_t
H5D__btree_idx_copy_shutdown(H5O_storage_chunk_t *storage_src,
H5O_storage_chunk_t *storage_dst)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(storage_src);
HDassert(storage_dst);
if(H5UC_DEC(storage_src->u.btree.shared) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to decrement ref-counted page")
if(H5UC_DEC(storage_dst->u.btree.shared) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to decrement ref-counted page")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__btree_idx_size(const H5D_chk_idx_info_t *idx_info, hsize_t *index_size)
{
H5D_chunk_common_ud_t udata;
H5B_info_t bt_info;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(idx_info);
HDassert(idx_info->f);
HDassert(idx_info->pline);
HDassert(idx_info->layout);
HDassert(idx_info->storage);
HDassert(index_size);
HDmemset(&udata, 0, sizeof udata);
udata.layout = idx_info->layout;
udata.storage = idx_info->storage;
if(H5B_get_info(idx_info->f, H5B_BTREE, idx_info->storage->idx_addr, &bt_info, NULL, &udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to iterate over chunk B-tree")
*index_size = bt_info.size;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__btree_idx_reset(H5O_storage_chunk_t *storage, hbool_t reset_addr)
{
FUNC_ENTER_STATIC_NOERR
HDassert(storage);
if(reset_addr)
storage->idx_addr = HADDR_UNDEF;
storage->u.btree.shared = NULL;
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__btree_idx_dump(const H5O_storage_chunk_t *storage, FILE *stream)
{
FUNC_ENTER_STATIC_NOERR
HDassert(storage);
HDassert(stream);
HDfprintf(stream, " Address: %a\n", storage->idx_addr);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__btree_idx_dest(const H5D_chk_idx_info_t *idx_info)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(idx_info);
HDassert(idx_info->f);
HDassert(idx_info->pline);
HDassert(idx_info->layout);
HDassert(idx_info->storage);
if(NULL == idx_info->storage->u.btree.shared)
HGOTO_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "ref-counted page nil")
if(H5UC_DEC(idx_info->storage->u.btree.shared) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "unable to decrement ref-counted page")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5D_btree_debug(H5F_t *f, haddr_t addr, FILE * stream, int indent,
int fwidth, unsigned ndims, const uint32_t *dim)
{
H5D_btree_dbg_t udata;
H5O_storage_chunk_t storage;
H5O_layout_chunk_t layout;
hbool_t shared_init = FALSE;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDmemset(&storage, 0, sizeof(storage));
storage.idx_type = H5D_CHUNK_IDX_BTREE;
HDmemset(&layout, 0, sizeof(layout));
layout.ndims = ndims;
for(u = 0; u < ndims; u++)
layout.dim[u] = dim[u];
if(H5D__btree_shared_create(f, &storage, &layout) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create wrapper for shared B-tree info")
shared_init = TRUE;
udata.common.layout = &layout;
udata.common.storage = &storage;
udata.common.scaled = NULL;
udata.ndims = ndims;
(void)H5B_debug(f, addr, stream, indent, fwidth, H5B_BTREE, &udata);
done:
if(shared_init) {
if(NULL == storage.u.btree.shared)
HDONE_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "ref-counted shared info nil")
else
if(H5UC_DEC(storage.u.btree.shared) < 0)
HDONE_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "unable to decrement ref-counted shared info")
}
FUNC_LEAVE_NOAPI(ret_value)
}