#include "H5Dmodule.h"
#include "H5private.h"
#include "H5Dpkg.h"
#include "H5FLprivate.h"
#include "H5MFprivate.h"
#include "H5MMprivate.h"
#include "H5VMprivate.h"
typedef struct H5D_bt2_ctx_ud_t {
const H5F_t *f;
uint32_t chunk_size;
unsigned ndims;
uint32_t *dim;
} H5D_bt2_ctx_ud_t;
typedef struct H5D_bt2_ctx_t {
uint32_t chunk_size;
size_t sizeof_addr;
size_t chunk_size_len;
unsigned ndims;
uint32_t *dim;
} H5D_bt2_ctx_t;
typedef struct H5D_bt2_it_ud_t {
H5D_chunk_cb_func_t cb;
void *udata;
} H5D_bt2_it_ud_t;
typedef struct H5D_bt2_ud_t {
H5D_chunk_rec_t rec;
unsigned ndims;
} H5D_bt2_ud_t;
static void *H5D__bt2_crt_context(void *udata);
static herr_t H5D__bt2_dst_context(void *ctx);
static herr_t H5D__bt2_store(void *native, const void *udata);
static herr_t H5D__bt2_compare(const void *rec1, const void *rec2, int *result);
static herr_t H5D__bt2_unfilt_encode(uint8_t *raw, const void *native, void *ctx);
static herr_t H5D__bt2_unfilt_decode(const uint8_t *raw, void *native, void *ctx);
static herr_t H5D__bt2_unfilt_debug(FILE *stream, int indent, int fwidth,
const void *record, const void *u_ctx);
static herr_t H5D__bt2_filt_encode(uint8_t *raw, const void *native, void *ctx);
static herr_t H5D__bt2_filt_decode(const uint8_t *raw, void *native, void *ctx);
static herr_t H5D__bt2_filt_debug(FILE *stream, int indent, int fwidth,
const void *record, const void *u_ctx);
static herr_t H5D__bt2_idx_open(const H5D_chk_idx_info_t *idx_info);
static herr_t H5D__btree2_idx_depend(const H5D_chk_idx_info_t *idx_info);
static int H5D__bt2_idx_iterate_cb(const void *_record, void *_udata);
static herr_t H5D__bt2_found_cb(const void *nrecord, void *op_data);
static herr_t H5D__bt2_remove_cb(const void *nrecord, void *_udata);
static herr_t H5D__bt2_mod_cb(void *_record, void *_op_data, hbool_t *changed);
static herr_t H5D__bt2_idx_init(const H5D_chk_idx_info_t *idx_info,
const H5S_t *space, haddr_t dset_ohdr_addr);
static herr_t H5D__bt2_idx_create(const H5D_chk_idx_info_t *idx_info);
static hbool_t H5D__bt2_idx_is_space_alloc(const H5O_storage_chunk_t *storage);
static herr_t H5D__bt2_idx_insert(const H5D_chk_idx_info_t *idx_info,
H5D_chunk_ud_t *udata, const H5D_t *dset);
static herr_t H5D__bt2_idx_get_addr(const H5D_chk_idx_info_t *idx_info,
H5D_chunk_ud_t *udata);
static int H5D__bt2_idx_iterate(const H5D_chk_idx_info_t *idx_info,
H5D_chunk_cb_func_t chunk_cb, void *chunk_udata);
static herr_t H5D__bt2_idx_remove(const H5D_chk_idx_info_t *idx_info,
H5D_chunk_common_ud_t *udata);
static herr_t H5D__bt2_idx_delete(const H5D_chk_idx_info_t *idx_info);
static herr_t H5D__bt2_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__bt2_idx_copy_shutdown(H5O_storage_chunk_t *storage_src,
H5O_storage_chunk_t *storage_dst);
static herr_t H5D__bt2_idx_size(const H5D_chk_idx_info_t *idx_info, hsize_t *size);
static herr_t H5D__bt2_idx_reset(H5O_storage_chunk_t *storage, hbool_t reset_addr);
static herr_t H5D__bt2_idx_dump(const H5O_storage_chunk_t *storage,
FILE *stream);
static herr_t H5D__bt2_idx_dest(const H5D_chk_idx_info_t *idx_info);
const H5D_chunk_ops_t H5D_COPS_BT2[1] = {{
TRUE,
H5D__bt2_idx_init,
H5D__bt2_idx_create,
H5D__bt2_idx_is_space_alloc,
H5D__bt2_idx_insert,
H5D__bt2_idx_get_addr,
NULL,
H5D__bt2_idx_iterate,
H5D__bt2_idx_remove,
H5D__bt2_idx_delete,
H5D__bt2_idx_copy_setup,
H5D__bt2_idx_copy_shutdown,
H5D__bt2_idx_size,
H5D__bt2_idx_reset,
H5D__bt2_idx_dump,
H5D__bt2_idx_dest
}};
const H5B2_class_t H5D_BT2[1] = {{
H5B2_CDSET_ID,
"H5B2_CDSET_ID",
sizeof(H5D_chunk_rec_t),
H5D__bt2_crt_context,
H5D__bt2_dst_context,
H5D__bt2_store,
H5D__bt2_compare,
H5D__bt2_unfilt_encode,
H5D__bt2_unfilt_decode,
H5D__bt2_unfilt_debug
}};
const H5B2_class_t H5D_BT2_FILT[1] = {{
H5B2_CDSET_FILT_ID,
"H5B2_CDSET_FILT_ID",
sizeof(H5D_chunk_rec_t),
H5D__bt2_crt_context,
H5D__bt2_dst_context,
H5D__bt2_store,
H5D__bt2_compare,
H5D__bt2_filt_encode,
H5D__bt2_filt_decode,
H5D__bt2_filt_debug
}};
H5FL_DEFINE_STATIC(H5D_bt2_ctx_t);
H5FL_ARR_DEFINE_STATIC(uint32_t, H5O_LAYOUT_NDIMS);
static void *
H5D__bt2_crt_context(void *_udata)
{
H5D_bt2_ctx_ud_t *udata = (H5D_bt2_ctx_ud_t *)_udata;
H5D_bt2_ctx_t *ctx;
uint32_t *my_dim = NULL;
void *ret_value = NULL;
FUNC_ENTER_STATIC
HDassert(udata);
HDassert(udata->f);
HDassert(udata->ndims > 0 && udata->ndims < H5O_LAYOUT_NDIMS);
if(NULL == (ctx = H5FL_MALLOC(H5D_bt2_ctx_t)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, NULL, "can't allocate callback context")
ctx->sizeof_addr = H5F_SIZEOF_ADDR(udata->f);
ctx->chunk_size = udata->chunk_size;
ctx->ndims = udata->ndims;
if(NULL == (my_dim = (uint32_t *)H5FL_ARR_MALLOC(uint32_t, H5O_LAYOUT_NDIMS)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, NULL, "can't allocate chunk dims")
H5MM_memcpy(my_dim, udata->dim, H5O_LAYOUT_NDIMS * sizeof(uint32_t));
ctx->dim = my_dim;
ctx->chunk_size_len = 1 + ((H5VM_log2_gen((uint64_t)udata->chunk_size) + 8) / 8);
if(ctx->chunk_size_len > 8)
ctx->chunk_size_len = 8;
ret_value = ctx;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__bt2_dst_context(void *_ctx)
{
H5D_bt2_ctx_t *ctx = (H5D_bt2_ctx_t *)_ctx;
FUNC_ENTER_STATIC_NOERR
HDassert(ctx);
if(ctx->dim)
H5FL_ARR_FREE(uint32_t, ctx->dim);
ctx = H5FL_FREE(H5D_bt2_ctx_t, ctx);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__bt2_store(void *record, const void *_udata)
{
const H5D_bt2_ud_t *udata = (const H5D_bt2_ud_t *)_udata;
FUNC_ENTER_STATIC_NOERR
*(H5D_chunk_rec_t *)record = udata->rec;
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__bt2_compare(const void *_udata, const void *_rec2, int *result)
{
const H5D_bt2_ud_t *udata = (const H5D_bt2_ud_t *)_udata;
const H5D_chunk_rec_t *rec1 = &(udata->rec);
const H5D_chunk_rec_t *rec2 = (const H5D_chunk_rec_t *)_rec2;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC_NOERR
HDassert(rec1);
HDassert(rec2);
*result = H5VM_vector_cmp_u(udata->ndims, rec1->scaled, rec2->scaled);
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__bt2_unfilt_encode(uint8_t *raw, const void *_record, void *_ctx)
{
H5D_bt2_ctx_t *ctx = (H5D_bt2_ctx_t *)_ctx;
const H5D_chunk_rec_t *record = (const H5D_chunk_rec_t *)_record;
unsigned u;
FUNC_ENTER_STATIC_NOERR
HDassert(ctx);
H5F_addr_encode_len(ctx->sizeof_addr, &raw, record->chunk_addr);
for(u = 0; u < ctx->ndims; u++)
UINT64ENCODE(raw, record->scaled[u]);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__bt2_unfilt_decode(const uint8_t *raw, void *_record, void *_ctx)
{
H5D_bt2_ctx_t *ctx = (H5D_bt2_ctx_t *)_ctx;
H5D_chunk_rec_t *record = (H5D_chunk_rec_t *)_record;
unsigned u;
FUNC_ENTER_STATIC_NOERR
HDassert(ctx);
H5F_addr_decode_len(ctx->sizeof_addr, &raw, &record->chunk_addr);
record->nbytes = ctx->chunk_size;
record->filter_mask = 0;
for(u = 0; u < ctx->ndims; u++)
UINT64DECODE(raw, record->scaled[u]);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__bt2_unfilt_debug(FILE *stream, int indent, int fwidth,
const void *_record, const void *_ctx)
{
const H5D_chunk_rec_t *record = (const H5D_chunk_rec_t *)_record;
const H5D_bt2_ctx_t *ctx = (const H5D_bt2_ctx_t *)_ctx;
unsigned u;
FUNC_ENTER_STATIC_NOERR
HDassert(record);
HDassert(ctx->chunk_size == record->nbytes);
HDassert(0 == record->filter_mask);
HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, "Chunk address:", record->chunk_addr);
HDfprintf(stream, "%*s%-*s {", indent, "", fwidth, "Logical offset:");
for(u = 0; u < ctx->ndims; u++)
HDfprintf(stream, "%s%Hd", u?", ":"", record->scaled[u] * ctx->dim[u]);
HDfputs("}\n", stream);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__bt2_filt_encode(uint8_t *raw, const void *_record, void *_ctx)
{
H5D_bt2_ctx_t *ctx = (H5D_bt2_ctx_t *)_ctx;
const H5D_chunk_rec_t *record = (const H5D_chunk_rec_t *)_record;
unsigned u;
FUNC_ENTER_STATIC_NOERR
HDassert(ctx);
HDassert(record);
HDassert(H5F_addr_defined(record->chunk_addr));
HDassert(0 != record->nbytes);
H5F_addr_encode_len(ctx->sizeof_addr, &raw, record->chunk_addr);
UINT64ENCODE_VAR(raw, record->nbytes, ctx->chunk_size_len);
UINT32ENCODE(raw, record->filter_mask);
for(u = 0; u < ctx->ndims; u++)
UINT64ENCODE(raw, record->scaled[u]);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__bt2_filt_decode(const uint8_t *raw, void *_record, void *_ctx)
{
H5D_bt2_ctx_t *ctx = (H5D_bt2_ctx_t *)_ctx;
H5D_chunk_rec_t *record = (H5D_chunk_rec_t *)_record;
unsigned u;
FUNC_ENTER_STATIC_NOERR
HDassert(ctx);
HDassert(record);
H5F_addr_decode_len(ctx->sizeof_addr, &raw, &record->chunk_addr);
UINT64DECODE_VAR(raw, record->nbytes, ctx->chunk_size_len);
UINT32DECODE(raw, record->filter_mask);
for(u = 0; u < ctx->ndims; u++)
UINT64DECODE(raw, record->scaled[u]);
HDassert(H5F_addr_defined(record->chunk_addr));
HDassert(0 != record->nbytes);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__bt2_filt_debug(FILE *stream, int indent, int fwidth,
const void *_record, const void *_ctx)
{
const H5D_chunk_rec_t *record = (const H5D_chunk_rec_t *)_record;
const H5D_bt2_ctx_t *ctx = (const H5D_bt2_ctx_t *)_ctx;
unsigned u;
FUNC_ENTER_STATIC_NOERR
HDassert(record);
HDassert(H5F_addr_defined(record->chunk_addr));
HDassert(0 != record->nbytes);
HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, "Chunk address:", record->chunk_addr);
HDfprintf(stream, "%*s%-*s %u bytes\n", indent, "", fwidth, "Chunk size:", (unsigned)record->nbytes);
HDfprintf(stream, "%*s%-*s 0x%08x\n", indent, "", fwidth, "Filter mask:", record->filter_mask);
HDfprintf(stream, "%*s%-*s {", indent, "", fwidth, "Logical offset:");
for(u = 0; u < ctx->ndims; u++)
HDfprintf(stream, "%s%Hd", u?", ":"", record->scaled[u] * ctx->dim[u]);
HDfputs("}\n", stream);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__bt2_idx_init(const H5D_chk_idx_info_t H5_ATTR_UNUSED *idx_info,
const H5S_t H5_ATTR_UNUSED *space, haddr_t dset_ohdr_addr)
{
FUNC_ENTER_STATIC_NOERR
HDassert(H5F_addr_defined(dset_ohdr_addr));
idx_info->storage->u.btree2.dset_ohdr_addr = dset_ohdr_addr;
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__btree2_idx_depend(const H5D_chk_idx_info_t *idx_info)
{
H5O_t *oh = NULL;
H5O_loc_t oloc;
H5AC_proxy_entry_t *oh_proxy;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(idx_info);
HDassert(idx_info->f);
HDassert(H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE);
HDassert(idx_info->pline);
HDassert(idx_info->layout);
HDassert(H5D_CHUNK_IDX_BT2 == idx_info->layout->idx_type);
HDassert(idx_info->storage);
HDassert(H5D_CHUNK_IDX_BT2 == idx_info->storage->idx_type);
HDassert(H5F_addr_defined(idx_info->storage->idx_addr));
HDassert(idx_info->storage->u.btree2.bt2);
H5O_loc_reset(&oloc);
oloc.file = idx_info->f;
oloc.addr = idx_info->storage->u.btree.dset_ohdr_addr;
if(NULL == (oh = H5O_protect(&oloc, H5AC__READ_ONLY_FLAG, TRUE)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTPROTECT, FAIL, "unable to protect object header")
if(NULL == (oh_proxy = H5O_get_proxy(oh)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get dataset object header proxy")
if(H5B2_depend(idx_info->storage->u.btree2.bt2, oh_proxy) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTDEPEND, FAIL, "unable to create flush dependency on object header proxy")
done:
if(oh && H5O_unprotect(&oloc, oh, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__bt2_idx_open(const H5D_chk_idx_info_t *idx_info)
{
H5D_bt2_ctx_ud_t u_ctx;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(idx_info);
HDassert(idx_info->f);
HDassert(idx_info->pline);
HDassert(idx_info->layout);
HDassert(H5D_CHUNK_IDX_BT2 == idx_info->layout->idx_type);
HDassert(idx_info->storage);
HDassert(H5F_addr_defined(idx_info->storage->idx_addr));
HDassert(NULL == idx_info->storage->u.btree2.bt2);
u_ctx.f = idx_info->f;
u_ctx.ndims = idx_info->layout->ndims - 1;
u_ctx.chunk_size = idx_info->layout->size;
u_ctx.dim = idx_info->layout->dim;
if(NULL == (idx_info->storage->u.btree2.bt2 = H5B2_open(idx_info->f, idx_info->storage->idx_addr, &u_ctx)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't open v2 B-tree for tracking chunked dataset")
if(H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE)
if(H5D__btree2_idx_depend(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTDEPEND, FAIL, "unable to create flush dependency on object header")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__bt2_idx_create(const H5D_chk_idx_info_t *idx_info)
{
H5B2_create_t bt2_cparam;
H5D_bt2_ctx_ud_t u_ctx;
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));
bt2_cparam.rrec_size = H5F_SIZEOF_ADDR(idx_info->f)
+ (idx_info->layout->ndims - 1) * 8;
if(idx_info->pline->nused > 0) {
unsigned chunk_size_len;
chunk_size_len = 1 + ((H5VM_log2_gen((uint64_t)idx_info->layout->size) + 8) / 8);
if(chunk_size_len > 8)
chunk_size_len = 8;
bt2_cparam.rrec_size += chunk_size_len + 4;
bt2_cparam.cls = H5D_BT2_FILT;
}
else
bt2_cparam.cls = H5D_BT2;
bt2_cparam.node_size = idx_info->layout->u.btree2.cparam.node_size;
bt2_cparam.split_percent = idx_info->layout->u.btree2.cparam.split_percent;
bt2_cparam.merge_percent = idx_info->layout->u.btree2.cparam.merge_percent;
u_ctx.f = idx_info->f;
u_ctx.ndims = idx_info->layout->ndims - 1;
u_ctx.chunk_size = idx_info->layout->size;
u_ctx.dim = idx_info->layout->dim;
if(NULL == (idx_info->storage->u.btree2.bt2 = H5B2_create(idx_info->f, &bt2_cparam, &u_ctx)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "can't create v2 B-tree for tracking chunked dataset")
if(H5B2_get_addr(idx_info->storage->u.btree2.bt2, &(idx_info->storage->idx_addr)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get v2 B-tree address for tracking chunked dataset")
if(H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE)
if(H5D__btree2_idx_depend(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTDEPEND, FAIL, "unable to create flush dependency on object header")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static hbool_t
H5D__bt2_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__bt2_mod_cb(void *_record, void *_op_data, hbool_t *changed)
{
H5D_bt2_ud_t *op_data = (H5D_bt2_ud_t *)_op_data;
H5D_chunk_rec_t *record = (H5D_chunk_rec_t *)_record;
FUNC_ENTER_STATIC_NOERR
#ifndef NDEBUG
{
unsigned u;
for(u = 0; u < op_data->ndims; u++)
HDassert(record->scaled[u] == op_data->rec.scaled[u]);
}
#endif
*record = op_data->rec;
*changed = TRUE;
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__bt2_idx_insert(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata,
const H5D_t H5_ATTR_UNUSED *dset)
{
H5B2_t *bt2;
H5D_bt2_ud_t bt2_udata;
unsigned u;
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);
HDassert(H5F_addr_defined(udata->chunk_block.offset));
if(NULL == idx_info->storage->u.btree2.bt2) {
if(H5D__bt2_idx_open(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open v2 B-tree")
}
else
if(H5B2_patch_file(idx_info->storage->u.btree2.bt2, idx_info->f) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't patch v2 B-tree file pointer")
bt2 = idx_info->storage->u.btree2.bt2;
bt2_udata.ndims = idx_info->layout->ndims - 1;
bt2_udata.rec.chunk_addr = udata->chunk_block.offset;
if(idx_info->pline->nused > 0) {
H5_CHECKED_ASSIGN(bt2_udata.rec.nbytes, uint32_t, udata->chunk_block.length, hsize_t);
bt2_udata.rec.filter_mask = udata->filter_mask;
}
else {
bt2_udata.rec.nbytes = idx_info->layout->size;
bt2_udata.rec.filter_mask = 0;
}
for(u = 0; u < (idx_info->layout->ndims - 1); u++)
bt2_udata.rec.scaled[u] = udata->common.scaled[u];
if(H5B2_update(bt2, &bt2_udata, H5D__bt2_mod_cb, &bt2_udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTUPDATE, FAIL, "unable to update record in v2 B-tree")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__bt2_found_cb(const void *nrecord, void *op_data)
{
FUNC_ENTER_STATIC_NOERR
*(H5D_chunk_rec_t *)op_data = *(const H5D_chunk_rec_t *)nrecord;
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__bt2_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata)
{
H5B2_t *bt2;
H5D_bt2_ud_t bt2_udata;
H5D_chunk_rec_t found_rec;
unsigned u;
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(NULL == idx_info->storage->u.btree2.bt2) {
if(H5D__bt2_idx_open(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open v2 B-tree")
}
else
if(H5B2_patch_file(idx_info->storage->u.btree2.bt2, idx_info->f) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't patch v2 B-tree file pointer")
bt2 = idx_info->storage->u.btree2.bt2;
found_rec.chunk_addr = HADDR_UNDEF;
found_rec.nbytes = 0;
found_rec.filter_mask = 0;
bt2_udata.rec.chunk_addr = HADDR_UNDEF;
bt2_udata.ndims = idx_info->layout->ndims - 1;
for(u = 0; u < (idx_info->layout->ndims - 1); u++)
bt2_udata.rec.scaled[u] = udata->common.scaled[u];
if(H5B2_find(bt2, &bt2_udata, H5D__bt2_found_cb, &found_rec) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree")
udata->chunk_block.offset = found_rec.chunk_addr;
if(H5F_addr_defined(udata->chunk_block.offset)) {
HDassert(0 != found_rec.nbytes);
if(idx_info->pline->nused > 0) {
udata->chunk_block.length = found_rec.nbytes;
udata->filter_mask = found_rec.filter_mask;
}
else {
udata->chunk_block.length = idx_info->layout->size;
udata->filter_mask = 0;
}
}
else {
udata->chunk_block.length = 0;
udata->filter_mask = 0;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static int
H5D__bt2_idx_iterate_cb(const void *_record, void *_udata)
{
H5D_bt2_it_ud_t *udata = (H5D_bt2_it_ud_t *)_udata;
const H5D_chunk_rec_t *record = (const H5D_chunk_rec_t *)_record;
int ret_value = -1;
FUNC_ENTER_STATIC_NOERR
if((ret_value = (udata->cb)(record, udata->udata)) < 0)
HERROR(H5E_DATASET, H5E_CALLBACK, "failure in generic chunk iterator callback");
FUNC_LEAVE_NOAPI(ret_value)
}
static int
H5D__bt2_idx_iterate(const H5D_chk_idx_info_t *idx_info,
H5D_chunk_cb_func_t chunk_cb, void *chunk_udata)
{
H5B2_t *bt2;
H5D_bt2_it_ud_t udata;
int ret_value = FAIL;
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(chunk_cb);
HDassert(chunk_udata);
if(NULL == idx_info->storage->u.btree2.bt2) {
if(H5D__bt2_idx_open(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open v2 B-tree")
}
else
if(H5B2_patch_file(idx_info->storage->u.btree2.bt2, idx_info->f) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't patch v2 B-tree file pointer")
bt2 = idx_info->storage->u.btree2.bt2;
udata.cb = chunk_cb;
udata.udata = chunk_udata;
if((ret_value = H5B2_iterate(bt2, H5D__bt2_idx_iterate_cb, &udata)) < 0)
HERROR(H5E_DATASET, H5E_BADITER, "unable to iterate over chunk v2 B-tree");
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__bt2_remove_cb(const void *_record, void *_udata)
{
const H5D_chunk_rec_t *record = (const H5D_chunk_rec_t *)_record;
H5F_t *f = (H5F_t *)_udata;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(f);
H5_CHECK_OVERFLOW(record->nbytes, uint32_t, hsize_t);
if(H5MF_xfree(f, H5FD_MEM_DRAW, record->chunk_addr, (hsize_t)record->nbytes) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to free chunk")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__bt2_idx_remove(const H5D_chk_idx_info_t *idx_info, H5D_chunk_common_ud_t *udata)
{
H5B2_t *bt2;
H5D_bt2_ud_t bt2_udata;
unsigned u;
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(NULL == idx_info->storage->u.btree2.bt2) {
if(H5D__bt2_idx_open(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open v2 B-tree")
}
else
if(H5B2_patch_file(idx_info->storage->u.btree2.bt2, idx_info->f) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't patch v2 B-tree file pointer")
bt2 = idx_info->storage->u.btree2.bt2;
bt2_udata.ndims = idx_info->layout->ndims - 1;
for(u = 0; u < (idx_info->layout->ndims - 1); u++)
bt2_udata.rec.scaled[u] = udata->scaled[u];
if(H5B2_remove(bt2, &bt2_udata, (H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE) ? NULL : H5D__bt2_remove_cb, idx_info->f) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTREMOVE, FAIL, "can't remove object from B-tree")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__bt2_idx_delete(const H5D_chk_idx_info_t *idx_info)
{
H5B2_remove_t remove_op;
H5D_bt2_ctx_ud_t u_ctx;
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)) {
u_ctx.f = idx_info->f;
u_ctx.ndims = idx_info->layout->ndims - 1;
u_ctx.chunk_size = idx_info->layout->size;
u_ctx.dim = idx_info->layout->dim;
if(H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE)
remove_op = NULL;
else
remove_op = H5D__bt2_remove_cb;
if(H5B2_delete(idx_info->f, idx_info->storage->idx_addr, &u_ctx, remove_op, idx_info->f) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTDELETE, FAIL, "can't delete v2 B-tree")
idx_info->storage->idx_addr = HADDR_UNDEF;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__bt2_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
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(NULL == idx_info_src->storage->u.btree2.bt2)
if(H5D__bt2_idx_open(idx_info_src) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open v2 B-tree")
H5_BEGIN_TAG(H5AC__COPIED_TAG);
if(H5D__bt2_idx_create(idx_info_dst) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize chunked storage")
HDassert(H5F_addr_defined(idx_info_dst->storage->idx_addr));
H5_END_TAG
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__bt2_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_src->u.btree2.bt2);
HDassert(storage_dst);
HDassert(storage_dst->u.btree2.bt2);
if(H5B2_close(storage_src->u.btree2.bt2) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close v2 B-tree")
storage_src->u.btree2.bt2 = NULL;
if(H5B2_close(storage_dst->u.btree2.bt2) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close v2 B-tree")
storage_dst->u.btree2.bt2 = NULL;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__bt2_idx_size(const H5D_chk_idx_info_t *idx_info, hsize_t *index_size)
{
H5B2_t *bt2_cdset = NULL;
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(index_size);
if(H5D__bt2_idx_open(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open v2 B-tree")
bt2_cdset = idx_info->storage->u.btree2.bt2;
if(H5B2_size(bt2_cdset, index_size) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve v2 B-tree storage info for chunked dataset")
done:
if(bt2_cdset && H5B2_close(bt2_cdset) < 0)
HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for tracking chunked dataset")
idx_info->storage->u.btree2.bt2 = NULL;
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__bt2_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.btree2.bt2 = NULL;
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__bt2_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__bt2_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->storage);
if(idx_info->storage->u.btree2.bt2) {
if(H5B2_patch_file(idx_info->storage->u.btree2.bt2, idx_info->f) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't patch v2 B-tree file pointer")
if(H5B2_close(idx_info->storage->u.btree2.bt2) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree")
idx_info->storage->u.btree2.bt2 = NULL;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}