#include "H5Dmodule.h"
#include "H5private.h"
#ifdef H5_HAVE_PARALLEL
#include "H5ACprivate.h"
#endif
#include "H5CXprivate.h"
#include "H5Dpkg.h"
#include "H5Eprivate.h"
#include "H5Fprivate.h"
#include "H5FLprivate.h"
#include "H5Iprivate.h"
#include "H5MMprivate.h"
#include "H5MFprivate.h"
#include "H5VMprivate.h"
#define H5D_CHUNK_GET_FIRST_NODE(map) (map->use_single ? (H5SL_node_t *)(1) : H5SL_first(map->sel_chunks))
#define H5D_CHUNK_GET_NODE_INFO(map, node) (map->use_single ? map->single_chunk_info : (H5D_chunk_info_t *)H5SL_item(node))
#define H5D_CHUNK_GET_NEXT_NODE(map, node) (map->use_single ? (H5SL_node_t *)NULL : H5SL_next(node))
#define H5D_CHUNK_STORAGE_INDEX_CHK(storage) \
HDassert((H5D_CHUNK_IDX_EARRAY == (storage)->idx_type && H5D_COPS_EARRAY == (storage)->ops) || \
(H5D_CHUNK_IDX_FARRAY == (storage)->idx_type && H5D_COPS_FARRAY == (storage)->ops) || \
(H5D_CHUNK_IDX_BT2 == (storage)->idx_type && H5D_COPS_BT2 == (storage)->ops) || \
(H5D_CHUNK_IDX_BTREE == (storage)->idx_type && H5D_COPS_BTREE == (storage)->ops) || \
(H5D_CHUNK_IDX_SINGLE == (storage)->idx_type && H5D_COPS_SINGLE == (storage)->ops) || \
(H5D_CHUNK_IDX_NONE == (storage)->idx_type && H5D_COPS_NONE == (storage)->ops));
#define H5D_RDCC_DISABLE_FILTERS 0x01u
#define H5D_RDCC_NEWLY_DISABLED_FILTERS 0x02u
typedef struct H5D_rdcc_ent_t {
hbool_t locked;
hbool_t dirty;
hbool_t deleted;
unsigned edge_chunk_state;
hsize_t scaled[H5O_LAYOUT_NDIMS];
uint32_t rd_count;
uint32_t wr_count;
H5F_block_t chunk_block;
hsize_t chunk_idx;
uint8_t *chunk;
unsigned idx;
struct H5D_rdcc_ent_t *next;
struct H5D_rdcc_ent_t *prev;
struct H5D_rdcc_ent_t *tmp_next;
struct H5D_rdcc_ent_t *tmp_prev;
} H5D_rdcc_ent_t;
typedef H5D_rdcc_ent_t *H5D_rdcc_ent_ptr_t;
typedef struct H5D_chunk_it_ud1_t {
H5D_chunk_common_ud_t common;
const H5D_chk_idx_info_t *idx_info;
const H5D_io_info_t *io_info;
const hsize_t *space_dim;
const hbool_t *shrunk_dim;
H5S_t *chunk_space;
uint32_t elmts_per_chunk;
hsize_t *hyper_start;
H5D_fill_buf_info_t fb_info;
hbool_t fb_info_init;
} H5D_chunk_it_ud1_t;
typedef struct H5D_chunk_it_ud2_t {
H5D_chunk_common_ud_t common;
haddr_t *chunk_addr;
} H5D_chunk_it_ud2_t;
typedef struct H5D_chunk_it_ud3_t {
H5D_chunk_common_ud_t common;
H5F_t *file_src;
H5D_chk_idx_info_t *idx_info_dst;
void *buf;
void *bkg;
size_t buf_size;
hbool_t do_convert;
hid_t tid_src;
hid_t tid_dst;
hid_t tid_mem;
const H5T_t *dt_src;
H5T_path_t *tpath_src_mem;
H5T_path_t *tpath_mem_dst;
void *reclaim_buf;
size_t reclaim_buf_size;
uint32_t nelmts;
H5S_t *buf_space;
const H5O_pline_t *pline;
unsigned dset_ndims;
const hsize_t *dset_dims;
H5O_copy_t *cpy_info;
hbool_t chunk_in_cache;
uint8_t *chunk;
} H5D_chunk_it_ud3_t;
typedef struct H5D_chunk_it_ud4_t {
FILE *stream;
hbool_t header_displayed;
unsigned ndims;
uint32_t *chunk_dim;
} H5D_chunk_it_ud4_t;
typedef struct H5D_chunk_it_ud5_t {
H5D_chk_idx_info_t *new_idx_info;
unsigned dset_ndims;
hsize_t *dset_dims;
} H5D_chunk_it_ud5_t;
typedef struct H5D_chunk_readvv_ud_t {
unsigned char *rbuf;
const H5D_t *dset;
} H5D_chunk_readvv_ud_t;
typedef struct H5D_chunk_info_iter_ud_t {
hsize_t scaled[H5O_LAYOUT_NDIMS];
hsize_t ndims;
uint32_t nbytes;
unsigned filter_mask;
haddr_t chunk_addr;
hsize_t chunk_idx;
hsize_t curr_idx;
hbool_t found;
} H5D_chunk_info_iter_ud_t;
typedef struct H5D_chunk_file_iter_ud_t {
H5D_chunk_map_t *fm;
#ifdef H5_HAVE_PARALLEL
const H5D_io_info_t *io_info;
#endif
} H5D_chunk_file_iter_ud_t;
#ifdef H5_HAVE_PARALLEL
typedef struct H5D_chunk_coll_info_t {
size_t num_io;
haddr_t *addr;
} H5D_chunk_coll_info_t;
#endif
static herr_t H5D__chunk_construct(H5F_t *f, H5D_t *dset);
static herr_t H5D__chunk_init(H5F_t *f, const H5D_t *dset, hid_t dapl_id);
static herr_t H5D__chunk_io_init(const H5D_io_info_t *io_info,
const H5D_type_info_t *type_info, hsize_t nelmts, const H5S_t *file_space,
const H5S_t *mem_space, H5D_chunk_map_t *fm);
static herr_t H5D__chunk_io_init_selections(const H5D_io_info_t *io_info,
const H5D_type_info_t *type_info, H5D_chunk_map_t *fm);
static herr_t H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
H5D_chunk_map_t *fm);
static herr_t H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
H5D_chunk_map_t *fm);
static herr_t H5D__chunk_flush(H5D_t *dset);
static herr_t H5D__chunk_io_term(const H5D_chunk_map_t *fm);
static herr_t H5D__chunk_dest(H5D_t *dset);
static int H5D__get_num_chunks_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata);
static int H5D__get_chunk_info_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata);
static int H5D__get_chunk_info_by_coord_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata);
static ssize_t
H5D__nonexistent_readvv(const H5D_io_info_t *io_info,
size_t chunk_max_nseq, size_t *chunk_curr_seq, size_t chunk_len_arr[], hsize_t chunk_offset_arr[],
size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
static int H5D__chunk_format_convert_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata);
static herr_t H5D__chunk_set_info_real(H5O_layout_chunk_t *layout, unsigned ndims,
const hsize_t *curr_dims, const hsize_t *max_dims);
static void *H5D__chunk_mem_alloc(size_t size, const H5O_pline_t *pline);
static void *H5D__chunk_mem_xfree(void *chk, const H5O_pline_t *pline);
static void *H5D__chunk_mem_realloc(void *chk, size_t size,
const H5O_pline_t *pline);
static herr_t H5D__chunk_cinfo_cache_reset(H5D_chunk_cached_t *last);
static herr_t H5D__chunk_cinfo_cache_update(H5D_chunk_cached_t *last,
const H5D_chunk_ud_t *udata);
static hbool_t H5D__chunk_cinfo_cache_found(const H5D_chunk_cached_t *last,
H5D_chunk_ud_t *udata);
static herr_t H5D__free_chunk_info(void *item, void *key, void *opdata);
static herr_t H5D__create_chunk_map_single(H5D_chunk_map_t *fm,
const H5D_io_info_t *io_info);
static herr_t H5D__create_chunk_file_map_all(H5D_chunk_map_t *fm,
const H5D_io_info_t *io_info);
static herr_t H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm,
const H5D_io_info_t *io_info);
static herr_t H5D__create_chunk_mem_map_1d(const H5D_chunk_map_t *fm);
static herr_t H5D__create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm);
static herr_t H5D__chunk_file_cb(void *elem, const H5T_t *type, unsigned ndims,
const hsize_t *coords, void *fm);
static herr_t H5D__chunk_mem_cb(void *elem, const H5T_t *type, unsigned ndims,
const hsize_t *coords, void *fm);
static unsigned H5D__chunk_hash_val(const H5D_shared_t *shared, const hsize_t *scaled);
static herr_t H5D__chunk_flush_entry(const H5D_t *dset, H5D_rdcc_ent_t *ent,
hbool_t reset);
static herr_t H5D__chunk_cache_evict(const H5D_t *dset, H5D_rdcc_ent_t *ent,
hbool_t flush);
static hbool_t H5D__chunk_is_partial_edge_chunk(unsigned dset_ndims,
const uint32_t *chunk_dims, const hsize_t *chunk_scaled, const hsize_t *dset_dims);
static void *H5D__chunk_lock(const H5D_io_info_t *io_info,
H5D_chunk_ud_t *udata, hbool_t relax, hbool_t prev_unfilt_chunk);
static herr_t H5D__chunk_unlock(const H5D_io_info_t *io_info,
const H5D_chunk_ud_t *udata, hbool_t dirty, void *chunk, uint32_t naccessed);
static herr_t H5D__chunk_cache_prune(const H5D_t *dset, size_t size);
static herr_t H5D__chunk_prune_fill(H5D_chunk_it_ud1_t *udata, hbool_t new_unfilt_chunk);
#ifdef H5_HAVE_PARALLEL
static herr_t H5D__chunk_collective_fill(const H5D_t *dset,
H5D_chunk_coll_info_t *chunk_info, size_t chunk_size, const void *fill_buf);
static int H5D__chunk_cmp_addr(const void *addr1, const void *addr2);
#endif
static int H5D__chunk_dump_index_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata);
const H5D_layout_ops_t H5D_LOPS_CHUNK[1] = {{
H5D__chunk_construct,
H5D__chunk_init,
H5D__chunk_is_space_alloc,
H5D__chunk_is_data_cached,
H5D__chunk_io_init,
H5D__chunk_read,
H5D__chunk_write,
#ifdef H5_HAVE_PARALLEL
H5D__chunk_collective_read,
H5D__chunk_collective_write,
#endif
NULL,
NULL,
H5D__chunk_flush,
H5D__chunk_io_term,
H5D__chunk_dest
}};
const H5D_layout_ops_t H5D_LOPS_NONEXISTENT[1] = {{
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
#ifdef H5_HAVE_PARALLEL
NULL,
NULL,
#endif
H5D__nonexistent_readvv,
NULL,
NULL,
NULL,
NULL
}};
H5FL_SEQ_DEFINE_STATIC(H5D_rdcc_ent_ptr_t);
H5FL_DEFINE_STATIC(H5D_rdcc_ent_t);
H5FL_DEFINE(H5D_chunk_info_t);
H5FL_BLK_DEFINE_STATIC(chunk);
H5FL_EXTERN(H5S_sel_iter_t);
herr_t
H5D__chunk_direct_write(const H5D_t *dset, uint32_t filters, hsize_t *offset,
uint32_t data_size, const void *buf)
{
const H5O_layout_t *layout = &(dset->shared->layout);
H5D_chunk_ud_t udata;
H5F_block_t old_chunk;
H5D_chk_idx_info_t idx_info;
hsize_t scaled[H5S_MAX_RANK];
hbool_t need_insert = FALSE;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE_TAG(dset->oloc.addr)
HDassert(layout->type == H5D_CHUNKED);
if(!H5D__chunk_is_space_alloc(&layout->storage)) {
H5D_io_info_t io_info;
io_info.dset = dset;
if(H5D__alloc_storage(&io_info, H5D_ALLOC_WRITE, FALSE, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize storage")
}
H5VM_chunk_scaled(dset->shared->ndims, offset, layout->u.chunk.dim, scaled);
scaled[dset->shared->ndims] = 0;
if(H5D__chunk_lookup(dset, scaled, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
HDassert((H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length > 0) ||
(!H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length == 0));
old_chunk.offset = udata.chunk_block.offset;
old_chunk.length = udata.chunk_block.length;
idx_info.f = dset->oloc.file;
idx_info.pline = &(dset->shared->dcpl_cache.pline);
idx_info.layout = &(dset->shared->layout.u.chunk);
idx_info.storage = &(dset->shared->layout.storage.u.chunk);
udata.chunk_block.length = data_size;
if(0 == idx_info.pline->nused && H5F_addr_defined(old_chunk.offset))
need_insert = FALSE;
else {
if(H5D__chunk_file_alloc(&idx_info, &old_chunk, &udata.chunk_block, &need_insert, scaled) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "unable to allocate chunk")
H5D__chunk_cinfo_cache_update(&dset->shared->cache.chunk.last, &udata);
}
if(!H5F_addr_defined(udata.chunk_block.offset))
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "chunk address isn't defined")
if(UINT_MAX != udata.idx_hint) {
const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
if(H5D__chunk_cache_evict(dset, rdcc->slot[udata.idx_hint], FALSE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTREMOVE, FAIL, "unable to evict chunk")
}
if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.chunk_block.offset, data_size, buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to write raw data to file")
if(need_insert && layout->storage.u.chunk.ops->insert) {
udata.filter_mask = filters;
if((layout->storage.u.chunk.ops->insert)(&idx_info, &udata, dset) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert chunk addr into index")
}
done:
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
herr_t
H5D__chunk_direct_read(const H5D_t *dset, hsize_t *offset, uint32_t* filters,
void *buf)
{
const H5O_layout_t *layout = &(dset->shared->layout);
const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
H5D_chunk_ud_t udata;
hsize_t scaled[H5S_MAX_RANK];
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE_TAG(dset->oloc.addr)
HDassert(dset && H5D_CHUNKED == layout->type);
HDassert(offset);
HDassert(filters);
HDassert(buf);
*filters = 0;
if(!H5D__chunk_is_space_alloc(&layout->storage)
&& !H5D__chunk_is_data_cached(dset->shared))
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "storage is not initialized")
H5VM_chunk_scaled(dset->shared->ndims, offset, layout->u.chunk.dim, scaled);
scaled[dset->shared->ndims] = 0;
udata.filter_mask = 0;
udata.chunk_block.offset = HADDR_UNDEF;
udata.chunk_block.length = 0;
udata.idx_hint = UINT_MAX;
if(H5D__chunk_lookup(dset, scaled, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
HDassert((H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length > 0) ||
(!H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length == 0));
if(UINT_MAX != udata.idx_hint) {
H5D_rdcc_ent_t *ent = rdcc->slot[udata.idx_hint];
hbool_t flush;
HDassert(udata.idx_hint < rdcc->nslots);
HDassert(rdcc->slot[udata.idx_hint]);
flush = (ent->dirty == TRUE) ? TRUE : FALSE;
if(H5D__chunk_cache_evict(dset, rdcc->slot[udata.idx_hint], flush) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTREMOVE, FAIL, "unable to evict chunk")
udata.filter_mask = 0;
udata.chunk_block.offset = HADDR_UNDEF;
udata.chunk_block.length = 0;
udata.idx_hint = UINT_MAX;
if(H5D__chunk_lookup(dset, scaled, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
}
if(!H5F_addr_defined(udata.chunk_block.offset))
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "chunk address isn't defined")
if(H5F_block_read(dset->oloc.file, H5FD_MEM_DRAW, udata.chunk_block.offset, udata.chunk_block.length, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
*filters = udata.filter_mask;
done:
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
herr_t
H5D__get_chunk_storage_size(H5D_t *dset, const hsize_t *offset, hsize_t *storage_size)
{
const H5O_layout_t *layout = &(dset->shared->layout);
const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
hsize_t scaled[H5S_MAX_RANK];
H5D_chunk_ud_t udata;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE_TAG(dset->oloc.addr)
HDassert(dset && H5D_CHUNKED == layout->type);
HDassert(offset);
HDassert(storage_size);
*storage_size = 0;
if(!(*layout->ops->is_space_alloc)(&layout->storage))
HGOTO_DONE(SUCCEED)
H5VM_chunk_scaled(dset->shared->ndims, offset, layout->u.chunk.dim, scaled);
scaled[dset->shared->ndims] = 0;
udata.chunk_block.offset = HADDR_UNDEF;
udata.chunk_block.length = 0;
udata.idx_hint = UINT_MAX;
if(H5D__chunk_lookup(dset, scaled, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
HDassert((H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length > 0) ||
(!H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length == 0));
if(!H5F_addr_defined(udata.chunk_block.offset) && UINT_MAX == udata.idx_hint)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "chunk storage is not allocated")
if( dset->shared->dcpl_cache.pline.nused > 0 ) {
if(UINT_MAX != udata.idx_hint) {
H5D_rdcc_ent_t *ent = rdcc->slot[udata.idx_hint];
HDassert(udata.idx_hint < rdcc->nslots);
HDassert(rdcc->slot[udata.idx_hint]);
if( ent->dirty == TRUE ) {
if(H5D__chunk_cache_evict(dset, rdcc->slot[udata.idx_hint], TRUE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTREMOVE, FAIL, "unable to evict chunk")
udata.chunk_block.offset = HADDR_UNDEF;
udata.chunk_block.length = 0;
udata.idx_hint = UINT_MAX;
if(H5D__chunk_lookup(dset, scaled, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
}
}
if(!H5F_addr_defined(udata.chunk_block.offset))
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "chunk address isn't defined")
*storage_size = udata.chunk_block.length;
}
else
*storage_size = dset->shared->layout.u.chunk.size;
done:
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
static herr_t
H5D__chunk_set_info_real(H5O_layout_chunk_t *layout, unsigned ndims,
const hsize_t *curr_dims, const hsize_t *max_dims)
{
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(layout);
HDassert(ndims > 0);
HDassert(curr_dims);
for(u = 0, layout->nchunks = 1, layout->max_nchunks = 1; u < ndims; u++) {
layout->chunks[u] = ((curr_dims[u] + layout->dim[u]) - 1) / layout->dim[u];
if(H5S_UNLIMITED == max_dims[u])
layout->max_chunks[u] = H5S_UNLIMITED;
else
{
if(layout->dim[u] == 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "dimension size must be > 0, dim = %u ", u)
layout->max_chunks[u] = ((max_dims[u] + layout->dim[u]) - 1) / layout->dim[u];
}
layout->nchunks *= layout->chunks[u];
layout->max_nchunks *= layout->max_chunks[u];
}
if(H5VM_array_down(ndims, layout->chunks, layout->down_chunks) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't compute 'down' chunk size value")
if(H5VM_array_down(ndims, layout->max_chunks, layout->max_down_chunks) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't compute 'down' chunk size value")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5D__chunk_set_info(const H5D_t *dset)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(dset);
if(H5D__chunk_set_info_real(&dset->shared->layout.u.chunk, dset->shared->ndims, dset->shared->curr_dims, dset->shared->max_dims) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set layout's chunk info")
if(dset->shared->layout.storage.u.chunk.ops->resize && (dset->shared->layout.storage.u.chunk.ops->resize)(&dset->shared->layout.u.chunk) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to resize chunk index information")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5D__chunk_set_sizes(H5D_t *dset)
{
uint64_t chunk_size;
unsigned max_enc_bytes_per_dim;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(dset);
dset->shared->layout.u.chunk.ndims++;
dset->shared->layout.u.chunk.dim[dset->shared->layout.u.chunk.ndims - 1] = (uint32_t)H5T_GET_SIZE(dset->shared->type);
max_enc_bytes_per_dim = 0;
for(u = 0; u < (unsigned)dset->shared->layout.u.chunk.ndims; u++) {
unsigned enc_bytes_per_dim;
enc_bytes_per_dim = (H5VM_log2_gen(dset->shared->layout.u.chunk.dim[u]) + 8) / 8;
if(enc_bytes_per_dim > max_enc_bytes_per_dim)
max_enc_bytes_per_dim = enc_bytes_per_dim;
}
HDassert(max_enc_bytes_per_dim > 0 && max_enc_bytes_per_dim <= 8);
dset->shared->layout.u.chunk.enc_bytes_per_dim = max_enc_bytes_per_dim;
for(u = 1, chunk_size = (uint64_t)dset->shared->layout.u.chunk.dim[0]; u < dset->shared->layout.u.chunk.ndims; u++)
chunk_size *= (uint64_t)dset->shared->layout.u.chunk.dim[u];
if(chunk_size > (uint64_t)0xffffffff)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "chunk size must be < 4GB")
H5_CHECKED_ASSIGN(dset->shared->layout.u.chunk.size, uint32_t, chunk_size, uint64_t);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__chunk_construct(H5F_t H5_ATTR_UNUSED *f, H5D_t *dset)
{
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(f);
HDassert(dset);
if(0 == dset->shared->layout.u.chunk.ndims)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "no chunk information set?")
if(dset->shared->layout.u.chunk.ndims != dset->shared->ndims)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "dimensionality of chunks doesn't match the dataspace")
if(H5D__chunk_set_sizes(dset) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "unable to set chunk sizes")
HDassert((unsigned)(dset->shared->layout.u.chunk.ndims) <= NELMTS(dset->shared->layout.u.chunk.dim));
if(dset->shared->dcpl_cache.efl.nused > 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "external storage not supported with chunked layout")
for(u = 0; u < dset->shared->layout.u.chunk.ndims - 1; u++) {
if(0 == dset->shared->layout.u.chunk.dim[u])
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "chunk size must be > 0, dim = %u ", u)
if(dset->shared->curr_dims[u] && dset->shared->max_dims[u] != H5S_UNLIMITED && dset->shared->max_dims[u] < dset->shared->layout.u.chunk.dim[u])
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "chunk size must be <= maximum dimension size for fixed-sized dimensions")
}
if(H5D_chunk_idx_reset(&dset->shared->layout.storage.u.chunk, TRUE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to reset chunked storage index")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__chunk_init(H5F_t *f, const H5D_t * const dset, hid_t dapl_id)
{
H5D_chk_idx_info_t idx_info;
H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
H5P_genplist_t *dapl;
H5O_storage_chunk_t *sc = &(dset->shared->layout.storage.u.chunk);
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(f);
HDassert(dset);
H5D_CHUNK_STORAGE_INDEX_CHK(sc);
if(NULL == (dapl = (H5P_genplist_t *)H5I_object(dapl_id)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for fapl ID")
if(H5P_get(dapl, H5D_ACS_DATA_CACHE_NUM_SLOTS_NAME, &rdcc->nslots) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get data cache number of slots")
if(rdcc->nslots == H5D_CHUNK_CACHE_NSLOTS_DEFAULT)
rdcc->nslots = H5F_RDCC_NSLOTS(f);
if(H5P_get(dapl, H5D_ACS_DATA_CACHE_BYTE_SIZE_NAME, &rdcc->nbytes_max) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get data cache byte size")
if(rdcc->nbytes_max == H5D_CHUNK_CACHE_NBYTES_DEFAULT)
rdcc->nbytes_max = H5F_RDCC_NBYTES(f);
if(H5P_get(dapl, H5D_ACS_PREEMPT_READ_CHUNKS_NAME, &rdcc->w0) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get preempt read chunks")
if(rdcc->w0 < 0)
rdcc->w0 = H5F_RDCC_W0(f);
if(!rdcc->nbytes_max || !rdcc->nslots)
rdcc->nbytes_max = rdcc->nslots = 0;
else {
rdcc->slot = H5FL_SEQ_CALLOC(H5D_rdcc_ent_ptr_t, rdcc->nslots);
if(NULL == rdcc->slot)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
H5D__chunk_cinfo_cache_reset(&(rdcc->last));
}
if(dset->shared->ndims > 1) {
unsigned u;
for(u = 0; u < dset->shared->ndims; u++) {
hsize_t scaled_power2up;
if(dset->shared->layout.u.chunk.dim[u] == 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "chunk size must be > 0, dim = %u ", u)
rdcc->scaled_dims[u] = (dset->shared->curr_dims[u] + dset->shared->layout.u.chunk.dim[u] - 1) /
dset->shared->layout.u.chunk.dim[u];
if( !(scaled_power2up = H5VM_power2up(rdcc->scaled_dims[u])) )
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get the next power of 2")
rdcc->scaled_power2up[u] = scaled_power2up;
rdcc->scaled_encode_bits[u] = H5VM_log2_gen(rdcc->scaled_power2up[u]);
}
}
idx_info.f = f;
idx_info.pline = &dset->shared->dcpl_cache.pline;
idx_info.layout = &dset->shared->layout.u.chunk;
idx_info.storage = sc;
if(sc->ops->init && (sc->ops->init)(&idx_info, dset->shared->space, dset->oloc.addr) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize indexing information")
if(H5D__chunk_set_info(dset) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set # of chunks for dataset")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
hbool_t
H5D__chunk_is_space_alloc(const H5O_storage_t *storage)
{
const H5O_storage_chunk_t *sc = &(storage->u.chunk);
hbool_t ret_value = FALSE;
FUNC_ENTER_PACKAGE_NOERR
HDassert(storage);
H5D_CHUNK_STORAGE_INDEX_CHK(sc);
ret_value = (sc->ops->is_space_alloc)(sc);
FUNC_LEAVE_NOAPI(ret_value)
}
hbool_t
H5D__chunk_is_data_cached(const H5D_shared_t *shared_dset)
{
FUNC_ENTER_PACKAGE_NOERR
HDassert(shared_dset);
FUNC_LEAVE_NOAPI(shared_dset->cache.chunk.nused > 0)
}
static herr_t
H5D__chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
H5D_chunk_map_t *fm)
{
const H5D_t *dataset = io_info->dset;
hssize_t old_offset[H5O_LAYOUT_NDIMS];
htri_t file_space_normalized = FALSE;
unsigned f_ndims;
int sm_ndims;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
fm->layout = &(dataset->shared->layout);
fm->nelmts = nelmts;
if((sm_ndims = H5S_GET_EXTENT_NDIMS(mem_space)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimension number")
H5_CHECKED_ASSIGN(fm->m_ndims, unsigned, sm_ndims, int);
fm->f_ndims = f_ndims = dataset->shared->layout.u.chunk.ndims - 1;
if((file_space_normalized = H5S_hyper_normalize_offset((H5S_t *)file_space, old_offset)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to normalize selection")
for(u = 0; u < f_ndims; u++)
fm->chunk_dim[u] = fm->layout->u.chunk.dim[u];
#ifdef H5_HAVE_PARALLEL
fm->select_chunk = NULL;
if(io_info->using_mpi_vfd) {
H5_CHECK_OVERFLOW(fm->layout->u.chunk.nchunks, hsize_t, size_t);
if(fm->layout->u.chunk.nchunks)
if(NULL == (fm->select_chunk = (H5D_chunk_info_t **)H5MM_calloc((size_t)fm->layout->u.chunk.nchunks * sizeof(H5D_chunk_info_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
}
#endif
fm->last_index = (hsize_t)-1;
fm->last_chunk_info = NULL;
fm->file_space = file_space;
fm->mem_space = mem_space;
if(H5D__chunk_io_init_selections(io_info, type_info, fm) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file and memory chunk selections")
done:
fm->file_space = NULL;
fm->mem_space = NULL;
if(file_space_normalized == TRUE)
if(H5S_hyper_denormalize_offset((H5S_t *)file_space, old_offset) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't denormalize selection")
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__chunk_io_init_selections(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, H5D_chunk_map_t *fm)
{
const H5D_t *dataset = io_info->dset;
const H5T_t *mem_type = type_info->mem_type;
H5S_t *tmp_mspace = NULL;
H5T_t *file_type = NULL;
hbool_t iter_init = FALSE;
char bogus;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
if(fm->nelmts == 1
#ifdef H5_HAVE_PARALLEL
&& !(io_info->using_mpi_vfd)
#endif
&& H5S_SEL_ALL != H5S_GET_SELECT_TYPE(fm->file_space)) {
fm->sel_chunks = NULL;
fm->use_single = TRUE;
if(NULL == dataset->shared->cache.chunk.single_space) {
if((dataset->shared->cache.chunk.single_space = H5S_copy(fm->file_space, TRUE, FALSE)) == NULL)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file space")
if(H5S_set_extent_real(dataset->shared->cache.chunk.single_space, fm->chunk_dim) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't adjust chunk dimensions")
if(H5S_select_all(dataset->shared->cache.chunk.single_space, TRUE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, FAIL, "unable to set all selection")
}
fm->single_space = dataset->shared->cache.chunk.single_space;
HDassert(fm->single_space);
if(NULL == dataset->shared->cache.chunk.single_chunk_info)
if(NULL == (dataset->shared->cache.chunk.single_chunk_info = H5FL_MALLOC(H5D_chunk_info_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
fm->single_chunk_info = dataset->shared->cache.chunk.single_chunk_info;
HDassert(fm->single_chunk_info);
fm->mchunk_tmpl = NULL;
if(H5D__create_chunk_map_single(fm, io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create chunk selections for single element")
}
else {
hbool_t sel_hyper_flag;
if(NULL == dataset->shared->cache.chunk.sel_chunks)
if(NULL == (dataset->shared->cache.chunk.sel_chunks = H5SL_create(H5SL_TYPE_HSIZE, NULL)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "can't create skip list for chunk selections")
fm->sel_chunks = dataset->shared->cache.chunk.sel_chunks;
HDassert(fm->sel_chunks);
fm->use_single = FALSE;
if((fm->fsel_type = H5S_GET_SELECT_TYPE(fm->file_space)) < H5S_SEL_NONE)
HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to get type of selection")
if((fm->msel_type = H5S_GET_SELECT_TYPE(fm->mem_space)) < H5S_SEL_NONE)
HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to get type of selection")
if(fm->fsel_type == H5S_SEL_POINTS || fm->fsel_type == H5S_SEL_NONE)
sel_hyper_flag = FALSE;
else
sel_hyper_flag = TRUE;
if(sel_hyper_flag) {
if(H5S_SEL_ALL == fm->fsel_type) {
if(H5D__create_chunk_file_map_all(fm, io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections")
}
else {
HDassert(fm->fsel_type == H5S_SEL_HYPERSLABS);
if(H5D__create_chunk_file_map_hyper(fm, io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections")
}
}
else {
H5S_sel_iter_op_t iter_op;
H5D_chunk_file_iter_ud_t udata;
if(NULL == (file_type = H5T_copy(dataset->shared->type, H5T_COPY_ALL)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy file datatype")
udata.fm = fm;
#ifdef H5_HAVE_PARALLEL
udata.io_info = io_info;
#endif
iter_op.op_type = H5S_SEL_ITER_OP_LIB;
iter_op.u.lib_op = H5D__chunk_file_cb;
if(H5S_select_iterate(&bogus, file_type, fm->file_space, &iter_op, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections")
fm->last_index = (hsize_t)-1;
fm->last_chunk_info = NULL;
}
if(sel_hyper_flag && H5S_SELECT_SHAPE_SAME(fm->file_space, fm->mem_space) == TRUE) {
fm->mchunk_tmpl = NULL;
if(H5D__create_chunk_mem_map_hyper(fm) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create memory chunk selections")
}
else if(sel_hyper_flag && fm->f_ndims == 1 && fm->m_ndims == 1 &&
H5S_SELECT_IS_REGULAR(fm->mem_space) && H5S_SELECT_IS_SINGLE(fm->mem_space)) {
if(H5D__create_chunk_mem_map_1d(fm) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections")
}
else {
H5S_sel_iter_op_t iter_op;
size_t elmt_size;
if((tmp_mspace = H5S_copy(fm->mem_space, TRUE, FALSE)) == NULL)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
if(H5S_select_none(tmp_mspace) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to de-select memory space")
fm->mchunk_tmpl = tmp_mspace;
if(!file_type)
if(NULL == (file_type = H5T_copy(dataset->shared->type, H5T_COPY_ALL)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy file datatype")
if(0 == (elmt_size = H5T_get_size(mem_type)))
HGOTO_ERROR(H5E_DATATYPE, H5E_BADSIZE, FAIL, "datatype size invalid")
if(H5S_select_iter_init(&(fm->mem_iter), fm->mem_space, elmt_size, 0) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
iter_init = TRUE;
iter_op.op_type = H5S_SEL_ITER_OP_LIB;
iter_op.u.lib_op = H5D__chunk_mem_cb;
if(H5S_select_iterate(&bogus, file_type, fm->file_space, &iter_op, fm) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create memory chunk selections")
}
}
done:
if(ret_value < 0) {
if(tmp_mspace && !fm->mchunk_tmpl)
if(H5S_close(tmp_mspace) < 0)
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "can't release memory chunk dataspace template")
if(H5D__chunk_io_term(fm) < 0)
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release chunk mapping")
}
if(iter_init && H5S_SELECT_ITER_RELEASE(&(fm->mem_iter)) < 0)
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator")
if(file_type && (H5T_close_real(file_type) < 0))
HDONE_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "Can't free temporary datatype")
FUNC_LEAVE_NOAPI(ret_value)
}
static void *
H5D__chunk_mem_alloc(size_t size, const H5O_pline_t *pline)
{
void *ret_value = NULL;
FUNC_ENTER_STATIC_NOERR
HDassert(size);
if(pline && pline->nused)
ret_value = H5MM_malloc(size);
else
ret_value = H5FL_BLK_MALLOC(chunk, size);
FUNC_LEAVE_NOAPI(ret_value)
}
static void *
H5D__chunk_mem_xfree(void *chk, const H5O_pline_t *pline)
{
FUNC_ENTER_STATIC_NOERR
if(chk) {
if(pline && pline->nused)
H5MM_xfree(chk);
else
chk = H5FL_BLK_FREE(chunk, chk);
}
FUNC_LEAVE_NOAPI(NULL)
}
static void *
H5D__chunk_mem_realloc(void *chk, size_t size, const H5O_pline_t *pline)
{
void *ret_value = NULL;
FUNC_ENTER_STATIC_NOERR
HDassert(size);
HDassert(pline);
if(pline->nused > 0)
ret_value = H5MM_realloc(chk, size);
else
ret_value = H5FL_BLK_REALLOC(chunk, chk, size);
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__free_chunk_info(void *item, void H5_ATTR_UNUSED *key, void H5_ATTR_UNUSED *opdata)
{
H5D_chunk_info_t *chunk_info = (H5D_chunk_info_t *)item;
FUNC_ENTER_STATIC_NOERR
HDassert(chunk_info);
if(!chunk_info->fspace_shared)
(void)H5S_close(chunk_info->fspace);
else
H5S_select_all(chunk_info->fspace, TRUE);
if(!chunk_info->mspace_shared && chunk_info->mspace)
(void)H5S_close(chunk_info->mspace);
chunk_info = H5FL_FREE(H5D_chunk_info_t, chunk_info);
FUNC_LEAVE_NOAPI(0)
}
static herr_t
H5D__create_chunk_map_single(H5D_chunk_map_t *fm, const H5D_io_info_t
#ifndef H5_HAVE_PARALLEL
H5_ATTR_UNUSED
#endif
*io_info)
{
H5D_chunk_info_t *chunk_info;
hsize_t coords[H5O_LAYOUT_NDIMS];
hsize_t sel_start[H5O_LAYOUT_NDIMS];
hsize_t sel_end[H5O_LAYOUT_NDIMS];
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(fm->f_ndims > 0);
if(H5S_SELECT_BOUNDS(fm->file_space, sel_start, sel_end) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
chunk_info = fm->single_chunk_info;
chunk_info->chunk_points = 1;
for(u = 0; u < fm->f_ndims; u++) {
if(fm->layout->u.chunk.dim[u] == 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "chunk size must be > 0, dim = %u ", u)
HDassert(sel_start[u] == sel_end[u]);
chunk_info->scaled[u] = sel_start[u] / fm->layout->u.chunk.dim[u];
coords[u] = chunk_info->scaled[u] * fm->layout->u.chunk.dim[u];
}
chunk_info->scaled[fm->f_ndims] = 0;
chunk_info->index = H5VM_array_offset_pre(fm->f_ndims, fm->layout->u.chunk.down_chunks, chunk_info->scaled);
if(H5S_select_copy(fm->single_space, fm->file_space, FALSE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file selection")
if(H5S_SELECT_ADJUST_U(fm->single_space, coords) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk selection")
#ifdef H5_HAVE_PARALLEL
if(io_info->using_mpi_vfd)
fm->select_chunk[chunk_info->index] = chunk_info;
#endif
chunk_info->fspace = fm->single_space;
chunk_info->fspace_shared = TRUE;
chunk_info->mspace = (H5S_t *)fm->mem_space;
chunk_info->mspace_shared = TRUE;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__create_chunk_file_map_all(H5D_chunk_map_t *fm, const H5D_io_info_t
#ifndef H5_HAVE_PARALLEL
H5_ATTR_UNUSED
#endif
*io_info)
{
H5S_t *tmp_fchunk = NULL;
hsize_t file_dims[H5S_MAX_RANK];
hsize_t sel_points;
hsize_t zeros[H5S_MAX_RANK];
hsize_t coords[H5S_MAX_RANK];
hsize_t end[H5S_MAX_RANK];
hsize_t scaled[H5S_MAX_RANK];
hsize_t chunk_index;
hsize_t curr_partial_clip[H5S_MAX_RANK];
hsize_t partial_dim_size[H5S_MAX_RANK];
hbool_t is_partial_dim[H5S_MAX_RANK];
unsigned num_partial_dims;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(fm->f_ndims > 0);
sel_points = fm->nelmts;
if(H5S_get_simple_extent_dims(fm->file_space, file_dims, NULL) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
num_partial_dims = 0;
HDmemset(zeros, 0, sizeof(zeros));
for(u = 0; u < fm->f_ndims; u++) {
if(fm->layout->u.chunk.dim[u] == 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "chunk size must be > 0, dim = %u ", u)
scaled[u] = 0;
coords[u] = 0;
end[u] = fm->chunk_dim[u] - 1;
partial_dim_size[u] = file_dims[u] % fm->chunk_dim[u];
if(file_dims[u] < fm->chunk_dim[u]) {
curr_partial_clip[u] = partial_dim_size[u];
is_partial_dim[u] = TRUE;
num_partial_dims++;
}
else {
curr_partial_clip[u] = fm->chunk_dim[u];
is_partial_dim[u] = FALSE;
}
}
chunk_index = 0;
if(NULL == (tmp_fchunk = H5S_create_simple(fm->f_ndims, fm->chunk_dim, NULL)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "unable to create dataspace for chunk")
while(sel_points) {
H5D_chunk_info_t *new_chunk_info;
hsize_t chunk_points;
if(NULL == (new_chunk_info = H5FL_MALLOC(H5D_chunk_info_t)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate chunk info")
new_chunk_info->index = chunk_index;
#ifdef H5_HAVE_PARALLEL
if(io_info->using_mpi_vfd)
fm->select_chunk[chunk_index] = new_chunk_info;
#endif
if(NULL == (new_chunk_info->fspace = H5S_copy(tmp_fchunk, TRUE, FALSE)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy chunk dataspace")
new_chunk_info->fspace_shared = FALSE;
if(num_partial_dims > 0)
if(H5S_select_hyperslab(new_chunk_info->fspace, H5S_SELECT_SET, zeros, NULL, curr_partial_clip, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, FAIL, "can't create chunk selection")
new_chunk_info->mspace = NULL;
new_chunk_info->mspace_shared = FALSE;
H5MM_memcpy(new_chunk_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims);
new_chunk_info->scaled[fm->f_ndims] = 0;
if(H5SL_insert(fm->sel_chunks, new_chunk_info, &new_chunk_info->index) < 0) {
H5D__free_chunk_info(new_chunk_info, NULL, NULL);
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert chunk into skip list")
}
chunk_points = H5S_GET_SELECT_NPOINTS(new_chunk_info->fspace);
H5_CHECKED_ASSIGN(new_chunk_info->chunk_points, uint32_t, chunk_points, hsize_t);
sel_points -= chunk_points;
if(sel_points > 0) {
int curr_dim;
chunk_index++;
curr_dim = (int)fm->f_ndims - 1;
coords[curr_dim] += fm->chunk_dim[curr_dim];
scaled[curr_dim]++;
end[curr_dim] += fm->chunk_dim[curr_dim];
if(coords[curr_dim] >= file_dims[curr_dim]) {
do {
coords[curr_dim] = 0;
scaled[curr_dim] = 0;
end[curr_dim] = fm->chunk_dim[curr_dim] - 1;
if(is_partial_dim[curr_dim] && end[curr_dim] < file_dims[curr_dim]) {
HDassert(num_partial_dims > 0);
curr_partial_clip[curr_dim] = fm->chunk_dim[curr_dim];
is_partial_dim[curr_dim] = FALSE;
num_partial_dims--;
}
curr_dim--;
if(curr_dim >= 0) {
coords[curr_dim] += fm->chunk_dim[curr_dim];
scaled[curr_dim]++;
end[curr_dim] = (coords[curr_dim] + fm->chunk_dim[curr_dim]) - 1;
}
} while(curr_dim >= 0 && (coords[curr_dim] >= file_dims[curr_dim]));
}
if(curr_dim >= 0) {
if(!is_partial_dim[curr_dim] && file_dims[curr_dim] <= end[curr_dim]) {
curr_partial_clip[curr_dim] = partial_dim_size[curr_dim];
is_partial_dim[curr_dim] = TRUE;
num_partial_dims++;
HDassert(num_partial_dims <= fm->f_ndims);
}
}
}
}
done:
if(tmp_fchunk && H5S_close(tmp_fchunk) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't release temporary dataspace")
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t
#ifndef H5_HAVE_PARALLEL
H5_ATTR_UNUSED
#endif
*io_info)
{
H5S_t *tmp_fchunk = NULL;
hsize_t sel_start[H5O_LAYOUT_NDIMS];
hsize_t sel_end[H5O_LAYOUT_NDIMS];
hsize_t sel_points;
hsize_t start_coords[H5O_LAYOUT_NDIMS];
hsize_t coords[H5O_LAYOUT_NDIMS];
hsize_t end[H5O_LAYOUT_NDIMS];
hsize_t chunk_index;
hsize_t start_scaled[H5S_MAX_RANK];
hsize_t scaled[H5S_MAX_RANK];
int curr_dim;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(fm->f_ndims > 0);
sel_points = fm->nelmts;
if(H5S_SELECT_BOUNDS(fm->file_space, sel_start, sel_end) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
for(u = 0; u < fm->f_ndims; u++) {
if(fm->layout->u.chunk.dim[u] == 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "chunk size must be > 0, dim = %u ", u)
scaled[u] = start_scaled[u] = sel_start[u] / fm->layout->u.chunk.dim[u];
coords[u] = start_coords[u] = scaled[u] * fm->layout->u.chunk.dim[u];
end[u] = (coords[u] + fm->chunk_dim[u]) - 1;
}
chunk_index = H5VM_array_offset_pre(fm->f_ndims, fm->layout->u.chunk.down_chunks, scaled);
while(sel_points) {
if(TRUE == H5S_SELECT_INTERSECT_BLOCK(fm->file_space, coords, end)) {
H5D_chunk_info_t *new_chunk_info;
hsize_t chunk_points;
if(H5S_combine_hyperslab(fm->file_space, H5S_SELECT_AND, coords, NULL, fm->chunk_dim, NULL, &tmp_fchunk) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to combine file space selection with chunk block")
if(H5S_set_extent_real(tmp_fchunk, fm->chunk_dim) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, FAIL, "can't adjust chunk dimensions")
if(H5S_SELECT_ADJUST_U(tmp_fchunk, coords) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, FAIL, "can't adjust chunk selection")
if(NULL == (new_chunk_info = H5FL_MALLOC(H5D_chunk_info_t)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate chunk info")
new_chunk_info->index = chunk_index;
#ifdef H5_HAVE_PARALLEL
if(io_info->using_mpi_vfd)
fm->select_chunk[chunk_index] = new_chunk_info;
#endif
new_chunk_info->fspace = tmp_fchunk;
new_chunk_info->fspace_shared = FALSE;
tmp_fchunk = NULL;
new_chunk_info->mspace = NULL;
new_chunk_info->mspace_shared = FALSE;
H5MM_memcpy(new_chunk_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims);
new_chunk_info->scaled[fm->f_ndims] = 0;
if(H5SL_insert(fm->sel_chunks, new_chunk_info, &new_chunk_info->index) < 0) {
H5D__free_chunk_info(new_chunk_info, NULL, NULL);
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert chunk into skip list")
}
chunk_points = H5S_GET_SELECT_NPOINTS(new_chunk_info->fspace);
H5_CHECKED_ASSIGN(new_chunk_info->chunk_points, uint32_t, chunk_points, hsize_t);
sel_points -= chunk_points;
if(sel_points == 0)
HGOTO_DONE(SUCCEED)
}
chunk_index++;
curr_dim = (int)fm->f_ndims - 1;
coords[curr_dim] += fm->chunk_dim[curr_dim];
end[curr_dim] += fm->chunk_dim[curr_dim];
scaled[curr_dim]++;
if(coords[curr_dim] > sel_end[curr_dim]) {
do {
scaled[curr_dim] = start_scaled[curr_dim];
coords[curr_dim] = start_coords[curr_dim];
end[curr_dim] = (coords[curr_dim] + fm->chunk_dim[curr_dim]) - 1;
curr_dim--;
if(curr_dim >= 0) {
scaled[curr_dim]++;
coords[curr_dim] += fm->chunk_dim[curr_dim];
end[curr_dim] = (coords[curr_dim] + fm->chunk_dim[curr_dim]) - 1;
}
} while(curr_dim >= 0 && (coords[curr_dim] > sel_end[curr_dim]));
chunk_index = H5VM_array_offset_pre(fm->f_ndims, fm->layout->u.chunk.down_chunks, scaled);
}
}
done:
if(ret_value < 0)
if(tmp_fchunk && H5S_close(tmp_fchunk) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't release temporary dataspace")
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm)
{
H5D_chunk_info_t *chunk_info;
H5SL_node_t *curr_node;
hsize_t file_sel_start[H5S_MAX_RANK];
hsize_t file_sel_end[H5S_MAX_RANK];
hsize_t mem_sel_start[H5S_MAX_RANK];
hsize_t mem_sel_end[H5S_MAX_RANK];
hssize_t adjust[H5S_MAX_RANK];
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(fm->f_ndims>0);
if(H5SL_count(fm->sel_chunks)==1) {
curr_node = H5SL_first(fm->sel_chunks);
chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
HDassert(chunk_info);
chunk_info->mspace = (H5S_t *)fm->mem_space;
chunk_info->mspace_shared = TRUE;
}
else {
if(H5S_SELECT_BOUNDS(fm->file_space, file_sel_start, file_sel_end) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
if(H5S_SELECT_BOUNDS(fm->mem_space, mem_sel_start, mem_sel_end) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
HDassert(fm->m_ndims == fm->f_ndims);
for(u = 0; u < fm->f_ndims; u++) {
H5_CHECK_OVERFLOW(file_sel_start[u], hsize_t, hssize_t);
H5_CHECK_OVERFLOW(mem_sel_start[u], hsize_t, hssize_t);
adjust[u] = (hssize_t)file_sel_start[u] - (hssize_t)mem_sel_start[u];
}
curr_node = H5SL_first(fm->sel_chunks);
while(curr_node) {
hsize_t coords[H5S_MAX_RANK];
hssize_t chunk_adjust[H5S_MAX_RANK];
H5S_sel_type chunk_sel_type;
chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
HDassert(chunk_info);
for(u = 0; u < fm->f_ndims; u++)
coords[u] = chunk_info->scaled[u] * fm->layout->u.chunk.dim[u];
if((chunk_info->mspace = H5S_copy(fm->mem_space, TRUE, FALSE)) == NULL)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
if((chunk_sel_type = H5S_GET_SELECT_TYPE(chunk_info->fspace)) < H5S_SEL_NONE)
HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to get type of selection")
if(H5S_SEL_ALL == chunk_sel_type) {
for(u = 0; u < fm->f_ndims; u++)
coords[u] = (hsize_t)((hssize_t)coords[u] - adjust[u]);
if(H5S_select_hyperslab(chunk_info->mspace, H5S_SELECT_SET, coords, NULL, fm->chunk_dim, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, FAIL, "can't create chunk memory selection")
}
else {
HDassert(H5S_SEL_HYPERSLABS == chunk_sel_type);
if(H5S_SELECT_COPY(chunk_info->mspace, chunk_info->fspace, FALSE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy selection")
for(u = 0; u < fm->f_ndims; u++) {
H5_CHECK_OVERFLOW(coords[u], hsize_t, hssize_t);
chunk_adjust[u] = adjust[u] - (hssize_t)coords[u];
}
if(H5S_SELECT_ADJUST_S(chunk_info->mspace, chunk_adjust) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to adjust selection")
}
curr_node = H5SL_next(curr_node);
}
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__create_chunk_mem_map_1d(const H5D_chunk_map_t *fm)
{
H5D_chunk_info_t *chunk_info;
H5SL_node_t *curr_node;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(fm->f_ndims>0);
if(H5SL_count(fm->sel_chunks)==1) {
curr_node = H5SL_first(fm->sel_chunks);
chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
HDassert(chunk_info);
chunk_info->mspace = (H5S_t *)fm->mem_space;
chunk_info->mspace_shared = TRUE;
}
else {
hsize_t mem_sel_start[H5S_MAX_RANK];
hsize_t mem_sel_end[H5S_MAX_RANK];
HDassert(fm->m_ndims == 1);
if(H5S_SELECT_BOUNDS(fm->mem_space, mem_sel_start, mem_sel_end) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
curr_node = H5SL_first(fm->sel_chunks);
while(curr_node) {
hsize_t chunk_points;
hsize_t tmp_count = 1;
chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
HDassert(chunk_info);
if((chunk_info->mspace = H5S_copy(fm->mem_space, TRUE, FALSE)) == NULL)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
chunk_points = H5S_GET_SELECT_NPOINTS(chunk_info->fspace);
if(H5S_select_hyperslab(chunk_info->mspace, H5S_SELECT_SET, mem_sel_start, NULL, &tmp_count, &chunk_points) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, FAIL, "can't create chunk memory selection")
mem_sel_start[0] += chunk_points;
curr_node = H5SL_next(curr_node);
}
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__chunk_file_cb(void H5_ATTR_UNUSED *elem, const H5T_t H5_ATTR_UNUSED *type, unsigned ndims, const hsize_t *coords, void *_udata)
{
H5D_chunk_file_iter_ud_t *udata = (H5D_chunk_file_iter_ud_t *)_udata;
H5D_chunk_map_t *fm = udata->fm;
H5D_chunk_info_t *chunk_info;
hsize_t coords_in_chunk[H5O_LAYOUT_NDIMS];
hsize_t chunk_index;
hsize_t scaled[H5S_MAX_RANK];
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
chunk_index = H5VM_chunk_index_scaled(ndims, coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks, scaled);
if(chunk_index==fm->last_index) {
chunk_info = fm->last_chunk_info;
}
else {
if(NULL == (chunk_info = (H5D_chunk_info_t *)H5SL_search(fm->sel_chunks, &chunk_index))) {
H5S_t *fspace;
if (NULL==(chunk_info = H5FL_MALLOC (H5D_chunk_info_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
chunk_info->index=chunk_index;
if((fspace = H5S_create_simple(fm->f_ndims,fm->chunk_dim,NULL))==NULL) {
chunk_info = H5FL_FREE(H5D_chunk_info_t, chunk_info);
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create dataspace for chunk")
}
if(H5S_select_none(fspace) < 0) {
(void)H5S_close(fspace);
chunk_info = H5FL_FREE(H5D_chunk_info_t, chunk_info);
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to de-select dataspace")
}
chunk_info->fspace = fspace;
chunk_info->fspace_shared = FALSE;
chunk_info->mspace = NULL;
chunk_info->mspace_shared = FALSE;
chunk_info->chunk_points = 0;
H5MM_memcpy(chunk_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims);
chunk_info->scaled[fm->f_ndims] = 0;
H5MM_memcpy(chunk_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims);
if(H5SL_insert(fm->sel_chunks,chunk_info,&chunk_info->index) < 0) {
H5D__free_chunk_info(chunk_info,NULL,NULL);
HGOTO_ERROR(H5E_DATASPACE,H5E_CANTINSERT,FAIL,"can't insert chunk into skip list")
}
}
#ifdef H5_HAVE_PARALLEL
if(udata->io_info->using_mpi_vfd)
fm->select_chunk[chunk_index] = chunk_info;
#endif
fm->last_index = chunk_index;
fm->last_chunk_info = chunk_info;
}
for(u = 0; u < fm->f_ndims; u++)
coords_in_chunk[u] = coords[u] - (scaled[u] * fm->layout->u.chunk.dim[u]);
if(H5S_select_elements(chunk_info->fspace, H5S_SELECT_APPEND, (size_t)1, coords_in_chunk) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element")
chunk_info->chunk_points++;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__chunk_mem_cb(void H5_ATTR_UNUSED *elem, const H5T_t H5_ATTR_UNUSED *type, unsigned ndims, const hsize_t *coords, void *_fm)
{
H5D_chunk_map_t *fm = (H5D_chunk_map_t *)_fm;
H5D_chunk_info_t *chunk_info;
hsize_t coords_in_mem[H5S_MAX_RANK];
hsize_t chunk_index;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
chunk_index = H5VM_chunk_index(ndims, coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks);
if(chunk_index == fm->last_index) {
chunk_info = fm->last_chunk_info;
}
else {
if(NULL == (chunk_info = (H5D_chunk_info_t *)H5SL_search(fm->sel_chunks, &chunk_index)))
HGOTO_ERROR(H5E_DATASPACE, H5E_NOTFOUND, H5_ITER_ERROR, "can't locate chunk in skip list")
if(NULL == chunk_info->mspace)
if(NULL == (chunk_info->mspace = H5S_copy(fm->mchunk_tmpl, FALSE, FALSE)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, H5_ITER_ERROR, "unable to copy file space")
fm->last_index = chunk_index;
fm->last_chunk_info = chunk_info;
}
if(H5S_SELECT_ITER_COORDS(&fm->mem_iter, coords_in_mem) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, H5_ITER_ERROR, "unable to get iterator coordinates")
if(fm->msel_type == H5S_SEL_POINTS) {
if(H5S_select_elements(chunk_info->mspace, H5S_SELECT_APPEND, (size_t)1, coords_in_mem) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, H5_ITER_ERROR, "unable to select element")
}
else {
if(H5S_hyper_add_span_element(chunk_info->mspace, fm->m_ndims, coords_in_mem) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, H5_ITER_ERROR, "unable to select element")
}
if(H5S_SELECT_ITER_NEXT(&fm->mem_iter, (size_t)1) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, H5_ITER_ERROR, "unable to move to next iterator location")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
htri_t
H5D__chunk_cacheable(const H5D_io_info_t *io_info, haddr_t caddr, hbool_t write_op)
{
const H5D_t *dataset = io_info->dset;
hbool_t has_filters = FALSE;
htri_t ret_value = FAIL;
FUNC_ENTER_PACKAGE
HDassert(io_info);
HDassert(dataset);
if(dataset->shared->dcpl_cache.pline.nused > 0) {
if(dataset->shared->layout.u.chunk.flags
& H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS) {
has_filters = !H5D__chunk_is_partial_edge_chunk(
io_info->dset->shared->ndims,
io_info->dset->shared->layout.u.chunk.dim,
io_info->store->chunk.scaled,
io_info->dset->shared->curr_dims);
}
else
has_filters = TRUE;
}
if(has_filters)
ret_value = TRUE;
else {
#ifdef H5_HAVE_PARALLEL
if(io_info->using_mpi_vfd && (H5F_ACC_RDWR & H5F_INTENT(dataset->oloc.file)))
ret_value = FALSE;
else {
#endif
H5_CHECK_OVERFLOW(dataset->shared->layout.u.chunk.size, uint32_t, size_t);
if((size_t)dataset->shared->layout.u.chunk.size > dataset->shared->cache.chunk.nbytes_max) {
if(write_op && !H5F_addr_defined(caddr)) {
const H5O_fill_t *fill = &(dataset->shared->dcpl_cache.fill);
H5D_fill_value_t fill_status;
if(H5P_is_fill_value_defined(fill, &fill_status) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't tell if fill value defined")
if(fill->fill_time == H5D_FILL_TIME_ALLOC ||
(fill->fill_time == H5D_FILL_TIME_IFSET &&
(fill_status == H5D_FILL_VALUE_USER_DEFINED ||
fill_status == H5D_FILL_VALUE_DEFAULT)))
ret_value = TRUE;
else
ret_value = FALSE;
} else
ret_value = FALSE;
} else
ret_value = TRUE;
#ifdef H5_HAVE_PARALLEL
}
#endif
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t H5_ATTR_UNUSED nelmts, const H5S_t H5_ATTR_UNUSED *file_space, const H5S_t H5_ATTR_UNUSED *mem_space,
H5D_chunk_map_t *fm)
{
H5SL_node_t *chunk_node;
H5D_io_info_t nonexistent_io_info;
H5D_io_info_t ctg_io_info;
H5D_storage_t ctg_store;
H5D_io_info_t cpt_io_info;
H5D_storage_t cpt_store;
hbool_t cpt_dirty;
uint32_t src_accessed_bytes = 0;
hbool_t skip_missing_chunks = FALSE;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(io_info);
HDassert(io_info->u.rbuf);
HDassert(type_info);
HDassert(fm);
H5MM_memcpy(&nonexistent_io_info, io_info, sizeof(nonexistent_io_info));
nonexistent_io_info.layout_ops = *H5D_LOPS_NONEXISTENT;
H5MM_memcpy(&ctg_io_info, io_info, sizeof(ctg_io_info));
ctg_io_info.store = &ctg_store;
ctg_io_info.layout_ops = *H5D_LOPS_CONTIG;
H5_CHECKED_ASSIGN(ctg_store.contig.dset_size, hsize_t, io_info->dset->shared->layout.u.chunk.size, uint32_t);
H5MM_memcpy(&cpt_io_info, io_info, sizeof(cpt_io_info));
cpt_io_info.store = &cpt_store;
cpt_io_info.layout_ops = *H5D_LOPS_COMPACT;
cpt_store.compact.dirty = &cpt_dirty;
{
const H5O_fill_t *fill = &(io_info->dset->shared->dcpl_cache.fill);
H5D_fill_value_t fill_status;
if(H5P_is_fill_value_defined(fill, &fill_status) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't tell if fill value defined")
if(fill->fill_time == H5D_FILL_TIME_NEVER ||
(fill->fill_time == H5D_FILL_TIME_IFSET &&
fill_status != H5D_FILL_VALUE_USER_DEFINED &&
fill_status != H5D_FILL_VALUE_DEFAULT))
skip_missing_chunks = TRUE;
}
chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm);
while(chunk_node) {
H5D_chunk_info_t *chunk_info;
H5D_chunk_ud_t udata;
chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node);
if(H5D__chunk_lookup(io_info->dset, chunk_info->scaled, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
HDassert((H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length > 0) ||
(!H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length == 0));
if(H5F_addr_defined(udata.chunk_block.offset) || UINT_MAX != udata.idx_hint
|| !skip_missing_chunks) {
H5D_io_info_t *chk_io_info;
void *chunk = NULL;
htri_t cacheable;
io_info->store->chunk.scaled = chunk_info->scaled;
if((cacheable = H5D__chunk_cacheable(io_info, udata.chunk_block.offset, FALSE)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't tell if chunk is cacheable")
if(cacheable) {
H5_CHECK_OVERFLOW(type_info->src_type_size, size_t, uint32_t);
src_accessed_bytes = chunk_info->chunk_points * (uint32_t)type_info->src_type_size;
if(NULL == (chunk = H5D__chunk_lock(io_info, &udata, FALSE, FALSE)))
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
cpt_store.compact.buf = chunk;
chk_io_info = &cpt_io_info;
}
else if(H5F_addr_defined(udata.chunk_block.offset)) {
ctg_store.contig.dset_addr = udata.chunk_block.offset;
chk_io_info = &ctg_io_info;
}
else {
chk_io_info = &nonexistent_io_info;
}
if((io_info->io_ops.single_read)(chk_io_info, type_info,
(hsize_t)chunk_info->chunk_points, chunk_info->fspace, chunk_info->mspace) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunked read failed")
if(chunk && H5D__chunk_unlock(io_info, &udata, FALSE, chunk, src_accessed_bytes) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
}
chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node);
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t H5_ATTR_UNUSED nelmts, const H5S_t H5_ATTR_UNUSED *file_space, const H5S_t H5_ATTR_UNUSED *mem_space,
H5D_chunk_map_t *fm)
{
H5SL_node_t *chunk_node;
H5D_io_info_t ctg_io_info;
H5D_storage_t ctg_store;
H5D_io_info_t cpt_io_info;
H5D_storage_t cpt_store;
hbool_t cpt_dirty;
uint32_t dst_accessed_bytes = 0;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(io_info);
HDassert(io_info->u.wbuf);
HDassert(type_info);
HDassert(fm);
H5MM_memcpy(&ctg_io_info, io_info, sizeof(ctg_io_info));
ctg_io_info.store = &ctg_store;
ctg_io_info.layout_ops = *H5D_LOPS_CONTIG;
H5_CHECKED_ASSIGN(ctg_store.contig.dset_size, hsize_t, io_info->dset->shared->layout.u.chunk.size, uint32_t);
H5MM_memcpy(&cpt_io_info, io_info, sizeof(cpt_io_info));
cpt_io_info.store = &cpt_store;
cpt_io_info.layout_ops = *H5D_LOPS_COMPACT;
cpt_store.compact.dirty = &cpt_dirty;
chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm);
while(chunk_node) {
H5D_chunk_info_t *chunk_info;
H5D_chk_idx_info_t idx_info;
H5D_io_info_t *chk_io_info;
void *chunk;
H5D_chunk_ud_t udata;
htri_t cacheable;
hbool_t need_insert = FALSE;
chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node);
if(H5D__chunk_lookup(io_info->dset, chunk_info->scaled, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
HDassert((H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length > 0) ||
(!H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length == 0));
io_info->store->chunk.scaled = chunk_info->scaled;
if((cacheable = H5D__chunk_cacheable(io_info, udata.chunk_block.offset, TRUE)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't tell if chunk is cacheable")
if(cacheable) {
hbool_t entire_chunk = TRUE;
H5_CHECK_OVERFLOW(type_info->dst_type_size, size_t, uint32_t);
dst_accessed_bytes = chunk_info->chunk_points * (uint32_t)type_info->dst_type_size;
if(dst_accessed_bytes != ctg_store.contig.dset_size ||
(chunk_info->chunk_points * type_info->src_type_size) != ctg_store.contig.dset_size ||
fm->fsel_type == H5S_SEL_POINTS)
entire_chunk = FALSE;
if(NULL == (chunk = H5D__chunk_lock(io_info, &udata, entire_chunk, FALSE)))
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
cpt_store.compact.buf = chunk;
chk_io_info = &cpt_io_info;
}
else {
if(!H5F_addr_defined(udata.chunk_block.offset)) {
idx_info.f = io_info->dset->oloc.file;
idx_info.pline = &(io_info->dset->shared->dcpl_cache.pline);
idx_info.layout = &(io_info->dset->shared->layout.u.chunk);
idx_info.storage = &(io_info->dset->shared->layout.storage.u.chunk);
udata.chunk_block.length = io_info->dset->shared->layout.u.chunk.size;
if(H5D__chunk_file_alloc(&idx_info, NULL, &udata.chunk_block, &need_insert, chunk_info->scaled) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert/resize chunk on chunk level")
if(!H5F_addr_defined(udata.chunk_block.offset))
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "chunk address isn't defined")
H5D__chunk_cinfo_cache_update(&io_info->dset->shared->cache.chunk.last, &udata);
}
ctg_store.contig.dset_addr = udata.chunk_block.offset;
chunk = NULL;
chk_io_info = &ctg_io_info;
}
if((io_info->io_ops.single_write)(chk_io_info, type_info,
(hsize_t)chunk_info->chunk_points, chunk_info->fspace, chunk_info->mspace) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunked write failed")
if(chunk) {
if(H5D__chunk_unlock(io_info, &udata, TRUE, chunk, dst_accessed_bytes) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
}
else {
if(need_insert && io_info->dset->shared->layout.storage.u.chunk.ops->insert)
if((io_info->dset->shared->layout.storage.u.chunk.ops->insert)(&idx_info, &udata, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert chunk addr into index")
}
chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node);
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__chunk_flush(H5D_t *dset)
{
H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
H5D_rdcc_ent_t *ent, *next;
unsigned nerrors = 0;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(dset);
for(ent = rdcc->head; ent; ent = next) {
next = ent->next;
if(H5D__chunk_flush_entry(dset, ent, FALSE) < 0)
nerrors++;
}
if(nerrors)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFLUSH, FAIL, "unable to flush one or more raw data chunks")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__chunk_io_term(const H5D_chunk_map_t *fm)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
if(fm->use_single) {
HDassert(fm->sel_chunks == NULL);
HDassert(fm->single_chunk_info);
HDassert(fm->single_chunk_info->fspace_shared);
HDassert(fm->single_chunk_info->mspace_shared);
H5S_select_all(fm->single_space, TRUE);
}
else {
if(fm->sel_chunks)
if(H5SL_free(fm->sel_chunks, H5D__free_chunk_info, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTNEXT, FAIL, "can't iterate over chunks")
}
if(fm->mchunk_tmpl)
if(H5S_close(fm->mchunk_tmpl) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "can't release memory chunk dataspace template")
#ifdef H5_HAVE_PARALLEL
if(fm->select_chunk)
H5MM_xfree(fm->select_chunk);
#endif
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__chunk_dest(H5D_t *dset)
{
H5D_chk_idx_info_t idx_info;
H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
H5D_rdcc_ent_t *ent = NULL, *next = NULL;
int nerrors = 0;
H5O_storage_chunk_t *sc = &(dset->shared->layout.storage.u.chunk);
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC_TAG(dset->oloc.addr)
HDassert(dset);
H5D_CHUNK_STORAGE_INDEX_CHK(sc);
for(ent = rdcc->head; ent; ent = next) {
next = ent->next;
if(H5D__chunk_cache_evict(dset, ent, TRUE) < 0)
nerrors++;
}
if(nerrors)
HDONE_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush one or more raw data chunks")
if(rdcc->slot)
rdcc->slot = H5FL_SEQ_FREE(H5D_rdcc_ent_ptr_t, rdcc->slot);
HDmemset(rdcc, 0, sizeof(H5D_rdcc_t));
idx_info.f = dset->oloc.file;
idx_info.pline = &dset->shared->dcpl_cache.pline;
idx_info.layout = &dset->shared->layout.u.chunk;
idx_info.storage = sc;
if(sc->ops->dest && (sc->ops->dest)(&idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to release chunk index info")
done:
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
herr_t
H5D_chunk_idx_reset(H5O_storage_chunk_t *storage, hbool_t reset_addr)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(storage);
HDassert(storage->ops);
H5D_CHUNK_STORAGE_INDEX_CHK(storage);
if((storage->ops->reset)(storage, reset_addr) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to reset chunk index info")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__chunk_cinfo_cache_reset(H5D_chunk_cached_t *last)
{
FUNC_ENTER_STATIC_NOERR
HDassert(last);
last->valid = FALSE;
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5D__chunk_cinfo_cache_update(H5D_chunk_cached_t *last, const H5D_chunk_ud_t *udata)
{
FUNC_ENTER_STATIC_NOERR
HDassert(last);
HDassert(udata);
HDassert(udata->common.layout);
HDassert(udata->common.scaled);
H5MM_memcpy(last->scaled, udata->common.scaled, sizeof(hsize_t) * udata->common.layout->ndims);
last->addr = udata->chunk_block.offset;
H5_CHECKED_ASSIGN(last->nbytes, uint32_t, udata->chunk_block.length, hsize_t);
last->chunk_idx = udata->chunk_idx;
last->filter_mask = udata->filter_mask;
last->valid = TRUE;
FUNC_LEAVE_NOAPI(SUCCEED)
}
static hbool_t
H5D__chunk_cinfo_cache_found(const H5D_chunk_cached_t *last, H5D_chunk_ud_t *udata)
{
hbool_t ret_value = FALSE;
FUNC_ENTER_STATIC_NOERR
HDassert(last);
HDassert(udata);
HDassert(udata->common.layout);
HDassert(udata->common.scaled);
if(last->valid) {
unsigned u;
for(u = 0; u < udata->common.layout->ndims; u++)
if(last->scaled[u] != udata->common.scaled[u])
HGOTO_DONE(FALSE)
udata->chunk_block.offset = last->addr;
udata->chunk_block.length = last->nbytes;
udata->chunk_idx = last->chunk_idx;
udata->filter_mask = last->filter_mask;
HGOTO_DONE(TRUE)
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5D__chunk_create(const H5D_t *dset )
{
H5D_chk_idx_info_t idx_info;
H5O_storage_chunk_t *sc = &(dset->shared->layout.storage.u.chunk);
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(dset);
HDassert(H5D_CHUNKED == dset->shared->layout.type);
HDassert(dset->shared->layout.u.chunk.ndims > 0 && dset->shared->layout.u.chunk.ndims <= H5O_LAYOUT_NDIMS);
H5D_CHUNK_STORAGE_INDEX_CHK(sc);
#ifndef NDEBUG
{
unsigned u;
for(u = 0; u < dset->shared->layout.u.chunk.ndims; u++)
HDassert(dset->shared->layout.u.chunk.dim[u] > 0);
}
#endif
idx_info.f = dset->oloc.file;
idx_info.pline = &dset->shared->dcpl_cache.pline;
idx_info.layout = &dset->shared->layout.u.chunk;
idx_info.storage = sc;
if((sc->ops->create)(&idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't create chunk index")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static unsigned
H5D__chunk_hash_val(const H5D_shared_t *shared, const hsize_t *scaled)
{
hsize_t val;
unsigned ndims = shared->ndims;
unsigned ret = 0;
unsigned u;
FUNC_ENTER_STATIC_NOERR
HDassert(shared);
HDassert(scaled);
val = scaled[0];
for(u = 1; u < ndims; u++) {
val <<= shared->cache.chunk.scaled_encode_bits[u];
val ^= scaled[u];
}
ret = (unsigned)(val % shared->cache.chunk.nslots);
FUNC_LEAVE_NOAPI(ret)
}
herr_t
H5D__chunk_lookup(const H5D_t *dset, const hsize_t *scaled,
H5D_chunk_ud_t *udata)
{
H5D_rdcc_ent_t *ent = NULL;
H5O_storage_chunk_t *sc = &(dset->shared->layout.storage.u.chunk);
unsigned idx;
hbool_t found = FALSE;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(dset);
HDassert(dset->shared->layout.u.chunk.ndims > 0);
H5D_CHUNK_STORAGE_INDEX_CHK(sc);
HDassert(scaled);
HDassert(udata);
udata->common.layout = &(dset->shared->layout.u.chunk);
udata->common.storage = sc;
udata->common.scaled = scaled;
udata->chunk_block.offset = HADDR_UNDEF;
udata->chunk_block.length = 0;
udata->filter_mask = 0;
udata->new_unfilt_chunk = FALSE;
if(dset->shared->cache.chunk.nslots > 0) {
idx = H5D__chunk_hash_val(dset->shared, scaled);
ent = dset->shared->cache.chunk.slot[idx];
if(ent) {
unsigned u;
found = TRUE;
for(u = 0; u < dset->shared->ndims; u++)
if(scaled[u] != ent->scaled[u]) {
found = FALSE;
break;
}
}
}
if(found) {
udata->idx_hint = idx;
udata->chunk_block.offset = ent->chunk_block.offset;
udata->chunk_block.length = ent->chunk_block.length;;
udata->chunk_idx = ent->chunk_idx;
}
else {
udata->idx_hint = UINT_MAX;
if(!H5D__chunk_cinfo_cache_found(&dset->shared->cache.chunk.last, udata)) {
H5D_chk_idx_info_t idx_info;
idx_info.f = dset->oloc.file;
idx_info.pline = &dset->shared->dcpl_cache.pline;
idx_info.layout = &dset->shared->layout.u.chunk;
idx_info.storage = sc;
#ifdef H5_HAVE_PARALLEL
if(H5F_HAS_FEATURE(idx_info.f, H5FD_FEAT_HAS_MPI))
H5CX_set_coll_metadata_read(FALSE);
#endif
if((sc->ops->get_addr)(&idx_info, udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't query chunk address")
#ifdef H5_HAVE_PARALLEL
if ( !( (H5F_HAS_FEATURE(idx_info.f, H5FD_FEAT_HAS_MPI))
&& (H5F_INTENT(dset->oloc.file) & H5F_ACC_RDWR)
&& dset->shared->dcpl_cache.pline.nused
)
)
#endif
H5D__chunk_cinfo_cache_update(&dset->shared->cache.chunk.last, udata);
}
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__chunk_flush_entry(const H5D_t *dset, H5D_rdcc_ent_t *ent, hbool_t reset)
{
void *buf = NULL;
hbool_t point_of_no_return = FALSE;
H5O_storage_chunk_t *sc = &(dset->shared->layout.storage.u.chunk);
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC_TAG(dset->oloc.addr)
HDassert(dset);
HDassert(dset->shared);
H5D_CHUNK_STORAGE_INDEX_CHK(sc);
HDassert(ent);
HDassert(!ent->locked);
buf = ent->chunk;
if(ent->dirty) {
H5D_chk_idx_info_t idx_info;
H5D_chunk_ud_t udata;
hbool_t must_alloc = FALSE;
hbool_t need_insert = FALSE;
udata.common.layout = &dset->shared->layout.u.chunk;
udata.common.storage = sc;
udata.common.scaled = ent->scaled;
udata.chunk_block.offset = ent->chunk_block.offset;
udata.chunk_block.length = dset->shared->layout.u.chunk.size;
udata.filter_mask = 0;
udata.chunk_idx = ent->chunk_idx;
if(dset->shared->dcpl_cache.pline.nused
&& !(ent->edge_chunk_state & H5D_RDCC_DISABLE_FILTERS)) {
H5Z_EDC_t err_detect;
H5Z_cb_t filter_cb;
size_t alloc = udata.chunk_block.length;
size_t nbytes;
if(H5CX_get_err_detect(&err_detect) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get error detection info")
if(H5CX_get_filter_cb(&filter_cb) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get I/O filter callback function")
if(!reset) {
if(NULL == (buf = H5MM_malloc(alloc)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for pipeline")
H5MM_memcpy(buf, ent->chunk, alloc);
}
else {
point_of_no_return = TRUE;
ent->chunk = NULL;
}
H5_CHECKED_ASSIGN(nbytes, size_t, udata.chunk_block.length, hsize_t);
if(H5Z_pipeline(&(dset->shared->dcpl_cache.pline), 0, &(udata.filter_mask),
err_detect, filter_cb, &nbytes, &alloc, &buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFILTER, FAIL, "output pipeline failed")
#if H5_SIZEOF_SIZE_T > 4
if(nbytes > ((size_t)0xffffffff))
HGOTO_ERROR(H5E_DATASET, H5E_BADRANGE, FAIL, "chunk too large for 32-bit length")
#endif
H5_CHECKED_ASSIGN(udata.chunk_block.length, hsize_t, nbytes, size_t);
must_alloc = TRUE;
}
else if(!H5F_addr_defined(udata.chunk_block.offset)) {
must_alloc = TRUE;
ent->edge_chunk_state &= ~H5D_RDCC_NEWLY_DISABLED_FILTERS;
}
else if(ent->edge_chunk_state & H5D_RDCC_NEWLY_DISABLED_FILTERS) {
must_alloc = TRUE;
ent->edge_chunk_state &= ~H5D_RDCC_NEWLY_DISABLED_FILTERS;
}
HDassert(!(ent->edge_chunk_state & H5D_RDCC_NEWLY_DISABLED_FILTERS));
if(must_alloc) {
idx_info.f = dset->oloc.file;
idx_info.pline = &dset->shared->dcpl_cache.pline;
idx_info.layout = &dset->shared->layout.u.chunk;
idx_info.storage = sc;
if(H5D__chunk_file_alloc(&idx_info, &(ent->chunk_block), &udata.chunk_block, &need_insert, ent->scaled) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert/resize chunk on chunk level")
ent->chunk_block.offset = udata.chunk_block.offset;
ent->chunk_block.length = udata.chunk_block.length;
}
HDassert(H5F_addr_defined(udata.chunk_block.offset));
H5_CHECK_OVERFLOW(udata.chunk_block.length, hsize_t, size_t);
if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.chunk_block.offset, (size_t)udata.chunk_block.length, buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to write raw data to file")
if(need_insert && sc->ops->insert)
if((sc->ops->insert)(&idx_info, &udata, dset) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert chunk addr into index")
H5D__chunk_cinfo_cache_update(&dset->shared->cache.chunk.last, &udata);
ent->dirty = FALSE;
dset->shared->cache.chunk.stats.nflushes++;
}
if(reset) {
point_of_no_return = FALSE;
if(buf == ent->chunk)
buf = NULL;
if(ent->chunk != NULL)
ent->chunk = (uint8_t *)H5D__chunk_mem_xfree(ent->chunk,
((ent->edge_chunk_state & H5D_RDCC_DISABLE_FILTERS) ? NULL
: &(dset->shared->dcpl_cache.pline)));
}
done:
if(buf != ent->chunk)
H5MM_xfree(buf);
if(ret_value < 0 && point_of_no_return)
if(ent->chunk)
ent->chunk = (uint8_t *)H5D__chunk_mem_xfree(ent->chunk,
((ent->edge_chunk_state & H5D_RDCC_DISABLE_FILTERS) ? NULL
: &(dset->shared->dcpl_cache.pline)));
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
static herr_t
H5D__chunk_cache_evict(const H5D_t *dset, H5D_rdcc_ent_t *ent, hbool_t flush)
{
H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(dset);
HDassert(ent);
HDassert(!ent->locked);
HDassert(ent->idx < rdcc->nslots);
if(flush) {
if(H5D__chunk_flush_entry(dset, ent, TRUE) < 0)
HDONE_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush indexed storage buffer")
}
else {
if(ent->chunk != NULL)
ent->chunk = (uint8_t *)H5D__chunk_mem_xfree(ent->chunk,
((ent->edge_chunk_state & H5D_RDCC_DISABLE_FILTERS) ? NULL
: &(dset->shared->dcpl_cache.pline)));
}
if(ent->prev)
ent->prev->next = ent->next;
else
rdcc->head = ent->next;
if(ent->next)
ent->next->prev = ent->prev;
else
rdcc->tail = ent->prev;
ent->prev = ent->next = NULL;
if(ent->tmp_prev) {
HDassert(rdcc->tmp_head->tmp_next);
ent->tmp_prev->tmp_next = ent->tmp_next;
if(ent->tmp_next) {
ent->tmp_next->tmp_prev = ent->tmp_prev;
ent->tmp_next = NULL;
}
ent->tmp_prev = NULL;
}
else
rdcc->slot[ent->idx] = NULL;
HDassert(rdcc->slot[ent->idx] != ent);
ent->idx = UINT_MAX;
rdcc->nbytes_used -= dset->shared->layout.u.chunk.size;
--rdcc->nused;
ent = H5FL_FREE(H5D_rdcc_ent_t, ent);
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__chunk_cache_prune(const H5D_t *dset, size_t size)
{
const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
size_t total = rdcc->nbytes_max;
const int nmeth = 2;
int w[1];
H5D_rdcc_ent_t *p[2], *cur;
H5D_rdcc_ent_t *n[2];
int nerrors = 0;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
w[0] = (int)(rdcc->nused * rdcc->w0);
p[0] = rdcc->head;
p[1] = NULL;
while((p[0] || p[1]) && (rdcc->nbytes_used + size) > total) {
int i;
for(i = 0; i < nmeth - 1; i++)
if(0 == w[i])
p[i + 1] = rdcc->head;
for(i = 0; i < nmeth; i++)
n[i] = p[i] ? p[i]->next : NULL;
for(i = 0; i < nmeth && (rdcc->nbytes_used + size) > total; i++) {
if(0 == i && p[0] && !p[0]->locked &&
((0 == p[0]->rd_count && 0 == p[0]->wr_count) ||
(0 == p[0]->rd_count && dset->shared->layout.u.chunk.size == p[0]->wr_count) ||
(dset->shared->layout.u.chunk.size == p[0]->rd_count && 0 == p[0]->wr_count))) {
cur = p[0];
} else if(1 == i && p[1] && !p[1]->locked) {
cur = p[1];
} else {
cur = NULL;
}
if(cur) {
int j;
for(j = 0; j < nmeth; j++) {
if(p[j] == cur)
p[j] = NULL;
if(n[j] == cur)
n[j] = cur->next;
}
if(H5D__chunk_cache_evict(dset, cur, TRUE) < 0)
nerrors++;
}
}
for(i = 0; i < nmeth; i++)
p[i] = n[i];
for(i = 0; i < nmeth - 1; i++)
w[i] -= 1;
}
if(nerrors)
HGOTO_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to preempt one or more raw data cache entry")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static void *
H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata,
hbool_t relax, hbool_t prev_unfilt_chunk)
{
const H5D_t *dset = io_info->dset;
const H5O_pline_t *pline = &(dset->shared->dcpl_cache.pline);
const H5O_pline_t *old_pline = pline;
const H5O_layout_t *layout = &(dset->shared->layout);
const H5O_fill_t *fill = &(dset->shared->dcpl_cache.fill);
H5D_fill_buf_info_t fb_info;
hbool_t fb_info_init = FALSE;
H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
H5D_rdcc_ent_t *ent;
size_t chunk_size;
hbool_t disable_filters = FALSE;
void *chunk = NULL;
void *ret_value = NULL;
FUNC_ENTER_STATIC
HDassert(io_info);
HDassert(io_info->store);
HDassert(udata);
HDassert(dset);
HDassert(!(udata->new_unfilt_chunk && prev_unfilt_chunk));
HDassert(!rdcc->tmp_head);
HDassert(layout->u.chunk.size > 0);
H5_CHECKED_ASSIGN(chunk_size, size_t, layout->u.chunk.size, uint32_t);
if(UINT_MAX != udata->idx_hint) {
HDassert(udata->idx_hint < rdcc->nslots);
HDassert(rdcc->slot[udata->idx_hint]);
ent = rdcc->slot[udata->idx_hint];
#ifndef NDEBUG
{
unsigned u;
for(u = 0; u < layout->u.chunk.ndims - 1; u++)
HDassert(io_info->store->chunk.scaled[u] == ent->scaled[u]);
}
#endif
rdcc->stats.nhits++;
if(pline->nused) {
if(udata->new_unfilt_chunk) {
HDassert(layout->u.chunk.flags
& H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS);
HDassert(!(ent->edge_chunk_state & H5D_RDCC_DISABLE_FILTERS));
HDassert(old_pline->nused);
pline = NULL;
if(NULL == (chunk = H5D__chunk_mem_alloc(chunk_size, pline)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk")
H5MM_memcpy(chunk, ent->chunk, chunk_size);
ent->chunk = (uint8_t *)H5D__chunk_mem_xfree(ent->chunk, old_pline);
ent->chunk = (uint8_t *)chunk;
chunk = NULL;
ent->edge_chunk_state |= H5D_RDCC_DISABLE_FILTERS;
ent->edge_chunk_state |= H5D_RDCC_NEWLY_DISABLED_FILTERS;
}
else if(prev_unfilt_chunk) {
HDassert(layout->u.chunk.flags
& H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS);
HDassert((ent->edge_chunk_state & H5D_RDCC_DISABLE_FILTERS));
HDassert(pline->nused);
old_pline = NULL;
if(NULL == (chunk = H5D__chunk_mem_alloc(chunk_size, pline)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk")
H5MM_memcpy(chunk, ent->chunk, chunk_size);
ent->chunk = (uint8_t *)H5D__chunk_mem_xfree(ent->chunk, old_pline);
ent->chunk = (uint8_t *)chunk;
chunk = NULL;
ent->edge_chunk_state &= ~(H5D_RDCC_DISABLE_FILTERS
| H5D_RDCC_NEWLY_DISABLED_FILTERS);
}
}
if(ent->next) {
if(ent->next->next)
ent->next->next->prev = ent;
else
rdcc->tail = ent;
ent->next->prev = ent->prev;
if(ent->prev)
ent->prev->next = ent->next;
else
rdcc->head = ent->next;
ent->prev = ent->next;
ent->next = ent->next->next;
ent->prev->next = ent;
}
}
else {
haddr_t chunk_addr;
hsize_t chunk_alloc;
chunk_addr = udata->chunk_block.offset;
chunk_alloc = udata->chunk_block.length;
if(pline->nused) {
if(udata->new_unfilt_chunk) {
HDassert(layout->u.chunk.flags
& H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS);
disable_filters = TRUE;
pline = NULL;
}
else if(prev_unfilt_chunk) {
HDassert(layout->u.chunk.flags
& H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS);
old_pline = NULL;
}
else if(layout->u.chunk.flags
& H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS) {
if(H5D__chunk_is_partial_edge_chunk(io_info->dset->shared->ndims,
layout->u.chunk.dim, io_info->store->chunk.scaled,
io_info->dset->shared->curr_dims)) {
disable_filters = TRUE;
old_pline = NULL;
pline = NULL;
}
}
}
if(relax) {
rdcc->stats.nhits++;
if(NULL == (chunk = H5D__chunk_mem_alloc(chunk_size, pline)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk")
HDmemset(chunk, 0, chunk_size);
}
else {
if(H5F_addr_defined(chunk_addr)) {
size_t my_chunk_alloc = chunk_alloc;
size_t buf_alloc = chunk_alloc;
if(NULL == (chunk = H5D__chunk_mem_alloc(my_chunk_alloc, (udata->new_unfilt_chunk ? old_pline : pline))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk")
if(H5F_block_read(dset->oloc.file, H5FD_MEM_DRAW, chunk_addr, my_chunk_alloc, chunk) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "unable to read raw data chunk")
if(old_pline && old_pline->nused) {
H5Z_EDC_t err_detect;
H5Z_cb_t filter_cb;
if(H5CX_get_err_detect(&err_detect) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't get error detection info")
if(H5CX_get_filter_cb(&filter_cb) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't get I/O filter callback function")
if(H5Z_pipeline(old_pline, H5Z_FLAG_REVERSE, &(udata->filter_mask),
err_detect, filter_cb, &my_chunk_alloc, &buf_alloc, &chunk) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFILTER, NULL, "data pipeline read failed")
if(udata->new_unfilt_chunk) {
void *tmp_chunk = chunk;
if(NULL == (chunk = H5D__chunk_mem_alloc(my_chunk_alloc, pline))) {
(void)H5D__chunk_mem_xfree(tmp_chunk, old_pline);
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk")
}
H5MM_memcpy(chunk, tmp_chunk, chunk_size);
(void)H5D__chunk_mem_xfree(tmp_chunk, old_pline);
}
}
rdcc->stats.nmisses++;
}
else {
H5D_fill_value_t fill_status;
HDassert(fill->alloc_time != H5D_ALLOC_TIME_EARLY);
if(NULL == (chunk = H5D__chunk_mem_alloc(chunk_size, pline)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk")
if(H5P_is_fill_value_defined(fill, &fill_status) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't tell if fill value defined")
if(fill->fill_time == H5D_FILL_TIME_ALLOC ||
(fill->fill_time == H5D_FILL_TIME_IFSET &&
(fill_status == H5D_FILL_VALUE_USER_DEFINED ||
fill_status == H5D_FILL_VALUE_DEFAULT))) {
if(H5D__fill_init(&fb_info, chunk, NULL, NULL, NULL, NULL,
&dset->shared->dcpl_cache.fill, dset->shared->type,
dset->shared->type_id, (size_t)0, chunk_size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "can't initialize fill buffer info")
fb_info_init = TRUE;
if(fb_info.has_vlen_fill_type)
if(H5D__fill_refill_vl(&fb_info, fb_info.elmts_per_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, NULL, "can't refill fill value buffer")
}
else
HDmemset(chunk, 0, chunk_size);
rdcc->stats.ninits++;
}
}
if(rdcc->nslots > 0 && chunk_size <= rdcc->nbytes_max) {
udata->idx_hint = H5D__chunk_hash_val(io_info->dset->shared, udata->common.scaled);
ent = rdcc->slot[udata->idx_hint];
if(!ent || !ent->locked) {
if(ent) {
if(H5D__chunk_cache_evict(io_info->dset, ent, TRUE) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "unable to preempt chunk from cache")
}
if(H5D__chunk_cache_prune(io_info->dset, chunk_size) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "unable to preempt chunk(s) from cache")
if(NULL == (ent = H5FL_CALLOC(H5D_rdcc_ent_t)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, NULL, "can't allocate raw data chunk entry")
ent->edge_chunk_state = disable_filters ? H5D_RDCC_DISABLE_FILTERS : 0;
if(udata->new_unfilt_chunk)
ent->edge_chunk_state |= H5D_RDCC_NEWLY_DISABLED_FILTERS;
ent->chunk_block.offset = chunk_addr;
ent->chunk_block.length = chunk_alloc;
ent->chunk_idx = udata->chunk_idx;
H5MM_memcpy(ent->scaled, udata->common.scaled, sizeof(hsize_t) * layout->u.chunk.ndims);
H5_CHECKED_ASSIGN(ent->rd_count, uint32_t, chunk_size, size_t);
H5_CHECKED_ASSIGN(ent->wr_count, uint32_t, chunk_size, size_t);
ent->chunk = (uint8_t *)chunk;
HDassert(NULL == rdcc->slot[udata->idx_hint]);
rdcc->slot[udata->idx_hint] = ent;
ent->idx = udata->idx_hint;
rdcc->nbytes_used += chunk_size;
rdcc->nused++;
if(rdcc->tail) {
rdcc->tail->next = ent;
ent->prev = rdcc->tail;
rdcc->tail = ent;
}
else
rdcc->head = rdcc->tail = ent;
ent->tmp_next = NULL;
ent->tmp_prev = NULL;
}
else
ent = NULL;
}
else
ent = NULL;
}
if(ent) {
HDassert(!ent->locked);
ent->locked = TRUE;
chunk = ent->chunk;
}
else
udata->idx_hint = UINT_MAX;
ret_value = chunk;
done:
if(fb_info_init && H5D__fill_term(&fb_info) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, NULL, "Can't release fill buffer info")
if(!ret_value)
if(chunk)
chunk = H5D__chunk_mem_xfree(chunk, pline);
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5D__chunk_unlock(const H5D_io_info_t *io_info, const H5D_chunk_ud_t *udata,
hbool_t dirty, void *chunk, uint32_t naccessed)
{
const H5O_layout_t *layout = &(io_info->dset->shared->layout);
const H5D_rdcc_t *rdcc = &(io_info->dset->shared->cache.chunk);
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(io_info);
HDassert(udata);
if(UINT_MAX == udata->idx_hint) {
hbool_t is_unfiltered_edge_chunk = FALSE;
if(udata->new_unfilt_chunk) {
HDassert(layout->u.chunk.flags & H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS);
is_unfiltered_edge_chunk = TRUE;
}
else if(layout->u.chunk.flags & H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS) {
is_unfiltered_edge_chunk = H5D__chunk_is_partial_edge_chunk(
io_info->dset->shared->ndims, layout->u.chunk.dim,
io_info->store->chunk.scaled, io_info->dset->shared->curr_dims);
}
if(dirty) {
H5D_rdcc_ent_t fake_ent;
HDmemset(&fake_ent, 0, sizeof(fake_ent));
fake_ent.dirty = TRUE;
if(is_unfiltered_edge_chunk)
fake_ent.edge_chunk_state = H5D_RDCC_DISABLE_FILTERS;
if(udata->new_unfilt_chunk)
fake_ent.edge_chunk_state |= H5D_RDCC_NEWLY_DISABLED_FILTERS;
H5MM_memcpy(fake_ent.scaled, udata->common.scaled, sizeof(hsize_t) * layout->u.chunk.ndims);
HDassert(layout->u.chunk.size > 0);
fake_ent.chunk_idx = udata->chunk_idx;
fake_ent.chunk_block.offset = udata->chunk_block.offset;
fake_ent.chunk_block.length = udata->chunk_block.length;
fake_ent.chunk = (uint8_t *)chunk;
if(H5D__chunk_flush_entry(io_info->dset, &fake_ent, TRUE) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush indexed storage buffer")
}
else {
if(chunk)
chunk = H5D__chunk_mem_xfree(chunk, (is_unfiltered_edge_chunk ? NULL
: &(io_info->dset->shared->dcpl_cache.pline)));
}
}
else {
H5D_rdcc_ent_t *ent;
HDassert(udata->idx_hint < rdcc->nslots);
HDassert(rdcc->slot[udata->idx_hint]);
HDassert(rdcc->slot[udata->idx_hint]->chunk == chunk);
ent = rdcc->slot[udata->idx_hint];
HDassert(ent->locked);
if(dirty) {
ent->dirty = TRUE;
ent->wr_count -= MIN(ent->wr_count, naccessed);
}
else
ent->rd_count -= MIN(ent->rd_count, naccessed);
ent->locked = FALSE;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static int
H5D__chunk_allocated_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
{
hsize_t *nbytes = (hsize_t *)_udata;
FUNC_ENTER_STATIC_NOERR
*(hsize_t *)nbytes += chunk_rec->nbytes;
FUNC_LEAVE_NOAPI(H5_ITER_CONT)
}
herr_t
H5D__chunk_allocated(const H5D_t *dset, hsize_t *nbytes)
{
H5D_chk_idx_info_t idx_info;
const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
H5D_rdcc_ent_t *ent;
hsize_t chunk_bytes = 0;
H5O_storage_chunk_t *sc = &(dset->shared->layout.storage.u.chunk);
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(dset);
HDassert(dset->shared);
H5D_CHUNK_STORAGE_INDEX_CHK(sc);
for(ent = rdcc->head; ent; ent = ent->next)
if(H5D__chunk_flush_entry(dset, ent, FALSE) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush indexed storage buffer")
idx_info.f = dset->oloc.file;
idx_info.pline = &dset->shared->dcpl_cache.pline;
idx_info.layout = &dset->shared->layout.u.chunk;
idx_info.storage = sc;
if((sc->ops->iterate)(&idx_info, H5D__chunk_allocated_cb, &chunk_bytes) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve allocated chunk information from index")
*nbytes = chunk_bytes;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5D__chunk_allocate(const H5D_io_info_t *io_info, hbool_t full_overwrite, hsize_t old_dim[])
{
const H5D_t *dset = io_info->dset;
H5D_chk_idx_info_t idx_info;
const H5D_chunk_ops_t *ops = dset->shared->layout.storage.u.chunk.ops;
hsize_t min_unalloc[H5O_LAYOUT_NDIMS];
hsize_t max_unalloc[H5O_LAYOUT_NDIMS];
hsize_t scaled[H5O_LAYOUT_NDIMS];
size_t orig_chunk_size;
size_t chunk_size;
unsigned filter_mask = 0;
const H5O_layout_t *layout = &(dset->shared->layout);
const H5O_pline_t *pline = &(dset->shared->dcpl_cache.pline);
const H5O_pline_t def_pline = H5O_CRT_PIPELINE_DEF;
const H5O_fill_t *fill = &(dset->shared->dcpl_cache.fill);
H5D_fill_value_t fill_status;
hbool_t should_fill = FALSE;
void *unfilt_fill_buf = NULL;
void **fill_buf = NULL;
#ifdef H5_HAVE_PARALLEL
hbool_t blocks_written = FALSE;
hbool_t using_mpi = FALSE;
H5D_chunk_coll_info_t chunk_info;
#endif
hbool_t carry;
unsigned space_ndims;
const hsize_t *space_dim;
const uint32_t *chunk_dim = layout->u.chunk.dim;
unsigned op_dim;
H5D_fill_buf_info_t fb_info;
hbool_t fb_info_init = FALSE;
hbool_t has_unfilt_edge_chunks = FALSE;
hbool_t unfilt_edge_chunk_dim[H5O_LAYOUT_NDIMS];
hsize_t edge_chunk_scaled[H5O_LAYOUT_NDIMS];
unsigned nunfilt_edge_chunk_dims = 0;
const H5O_storage_chunk_t *sc = &(layout->storage.u.chunk);
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE_TAG(dset->oloc.addr)
HDassert(dset && H5D_CHUNKED == layout->type);
HDassert(layout->u.chunk.ndims > 0 && layout->u.chunk.ndims <= H5O_LAYOUT_NDIMS);
H5D_CHUNK_STORAGE_INDEX_CHK(sc);
space_dim = dset->shared->curr_dims;
space_ndims = dset->shared->ndims;
scaled[space_ndims] = (hsize_t)0;
for(op_dim = 0; op_dim < (unsigned)space_ndims; op_dim++)
if(space_dim[op_dim] == 0) {
H5D__chunk_cinfo_cache_reset(&dset->shared->cache.chunk.last);
HGOTO_DONE(SUCCEED)
}
#ifdef H5_HAVE_PARALLEL
if(H5F_HAS_FEATURE(dset->oloc.file, H5FD_FEAT_HAS_MPI)) {
using_mpi = TRUE;
chunk_info.num_io = 0;
chunk_info.addr = NULL;
}
#endif
for(op_dim=0; op_dim<space_ndims; op_dim++) {
if(chunk_dim[op_dim] == 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "chunk size must be > 0, dim = %u ", op_dim)
min_unalloc[op_dim] = (old_dim[op_dim] + chunk_dim[op_dim] - 1) / chunk_dim[op_dim];
max_unalloc[op_dim] = (space_dim[op_dim] - 1) / chunk_dim[op_dim];
if((layout->u.chunk.flags
& H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS)
&& pline->nused > 0
&& space_dim[op_dim] % chunk_dim[op_dim] != 0) {
has_unfilt_edge_chunks = TRUE;
unfilt_edge_chunk_dim[op_dim] = TRUE;
edge_chunk_scaled[op_dim] = max_unalloc[op_dim];
}
else
unfilt_edge_chunk_dim[op_dim] = FALSE;
}
H5_CHECKED_ASSIGN(orig_chunk_size, size_t, layout->u.chunk.size, uint32_t);
if(H5P_is_fill_value_defined(fill, &fill_status) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't tell if fill value defined")
if((!full_overwrite && (fill->fill_time == H5D_FILL_TIME_ALLOC ||
(fill->fill_time == H5D_FILL_TIME_IFSET &&
(fill_status == H5D_FILL_VALUE_USER_DEFINED ||
fill_status == H5D_FILL_VALUE_DEFAULT))))
|| pline->nused > 0)
should_fill = TRUE;
if(should_fill) {
if(H5D__fill_init(&fb_info, NULL, (H5MM_allocate_t)H5D__chunk_mem_alloc,
(void *)pline, (H5MM_free_t)H5D__chunk_mem_xfree, (void *)pline,
&dset->shared->dcpl_cache.fill, dset->shared->type,
dset->shared->type_id, (size_t)0, orig_chunk_size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize fill buffer info")
fb_info_init = TRUE;
fill_buf = &fb_info.fill_buf;
if(!fb_info.has_vlen_fill_type && pline->nused > 0) {
H5Z_EDC_t err_detect;
H5Z_cb_t filter_cb;
size_t buf_size = orig_chunk_size;
if(has_unfilt_edge_chunks) {
if(NULL == (unfilt_fill_buf = H5D__chunk_mem_alloc(orig_chunk_size, &def_pline)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for raw data chunk")
H5MM_memcpy(unfilt_fill_buf, fb_info.fill_buf, orig_chunk_size);
}
if(H5CX_get_err_detect(&err_detect) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get error detection info")
if(H5CX_get_filter_cb(&filter_cb) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get I/O filter callback function")
if(H5Z_pipeline(pline, 0, &filter_mask, err_detect, filter_cb, &orig_chunk_size, &buf_size, &fb_info.fill_buf) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_WRITEERROR, FAIL, "output pipeline failed")
#if H5_SIZEOF_SIZE_T > 4
if(orig_chunk_size > ((size_t)0xffffffff))
HGOTO_ERROR(H5E_DATASET, H5E_BADRANGE, FAIL, "chunk too large for 32-bit length")
#endif
}
}
idx_info.f = dset->oloc.file;
idx_info.pline = &dset->shared->dcpl_cache.pline;
idx_info.layout = &dset->shared->layout.u.chunk;
idx_info.storage = sc;
chunk_size = orig_chunk_size;
for(op_dim = 0; op_dim < space_ndims; op_dim++) {
H5D_chunk_ud_t udata;
unsigned u;
int i;
if(min_unalloc[op_dim] > max_unalloc[op_dim])
continue;
else {
HDmemset(scaled, 0, (space_ndims * sizeof(scaled[0])));
scaled[op_dim] = min_unalloc[op_dim];
if(has_unfilt_edge_chunks) {
nunfilt_edge_chunk_dims = 0;
for(u = 0; u < space_ndims; u++)
if(unfilt_edge_chunk_dim[u] && scaled[u]
== edge_chunk_scaled[u])
nunfilt_edge_chunk_dims++;
if(should_fill && !fb_info.has_vlen_fill_type) {
HDassert(fb_info_init);
HDassert(unfilt_fill_buf);
if(nunfilt_edge_chunk_dims) {
fill_buf = &unfilt_fill_buf;
chunk_size = layout->u.chunk.size;
}
else {
fill_buf = &fb_info.fill_buf;
chunk_size = orig_chunk_size;
}
}
}
carry = FALSE;
}
while(!carry) {
hbool_t need_insert = FALSE;
if(H5D__chunk_lookup(dset, scaled, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
#ifndef NDEBUG
if(H5D_CHUNK_IDX_NONE != sc->idx_type)
HDassert(!H5F_addr_defined(udata.chunk_block.offset));
{
unsigned v;
hbool_t outside_orig = FALSE;
for(v = 0; v < space_ndims; v++) {
HDassert((scaled[v] * chunk_dim[v]) < space_dim[v]);
if((scaled[v] * chunk_dim[v]) >= old_dim[v])
outside_orig = TRUE;
}
HDassert(outside_orig);
}
#endif
if(fb_info_init && fb_info.has_vlen_fill_type) {
HDassert(should_fill);
HDassert(!unfilt_fill_buf);
#ifdef H5_HAVE_PARALLEL
HDassert(!using_mpi);
#endif
if(fb_info.fill_buf_size < orig_chunk_size) {
if(NULL == (fb_info.fill_buf = H5D__chunk_mem_realloc(fb_info.fill_buf, orig_chunk_size, pline)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory reallocation failed for raw data chunk")
fb_info.fill_buf_size = orig_chunk_size;
}
if(H5D__fill_refill_vl(&fb_info, fb_info.elmts_per_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "can't refill fill value buffer")
if((pline->nused > 0) && !nunfilt_edge_chunk_dims) {
H5Z_EDC_t err_detect;
H5Z_cb_t filter_cb;
size_t nbytes = orig_chunk_size;
if(H5CX_get_err_detect(&err_detect) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get error detection info")
if(H5CX_get_filter_cb(&filter_cb) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get I/O filter callback function")
if(H5Z_pipeline(pline, 0, &filter_mask, err_detect, filter_cb, &nbytes, &fb_info.fill_buf_size, &fb_info.fill_buf) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_WRITEERROR, FAIL, "output pipeline failed")
#if H5_SIZEOF_SIZE_T > 4
if(nbytes > ((size_t)0xffffffff))
HGOTO_ERROR(H5E_DATASET, H5E_BADRANGE, FAIL, "chunk too large for 32-bit length")
#endif
chunk_size = nbytes;
}
else
chunk_size = layout->u.chunk.size;
HDassert(*fill_buf == fb_info.fill_buf);
}
udata.common.layout = &layout->u.chunk;
udata.common.storage = sc;
udata.common.scaled = scaled;
udata.chunk_block.offset = HADDR_UNDEF;
H5_CHECKED_ASSIGN(udata.chunk_block.length, uint32_t, chunk_size, size_t);
udata.filter_mask = filter_mask;
if(H5D__chunk_file_alloc(&idx_info, NULL, &udata.chunk_block, &need_insert, scaled) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert/resize chunk on chunk level")
HDassert(H5F_addr_defined(udata.chunk_block.offset));
if(should_fill) {
HDassert(fb_info_init);
HDassert(udata.chunk_block.length == chunk_size);
#ifdef H5_HAVE_PARALLEL
if(using_mpi) {
if(0 == chunk_info.num_io % 1024)
if(NULL == (chunk_info.addr = (haddr_t *)H5MM_realloc(chunk_info.addr, (chunk_info.num_io + 1024) * sizeof(haddr_t))))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "memory allocation failed for chunk addresses")
chunk_info.addr[chunk_info.num_io] = udata.chunk_block.offset;
chunk_info.num_io++;
blocks_written = TRUE;
}
else {
#endif
if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.chunk_block.offset, chunk_size, *fill_buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file")
#ifdef H5_HAVE_PARALLEL
}
#endif
}
if(need_insert && ops->insert)
if((ops->insert)(&idx_info, &udata, dset) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert chunk addr into index")
carry = TRUE;
for(i = ((int)space_ndims - 1); i >= 0; --i) {
scaled[i]++;
if(scaled[i] > max_unalloc[i]) {
if((unsigned)i == op_dim)
scaled[i] = min_unalloc[i];
else
scaled[i] = 0;
if(unfilt_edge_chunk_dim[i]
&& edge_chunk_scaled[i] == max_unalloc[i]
&& scaled[i] < edge_chunk_scaled[i]) {
nunfilt_edge_chunk_dims--;
if(should_fill && nunfilt_edge_chunk_dims == 0 && !fb_info.has_vlen_fill_type) {
HDassert(!H5D__chunk_is_partial_edge_chunk(space_ndims, chunk_dim, scaled, space_dim));
fill_buf = &fb_info.fill_buf;
chunk_size = orig_chunk_size;
}
}
}
else {
if(unfilt_edge_chunk_dim[i] && scaled[i] == edge_chunk_scaled[i]) {
HDassert(edge_chunk_scaled[i] == max_unalloc[i]);
nunfilt_edge_chunk_dims++;
if(should_fill && nunfilt_edge_chunk_dims == 1 && !fb_info.has_vlen_fill_type) {
HDassert(H5D__chunk_is_partial_edge_chunk(space_ndims, chunk_dim, scaled, space_dim));
fill_buf = &unfilt_fill_buf;
chunk_size = layout->u.chunk.size;
}
}
carry = FALSE;
break;
}
}
}
if(min_unalloc[op_dim] == 0)
break;
else
max_unalloc[op_dim] = min_unalloc[op_dim] - 1;
}
#ifdef H5_HAVE_PARALLEL
if(using_mpi && blocks_written)
if(H5D__chunk_collective_fill(dset, &chunk_info, chunk_size, fb_info.fill_buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file")
#endif
H5D__chunk_cinfo_cache_reset(&dset->shared->cache.chunk.last);
done:
if(fb_info_init && H5D__fill_term(&fb_info) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release fill buffer info")
unfilt_fill_buf = H5D__chunk_mem_xfree(unfilt_fill_buf, &def_pline);
#ifdef H5_HAVE_PARALLEL
if(using_mpi && chunk_info.addr)
H5MM_free(chunk_info.addr);
#endif
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
herr_t
H5D__chunk_update_old_edge_chunks(H5D_t *dset, hsize_t old_dim[])
{
hsize_t old_edge_chunk_sc[H5O_LAYOUT_NDIMS];
hsize_t max_edge_chunk_sc[H5O_LAYOUT_NDIMS];
hbool_t new_full_dim[H5O_LAYOUT_NDIMS];
const H5O_layout_t *layout = &(dset->shared->layout);
hsize_t chunk_sc[H5O_LAYOUT_NDIMS];
const uint32_t *chunk_dim = layout->u.chunk.dim;
unsigned space_ndims;
const hsize_t *space_dim;
unsigned op_dim;
H5D_io_info_t chk_io_info;
H5D_chunk_ud_t chk_udata;
H5D_storage_t chk_store;
void *chunk;
hbool_t carry;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(dset && H5D_CHUNKED == layout->type);
HDassert(layout->u.chunk.ndims > 0 && layout->u.chunk.ndims <= H5O_LAYOUT_NDIMS);
H5D_CHUNK_STORAGE_INDEX_CHK(&layout->storage.u.chunk);
HDassert(dset->shared->dcpl_cache.pline.nused > 0);
HDassert(layout->u.chunk.flags
& H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS);
space_dim = dset->shared->curr_dims;
space_ndims = dset->shared->ndims;
chunk_sc[space_ndims] = (hsize_t)0;
for(op_dim=0; op_dim<space_ndims; op_dim++)
if((space_dim[op_dim] < chunk_dim[op_dim]) || old_dim[op_dim] == 0) {
H5D__chunk_cinfo_cache_reset(&dset->shared->cache.chunk.last);
HGOTO_DONE(SUCCEED)
}
chk_store.chunk.scaled = chunk_sc;
H5D_BUILD_IO_INFO_RD(&chk_io_info, dset, &chk_store, NULL);
for(op_dim=0; op_dim<space_ndims; op_dim++) {
new_full_dim[op_dim] = FALSE;
if(chunk_dim[op_dim] == 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "chunk size must be > 0, dim = %u ", op_dim)
old_edge_chunk_sc[op_dim] = (old_dim[op_dim] / chunk_dim[op_dim]);
max_edge_chunk_sc[op_dim] = MIN((old_dim[op_dim] - 1) / chunk_dim[op_dim],
MAX((space_dim[op_dim] / chunk_dim[op_dim]), 1) - 1);
if(old_dim[op_dim] % chunk_dim[op_dim] == 0)
continue;
if((space_dim[op_dim]/chunk_dim[op_dim]) >= (old_edge_chunk_sc[op_dim] + 1))
new_full_dim[op_dim] = TRUE;
}
for(op_dim=0; op_dim<space_ndims; op_dim++) {
if(!new_full_dim[op_dim])
continue;
else {
HDassert(max_edge_chunk_sc[op_dim] == old_edge_chunk_sc[op_dim]);
HDmemset(chunk_sc, 0, (space_ndims * sizeof(chunk_sc[0])));
chunk_sc[op_dim] = old_edge_chunk_sc[op_dim];
carry = FALSE;
}
while(!carry) {
int i;
HDassert(H5D__chunk_is_partial_edge_chunk(space_ndims, chunk_dim, chunk_sc, old_dim)
&& !H5D__chunk_is_partial_edge_chunk(space_ndims, chunk_dim, chunk_sc, space_dim));
if(H5D__chunk_lookup(dset, chunk_sc, &chk_udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
if(H5F_addr_defined(chk_udata.chunk_block.offset)
|| (UINT_MAX != chk_udata.idx_hint)) {
if(NULL == (chunk = (void *)H5D__chunk_lock(&chk_io_info, &chk_udata, FALSE, TRUE)))
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "unable to lock raw data chunk")
if(H5D__chunk_unlock(&chk_io_info, &chk_udata, TRUE, chunk, (uint32_t)0) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to unlock raw data chunk")
}
carry = TRUE;
for(i = ((int)space_ndims - 1); i >= 0; --i) {
if((unsigned)i != op_dim) {
++chunk_sc[i];
if(chunk_sc[i] > (hsize_t) max_edge_chunk_sc[i])
chunk_sc[i] = 0;
else {
carry = FALSE;
break;
}
}
}
}
if(old_edge_chunk_sc[op_dim] == 0)
break;
else
--max_edge_chunk_sc[op_dim];
}
H5D__chunk_cinfo_cache_reset(&dset->shared->cache.chunk.last);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
#ifdef H5_HAVE_PARALLEL
static herr_t
H5D__chunk_collective_fill(const H5D_t *dset, H5D_chunk_coll_info_t *chunk_info,
size_t chunk_size, const void *fill_buf)
{
MPI_Comm mpi_comm = MPI_COMM_NULL;
int mpi_rank = (-1);
int mpi_size = (-1);
int mpi_code;
size_t num_blocks;
size_t leftover_blocks;
int blocks, leftover, block_len;
MPI_Aint *chunk_disp_array = NULL;
int *block_lens = NULL;
MPI_Datatype mem_type = MPI_BYTE, file_type = MPI_BYTE;
H5FD_mpio_xfer_t prev_xfer_mode;
hbool_t have_xfer_mode = FALSE;
hbool_t need_addr_sort = FALSE;
int i;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
if(MPI_COMM_NULL == (mpi_comm = H5F_mpi_get_comm(dset->oloc.file)))
HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI communicator")
if((mpi_rank = H5F_mpi_get_rank(dset->oloc.file)) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI rank")
if((mpi_size = H5F_mpi_get_size(dset->oloc.file)) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI size")
if(mpi_size == 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "Resulted in division by zero")
num_blocks = (size_t)(chunk_info->num_io / (size_t)mpi_size);
leftover_blocks = (size_t)(chunk_info->num_io % (size_t)mpi_size);
H5_CHECKED_ASSIGN(blocks, int, num_blocks, size_t);
H5_CHECKED_ASSIGN(leftover, int, leftover_blocks, size_t);
H5_CHECKED_ASSIGN(block_len, int, chunk_size, size_t);
if(num_blocks > 0 || (leftover && leftover > mpi_rank)) {
if(NULL == (block_lens = (int *)H5MM_malloc((size_t)(blocks + 1) * sizeof(int))))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk lengths buffer")
if(NULL == (chunk_disp_array = (MPI_Aint *)H5MM_malloc((size_t)(blocks + 1) * sizeof(MPI_Aint))))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk file displacement buffer")
for(i = 0 ; i < blocks ; i++) {
chunk_disp_array[i] = (MPI_Aint)(chunk_info->addr[i + (mpi_rank * blocks)]);
block_lens[i] = block_len;
if(i && (chunk_disp_array[i] < chunk_disp_array[i - 1]))
need_addr_sort = TRUE;
}
if(leftover && leftover > mpi_rank) {
chunk_disp_array[blocks] = (MPI_Aint)chunk_info->addr[(blocks * mpi_size) + mpi_rank];
if(blocks && (chunk_disp_array[blocks] < chunk_disp_array[blocks - 1]))
need_addr_sort = TRUE;
block_lens[blocks] = block_len;
blocks++;
}
if(need_addr_sort)
HDqsort(chunk_disp_array, blocks, sizeof(MPI_Aint), H5D__chunk_cmp_addr);
mpi_code = MPI_Type_create_hindexed(blocks, block_lens, chunk_disp_array, MPI_BYTE, &file_type);
if(mpi_code != MPI_SUCCESS)
HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed failed", mpi_code)
if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&file_type)))
HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code)
mpi_code = MPI_Type_create_hvector(blocks, block_len, 0, MPI_BYTE, &mem_type);
if(mpi_code != MPI_SUCCESS)
HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hvector failed", mpi_code)
if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&mem_type)))
HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code)
}
if(H5CX_set_mpi_coll_datatypes(mem_type, file_type) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set MPI-I/O properties")
if(H5CX_get_io_xfer_mode(&prev_xfer_mode) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set transfer mode")
have_xfer_mode = TRUE;
if(H5CX_set_io_xfer_mode(H5FD_MPIO_COLLECTIVE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set transfer mode")
if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, (haddr_t)0, (blocks) ? (size_t)1 : (size_t)0, fill_buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file")
if(MPI_SUCCESS != (mpi_code = MPI_Barrier(mpi_comm)))
HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code)
done:
if(have_xfer_mode)
if(H5CX_set_io_xfer_mode(prev_xfer_mode) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set transfer mode")
if(MPI_BYTE != file_type)
if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&file_type)))
HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
if(MPI_BYTE != mem_type)
if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&mem_type)))
HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
H5MM_xfree(chunk_disp_array);
H5MM_xfree(block_lens);
FUNC_LEAVE_NOAPI(ret_value)
}
static int
H5D__chunk_cmp_addr(const void *addr1, const void *addr2)
{
MPI_Aint _addr1 = (MPI_Aint)0, _addr2 = (MPI_Aint)0;
int ret_value = 0;
FUNC_ENTER_STATIC_NOERR
_addr1 = *((const MPI_Aint *) addr1);
_addr2 = *((const MPI_Aint *) addr2);
#if MPI_VERSION >= 3 && MPI_SUBVERSION >= 1
{
MPI_Aint diff = MPI_Aint_diff(_addr1, _addr2);
if(diff < (MPI_Aint)0)
ret_value = -1;
else if(diff > (MPI_Aint)0)
ret_value = 1;
else
ret_value = 0;
}
#else
ret_value = (_addr1 > _addr2) - (_addr1 < _addr2);
#endif
FUNC_LEAVE_NOAPI(ret_value)
}
#endif
static herr_t
H5D__chunk_prune_fill(H5D_chunk_it_ud1_t *udata, hbool_t new_unfilt_chunk)
{
const H5D_io_info_t *io_info = udata->io_info;
const H5D_t *dset = io_info->dset;
const H5O_layout_t *layout = &(dset->shared->layout);
unsigned rank = udata->common.layout->ndims - 1;
const hsize_t *scaled = udata->common.scaled;
H5S_sel_iter_t *chunk_iter = NULL;
hbool_t chunk_iter_init = FALSE;
hsize_t sel_nelmts;
hsize_t count[H5O_LAYOUT_NDIMS];
size_t chunk_size;
void *chunk;
H5D_chunk_ud_t chk_udata;
uint32_t bytes_accessed;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(layout->u.chunk.size > 0);
H5_CHECKED_ASSIGN(chunk_size, size_t, layout->u.chunk.size, uint32_t);
if(H5D__chunk_lookup(dset, scaled, &chk_udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
chk_udata.new_unfilt_chunk = new_unfilt_chunk;
if(!H5F_addr_defined(chk_udata.chunk_block.offset) && UINT_MAX == chk_udata.idx_hint)
HGOTO_DONE(SUCCEED)
if(!udata->fb_info_init) {
H5_CHECK_OVERFLOW(udata->elmts_per_chunk, uint32_t, size_t);
if(H5D__fill_init(&udata->fb_info, NULL, NULL, NULL, NULL, NULL,
&dset->shared->dcpl_cache.fill,
dset->shared->type, dset->shared->type_id, (size_t)udata->elmts_per_chunk,
chunk_size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize fill buffer info")
udata->fb_info_init = TRUE;
}
for(u = 0; u < rank; u++) {
count[u] = MIN(layout->u.chunk.dim[u], (udata->space_dim[u] - (scaled[u] * layout->u.chunk.dim[u])));
HDassert(count[u] > 0);
}
if(H5S_select_all(udata->chunk_space, TRUE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, FAIL, "unable to select space")
if(H5S_select_hyperslab(udata->chunk_space, H5S_SELECT_NOTB, udata->hyper_start, NULL, count, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, FAIL, "unable to select hyperslab")
if(NULL == (chunk = (void *)H5D__chunk_lock(io_info, &chk_udata, FALSE, FALSE)))
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "unable to lock raw data chunk")
sel_nelmts = H5S_GET_SELECT_NPOINTS(udata->chunk_space);
H5_CHECK_OVERFLOW(sel_nelmts, hsize_t, size_t);
if(udata->fb_info.has_vlen_fill_type)
if(H5D__fill_refill_vl(&udata->fb_info, (size_t)sel_nelmts) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "can't refill fill value buffer")
if(NULL == (chunk_iter = H5FL_MALLOC(H5S_sel_iter_t)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate chunk selection iterator")
if(H5S_select_iter_init(chunk_iter, udata->chunk_space, layout->u.chunk.dim[rank], 0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize chunk selection information")
chunk_iter_init = TRUE;
if(H5D__scatter_mem(udata->fb_info.fill_buf, chunk_iter, (size_t)sel_nelmts, chunk) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "scatter failed")
H5_CHECK_OVERFLOW(sel_nelmts, hssize_t, uint32_t);
bytes_accessed = (uint32_t)sel_nelmts * layout->u.chunk.dim[rank];
if(H5D__chunk_unlock(io_info, &chk_udata, TRUE, chunk, bytes_accessed) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to unlock raw data chunk")
done:
if(chunk_iter_init && H5S_SELECT_ITER_RELEASE(chunk_iter) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
if(chunk_iter)
chunk_iter = H5FL_FREE(H5S_sel_iter_t, chunk_iter);
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5D__chunk_prune_by_extent(H5D_t *dset, const hsize_t *old_dim)
{
hsize_t min_mod_chunk_sc[H5O_LAYOUT_NDIMS];
hsize_t max_mod_chunk_sc[H5O_LAYOUT_NDIMS];
hssize_t max_fill_chunk_sc[H5O_LAYOUT_NDIMS];
hbool_t fill_dim[H5O_LAYOUT_NDIMS];
hsize_t min_partial_chunk_sc[H5O_LAYOUT_NDIMS];
hbool_t new_unfilt_dim[H5O_LAYOUT_NDIMS];
H5D_chk_idx_info_t idx_info;
H5D_io_info_t chk_io_info;
H5D_storage_t chk_store;
const H5O_layout_t *layout = &(dset->shared->layout);
const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
unsigned space_ndims;
const hsize_t *space_dim;
unsigned op_dim;
hbool_t shrunk_dim[H5O_LAYOUT_NDIMS];
H5D_chunk_it_ud1_t udata;
hbool_t udata_init = FALSE;
H5D_chunk_common_ud_t idx_udata;
H5S_t *chunk_space = NULL;
hsize_t chunk_dim[H5O_LAYOUT_NDIMS];
hsize_t scaled[H5O_LAYOUT_NDIMS];
hsize_t hyper_start[H5O_LAYOUT_NDIMS];
uint32_t elmts_per_chunk;
hbool_t disable_edge_filters = FALSE;
hbool_t new_unfilt_chunk = FALSE;
unsigned u;
const H5O_storage_chunk_t *sc = &(layout->storage.u.chunk);
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(dset && H5D_CHUNKED == layout->type);
HDassert(layout->u.chunk.ndims > 0 && layout->u.chunk.ndims <= H5O_LAYOUT_NDIMS);
H5D_CHUNK_STORAGE_INDEX_CHK(sc);
space_dim = dset->shared->curr_dims;
space_ndims = dset->shared->ndims;
scaled[space_ndims] = (hsize_t)0;
for(op_dim = 0; op_dim < (unsigned)space_ndims; op_dim++)
if(old_dim[op_dim] == 0) {
H5D__chunk_cinfo_cache_reset(&dset->shared->cache.chunk.last);
HGOTO_DONE(SUCCEED)
}
elmts_per_chunk = 1;
for(u = 0; u < space_ndims; u++) {
elmts_per_chunk *= layout->u.chunk.dim[u];
chunk_dim[u] = layout->u.chunk.dim[u];
shrunk_dim[u] = (space_dim[u] < old_dim[u]);
}
if(NULL == (chunk_space = H5S_create_simple(space_ndims, chunk_dim, NULL)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace")
HDmemset(hyper_start, 0, sizeof(hyper_start));
chk_store.chunk.scaled = scaled;
H5D_BUILD_IO_INFO_RD(&chk_io_info, dset, &chk_store, NULL);
idx_info.f = dset->oloc.file;
idx_info.pline = &dset->shared->dcpl_cache.pline;
idx_info.layout = &dset->shared->layout.u.chunk;
idx_info.storage = &dset->shared->layout.storage.u.chunk;
HDmemset(&udata, 0, sizeof udata);
udata.common.layout = &layout->u.chunk;
udata.common.storage = sc;
udata.common.scaled = scaled;
udata.io_info = &chk_io_info;
udata.idx_info = &idx_info;
udata.space_dim = space_dim;
udata.shrunk_dim = shrunk_dim;
udata.elmts_per_chunk = elmts_per_chunk;
udata.chunk_space = chunk_space;
udata.hyper_start = hyper_start;
udata_init = TRUE;
idx_udata.layout = &layout->u.chunk;
idx_udata.storage = sc;
disable_edge_filters = (layout->u.chunk.flags
& H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS)
&& (idx_info.pline->nused > 0);
HDmemset(min_mod_chunk_sc, 0, sizeof(min_mod_chunk_sc));
HDmemset(max_mod_chunk_sc, 0, sizeof(max_mod_chunk_sc));
for(op_dim = 0; op_dim < (unsigned)space_ndims; op_dim++) {
if(chunk_dim[op_dim] == 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "chunk size must be > 0, dim = %u ", op_dim)
max_mod_chunk_sc[op_dim] = (old_dim[op_dim] - 1) / chunk_dim[op_dim];
if(0 == space_dim[op_dim])
max_fill_chunk_sc[op_dim] = -1;
else
max_fill_chunk_sc[op_dim] = (hssize_t)(((MIN(space_dim[op_dim], old_dim[op_dim]) - 1)
/ chunk_dim[op_dim]));
if(shrunk_dim[op_dim]) {
min_mod_chunk_sc[op_dim] = space_dim[op_dim] / chunk_dim[op_dim];
if((hssize_t)min_mod_chunk_sc[op_dim] == max_fill_chunk_sc[op_dim]) {
fill_dim[op_dim] = TRUE;
if(disable_edge_filters && old_dim[op_dim] >= (min_mod_chunk_sc[op_dim] + 1))
new_unfilt_dim[op_dim] = TRUE;
else
new_unfilt_dim[op_dim] = FALSE;
}
else {
fill_dim[op_dim] = FALSE;
new_unfilt_dim[op_dim] = FALSE;
}
}
else {
fill_dim[op_dim] = FALSE;
new_unfilt_dim[op_dim] = FALSE;
}
if(disable_edge_filters)
min_partial_chunk_sc[op_dim] = old_dim[op_dim] / chunk_dim[op_dim];
}
for(op_dim = 0; op_dim < (unsigned)space_ndims; op_dim++) {
hbool_t dims_outside_fill[H5O_LAYOUT_NDIMS];
int ndims_outside_fill;
hbool_t carry;
if(!shrunk_dim[op_dim])
continue;
else {
HDassert(max_mod_chunk_sc[op_dim] >= min_mod_chunk_sc[op_dim]);
HDmemset(scaled, 0, (space_ndims * sizeof(scaled[0])));
scaled[op_dim] = min_mod_chunk_sc[op_dim];
ndims_outside_fill = 0;
for(u = 0; u < space_ndims; u++)
if((hssize_t)scaled[u] > max_fill_chunk_sc[u]) {
dims_outside_fill[u] = TRUE;
ndims_outside_fill++;
}
else
dims_outside_fill[u] = FALSE;
}
carry = FALSE;
while(!carry) {
int i;
udata.common.scaled = scaled;
if(0 == ndims_outside_fill) {
HDassert(fill_dim[op_dim]);
HDassert(scaled[op_dim] == min_mod_chunk_sc[op_dim]);
HDassert(H5D__chunk_is_partial_edge_chunk(space_ndims, layout->u.chunk.dim, scaled, space_dim));
if(new_unfilt_dim[op_dim]) {
new_unfilt_chunk = TRUE;
for(u = 0; u < space_ndims; u++)
if(scaled[u] == min_partial_chunk_sc[u]) {
new_unfilt_chunk = FALSE;
break;
}
}
HDassert(!new_unfilt_dim[op_dim] || (!new_unfilt_chunk !=
!H5D__chunk_is_partial_edge_chunk(space_ndims, layout->u.chunk.dim, scaled, old_dim)));
HDassert(!new_unfilt_chunk || new_unfilt_dim[op_dim]);
if(H5D__chunk_prune_fill(&udata, new_unfilt_chunk) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to write fill value")
}
else {
H5D_chunk_ud_t chk_udata;
#ifndef NDEBUG
{
hbool_t outside_dim = FALSE;
for(u = 0; u < space_ndims; u++)
if((scaled[u] * chunk_dim[u]) >= space_dim[u]) {
outside_dim = TRUE;
break;
}
HDassert(outside_dim);
}
#endif
if(H5D__chunk_lookup(dset, scaled, &chk_udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk")
if(UINT_MAX != chk_udata.idx_hint)
if(H5D__chunk_cache_evict(dset, rdcc->slot[chk_udata.idx_hint], FALSE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTREMOVE, FAIL, "unable to evict chunk")
if(H5F_addr_defined(chk_udata.chunk_block.offset)) {
idx_udata.scaled = udata.common.scaled;
if((sc->ops->remove)(&idx_info, &idx_udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTDELETE, FAIL, "unable to remove chunk entry from index")
}
}
carry = TRUE;
for(i = (int)(space_ndims - 1); i >= 0; --i) {
scaled[i]++;
if(scaled[i] > max_mod_chunk_sc[i]) {
if((unsigned)i == op_dim) {
scaled[i] = min_mod_chunk_sc[i];
if(dims_outside_fill[i] && fill_dim[i]) {
dims_outside_fill[i] = FALSE;
ndims_outside_fill--;
}
}
else {
scaled[i] = 0;
if(dims_outside_fill[i] && max_fill_chunk_sc[i] >= 0) {
dims_outside_fill[i] = FALSE;
ndims_outside_fill--;
}
}
}
else {
if(!dims_outside_fill[i] && (hssize_t)scaled[i] > max_fill_chunk_sc[i]) {
dims_outside_fill[i] = TRUE;
ndims_outside_fill++;
}
carry = FALSE;
break;
}
}
}
if(min_mod_chunk_sc[op_dim] == 0)
break;
else
max_mod_chunk_sc[op_dim] = min_mod_chunk_sc[op_dim] - 1;
}
H5D__chunk_cinfo_cache_reset(&dset->shared->cache.chunk.last);
done:
if(chunk_space && H5S_close(chunk_space) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataspace")
if(udata_init)
if(udata.fb_info_init && H5D__fill_term(&udata.fb_info) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release fill buffer info")
FUNC_LEAVE_NOAPI(ret_value)
}
#ifdef H5_HAVE_PARALLEL
static int
H5D__chunk_addrmap_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
{
H5D_chunk_it_ud2_t *udata = (H5D_chunk_it_ud2_t *)_udata;
unsigned rank = udata->common.layout->ndims - 1;
hsize_t chunk_index;
FUNC_ENTER_STATIC_NOERR
chunk_index = H5VM_array_offset_pre(rank, udata->common.layout->down_chunks, chunk_rec->scaled);
udata->chunk_addr[chunk_index] = chunk_rec->chunk_addr;
FUNC_LEAVE_NOAPI(H5_ITER_CONT)
}
herr_t
H5D__chunk_addrmap(const H5D_io_info_t *io_info, haddr_t chunk_addr[])
{
H5D_chk_idx_info_t idx_info;
const H5D_t *dset = io_info->dset;
H5D_chunk_it_ud2_t udata;
H5O_storage_chunk_t *sc = &(dset->shared->layout.storage.u.chunk);
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(dset);
HDassert(dset->shared);
H5D_CHUNK_STORAGE_INDEX_CHK(sc);
HDassert(chunk_addr);
HDmemset(&udata, 0, sizeof(udata));
udata.common.layout = &dset->shared->layout.u.chunk;
udata.common.storage = sc;
udata.chunk_addr = chunk_addr;
idx_info.f = dset->oloc.file;
idx_info.pline = &dset->shared->dcpl_cache.pline;
idx_info.layout = &dset->shared->layout.u.chunk;
idx_info.storage = sc;
if((sc->ops->iterate)(&idx_info, H5D__chunk_addrmap_cb, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to iterate over chunk index to build address map")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
#endif
herr_t
H5D__chunk_delete(H5F_t *f, H5O_t *oh, H5O_storage_t *storage)
{
H5D_chk_idx_info_t idx_info;
H5O_layout_t layout;
hbool_t layout_read = FALSE;
H5O_pline_t pline;
hbool_t pline_read = FALSE;
htri_t exists;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(f);
HDassert(oh);
HDassert(storage);
H5D_CHUNK_STORAGE_INDEX_CHK(&storage->u.chunk);
if((exists = H5O_msg_exists_oh(oh, H5O_PLINE_ID)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to check for object header message")
else if(exists) {
if(NULL == H5O_msg_read_oh(f, oh, H5O_PLINE_ID, &pline))
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get I/O pipeline message")
pline_read = TRUE;
}
else
HDmemset(&pline, 0, sizeof(pline));
if((exists = H5O_msg_exists_oh(oh, H5O_LAYOUT_ID)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to check for object header message")
else if(exists) {
if(NULL == H5O_msg_read_oh(f, oh, H5O_LAYOUT_ID, &layout))
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get layout message")
layout_read = TRUE;
}
else
HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, FAIL, "can't find layout message")
idx_info.f = f;
idx_info.pline = &pline;
idx_info.layout = &layout.u.chunk;
idx_info.storage = &storage->u.chunk;
if((storage->u.chunk.ops->idx_delete)(&idx_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTDELETE, FAIL, "unable to delete chunk index")
done:
if(pline_read)
if(H5O_msg_reset(H5O_PLINE_ID, &pline) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTRESET, FAIL, "unable to reset I/O pipeline message")
if(layout_read)
if(H5O_msg_reset(H5O_LAYOUT_ID, &layout) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTRESET, FAIL, "unable to reset layout message")
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5D__chunk_update_cache(H5D_t *dset)
{
H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
H5D_rdcc_ent_t *ent, *next;
H5D_rdcc_ent_t tmp_head;
H5D_rdcc_ent_t *tmp_tail;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(dset && H5D_CHUNKED == dset->shared->layout.type);
HDassert(dset->shared->layout.u.chunk.ndims > 0 && dset->shared->layout.u.chunk.ndims <= H5O_LAYOUT_NDIMS);
HDassert((dset->shared->layout.u.chunk.ndims - 1) > 1);
(void)HDmemset(&tmp_head, 0, sizeof(tmp_head));
rdcc->tmp_head = &tmp_head;
tmp_tail = &tmp_head;
for(ent = rdcc->head; ent; ent = next) {
unsigned old_idx;
next = ent->next;
old_idx = ent->idx;
ent->idx = H5D__chunk_hash_val(dset->shared, ent->scaled);
if(old_idx != ent->idx) {
H5D_rdcc_ent_t *old_ent;
old_ent = rdcc->slot[ent->idx];
if(old_ent != NULL) {
HDassert(old_ent->locked == FALSE);
HDassert(old_ent->deleted == FALSE);
HDassert(!old_ent->tmp_next);
HDassert(!old_ent->tmp_prev);
tmp_tail->tmp_next = old_ent;
old_ent->tmp_prev = tmp_tail;
tmp_tail = old_ent;
}
rdcc->slot[ent->idx] = ent;
if(ent->tmp_prev) {
HDassert(tmp_head.tmp_next);
HDassert(tmp_tail != &tmp_head);
ent->tmp_prev->tmp_next = ent->tmp_next;
if(ent->tmp_next) {
ent->tmp_next->tmp_prev = ent->tmp_prev;
ent->tmp_next = NULL;
}
else {
HDassert(tmp_tail == ent);
tmp_tail = ent->tmp_prev;
}
ent->tmp_prev = NULL;
}
else
rdcc->slot[old_idx] = NULL;
}
}
tmp_tail = NULL;
while(tmp_head.tmp_next) {
ent = tmp_head.tmp_next;
if(H5D__chunk_cache_evict(dset, ent, TRUE) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush one or more raw data chunks")
}
done:
rdcc->tmp_head = NULL;
FUNC_LEAVE_NOAPI(ret_value)
}
static int
H5D__chunk_copy_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
{
H5D_chunk_it_ud3_t *udata = (H5D_chunk_it_ud3_t *)_udata;
H5D_chunk_ud_t udata_dst;
hbool_t is_vlen = FALSE;
hbool_t fix_ref = FALSE;
hbool_t need_insert = FALSE;
void *bkg = udata->bkg;
void *buf = udata->buf;
size_t buf_size = udata->buf_size;
const H5O_pline_t *pline = udata->pline;
hbool_t must_filter = FALSE;
size_t nbytes;
H5Z_cb_t filter_cb;
int ret_value = H5_ITER_CONT;
FUNC_ENTER_STATIC
H5_CHECKED_ASSIGN(nbytes, size_t, chunk_rec->nbytes, uint32_t);
filter_cb.op_data = NULL;
filter_cb.func = NULL;
if(pline && pline->nused) {
must_filter = TRUE;
if((udata->common.layout->flags & H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS) &&
H5D__chunk_is_partial_edge_chunk(udata->dset_ndims, udata->common.layout->dim, chunk_rec->scaled, udata->dset_dims))
must_filter = FALSE;
}
if(udata->do_convert) {
if(H5T_detect_class(udata->dt_src, H5T_VLEN, FALSE) > 0)
is_vlen = TRUE;
else if((H5T_get_class(udata->dt_src, FALSE) == H5T_REFERENCE) && (udata->file_src != udata->idx_info_dst->f))
fix_ref = TRUE;
else
HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, H5_ITER_ERROR, "unable to copy dataset elements")
}
if(nbytes > buf_size) {
void *new_buf;
if(NULL == (new_buf = H5MM_realloc(udata->buf, nbytes)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed for raw data chunk")
udata->buf = new_buf;
if(udata->bkg) {
if(NULL == (new_buf = H5MM_realloc(udata->bkg, nbytes)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed for raw data chunk")
udata->bkg = new_buf;
if(!udata->cpy_info->expand_ref)
HDmemset((uint8_t *)udata->bkg + buf_size, 0, (size_t)(nbytes - buf_size));
bkg = udata->bkg;
}
buf = udata->buf;
udata->buf_size = buf_size = nbytes;
}
if(udata->chunk_in_cache && udata->chunk) {
HDassert(!H5F_addr_defined(chunk_rec->chunk_addr));
H5MM_memcpy(buf, udata->chunk, nbytes);
udata->chunk = NULL;
}
else {
H5D_rdcc_ent_t *ent = NULL;
unsigned idx;
unsigned u;
H5D_shared_t *shared_fo = (H5D_shared_t *)udata->cpy_info->shared_fo;
if(shared_fo && shared_fo->cache.chunk.nslots > 0) {
idx = H5D__chunk_hash_val(shared_fo, chunk_rec->scaled);
ent = shared_fo->cache.chunk.slot[idx];
if(ent) {
udata->chunk_in_cache = TRUE;
for(u = 0; u < shared_fo->ndims; u++)
if(chunk_rec->scaled[u] != ent->scaled[u]) {
udata->chunk_in_cache = FALSE;
break;
}
}
}
if(udata->chunk_in_cache) {
HDassert(H5F_addr_defined(chunk_rec->chunk_addr));
HDassert(H5F_addr_defined(ent->chunk_block.offset));
H5_CHECKED_ASSIGN(nbytes, size_t, shared_fo->layout.u.chunk.size, uint32_t);
H5MM_memcpy(buf, ent->chunk, nbytes);
}
else {
if(H5F_block_read(udata->file_src, H5FD_MEM_DRAW, chunk_rec->chunk_addr, nbytes, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, H5_ITER_ERROR, "unable to read raw data chunk")
}
}
if(must_filter && (is_vlen || fix_ref) && !udata->chunk_in_cache) {
unsigned filter_mask = chunk_rec->filter_mask;
if(H5Z_pipeline(pline, H5Z_FLAG_REVERSE, &filter_mask, H5Z_NO_EDC, filter_cb, &nbytes, &buf_size, &buf) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, H5_ITER_ERROR, "data pipeline read failed")
}
if(is_vlen) {
H5T_path_t *tpath_src_mem = udata->tpath_src_mem;
H5T_path_t *tpath_mem_dst = udata->tpath_mem_dst;
H5S_t *buf_space = udata->buf_space;
hid_t tid_src = udata->tid_src;
hid_t tid_dst = udata->tid_dst;
hid_t tid_mem = udata->tid_mem;
void *reclaim_buf = udata->reclaim_buf;
size_t reclaim_buf_size = udata->reclaim_buf_size;
H5_CHECK_OVERFLOW(udata->nelmts, uint32_t, size_t);
if(H5T_convert(tpath_src_mem, tid_src, tid_mem, (size_t)udata->nelmts, (size_t)0, (size_t)0, buf, bkg) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5_ITER_ERROR, "datatype conversion failed")
H5MM_memcpy(reclaim_buf, buf, reclaim_buf_size);
HDmemset(bkg, 0, buf_size);
if(H5T_convert(tpath_mem_dst, tid_mem, tid_dst, udata->nelmts, (size_t)0, (size_t)0, buf, bkg) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5_ITER_ERROR, "datatype conversion failed")
if(H5D_vlen_reclaim(tid_mem, buf_space, reclaim_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADITER, H5_ITER_ERROR, "unable to reclaim variable-length data")
}
else if(fix_ref) {
if(udata->cpy_info->expand_ref) {
size_t ref_count;
size_t dt_size;
if((dt_size = H5T_get_size(udata->dt_src)) == 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "size must not be 0")
ref_count = nbytes / dt_size;
if(H5O_copy_expand_ref(udata->file_src, buf, udata->idx_info_dst->f, bkg, ref_count, H5T_get_ref_type(udata->dt_src), udata->cpy_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, H5_ITER_ERROR, "unable to copy reference attribute")
}
H5MM_memcpy(buf, bkg, buf_size);
}
udata_dst.common.layout = udata->idx_info_dst->layout;
udata_dst.common.storage = udata->idx_info_dst->storage;
udata_dst.common.scaled = chunk_rec->scaled;
udata_dst.chunk_block.offset = HADDR_UNDEF;
udata_dst.chunk_block.length = chunk_rec->nbytes;
udata_dst.filter_mask = chunk_rec->filter_mask;
if(must_filter && (is_vlen || fix_ref || udata->chunk_in_cache) ) {
if(H5Z_pipeline(pline, 0, &(udata_dst.filter_mask), H5Z_NO_EDC, filter_cb, &nbytes, &buf_size, &buf) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, H5_ITER_ERROR, "output pipeline failed")
#if H5_SIZEOF_SIZE_T > 4
if(nbytes > ((size_t)0xffffffff))
HGOTO_ERROR(H5E_DATASET, H5E_BADRANGE, H5_ITER_ERROR, "chunk too large for 32-bit length")
#endif
H5_CHECKED_ASSIGN(udata_dst.chunk_block.length, uint32_t, nbytes, size_t);
udata->buf = buf;
udata->buf_size = buf_size;
}
udata->chunk_in_cache = FALSE;
udata_dst.chunk_idx = H5VM_array_offset_pre(udata_dst.common.layout->ndims - 1,
udata_dst.common.layout->max_down_chunks, udata_dst.common.scaled);
if(H5D__chunk_file_alloc(udata->idx_info_dst, NULL, &udata_dst.chunk_block, &need_insert, udata_dst.common.scaled) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert/resize chunk on chunk level")
HDassert(H5F_addr_defined(udata_dst.chunk_block.offset));
if(H5F_block_write(udata->idx_info_dst->f, H5FD_MEM_DRAW, udata_dst.chunk_block.offset, nbytes, buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, H5_ITER_ERROR, "unable to write raw data to file")
H5_BEGIN_TAG(H5AC__COPIED_TAG);
if(need_insert && udata->idx_info_dst->storage->ops->insert)
if((udata->idx_info_dst->storage->ops->insert)(udata->idx_info_dst, &udata_dst, NULL) < 0)
HGOTO_ERROR_TAG(H5E_DATASET, H5E_CANTINSERT, H5_ITER_ERROR, "unable to insert chunk addr into index")
H5_END_TAG
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5D__chunk_copy(H5F_t *f_src, H5O_storage_chunk_t *storage_src,
H5O_layout_chunk_t *layout_src, H5F_t *f_dst, H5O_storage_chunk_t *storage_dst,
const H5S_extent_t *ds_extent_src, const H5T_t *dt_src,
const H5O_pline_t *pline_src, H5O_copy_t *cpy_info)
{
H5D_chunk_it_ud3_t udata;
H5D_chk_idx_info_t idx_info_dst;
H5D_chk_idx_info_t idx_info_src;
int sndims;
hsize_t curr_dims[H5O_LAYOUT_NDIMS];
hsize_t max_dims[H5O_LAYOUT_NDIMS];
H5O_pline_t _pline;
const H5O_pline_t *pline;
H5T_path_t *tpath_src_mem = NULL, *tpath_mem_dst = NULL;
hid_t tid_src = -1;
hid_t tid_dst = -1;
hid_t tid_mem = -1;
size_t buf_size;
size_t reclaim_buf_size;
void *buf = NULL;
void *bkg = NULL;
void *reclaim_buf = NULL;
H5S_t *buf_space = NULL;
hid_t sid_buf = -1;
uint32_t nelmts = 0;
hbool_t do_convert = FALSE;
hbool_t copy_setup_done = FALSE;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(f_src);
HDassert(storage_src);
H5D_CHUNK_STORAGE_INDEX_CHK(storage_src);
HDassert(layout_src);
HDassert(f_dst);
HDassert(storage_dst);
H5D_CHUNK_STORAGE_INDEX_CHK(storage_dst);
HDassert(ds_extent_src);
HDassert(dt_src);
if(NULL == pline_src) {
HDmemset(&_pline, 0, sizeof(_pline));
pline = &_pline;
}
else
pline = pline_src;
if(H5D_chunk_idx_reset(storage_dst, TRUE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to reset chunked storage index in dest")
{
unsigned ndims;
if((sndims = H5S_extent_get_dims(ds_extent_src, curr_dims, max_dims)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataspace dimensions")
H5_CHECKED_ASSIGN(ndims, unsigned, sndims, int);
if(H5D__chunk_set_info_real(layout_src, ndims, curr_dims, max_dims) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set layout's chunk info")
}
idx_info_src.f = f_src;
idx_info_src.pline = pline;
idx_info_src.layout = layout_src;
idx_info_src.storage = storage_src;
idx_info_dst.f = f_dst;
idx_info_dst.pline = pline;
idx_info_dst.layout = layout_src ;
idx_info_dst.storage = storage_dst;
if((storage_src->ops->copy_setup)(&idx_info_src, &idx_info_dst) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up index-specific chunk copying information")
copy_setup_done = TRUE;
if((tid_src = H5I_register(H5I_DATATYPE, dt_src, FALSE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register source file datatype")
if(H5T_detect_class(dt_src, H5T_VLEN, FALSE) > 0) {
H5T_t *dt_dst;
H5T_t *dt_mem;
size_t mem_dt_size;
size_t tmp_dt_size;
size_t max_dt_size;
hsize_t buf_dim;
unsigned u;
if(NULL == (dt_mem = H5T_copy(dt_src, H5T_COPY_TRANSIENT)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy")
if((tid_mem = H5I_register(H5I_DATATYPE, dt_mem, FALSE)) < 0) {
(void)H5T_close_real(dt_mem);
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register memory datatype")
}
if(NULL == (dt_dst = H5T_copy(dt_src, H5T_COPY_TRANSIENT)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy")
if(H5T_set_loc(dt_dst, f_dst, H5T_LOC_DISK) < 0) {
(void)H5T_close_real(dt_dst);
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "cannot mark datatype on disk")
}
if((tid_dst = H5I_register(H5I_DATATYPE, dt_dst, FALSE)) < 0) {
(void)H5T_close_real(dt_dst);
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register destination file datatype")
}
if(NULL == (tpath_src_mem = H5T_path_find(dt_src, dt_mem)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert between src and mem datatypes")
if(NULL == (tpath_mem_dst = H5T_path_find(dt_mem, dt_dst)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert between mem and dst datatypes")
if(0 == (max_dt_size = H5T_get_size(dt_src)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to determine datatype size")
if(0 == (mem_dt_size = H5T_get_size(dt_mem)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to determine datatype size")
max_dt_size = MAX(max_dt_size, mem_dt_size);
if(0 == (tmp_dt_size = H5T_get_size(dt_dst)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to determine datatype size")
max_dt_size = MAX(max_dt_size, tmp_dt_size);
nelmts = 1;
for(u = 0; u < (layout_src->ndims - 1); u++)
nelmts *= layout_src->dim[u];
buf_dim = nelmts;
if(NULL == (buf_space = H5S_create_simple((unsigned)1, &buf_dim, NULL)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace")
if((sid_buf = H5I_register(H5I_DATASPACE, buf_space, FALSE)) < 0) {
(void)H5S_close(buf_space);
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID")
}
buf_size = nelmts * max_dt_size;
reclaim_buf_size = nelmts * mem_dt_size;
if(NULL == (reclaim_buf = H5MM_malloc(reclaim_buf_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for raw data chunk")
do_convert = TRUE;
}
else {
if(H5T_get_class(dt_src, FALSE) == H5T_REFERENCE) {
do_convert = TRUE;
}
H5_CHECKED_ASSIGN(buf_size, size_t, layout_src->size, uint32_t);
reclaim_buf_size = 0;
}
if(do_convert) {
if(NULL == (bkg = H5MM_malloc(buf_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for raw data chunk")
if(!cpy_info->expand_ref &&
((H5T_get_class(dt_src, FALSE) == H5T_REFERENCE) && (f_src != f_dst)))
HDmemset(bkg, 0, buf_size);
}
if(NULL == (buf = H5MM_malloc(buf_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for raw data chunk")
HDmemset(&udata, 0, sizeof udata);
udata.common.layout = layout_src;
udata.common.storage = storage_src;
udata.file_src = f_src;
udata.idx_info_dst = &idx_info_dst;
udata.buf = buf;
udata.bkg = bkg;
udata.buf_size = buf_size;
udata.tid_src = tid_src;
udata.tid_mem = tid_mem;
udata.tid_dst = tid_dst;
udata.dt_src = dt_src;
udata.do_convert = do_convert;
udata.tpath_src_mem = tpath_src_mem;
udata.tpath_mem_dst = tpath_mem_dst;
udata.reclaim_buf = reclaim_buf;
udata.reclaim_buf_size = reclaim_buf_size;
udata.buf_space = buf_space;
udata.nelmts = nelmts;
udata.pline = pline;
udata.dset_ndims = (unsigned)sndims;
udata.dset_dims = curr_dims;
udata.cpy_info = cpy_info;
udata.chunk_in_cache = FALSE;
udata.chunk = NULL;
if((storage_src->ops->iterate)(&idx_info_src, H5D__chunk_copy_cb, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to iterate over chunk index to copy data")
if(udata.cpy_info->shared_fo) {
H5D_rdcc_ent_t *ent, *next;
H5D_chunk_rec_t chunk_rec;
H5D_shared_t *shared_fo = (H5D_shared_t *)udata.cpy_info->shared_fo;
chunk_rec.nbytes = layout_src->size;
chunk_rec.filter_mask = 0;
chunk_rec.chunk_addr = HADDR_UNDEF;
for(ent = shared_fo->cache.chunk.head; ent; ent = next) {
if(!H5F_addr_defined(ent->chunk_block.offset)) {
H5MM_memcpy(chunk_rec.scaled, ent->scaled, sizeof(chunk_rec.scaled));
udata.chunk = ent->chunk;
udata.chunk_in_cache = TRUE;
if(H5D__chunk_copy_cb(&chunk_rec, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "unable to copy chunk data in cache")
}
next = ent->next;
}
}
buf = udata.buf;
bkg = udata.bkg;
done:
if(sid_buf > 0 && H5I_dec_ref(sid_buf) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "can't decrement temporary dataspace ID")
if(tid_src > 0 && H5I_dec_ref(tid_src) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
if(tid_dst > 0 && H5I_dec_ref(tid_dst) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
if(tid_mem > 0 && H5I_dec_ref(tid_mem) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
if(buf)
H5MM_xfree(buf);
if(bkg)
H5MM_xfree(bkg);
if(reclaim_buf)
H5MM_xfree(reclaim_buf);
if(copy_setup_done)
if(storage_src->ops->copy_shutdown && (storage_src->ops->copy_shutdown)(storage_src, storage_dst) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "unable to shut down index copying info")
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5D__chunk_bh_info(const H5O_loc_t *loc, H5O_t *oh, H5O_layout_t *layout,
hsize_t *index_size)
{
H5D_chk_idx_info_t idx_info;
H5S_t *space = NULL;
H5O_pline_t pline;
H5O_storage_chunk_t *sc = &(layout->storage.u.chunk);
htri_t exists;
hbool_t idx_info_init = FALSE;
hbool_t pline_read = FALSE;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(loc);
HDassert(loc->file);
HDassert(H5F_addr_defined(loc->addr));
HDassert(layout);
H5D_CHUNK_STORAGE_INDEX_CHK(sc);
HDassert(index_size);
if((exists = H5O_msg_exists_oh(oh, H5O_PLINE_ID)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to read object header")
else if(exists) {
if(NULL == H5O_msg_read_oh(loc->file, oh, H5O_PLINE_ID, &pline))
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't find I/O pipeline message")
pline_read = TRUE;
}
else
HDmemset(&pline, 0, sizeof(pline));
idx_info.f = loc->file;
idx_info.pline = &pline;
idx_info.layout = &layout->u.chunk;
idx_info.storage = sc;
if(NULL == (space = H5S_read(loc)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to load dataspace info from dataset header")
if(sc->ops->init && (sc->ops->init)(&idx_info, space, loc->addr) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize indexing information")
idx_info_init = TRUE;
if(sc->ops->size && (sc->ops->size)(&idx_info, index_size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve chunk index info")
done:
if(idx_info_init && sc->ops->dest && (sc->ops->dest)(&idx_info) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to release chunk index info")
if(pline_read && H5O_msg_reset(H5O_PLINE_ID, &pline) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTRESET, FAIL, "unable to reset I/O pipeline message")
if(space && H5S_close(space) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataspace")
FUNC_LEAVE_NOAPI(ret_value)
}
static int
H5D__chunk_dump_index_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
{
H5D_chunk_it_ud4_t *udata = (H5D_chunk_it_ud4_t *)_udata;
FUNC_ENTER_STATIC_NOERR
if(udata->stream) {
unsigned u;
if(!udata->header_displayed) {
HDfprintf(udata->stream, " Flags Bytes Address Logical Offset\n");
HDfprintf(udata->stream, " ========== ======== ========== ==============================\n");
udata->header_displayed = TRUE;
}
HDfprintf(udata->stream, " 0x%08x %8Zu %10a [", chunk_rec->filter_mask, chunk_rec->nbytes, chunk_rec->chunk_addr);
for(u = 0; u < udata->ndims; u++)
HDfprintf(udata->stream, "%s%Hu", (u ? ", " : ""), (chunk_rec->scaled[u] * udata->chunk_dim[u]));
HDfputs("]\n", udata->stream);
}
FUNC_LEAVE_NOAPI(H5_ITER_CONT)
}
herr_t
H5D__chunk_dump_index(H5D_t *dset, FILE *stream)
{
H5O_storage_chunk_t *sc = &(dset->shared->layout.storage.u.chunk);
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(dset);
H5D_CHUNK_STORAGE_INDEX_CHK(sc);
if(stream) {
H5D_chk_idx_info_t idx_info;
H5D_chunk_it_ud4_t udata;
if((sc->ops->dump)(sc, stream) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to dump chunk index info")
idx_info.f = dset->oloc.file;
idx_info.pline = &dset->shared->dcpl_cache.pline;
idx_info.layout = &dset->shared->layout.u.chunk;
idx_info.storage = sc;
udata.stream = stream;
udata.header_displayed = FALSE;
udata.ndims = dset->shared->layout.u.chunk.ndims;
udata.chunk_dim = dset->shared->layout.u.chunk.dim;
if((sc->ops->iterate)(&idx_info, H5D__chunk_dump_index_cb, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to iterate over chunk index to dump chunk info")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
#ifdef H5D_CHUNK_DEBUG
herr_t
H5D__chunk_stats(const H5D_t *dset, hbool_t headers)
{
H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
double miss_rate;
char ascii[32];
herr_t ret_value=SUCCEED;
FUNC_ENTER_PACKAGE_NOERR
if (!H5DEBUG(AC))
HGOTO_DONE(SUCCEED)
if (headers) {
HDfprintf(H5DEBUG(AC), "H5D: raw data cache statistics\n");
HDfprintf(H5DEBUG(AC), " %-18s %8s %8s %8s %8s+%-8s\n",
"Layer", "Hits", "Misses", "MissRate", "Inits", "Flushes");
HDfprintf(H5DEBUG(AC), " %-18s %8s %8s %8s %8s-%-8s\n",
"-----", "----", "------", "--------", "-----", "-------");
}
#ifdef H5AC_DEBUG
if (H5DEBUG(AC))
headers = TRUE;
#endif
if (headers) {
if (rdcc->stats.nhits>0 || rdcc->stats.nmisses>0) {
miss_rate = 100.0 * rdcc->stats.nmisses /
(rdcc->stats.nhits + rdcc->stats.nmisses);
} else {
miss_rate = 0.0;
}
if (miss_rate > 100) {
HDsprintf(ascii, "%7d%%", (int) (miss_rate + 0.5));
} else {
HDsprintf(ascii, "%7.2f%%", miss_rate);
}
HDfprintf(H5DEBUG(AC), " %-18s %8u %8u %7s %8d+%-9ld\n",
"raw data chunks", rdcc->stats.nhits, rdcc->stats.nmisses, ascii,
rdcc->stats.ninits, (long)(rdcc->stats.nflushes)-(long)(rdcc->stats.ninits));
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
#endif
static herr_t
H5D__nonexistent_readvv_cb(hsize_t H5_ATTR_UNUSED dst_off, hsize_t src_off, size_t len,
void *_udata)
{
H5D_chunk_readvv_ud_t *udata = (H5D_chunk_readvv_ud_t *)_udata;
H5D_fill_buf_info_t fb_info;
hbool_t fb_info_init = FALSE;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
if(H5D__fill_init(&fb_info, (udata->rbuf + src_off), NULL, NULL, NULL, NULL,
&udata->dset->shared->dcpl_cache.fill, udata->dset->shared->type,
udata->dset->shared->type_id, (size_t)0, len) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize fill buffer info")
fb_info_init = TRUE;
if(fb_info.has_vlen_fill_type && H5D__fill_refill_vl(&fb_info, fb_info.elmts_per_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "can't refill fill value buffer")
done:
if(fb_info_init && H5D__fill_term(&fb_info) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release fill buffer info")
FUNC_LEAVE_NOAPI(ret_value)
}
static ssize_t
H5D__nonexistent_readvv(const H5D_io_info_t *io_info,
size_t chunk_max_nseq, size_t *chunk_curr_seq, size_t chunk_len_arr[], hsize_t chunk_off_arr[],
size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_off_arr[])
{
H5D_chunk_readvv_ud_t udata;
ssize_t ret_value = -1;
FUNC_ENTER_STATIC
HDassert(io_info);
HDassert(chunk_curr_seq);
HDassert(chunk_len_arr);
HDassert(chunk_off_arr);
HDassert(mem_curr_seq);
HDassert(mem_len_arr);
HDassert(mem_off_arr);
udata.rbuf = (unsigned char *)io_info->u.rbuf;
udata.dset = io_info->dset;
if((ret_value = H5VM_opvv(chunk_max_nseq, chunk_curr_seq, chunk_len_arr, chunk_off_arr,
mem_max_nseq, mem_curr_seq, mem_len_arr, mem_off_arr,
H5D__nonexistent_readvv_cb, &udata)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPERATE, FAIL, "can't perform vectorized fill value init")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static hbool_t
H5D__chunk_is_partial_edge_chunk(unsigned dset_ndims, const uint32_t *chunk_dims,
const hsize_t scaled[], const hsize_t *dset_dims)
{
unsigned u;
hbool_t ret_value = FALSE;
FUNC_ENTER_STATIC_NOERR
HDassert(scaled);
HDassert(dset_ndims > 0);
HDassert(dset_dims);
HDassert(chunk_dims);
for(u = 0; u < dset_ndims; u++)
if(((scaled[u] + 1) * chunk_dims[u]) > dset_dims[u])
HGOTO_DONE(TRUE);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5D__chunk_file_alloc(const H5D_chk_idx_info_t *idx_info, const H5F_block_t *old_chunk,
H5F_block_t *new_chunk, hbool_t *need_insert, hsize_t scaled[])
{
hbool_t alloc_chunk = FALSE;
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(new_chunk);
HDassert(need_insert);
*need_insert = FALSE;
if(idx_info->pline->nused > 0) {
HDassert(idx_info->storage->idx_type != H5D_CHUNK_IDX_NONE);
{
unsigned allow_chunk_size_len;
unsigned new_chunk_size_len;
allow_chunk_size_len = 1 + ((H5VM_log2_gen((uint64_t)(idx_info->layout->size)) + 8) / 8);
if(allow_chunk_size_len > 8)
allow_chunk_size_len = 8;
new_chunk_size_len = (H5VM_log2_gen((uint64_t)(new_chunk->length)) + 8) / 8;
if(new_chunk_size_len > 8)
HGOTO_ERROR(H5E_DATASET, H5E_BADRANGE, FAIL, "encoded chunk size is more than 8 bytes?!?")
if(new_chunk_size_len > allow_chunk_size_len)
HGOTO_ERROR(H5E_DATASET, H5E_BADRANGE, FAIL, "chunk size can't be encoded")
}
if(old_chunk && H5F_addr_defined(old_chunk->offset)) {
HDassert(!H5F_addr_defined(new_chunk->offset) || H5F_addr_eq(new_chunk->offset, old_chunk->offset));
if(new_chunk->length != old_chunk->length) {
if(!(H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE))
if(H5MF_xfree(idx_info->f, H5FD_MEM_DRAW, old_chunk->offset, old_chunk->length) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to free chunk")
alloc_chunk = TRUE;
}
else {
if(!H5F_addr_defined(new_chunk->offset))
new_chunk->offset = old_chunk->offset;
}
}
else {
HDassert(!H5F_addr_defined(new_chunk->offset));
alloc_chunk = TRUE;
}
}
else {
HDassert(!H5F_addr_defined(new_chunk->offset));
HDassert(new_chunk->length == idx_info->layout->size);
alloc_chunk = TRUE;
}
if(alloc_chunk) {
switch(idx_info->storage->idx_type) {
case H5D_CHUNK_IDX_NONE:
{
H5D_chunk_ud_t udata;
udata.common.scaled = scaled;
if((idx_info->storage->ops->get_addr)(idx_info, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't query chunk address")
new_chunk->offset = udata.chunk_block.offset;
HDassert(new_chunk->length == udata.chunk_block.length);
break;
}
case H5D_CHUNK_IDX_EARRAY:
case H5D_CHUNK_IDX_FARRAY:
case H5D_CHUNK_IDX_BT2:
case H5D_CHUNK_IDX_BTREE:
case H5D_CHUNK_IDX_SINGLE:
HDassert(new_chunk->length > 0);
H5_CHECK_OVERFLOW(new_chunk->length, uint32_t, hsize_t);
new_chunk->offset = H5MF_alloc(idx_info->f, H5FD_MEM_DRAW, (hsize_t)new_chunk->length);
if(!H5F_addr_defined(new_chunk->offset))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "file allocation failed")
*need_insert = TRUE;
break;
case H5D_CHUNK_IDX_NTYPES:
default:
HDassert(0 && "This should never be executed!");
break;
}
}
HDassert(H5F_addr_defined(new_chunk->offset));
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static int
H5D__chunk_format_convert_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
{
H5D_chunk_it_ud5_t *udata = (H5D_chunk_it_ud5_t *)_udata;
H5D_chk_idx_info_t *new_idx_info;
H5D_chunk_ud_t insert_udata;
haddr_t chunk_addr;
size_t nbytes;
void *buf = NULL;
int ret_value = H5_ITER_CONT;
FUNC_ENTER_STATIC
new_idx_info = udata->new_idx_info;
H5_CHECKED_ASSIGN(nbytes, size_t, chunk_rec->nbytes, uint32_t);
chunk_addr = chunk_rec->chunk_addr;
if (new_idx_info->pline->nused &&
(new_idx_info->layout->flags & H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS) &&
(H5D__chunk_is_partial_edge_chunk(udata->dset_ndims, new_idx_info->layout->dim, chunk_rec->scaled, udata->dset_dims))) {
unsigned filter_mask = chunk_rec->filter_mask;
H5Z_cb_t filter_cb;
size_t read_size = nbytes;
HDassert(read_size == new_idx_info->layout->size);
filter_cb.op_data = NULL;
filter_cb.func = NULL;
if (NULL == (buf = H5MM_malloc(read_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed for raw data chunk")
if (H5F_block_read(new_idx_info->f, H5FD_MEM_DRAW, chunk_addr, read_size, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, H5_ITER_ERROR, "unable to read raw data chunk")
if (H5Z_pipeline(new_idx_info->pline, 0, &filter_mask, H5Z_NO_EDC, filter_cb, &nbytes, &read_size, &buf) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, H5_ITER_ERROR, "output pipeline failed")
#if H5_SIZEOF_SIZE_T > 4
if (nbytes > ((size_t)0xffffffff))
HGOTO_ERROR(H5E_DATASET, H5E_BADRANGE, H5_ITER_ERROR, "chunk too large for 32-bit length")
#endif
if ((chunk_addr = H5MF_alloc(new_idx_info->f, H5FD_MEM_DRAW, (hsize_t)nbytes)) == HADDR_UNDEF)
HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, H5_ITER_ERROR, "file allocation failed for filtered chunk")
HDassert(H5F_addr_defined(chunk_addr));
if (H5F_block_write(new_idx_info->f, H5FD_MEM_DRAW, chunk_addr, nbytes, buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, H5_ITER_ERROR, "unable to write raw data to file")
}
insert_udata.chunk_block.offset = chunk_addr;
insert_udata.chunk_block.length = nbytes;
insert_udata.filter_mask = chunk_rec->filter_mask;
insert_udata.common.scaled = chunk_rec->scaled;
insert_udata.common.layout = new_idx_info->layout;
insert_udata.common.storage = new_idx_info->storage;
if ((new_idx_info->storage->ops->insert)(new_idx_info, &insert_udata, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, H5_ITER_ERROR, "unable to insert chunk addr into index")
done:
if (buf)
H5MM_xfree(buf);
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5D__chunk_format_convert(H5D_t *dset, H5D_chk_idx_info_t *idx_info, H5D_chk_idx_info_t *new_idx_info)
{
H5D_chunk_it_ud5_t udata;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(dset);
udata.new_idx_info = new_idx_info;
udata.dset_ndims = dset->shared->ndims;
udata.dset_dims = dset->shared->curr_dims;
if((idx_info->storage->ops->iterate)(idx_info, H5D__chunk_format_convert_cb, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to iterate over chunk index to chunk info")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static int
H5D__get_num_chunks_cb(const H5D_chunk_rec_t H5_ATTR_UNUSED *chunk_rec, void *_udata)
{
hsize_t *num_chunks = (hsize_t *)_udata;
int ret_value = H5_ITER_CONT;
FUNC_ENTER_STATIC_NOERR
HDassert(num_chunks);
(*num_chunks)++;
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5D__get_num_chunks(const H5D_t *dset, const H5S_t H5_ATTR_UNUSED *space, hsize_t *nchunks)
{
H5D_chk_idx_info_t idx_info;
hsize_t num_chunks = 0;
H5D_rdcc_ent_t *ent;
const H5D_rdcc_t *rdcc = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE_TAG(dset->oloc.addr)
HDassert(dset);
HDassert(dset->shared);
HDassert(space);
HDassert(nchunks);
rdcc = &(dset->shared->cache.chunk);
HDassert(rdcc);
for(ent = rdcc->head; ent; ent = ent->next)
if(H5D__chunk_flush_entry(dset, ent, FALSE) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush indexed storage buffer")
idx_info.f = dset->oloc.file;
idx_info.pline = &dset->shared->dcpl_cache.pline;
idx_info.layout = &dset->shared->layout.u.chunk;
idx_info.storage = &dset->shared->layout.storage.u.chunk;
if(!H5F_addr_defined(idx_info.storage->idx_addr))
*nchunks = 0;
else {
if((dset->shared->layout.storage.u.chunk.ops->iterate)(&idx_info, H5D__get_num_chunks_cb, &num_chunks) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve allocated chunk information from index")
*nchunks = num_chunks;
}
done:
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
static int
H5D__get_chunk_info_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
{
H5D_chunk_info_iter_ud_t *chunk_info = (H5D_chunk_info_iter_ud_t *)_udata;
int ret_value = H5_ITER_CONT;
FUNC_ENTER_STATIC_NOERR
HDassert(chunk_rec);
HDassert(chunk_info);
if(chunk_info->curr_idx == chunk_info->chunk_idx) {
hsize_t ii = 0;
chunk_info->filter_mask = chunk_rec->filter_mask;
chunk_info->chunk_addr = chunk_rec->chunk_addr;
chunk_info->nbytes = chunk_rec->nbytes;
for(ii = 0; ii < chunk_info->ndims; ii++)
chunk_info->scaled[ii] = chunk_rec->scaled[ii];
chunk_info->found = TRUE;
ret_value = H5_ITER_STOP;
}
else
chunk_info->curr_idx++;
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5D__get_chunk_info(const H5D_t *dset, const H5S_t H5_ATTR_UNUSED *space, hsize_t index, hsize_t *offset, unsigned *filter_mask, haddr_t *addr, hsize_t *size)
{
H5D_chk_idx_info_t idx_info;
H5D_chunk_info_iter_ud_t udata;
const H5D_rdcc_t *rdcc = NULL;
H5D_rdcc_ent_t *ent;
hsize_t ii = 0;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE_TAG(dset->oloc.addr)
HDassert(dset);
HDassert(dset->shared);
HDassert(space);
rdcc = &(dset->shared->cache.chunk);
HDassert(rdcc);
for(ent = rdcc->head; ent; ent = ent->next)
if(H5D__chunk_flush_entry(dset, ent, FALSE) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush indexed storage buffer")
idx_info.f = dset->oloc.file;
idx_info.pline = &dset->shared->dcpl_cache.pline;
idx_info.layout = &dset->shared->layout.u.chunk;
idx_info.storage = &dset->shared->layout.storage.u.chunk;
if (addr)
*addr = HADDR_UNDEF;
if (size)
*size = 0;
if(!H5F_addr_defined(idx_info.storage->idx_addr))
HGOTO_DONE(SUCCEED);
udata.chunk_idx = index;
udata.curr_idx = 0;
udata.ndims = dset->shared->ndims;
udata.nbytes = 0;
udata.filter_mask = 0;
udata.chunk_addr = HADDR_UNDEF;
udata.found = FALSE;
if((dset->shared->layout.storage.u.chunk.ops->iterate)(&idx_info, H5D__get_chunk_info_cb, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve allocated chunk information from index")
if (udata.found) {
if (filter_mask)
*filter_mask = udata.filter_mask;
if (addr)
*addr = udata.chunk_addr;
if (size)
*size = udata.nbytes;
if (offset)
for (ii = 0; ii < udata.ndims; ii++)
offset[ii] = udata.scaled[ii] * dset->shared->layout.u.chunk.dim[ii];
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static int
H5D__get_chunk_info_by_coord_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
{
H5D_chunk_info_iter_ud_t *chunk_info = (H5D_chunk_info_iter_ud_t *)_udata;
hbool_t different = FALSE;
hsize_t ii;
int ret_value = H5_ITER_CONT;
FUNC_ENTER_STATIC_NOERR
HDassert(chunk_rec);
HDassert(chunk_info);
for (ii = 0; ii < chunk_info->ndims && !different; ii++)
if (chunk_info->scaled[ii] != chunk_rec->scaled[ii])
different = TRUE;
if (!different) {
chunk_info->nbytes = chunk_rec->nbytes;
chunk_info->filter_mask = chunk_rec->filter_mask;
chunk_info->chunk_addr = chunk_rec->chunk_addr;
chunk_info->found = TRUE;
ret_value = H5_ITER_STOP;
}
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5D__get_chunk_info_by_coord(const H5D_t *dset, const hsize_t *offset, unsigned* filter_mask, haddr_t *addr, hsize_t *size)
{
const H5O_layout_t *layout = NULL;
const H5D_rdcc_t *rdcc = NULL;
H5D_rdcc_ent_t *ent;
H5D_chk_idx_info_t idx_info;
H5D_chunk_info_iter_ud_t udata;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE_TAG(dset->oloc.addr)
HDassert(dset);
HDassert(dset->shared);
HDassert(offset);
layout = &(dset->shared->layout);
rdcc = &(dset->shared->cache.chunk);
HDassert(layout);
HDassert(rdcc);
HDassert(H5D_CHUNKED == layout->type);
for(ent = rdcc->head; ent; ent = ent->next)
if(H5D__chunk_flush_entry(dset, ent, FALSE) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush indexed storage buffer")
if(addr)
*addr = HADDR_UNDEF;
if(size)
*size = 0;
idx_info.f = dset->oloc.file;
idx_info.pline = &dset->shared->dcpl_cache.pline;
idx_info.layout = &dset->shared->layout.u.chunk;
idx_info.storage = &dset->shared->layout.storage.u.chunk;
if(!H5F_addr_defined(idx_info.storage->idx_addr)) {
HGOTO_DONE(SUCCEED);
}
H5VM_chunk_scaled(dset->shared->ndims, offset, layout->u.chunk.dim, udata.scaled);
udata.scaled[dset->shared->ndims] = 0;
udata.ndims = dset->shared->ndims;
udata.nbytes = 0;
udata.filter_mask = 0;
udata.chunk_addr = HADDR_UNDEF;
udata.found = FALSE;
if((dset->shared->layout.storage.u.chunk.ops->iterate)(&idx_info, H5D__get_chunk_info_by_coord_cb, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve information of the chunk by its scaled coordinates")
if (udata.found) {
if (filter_mask)
*filter_mask = udata.filter_mask;
if (addr)
*addr = udata.chunk_addr;
if (size)
*size = udata.nbytes;
}
done:
FUNC_LEAVE_NOAPI_TAG(ret_value)
}