#include "H5Dmodule.h"
#include "H5private.h"
#include "H5Dpkg.h"
#include "H5Eprivate.h"
#include "H5FAprivate.h"
#include "H5FLprivate.h"
#include "H5MFprivate.h"
#include "H5VMprivate.h"
#define H5D_FARRAY_FILL HADDR_UNDEF
#define H5D_FARRAY_FILT_FILL {HADDR_UNDEF, 0, 0}
typedef struct H5D_farray_ctx_ud_t {
const H5F_t *f;
uint32_t chunk_size;
} H5D_farray_ctx_ud_t;
typedef struct H5D_farray_ctx_t {
size_t file_addr_len;
size_t chunk_size_len;
} H5D_farray_ctx_t;
typedef struct H5D_farray_it_ud_t {
H5D_chunk_common_ud_t common;
H5D_chunk_rec_t chunk_rec;
hbool_t filtered;
H5D_chunk_cb_func_t cb;
void *udata;
} H5D_farray_it_ud_t;
typedef struct H5D_farray_filt_elmt_t {
haddr_t addr;
uint32_t nbytes;
uint32_t filter_mask;
} H5D_farray_filt_elmt_t;
static int H5D__farray_idx_iterate_cb(hsize_t idx, const void *_elmt, void *_udata);
static int H5D__farray_idx_delete_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata);
static void *H5D__farray_crt_context(void *udata);
static herr_t H5D__farray_dst_context(void *ctx);
static herr_t H5D__farray_fill(void *nat_blk, size_t nelmts);
static herr_t H5D__farray_encode(void *raw, const void *elmt, size_t nelmts,
void *ctx);
static herr_t H5D__farray_decode(const void *raw, void *elmt, size_t nelmts,
void *ctx);
static herr_t H5D__farray_debug(FILE *stream, int indent, int fwidth,
hsize_t idx, const void *elmt);
static void *H5D__farray_crt_dbg_context(H5F_t *f, haddr_t obj_addr);
static herr_t H5D__farray_dst_dbg_context(void *dbg_ctx);
static herr_t H5D__farray_filt_fill(void *nat_blk, size_t nelmts);
static herr_t H5D__farray_filt_encode(void *raw, const void *elmt, size_t nelmts,
void *ctx);
static herr_t H5D__farray_filt_decode(const void *raw, void *elmt, size_t nelmts,
void *ctx);
static herr_t H5D__farray_filt_debug(FILE *stream, int indent, int fwidth,
hsize_t idx, const void *elmt);
static herr_t H5D__farray_idx_init(const H5D_chk_idx_info_t *idx_info,
const H5S_t *space, haddr_t dset_ohdr_addr);
static herr_t H5D__farray_idx_create(const H5D_chk_idx_info_t *idx_info);
static hbool_t H5D__farray_idx_is_space_alloc(const H5O_storage_chunk_t *storage);
static herr_t H5D__farray_idx_insert(const H5D_chk_idx_info_t *idx_info,
H5D_chunk_ud_t *udata, const H5D_t *dset);
static herr_t H5D__farray_idx_get_addr(const H5D_chk_idx_info_t *idx_info,
H5D_chunk_ud_t *udata);
static int H5D__farray_idx_iterate(const H5D_chk_idx_info_t *idx_info,
H5D_chunk_cb_func_t chunk_cb, void *chunk_udata);
static herr_t H5D__farray_idx_remove(const H5D_chk_idx_info_t *idx_info,
H5D_chunk_common_ud_t *udata);
static herr_t H5D__farray_idx_delete(const H5D_chk_idx_info_t *idx_info);
static herr_t H5D__farray_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__farray_idx_copy_shutdown(H5O_storage_chunk_t *storage_src,
H5O_storage_chunk_t *storage_dst);
static herr_t H5D__farray_idx_size(const H5D_chk_idx_info_t *idx_info,
hsize_t *size);
static herr_t H5D__farray_idx_reset(H5O_storage_chunk_t *storage, hbool_t reset_addr);
static herr_t H5D__farray_idx_dump(const H5O_storage_chunk_t *storage, FILE *stream);
static herr_t H5D__farray_idx_dest(const H5D_chk_idx_info_t *idx_info);
static herr_t H5D__farray_idx_open(const H5D_chk_idx_info_t *idx_info);
static herr_t H5D__farray_idx_depend(const H5D_chk_idx_info_t *idx_info);
const H5D_chunk_ops_t H5D_COPS_FARRAY[1] = {{
TRUE,
H5D__farray_idx_init,
H5D__farray_idx_create,
H5D__farray_idx_is_space_alloc,
H5D__farray_idx_insert,
H5D__farray_idx_get_addr,
NULL,
H5D__farray_idx_iterate,
H5D__farray_idx_remove,
H5D__farray_idx_delete,
H5D__farray_idx_copy_setup,
H5D__farray_idx_copy_shutdown,
H5D__farray_idx_size,
H5D__farray_idx_reset,
H5D__farray_idx_dump,
H5D__farray_idx_dest
}};
const H5FA_class_t H5FA_CLS_CHUNK[1]={{
H5FA_CLS_CHUNK_ID,
"Chunk w/o filters",
sizeof(haddr_t),
H5D__farray_crt_context,
H5D__farray_dst_context,
H5D__farray_fill,
H5D__farray_encode,
H5D__farray_decode,
H5D__farray_debug,
H5D__farray_crt_dbg_context,
H5D__farray_dst_dbg_context
}};
const H5FA_class_t H5FA_CLS_FILT_CHUNK[1]={{
H5FA_CLS_FILT_CHUNK_ID,
"Chunk w/filters",
sizeof(H5D_farray_filt_elmt_t),
H5D__farray_crt_context,
H5D__farray_dst_context,
H5D__farray_filt_fill,
H5D__farray_filt_encode,
H5D__farray_filt_decode,
H5D__farray_filt_debug,
H5D__farray_crt_dbg_context,
H5D__farray_dst_dbg_context
}};
H5FL_DEFINE_STATIC(H5D_farray_ctx_t);
H5FL_DEFINE_STATIC(H5D_farray_ctx_ud_t);
static void *
H5D__farray_crt_context(void *_udata)
{
H5D_farray_ctx_t *ctx;
H5D_farray_ctx_ud_t *udata = (H5D_farray_ctx_ud_t *)_udata;
void *ret_value = NULL;
FUNC_ENTER_STATIC
HDassert(udata);
HDassert(udata->f);
HDassert(udata->chunk_size > 0);
if(NULL == (ctx = H5FL_MALLOC(H5D_farray_ctx_t)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, NULL, "can't allocate fixed array client callback context")
ctx->file_addr_len = H5F_SIZEOF_ADDR(udata->f);
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__farray_dst_context(void *_ctx)
{
H5D_farray_ctx_t *ctx = (H5D_farray_ctx_t *)_ctx;
FUNC_ENTER_STATIC_NOERR
HDassert(ctx);
ctx = H5FL_FREE(H5D_farray_ctx_t, ctx);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__farray_fill(void *nat_blk, size_t nelmts)
{
haddr_t fill_val = H5D_FARRAY_FILL;
FUNC_ENTER_STATIC_NOERR
HDassert(nat_blk);
HDassert(nelmts);
H5VM_array_fill(nat_blk, &fill_val, H5FA_CLS_CHUNK->nat_elmt_size, nelmts);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__farray_encode(void *raw, const void *_elmt, size_t nelmts, void *_ctx)
{
H5D_farray_ctx_t *ctx = (H5D_farray_ctx_t *)_ctx;
const haddr_t *elmt = (const haddr_t *)_elmt;
FUNC_ENTER_STATIC_NOERR
HDassert(raw);
HDassert(elmt);
HDassert(nelmts);
HDassert(ctx);
while(nelmts) {
H5F_addr_encode_len(ctx->file_addr_len, (uint8_t **)&raw, *elmt);
elmt++;
nelmts--;
}
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__farray_decode(const void *_raw, void *_elmt, size_t nelmts, void *_ctx)
{
H5D_farray_ctx_t *ctx = (H5D_farray_ctx_t *)_ctx;
haddr_t *elmt = (haddr_t *)_elmt;
const uint8_t *raw = (const uint8_t *)_raw;
FUNC_ENTER_STATIC_NOERR
HDassert(raw);
HDassert(elmt);
HDassert(nelmts);
while(nelmts) {
H5F_addr_decode_len(ctx->file_addr_len, &raw, elmt);
elmt++;
nelmts--;
}
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__farray_debug(FILE *stream, int indent, int fwidth, hsize_t idx,
const void *elmt)
{
char temp_str[128];
FUNC_ENTER_STATIC_NOERR
HDassert(stream);
HDassert(elmt);
HDsprintf(temp_str, "Element #%llu:", (unsigned long long)idx);
HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, temp_str,
*(const haddr_t *)elmt);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static void *
H5D__farray_crt_dbg_context(H5F_t *f, haddr_t obj_addr)
{
H5D_farray_ctx_ud_t *dbg_ctx = NULL;
H5O_loc_t obj_loc;
hbool_t obj_opened = FALSE;
H5O_layout_t layout;
void *ret_value = NULL;
FUNC_ENTER_STATIC
HDassert(f);
HDassert(H5F_addr_defined(obj_addr));
if(NULL == (dbg_ctx = H5FL_MALLOC(H5D_farray_ctx_ud_t)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, NULL, "can't allocate fixed array client callback context")
H5O_loc_reset(&obj_loc);
obj_loc.file = f;
obj_loc.addr = obj_addr;
if(H5O_open(&obj_loc) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, NULL, "can't open object header")
obj_opened = TRUE;
if(NULL == H5O_msg_read(&obj_loc, H5O_LAYOUT_ID, &layout))
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't get layout info")
if(H5O_close(&obj_loc, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, NULL, "can't close object header")
dbg_ctx->f = f;
dbg_ctx->chunk_size = layout.u.chunk.size;
ret_value = dbg_ctx;
done:
if(ret_value == NULL) {
if(dbg_ctx)
dbg_ctx = H5FL_FREE(H5D_farray_ctx_ud_t, dbg_ctx);
if(obj_opened)
if(H5O_close(&obj_loc, NULL) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, NULL, "can't close object header")
}
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__farray_dst_dbg_context(void *_dbg_ctx)
{
H5D_farray_ctx_ud_t *dbg_ctx = (H5D_farray_ctx_ud_t *)_dbg_ctx;
FUNC_ENTER_STATIC_NOERR
HDassert(dbg_ctx);
dbg_ctx = H5FL_FREE(H5D_farray_ctx_ud_t, dbg_ctx);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__farray_filt_fill(void *nat_blk, size_t nelmts)
{
H5D_farray_filt_elmt_t fill_val = H5D_FARRAY_FILT_FILL;
FUNC_ENTER_STATIC_NOERR
HDassert(nat_blk);
HDassert(nelmts);
HDassert(sizeof(fill_val) == H5FA_CLS_FILT_CHUNK->nat_elmt_size);
H5VM_array_fill(nat_blk, &fill_val, H5FA_CLS_FILT_CHUNK->nat_elmt_size, nelmts);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__farray_filt_encode(void *_raw, const void *_elmt, size_t nelmts, void *_ctx)
{
H5D_farray_ctx_t *ctx = (H5D_farray_ctx_t *)_ctx;
uint8_t *raw = (uint8_t *)_raw;
const H5D_farray_filt_elmt_t *elmt = (const H5D_farray_filt_elmt_t *)_elmt;
FUNC_ENTER_STATIC_NOERR
HDassert(raw);
HDassert(elmt);
HDassert(nelmts);
HDassert(ctx);
while(nelmts) {
H5F_addr_encode_len(ctx->file_addr_len, &raw, elmt->addr);
UINT64ENCODE_VAR(raw, elmt->nbytes, ctx->chunk_size_len);
UINT32ENCODE(raw, elmt->filter_mask);
elmt++;
nelmts--;
}
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__farray_filt_decode(const void *_raw, void *_elmt, size_t nelmts, void *_ctx)
{
H5D_farray_ctx_t *ctx = (H5D_farray_ctx_t *)_ctx;
H5D_farray_filt_elmt_t *elmt = (H5D_farray_filt_elmt_t *)_elmt;
const uint8_t *raw = (const uint8_t *)_raw;
FUNC_ENTER_STATIC_NOERR
HDassert(raw);
HDassert(elmt);
HDassert(nelmts);
while(nelmts) {
H5F_addr_decode_len(ctx->file_addr_len, &raw, &elmt->addr);
UINT64DECODE_VAR(raw, elmt->nbytes, ctx->chunk_size_len);
UINT32DECODE(raw, elmt->filter_mask);
elmt++;
nelmts--;
}
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__farray_filt_debug(FILE *stream, int indent, int fwidth, hsize_t idx,
const void *_elmt)
{
const H5D_farray_filt_elmt_t *elmt = (const H5D_farray_filt_elmt_t *)_elmt;
char temp_str[128];
FUNC_ENTER_STATIC_NOERR
HDassert(stream);
HDassert(elmt);
HDsprintf(temp_str, "Element #%llu:", (unsigned long long)idx);
HDfprintf(stream, "%*s%-*s {%a, %u, %0x}\n", indent, "", fwidth, temp_str,
elmt->addr, elmt->nbytes, elmt->filter_mask);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__farray_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_FARRAY == idx_info->layout->idx_type);
HDassert(idx_info->storage);
HDassert(H5D_CHUNK_IDX_FARRAY == idx_info->storage->idx_type);
HDassert(H5F_addr_defined(idx_info->storage->idx_addr));
HDassert(idx_info->storage->u.farray.fa);
H5O_loc_reset(&oloc);
oloc.file = idx_info->f;
oloc.addr = idx_info->storage->u.farray.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(H5FA_depend(idx_info->storage->u.farray.fa, 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__farray_idx_init(const H5D_chk_idx_info_t *idx_info, const H5S_t H5_ATTR_UNUSED *space, haddr_t dset_ohdr_addr)
{
FUNC_ENTER_STATIC_NOERR
HDassert(idx_info);
HDassert(idx_info->storage);
HDassert(H5F_addr_defined(dset_ohdr_addr));
idx_info->storage->u.farray.dset_ohdr_addr = dset_ohdr_addr;
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__farray_idx_open(const H5D_chk_idx_info_t *idx_info)
{
H5D_farray_ctx_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(H5D_CHUNK_IDX_FARRAY == idx_info->layout->idx_type);
HDassert(idx_info->storage);
HDassert(H5D_CHUNK_IDX_FARRAY == idx_info->storage->idx_type);
HDassert(H5F_addr_defined(idx_info->storage->idx_addr));
HDassert(NULL == idx_info->storage->u.farray.fa);
udata.f = idx_info->f;
udata.chunk_size = idx_info->layout->size;
if(NULL == (idx_info->storage->u.farray.fa = H5FA_open(idx_info->f, idx_info->storage->idx_addr, &udata)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't open fixed array")
if(H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE)
if(H5D__farray_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__farray_idx_create(const H5D_chk_idx_info_t *idx_info)
{
H5FA_create_t cparam;
H5D_farray_ctx_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(NULL == idx_info->storage->u.farray.fa);
HDassert(idx_info->layout->nchunks);
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;
cparam.cls = H5FA_CLS_FILT_CHUNK;
cparam.raw_elmt_size = (uint8_t)(H5F_SIZEOF_ADDR(idx_info->f) + chunk_size_len + 4);
}
else {
cparam.cls = H5FA_CLS_CHUNK;
cparam.raw_elmt_size = (uint8_t)H5F_SIZEOF_ADDR(idx_info->f);
}
cparam.max_dblk_page_nelmts_bits = idx_info->layout->u.farray.cparam.max_dblk_page_nelmts_bits;
HDassert(cparam.max_dblk_page_nelmts_bits > 0);
cparam.nelmts = idx_info->layout->max_nchunks;
udata.f = idx_info->f;
udata.chunk_size = idx_info->layout->size;
if(NULL == (idx_info->storage->u.farray.fa = H5FA_create(idx_info->f, &cparam, &udata)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't create fixed array")
if(H5FA_get_addr(idx_info->storage->u.farray.fa, &(idx_info->storage->idx_addr)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't query fixed array address")
if(H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE)
if(H5D__farray_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__farray_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__farray_idx_insert(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata,
const H5D_t H5_ATTR_UNUSED *dset)
{
H5FA_t *fa;
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.farray.fa) {
if(H5D__farray_idx_open(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open fixed array")
} else
H5FA_patch_file(idx_info->storage->u.farray.fa, idx_info->f);
fa = idx_info->storage->u.farray.fa;
if(!H5F_addr_defined(udata->chunk_block.offset))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "The chunk should have allocated already")
if(udata->chunk_idx != (udata->chunk_idx & 0xffffffff))
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "chunk index must be less than 2^32")
if(idx_info->pline->nused > 0) {
H5D_farray_filt_elmt_t elmt;
elmt.addr = udata->chunk_block.offset;
H5_CHECKED_ASSIGN(elmt.nbytes, uint32_t, udata->chunk_block.length, hsize_t);
elmt.filter_mask = udata->filter_mask;
if(H5FA_set(fa, udata->chunk_idx, &elmt) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set chunk info")
}
else {
if(H5FA_set(fa, udata->chunk_idx, &udata->chunk_block.offset) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set chunk address")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__farray_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata)
{
H5FA_t *fa;
hsize_t idx;
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.farray.fa) {
if(H5D__farray_idx_open(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open fixed array")
} else
H5FA_patch_file(idx_info->storage->u.farray.fa, idx_info->f);
fa = idx_info->storage->u.farray.fa;
idx = H5VM_array_offset_pre((idx_info->layout->ndims - 1), idx_info->layout->max_down_chunks, udata->common.scaled);
udata->chunk_idx = idx;
if(idx_info->pline->nused > 0) {
H5D_farray_filt_elmt_t elmt;
if(H5FA_get(fa, idx, &elmt) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk info")
udata->chunk_block.offset = elmt.addr;
udata->chunk_block.length = elmt.nbytes;
udata->filter_mask = elmt.filter_mask;
}
else {
if(H5FA_get(fa, idx, &udata->chunk_block.offset) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address")
udata->chunk_block.length = idx_info->layout->size;
udata->filter_mask = 0;
}
if(!H5F_addr_defined(udata->chunk_block.offset))
udata->chunk_block.length = 0;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static int
H5D__farray_idx_iterate_cb(hsize_t H5_ATTR_UNUSED idx, const void *_elmt, void *_udata)
{
H5D_farray_it_ud_t *udata = (H5D_farray_it_ud_t *)_udata;
unsigned ndims;
int curr_dim;
int ret_value = H5_ITER_CONT;
FUNC_ENTER_STATIC_NOERR
if(udata->filtered) {
const H5D_farray_filt_elmt_t *filt_elmt = (const H5D_farray_filt_elmt_t *)_elmt;
udata->chunk_rec.chunk_addr = filt_elmt->addr;
udata->chunk_rec.nbytes = filt_elmt->nbytes;
udata->chunk_rec.filter_mask = filt_elmt->filter_mask;
}
else
udata->chunk_rec.chunk_addr = *(const haddr_t *)_elmt;
if(H5F_addr_defined(udata->chunk_rec.chunk_addr))
if((ret_value = (udata->cb)(&udata->chunk_rec, udata->udata)) < 0)
HERROR(H5E_DATASET, H5E_CALLBACK, "failure in generic chunk iterator callback");
ndims = udata->common.layout->ndims - 1;
HDassert(ndims > 0);
curr_dim = (int)(ndims - 1);
while(curr_dim >= 0) {
udata->chunk_rec.scaled[curr_dim]++;
if(udata->chunk_rec.scaled[curr_dim] >= udata->common.layout->max_chunks[curr_dim]) {
udata->chunk_rec.scaled[curr_dim] = 0;
curr_dim--;
}
else
break;
}
FUNC_LEAVE_NOAPI(ret_value)
}
static int
H5D__farray_idx_iterate(const H5D_chk_idx_info_t *idx_info,
H5D_chunk_cb_func_t chunk_cb, void *chunk_udata)
{
H5FA_t *fa;
H5FA_stat_t fa_stat;
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.farray.fa) {
if(H5D__farray_idx_open(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open fixed array")
} else
H5FA_patch_file(idx_info->storage->u.farray.fa, idx_info->f);
fa = idx_info->storage->u.farray.fa;
if(H5FA_get_stats(fa, &fa_stat) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't query fixed array statistics")
if(fa_stat.nelmts > 0) {
H5D_farray_it_ud_t udata;
HDmemset(&udata, 0, sizeof udata);
udata.common.layout = idx_info->layout;
udata.common.storage = idx_info->storage;
HDmemset(&udata.chunk_rec, 0, sizeof(udata.chunk_rec));
udata.filtered = (idx_info->pline->nused > 0);
if(!udata.filtered) {
udata.chunk_rec.nbytes = idx_info->layout->size;
udata.chunk_rec.filter_mask = 0;
}
udata.cb = chunk_cb;
udata.udata = chunk_udata;
if((ret_value = H5FA_iterate(fa, H5D__farray_idx_iterate_cb, &udata)) < 0)
HERROR(H5E_DATASET, H5E_BADITER, "unable to iterate over fixed array chunk index");
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__farray_idx_remove(const H5D_chk_idx_info_t *idx_info, H5D_chunk_common_ud_t *udata)
{
H5FA_t *fa;
hsize_t idx;
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.farray.fa) {
if(H5D__farray_idx_open(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open fixed array")
} else
if(H5FA_patch_file(idx_info->storage->u.farray.fa, idx_info->f) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't patch fixed array file pointer")
fa = idx_info->storage->u.farray.fa;
idx = H5VM_array_offset_pre((idx_info->layout->ndims - 1), idx_info->layout->max_down_chunks, udata->scaled);
if(idx_info->pline->nused > 0) {
H5D_farray_filt_elmt_t elmt;
if(H5FA_get(fa, idx, &elmt) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk info")
HDassert(H5F_addr_defined(elmt.addr));
if(!(H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE)) {
H5_CHECK_OVERFLOW(elmt.nbytes, uint32_t, hsize_t);
if(H5MF_xfree(idx_info->f, H5FD_MEM_DRAW, elmt.addr, (hsize_t)elmt.nbytes) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to free chunk")
}
elmt.addr = HADDR_UNDEF;
elmt.nbytes = 0;
elmt.filter_mask = 0;
if(H5FA_set(fa, idx, &elmt) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to reset chunk info")
}
else {
haddr_t addr = HADDR_UNDEF;
if(H5FA_get(fa, idx, &addr) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address")
HDassert(H5F_addr_defined(addr));
if(!(H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE)) {
H5_CHECK_OVERFLOW(idx_info->layout->size, uint32_t, hsize_t);
if(H5MF_xfree(idx_info->f, H5FD_MEM_DRAW, addr, (hsize_t)idx_info->layout->size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to free chunk")
}
addr = HADDR_UNDEF;
if(H5FA_set(fa, idx, &addr) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to reset chunk address")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static int
H5D__farray_idx_delete_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
{
H5F_t *f = (H5F_t *)_udata;
int ret_value = H5_ITER_CONT;
FUNC_ENTER_STATIC
HDassert(chunk_rec);
HDassert(H5F_addr_defined(chunk_rec->chunk_addr));
HDassert(chunk_rec->nbytes > 0);
HDassert(f);
H5_CHECK_OVERFLOW(chunk_rec->nbytes, uint32_t, hsize_t);
if(H5MF_xfree(f, H5FD_MEM_DRAW, chunk_rec->chunk_addr, (hsize_t)chunk_rec->nbytes) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, H5_ITER_ERROR, "unable to free chunk")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__farray_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)) {
H5D_farray_ctx_ud_t ctx_udata;
if(H5D__farray_idx_iterate(idx_info, H5D__farray_idx_delete_cb, idx_info->f) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to iterate over chunk addresses")
if(H5FA_close(idx_info->storage->u.farray.fa) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close fixed array")
idx_info->storage->u.farray.fa = NULL;
ctx_udata.f = idx_info->f;
ctx_udata.chunk_size = idx_info->layout->size;
if(H5FA_delete(idx_info->f, idx_info->storage->idx_addr, &ctx_udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTDELETE, FAIL, "unable to delete chunk fixed array")
idx_info->storage->idx_addr = HADDR_UNDEF;
}
else
HDassert(NULL == idx_info->storage->u.farray.fa);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__farray_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.farray.fa)
if(H5D__farray_idx_open(idx_info_src) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open fixed array")
H5_BEGIN_TAG(H5AC__COPIED_TAG);
if(H5D__farray_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__farray_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.farray.fa);
HDassert(storage_dst);
HDassert(storage_dst->u.farray.fa);
if(H5FA_close(storage_src->u.farray.fa) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close fixed array")
storage_src->u.farray.fa = NULL;
if(H5FA_close(storage_dst->u.farray.fa) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close fixed array")
storage_dst->u.farray.fa = NULL;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__farray_idx_size(const H5D_chk_idx_info_t *idx_info, hsize_t *index_size)
{
H5FA_t *fa;
H5FA_stat_t fa_stat;
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__farray_idx_open(idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open fixed array")
fa = idx_info->storage->u.farray.fa;
if(H5FA_get_stats(fa, &fa_stat) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't query fixed array statistics")
*index_size = fa_stat.hdr_size;
*index_size += fa_stat.dblk_size;
done:
if(idx_info->storage->u.farray.fa) {
if(H5FA_close(idx_info->storage->u.farray.fa) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close fixed array")
idx_info->storage->u.farray.fa = NULL;
}
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__farray_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.farray.fa = NULL;
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__farray_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__farray_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.farray.fa) {
if(H5FA_patch_file(idx_info->storage->u.farray.fa, idx_info->f) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't patch fixed array file pointer")
if(H5FA_close(idx_info->storage->u.farray.fa) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close fixed array")
idx_info->storage->u.farray.fa = NULL;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}