diff options
author | Neil Fortner <fortnern@gmail.com> | 2022-10-19 16:13:15 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-19 16:13:15 (GMT) |
commit | 93754cae33d4ed45850745664ce5e59f270f38f8 (patch) | |
tree | ac3154f44fe7969dacb452474c32fcaeb84e620d /src/H5Dchunk.c | |
parent | a898cef6c2e277f74cc99302a3c49c39a7428b5b (diff) | |
download | hdf5-93754cae33d4ed45850745664ce5e59f270f38f8.zip hdf5-93754cae33d4ed45850745664ce5e59f270f38f8.tar.gz hdf5-93754cae33d4ed45850745664ce5e59f270f38f8.tar.bz2 |
Multi Dataset (#2120)
* Fix bug with cross platform compatibility of references within vlens.
No testing yet.
* Merge from multi_rd_wd_coll_io to a more recent branch from develop.
Untested, probably does not work yet.
* Committing clang-format changes
* Committing clang-format changes
* Fix many bugs in multi dataset branch. Mostly works, some issues in
SWMR tests.
* Committing clang-format changes
* Disable test in swmr.c that was failing due to bug in HDF5 unrelated to
multi dataset.
* Committing clang-format changes
* Fixed fortran multi-dataset tests
* Fixed xlf errors
* Added benchmark code for multi-datasets
* loops over datasets
* added missing error arg.
* Added gnuplot formatting
* Jonathan Kim original MD benchmarking code
* updated MD benchmarking code
* code clean-up
* Only make files in feature test mode
* misc clean-up
* removed TEST_MDSET_NO_LAST_DSET_2ND_PROC option
* Committing clang-format changes
* Change multi dataset API to use arrays of individual parameters instead
of the parameter struct.
* Committing clang-format changes
* Update to new multi dataset Fortran API and tests. (#1724)
* Update to new multi dataset Fortran API and tests.
* Sync Fortran with develop.
* skipping h5pget_mpio_actual_io_mode_f for now
* Fixed issue with dxpl_id, changed to variable size dim. (#1770)
* Remove "is_coll_broken" field from H5D_io_info_t struct
* Committing clang-format changes
* Minor cleanup in multi dataset code.
* Committing clang-format changes
* Clean up in multi dataset code.
* Committing clang-format changes
* Committing clang-format changes
* Fix speeling
* Fix bug in parallel compression. Switch base_maddr in io_info to be a
union.
* Committing clang-format changes
* Implement selection I/O support with multi dataset. Will be broken in
parallel until PR 1803 is merged to develop then the MDS branch.
* Committing clang-format changes
* Spelling
* Fix bug in multi dataset that could cause errors when only some of the
datasets in the multi dataset I/O used type conversion.
* Committing clang-format changes
* Integrate multi dataset APIs with VOL layer. Add async versions of
multi dataset APIs.
* Committing clang-format changes
* Spelling fixes
* Fix bug in non-parallel HDF5 compilation.
* Committing clang-format changes
* Fix potential memory/free list error. Minor performance fix. Other minor
changes.
* Committing clang-format changes
* Fix memory leak with memory dataspace for I/O.
* Committing clang-format changes
* Fix stack variables too large. Rename H5D_dset_info_t to
H5D_dset_io_info_t.
* Committing clang-format changes
* Remove mem_space_alloc field from H5D_dset_io_info_t. Each function is
now responsible for freeing any spaces it adds to dset_info.
* Committing clang-format changes
* fixed _multi Fortran declaration
* Refactor various things in (mostly) the serial I/O code path to make
things more maintainable.
* Committing clang-format changes
* updated to array based, doxygen, and examples
* Reinstate H5D_chunk_map_t, stored (via pointer) inside
H5D_dset_io_info_t.
* Change from calloc to malloc for H5D_dset_io_info_t and H5D_chunk_map_t.
Switch temporary dset_infos to be local stack variables.
* Committing clang-format changes
* format cleanup
* format cleanup
* added coll and ind
* Modify all parallel I/O paths to take dset_info instead of assuming
dset_info[0].
* Committing clang-format changes
* fixed output
* Rework parallel I/O code to work properly with multi dataset in more
cases. Fix bug in parallel compression.
* Committing clang-format changes
* Prevent H5D__multi_chunk_collective_io() from messing up collective opt
property for other datasets in I/O. Other minor cleanup. Add new test
case to t_pmulti_dset.c for H5FD_MPIO_INDIVIDUAL_IO, disabled for now
due to failures apparently unrelated to multi dataset code.
* Fix spelling
* Committing clang-format changes
* Replace N log N algorithm for finding chunk in
H5D__multi_chunk_collective_io() with O(N) algorithm, and remove use of
io_info->sel_pieces in that function.
* Committing clang-format changes
* Replace sel_pieces skiplist in io_info with flat array of pointers, use
qsort in I/O routine only when necessary.
* Committing clang-format changes
* Add new test case to mdset.c
* Committing clang-format changes
* Fix spelling
* Very minor fix in H5VL__native_dataset_read()
* Fix bug that could affect filtered parallel multi-dataset I/O.
* Add RM entries for H5Dread_multi(), H5Dread_multi_async(),
H5Dwrite_multi(), and H5Dwrite_multi_async()
* Unskip test in swmr.c
* Committing clang-format changes
* Eliminate H5D__pre_read and H5D__pre_write
* Remove examples/ph5mdsettest.c. Will fix and re-add as a test.
* Enable hyperslab combinations in mdset test
* Committing clang-format changes
* Clarify H5Dread/write_multi documentation.
* Fix bugs in multi-dataset I/O. Expand serial multi dataset test.
Update macro in parallel multi dataset test.
* Committing clang-format changes
* Spelling
* Remove obsolete entry in bin/trace
* Rework type conversion buffer allocation. Only one buffer is shared
between datasets in mdset mode, and it is malloced instead of calloced.
* Committing clang-format changes
* Fix bug in error handling in H5D__read/write
* added multi-dataset fortran check with optional dataset creation id (#2150)
* removed dup. dll entry
* Address comments from code review.
* Remove spurious changes in H5Fmpi.c
* Fix issue with reading unallocated datasets in multi-dataset mode.
Address other comments from code review.
* Committing clang-format changes
* Delay chunk index lookup from io_init to mdio_init so it doesn't add
overhead to single dataset I/O.
* Committing clang-format changes
* Fix inappropriate use of piece_count
* updated copyright on new file, removed benchmark from testing dir.
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: M. Scot Breitenfeld <brtnfld@hdfgroup.org>
Co-authored-by: Dana Robinson <43805+derobins@users.noreply.github.com>
Diffstat (limited to 'src/H5Dchunk.c')
-rw-r--r-- | src/H5Dchunk.c | 1705 |
1 files changed, 953 insertions, 752 deletions
diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c index 256b441..a3f20c5 100644 --- a/src/H5Dchunk.c +++ b/src/H5Dchunk.c @@ -67,11 +67,19 @@ /****************/ /* Macros for iterating over chunks to operate on */ -#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_GET_NODE_COUNT(map) (map->use_single ? (size_t)1 : H5SL_count(map->sel_chunks)) +#define H5D_CHUNK_GET_FIRST_NODE(dinfo) \ + (dinfo->layout_io_info.chunk_map->use_single \ + ? (H5SL_node_t *)(1) \ + : H5SL_first(dinfo->layout_io_info.chunk_map->dset_sel_pieces)) +#define H5D_CHUNK_GET_NODE_INFO(dinfo, node) \ + (dinfo->layout_io_info.chunk_map->use_single ? dinfo->layout_io_info.chunk_map->single_piece_info \ + : (H5D_piece_info_t *)H5SL_item(node)) +#define H5D_CHUNK_GET_NEXT_NODE(dinfo, node) \ + (dinfo->layout_io_info.chunk_map->use_single ? (H5SL_node_t *)NULL : H5SL_next(node)) +#define H5D_CHUNK_GET_NODE_COUNT(dinfo) \ + (dinfo->layout_io_info.chunk_map->use_single \ + ? (size_t)1 \ + : H5SL_count(dinfo->layout_io_info.chunk_map->dset_sel_pieces)) /* Sanity check on chunk index types: commonly used by a lot of routines in this file */ #define H5D_CHUNK_STORAGE_INDEX_CHK(storage) \ @@ -143,6 +151,7 @@ typedef struct H5D_chunk_it_ud1_t { H5D_chunk_common_ud_t common; /* Common info for B-tree user data (must be first) */ const H5D_chk_idx_info_t *idx_info; /* Chunked index info */ const H5D_io_info_t *io_info; /* I/O info for dataset operation */ + const H5D_dset_io_info_t *dset_info; /* Dataset specific I/O info */ const hsize_t *space_dim; /* New dataset dimensions */ const hbool_t *shrunk_dim; /* Dimensions which have been shrunk */ H5S_t *chunk_space; /* Dataspace for a chunk */ @@ -231,14 +240,6 @@ typedef struct H5D_chunk_info_iter_ud_t { hbool_t found; /* Whether the chunk was found */ } H5D_chunk_info_iter_ud_t; -/* Callback info for file selection iteration */ -typedef struct H5D_chunk_file_iter_ud_t { - H5D_chunk_map_t *fm; /* File->memory chunk mapping info */ -#ifdef H5_HAVE_PARALLEL - const H5D_io_info_t *io_info; /* I/O info for operation */ -#endif /* H5_HAVE_PARALLEL */ -} H5D_chunk_file_iter_ud_t; - #ifdef H5_HAVE_PARALLEL /* information to construct a collective I/O operation for filling chunks */ typedef struct H5D_chunk_coll_fill_info_t { @@ -264,16 +265,13 @@ typedef struct H5D_chunk_iter_ud_t { /* Chunked layout operation callbacks */ 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(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, - H5S_t *file_space, 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, - H5S_t *file_space, 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, - H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *fm); +static herr_t H5D__chunk_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo); +static herr_t H5D__chunk_io_init_selections(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo); +static herr_t H5D__chunk_mdio_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo); +static herr_t H5D__chunk_read(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo); +static herr_t H5D__chunk_write(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo); 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_io_term(H5D_io_info_t *io_info, H5D_dset_io_info_t *di); static herr_t H5D__chunk_dest(H5D_t *dset); /* Chunk query operation callbacks */ @@ -283,8 +281,8 @@ static int H5D__get_chunk_info_by_coord_cb(const H5D_chunk_rec_t *chunk_rec, voi static int H5D__chunk_iter_cb(const H5D_chunk_rec_t *chunk_rec, void *udata); /* "Nonexistent" layout operation callback */ -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[], +static ssize_t H5D__nonexistent_readvv(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_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[]); @@ -292,29 +290,28 @@ static ssize_t H5D__nonexistent_readvv(const H5D_io_info_t *io_info, size_t chun static int H5D__chunk_format_convert_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata); /* Helper routines */ -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 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 htri_t H5D__chunk_may_use_select_io(const H5D_io_info_t *io_info); +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 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__create_piece_map_single(H5D_dset_io_info_t *di, H5D_io_info_t *io_info); +static herr_t H5D__create_piece_file_map_all(H5D_dset_io_info_t *di, H5D_io_info_t *io_info); +static herr_t H5D__create_piece_file_map_hyper(H5D_dset_io_info_t *di, H5D_io_info_t *io_info); +static herr_t H5D__create_piece_mem_map_1d(const H5D_dset_io_info_t *di); +static herr_t H5D__create_piece_mem_map_hyper(const H5D_dset_io_info_t *di); +static herr_t H5D__piece_file_cb(void *elem, const H5T_t *type, unsigned ndims, const hsize_t *coords, + void *_opdata); +static herr_t H5D__piece_mem_cb(void *elem, const H5T_t *type, unsigned ndims, const hsize_t *coords, + void *_opdata); +static htri_t H5D__chunk_may_use_select_io(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info); 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 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 void *H5D__chunk_lock(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_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_dset_io_info_t *dset_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 @@ -337,17 +334,14 @@ const H5D_layout_ops_t H5D_LOPS_CHUNK[1] = {{ H5D__chunk_is_space_alloc, /* is_space_alloc */ H5D__chunk_is_data_cached, /* is_data_cached */ H5D__chunk_io_init, /* io_init */ + H5D__chunk_mdio_init, /* mdio_init */ H5D__chunk_read, /* ser_read */ H5D__chunk_write, /* ser_write */ -#ifdef H5_HAVE_PARALLEL - H5D__chunk_collective_read, /* par_read */ - H5D__chunk_collective_write, /* par_write */ -#endif - NULL, /* readvv */ - NULL, /* writevv */ - H5D__chunk_flush, /* flush */ - H5D__chunk_io_term, /* io_term */ - H5D__chunk_dest /* dest */ + NULL, /* readvv */ + NULL, /* writevv */ + H5D__chunk_flush, /* flush */ + H5D__chunk_io_term, /* io_term */ + H5D__chunk_dest /* dest */ }}; /*******************/ @@ -355,11 +349,8 @@ const H5D_layout_ops_t H5D_LOPS_CHUNK[1] = {{ /*******************/ /* "nonexistent" storage layout I/O ops */ -const H5D_layout_ops_t H5D_LOPS_NONEXISTENT[1] = {{NULL, NULL, NULL, NULL, NULL, NULL, NULL, -#ifdef H5_HAVE_PARALLEL - NULL, NULL, -#endif /* H5_HAVE_PARALLEL */ - H5D__nonexistent_readvv, NULL, NULL, NULL, NULL}}; +const H5D_layout_ops_t H5D_LOPS_NONEXISTENT[1] = { + {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, H5D__nonexistent_readvv, NULL, NULL, NULL, NULL}}; /* Declare a free list to manage the H5F_rdcc_ent_ptr_t sequence information */ H5FL_SEQ_DEFINE_STATIC(H5D_rdcc_ent_ptr_t); @@ -368,7 +359,10 @@ H5FL_SEQ_DEFINE_STATIC(H5D_rdcc_ent_ptr_t); H5FL_DEFINE_STATIC(H5D_rdcc_ent_t); /* Declare a free list to manage the H5D_chunk_info_t struct */ -H5FL_DEFINE(H5D_chunk_info_t); +H5FL_DEFINE(H5D_chunk_map_t); + +/* Declare a free list to manage the H5D_piece_info_t struct */ +H5FL_DEFINE(H5D_piece_info_t); /* Declare a free list to manage the chunk sequence information */ H5FL_BLK_DEFINE_STATIC(chunk); @@ -389,8 +383,7 @@ 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) +H5D__chunk_direct_write(H5D_t *dset, uint32_t filters, hsize_t *offset, uint32_t data_size, const void *buf) { const H5O_layout_t *layout = &(dset->shared->layout); /* Dataset layout */ H5D_chunk_ud_t udata; /* User data for querying chunk info */ @@ -406,16 +399,9 @@ H5D__chunk_direct_write(const H5D_t *dset, uint32_t filters, hsize_t *offset, ui HDassert(layout->type == H5D_CHUNKED); /* Allocate dataspace and initialize it if it hasn't been. */ - if (!H5D__chunk_is_space_alloc(&layout->storage)) { - H5D_io_info_t io_info; /* to hold the dset info */ - - io_info.dset = dset; - io_info.f_sh = H5F_SHARED(dset->oloc.file); - - /* Allocate storage */ - if (H5D__alloc_storage(&io_info, H5D_ALLOC_WRITE, FALSE, NULL) < 0) + if (!H5D__chunk_is_space_alloc(&layout->storage)) + if (H5D__alloc_storage(dset, H5D_ALLOC_WRITE, FALSE, NULL) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize storage") - } /* Calculate the index of this chunk */ H5VM_chunk_scaled(dset->shared->ndims, offset, layout->u.chunk.dim, scaled); @@ -1069,26 +1055,40 @@ H5D__chunk_is_data_cached(const H5D_shared_t *shared_dset) *------------------------------------------------------------------------- */ static herr_t -H5D__chunk_io_init(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, - H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *fm) +H5D__chunk_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo) { - const H5D_t *dataset = io_info->dset; /* Local pointer to dataset info */ - hssize_t old_offset[H5O_LAYOUT_NDIMS]; /* Old selection offset */ - htri_t file_space_normalized = FALSE; /* File dataspace was normalized */ - unsigned f_ndims; /* The number of dimensions of the file's dataspace */ - int sm_ndims; /* The number of dimensions of the memory buffer's dataspace (signed) */ - htri_t use_selection_io = FALSE; /* Whether to use selection I/O */ - unsigned u; /* Local index variable */ - herr_t ret_value = SUCCEED; /* Return value */ + const H5D_t *dataset = dinfo->dset; /* Local pointer to dataset info */ + H5D_chunk_map_t *fm; /* Convenience pointer to chunk map */ + hssize_t old_offset[H5O_LAYOUT_NDIMS]; /* Old selection offset */ + htri_t file_space_normalized = FALSE; /* File dataspace was normalized */ + unsigned f_ndims; /* The number of dimensions of the file's dataspace */ + int sm_ndims; /* The number of dimensions of the memory buffer's dataspace (signed) */ + htri_t use_selection_io = FALSE; /* Whether to use selection I/O */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE + /* Allocate chunk map */ + if (NULL == (dinfo->layout_io_info.chunk_map = H5FL_MALLOC(H5D_chunk_map_t))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "unable to allocate chunk map") + fm = dinfo->layout_io_info.chunk_map; + /* Get layout for dataset */ - fm->layout = &(dataset->shared->layout); - fm->nelmts = nelmts; + dinfo->layout = &(dataset->shared->layout); + + /* Initialize "last chunk" information */ + fm->last_index = (hsize_t)-1; + fm->last_piece_info = NULL; + + /* Clear other fields */ + fm->mchunk_tmpl = NULL; + fm->dset_sel_pieces = NULL; + fm->single_space = NULL; + fm->single_piece_info = NULL; /* Check if the memory space is scalar & make equivalent memory space */ - if ((sm_ndims = H5S_GET_EXTENT_NDIMS(mem_space)) < 0) + if ((sm_ndims = H5S_GET_EXTENT_NDIMS(dinfo->mem_space)) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimension number") /* Set the number of dimensions for the memory dataspace */ H5_CHECKED_ASSIGN(fm->m_ndims, unsigned, sm_ndims, int); @@ -1102,49 +1102,28 @@ H5D__chunk_io_init(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsi * speed up hyperslab calculations by removing the extra checks and/or * additions involving the offset and the hyperslab selection -QAK) */ - if ((file_space_normalized = H5S_hyper_normalize_offset(file_space, old_offset)) < 0) + if ((file_space_normalized = H5S_hyper_normalize_offset(dinfo->file_space, old_offset)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to normalize selection") /* Decide the number of chunks in each dimension */ for (u = 0; u < f_ndims; u++) /* Keep the size of the chunk dimensions as hsize_t for various routines */ - fm->chunk_dim[u] = fm->layout->u.chunk.dim[u]; - -#ifdef H5_HAVE_PARALLEL - /* Calculate total chunk in file map*/ - 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") - } /* end if */ -#endif /* H5_HAVE_PARALLEL */ - - /* Initialize "last chunk" information */ - fm->last_index = (hsize_t)-1; - fm->last_chunk_info = NULL; - - /* Point at the dataspaces */ - fm->file_space = file_space; - fm->mem_space = mem_space; + fm->chunk_dim[u] = dinfo->layout->u.chunk.dim[u]; - if (H5D__chunk_io_init_selections(io_info, type_info, fm) < 0) + if (H5D__chunk_io_init_selections(io_info, dinfo) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file and memory chunk selections") - /* Check if we're performing selection I/O and save the result */ - if ((use_selection_io = H5D__chunk_may_use_select_io(io_info)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if selection I/O is possible") - io_info->use_select_io = (hbool_t)use_selection_io; + /* Check if we're performing selection I/O and save the result if it hasn't + * been disabled already */ + if (io_info->use_select_io) { + if ((use_selection_io = H5D__chunk_may_use_select_io(io_info, dinfo)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if selection I/O is possible") + io_info->use_select_io = (hbool_t)use_selection_io; + } done: - /* Reset the global dataspace info */ - fm->file_space = NULL; - fm->mem_space = NULL; - if (file_space_normalized == TRUE) - if (H5S_hyper_denormalize_offset(file_space, old_offset) < 0) + if (H5S_hyper_denormalize_offset(dinfo->file_space, old_offset) < 0) HDONE_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't denormalize selection") FUNC_LEAVE_NOAPI(ret_value) @@ -1163,34 +1142,44 @@ done: *------------------------------------------------------------------------- */ 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) +H5D__chunk_io_init_selections(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo) { - const H5D_t *dataset = io_info->dset; /* Local pointer to dataset info */ - const H5T_t *mem_type = type_info->mem_type; /* Local pointer to memory datatype */ - H5S_t *tmp_mspace = NULL; /* Temporary memory dataspace */ - H5T_t *file_type = NULL; /* Temporary copy of file datatype for iteration */ - hbool_t iter_init = FALSE; /* Selection iteration info has been initialized */ - char bogus; /* "bogus" buffer to pass to selection iterator */ - herr_t ret_value = SUCCEED; /* Return value */ + H5D_chunk_map_t *fm; /* Convenience pointer to chunk map */ + const H5D_t *dataset; /* Local pointer to dataset info */ + const H5T_t *mem_type; /* Local pointer to memory datatype */ + H5S_t *tmp_mspace = NULL; /* Temporary memory dataspace */ + H5T_t *file_type = NULL; /* Temporary copy of file datatype for iteration */ + hbool_t iter_init = FALSE; /* Selection iteration info has been initialized */ + char bogus; /* "bogus" buffer to pass to selection iterator */ + H5D_io_info_wrap_t io_info_wrap; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE + HDassert(io_info); + HDassert(dinfo); + + /* Set convenience pointers */ + fm = dinfo->layout_io_info.chunk_map; + HDassert(fm); + dataset = dinfo->dset; + mem_type = dinfo->type_info.mem_type; + /* Special case for only one element in selection */ /* (usually appending a record) */ - if (fm->nelmts == 1 + if (dinfo->nelmts == 1 #ifdef H5_HAVE_PARALLEL && !(io_info->using_mpi_vfd) #endif /* H5_HAVE_PARALLEL */ - && H5S_SEL_ALL != H5S_GET_SELECT_TYPE(fm->file_space)) { + && H5S_SEL_ALL != H5S_GET_SELECT_TYPE(dinfo->file_space)) { /* Initialize skip list for chunk selections */ - fm->sel_chunks = NULL; fm->use_single = TRUE; /* Initialize single chunk dataspace */ if (NULL == dataset->shared->cache.chunk.single_space) { /* Make a copy of the dataspace for the dataset */ - if ((dataset->shared->cache.chunk.single_space = H5S_copy(fm->file_space, TRUE, FALSE)) == NULL) + if ((dataset->shared->cache.chunk.single_space = H5S_copy(dinfo->file_space, TRUE, FALSE)) == + NULL) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file space") /* Resize chunk's dataspace dimensions to size of chunk */ @@ -1205,17 +1194,17 @@ H5D__chunk_io_init_selections(const H5D_io_info_t *io_info, const H5D_type_info_ HDassert(fm->single_space); /* Allocate the single chunk information */ - if (NULL == dataset->shared->cache.chunk.single_chunk_info) - if (NULL == (dataset->shared->cache.chunk.single_chunk_info = H5FL_MALLOC(H5D_chunk_info_t))) + if (NULL == dataset->shared->cache.chunk.single_piece_info) + if (NULL == (dataset->shared->cache.chunk.single_piece_info = H5FL_MALLOC(H5D_piece_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->single_piece_info = dataset->shared->cache.chunk.single_piece_info; + HDassert(fm->single_piece_info); /* Reset chunk template information */ fm->mchunk_tmpl = NULL; /* Set up chunk mapping for single element */ - if (H5D__create_chunk_map_single(fm, io_info) < 0) + if (H5D__create_piece_map_single(dinfo, io_info) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create chunk selections for single element") } /* end if */ @@ -1226,16 +1215,16 @@ H5D__chunk_io_init_selections(const H5D_io_info_t *io_info, const H5D_type_info_ 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->dset_sel_pieces = dataset->shared->cache.chunk.sel_chunks; + HDassert(fm->dset_sel_pieces); /* We are not using single element mode */ fm->use_single = FALSE; /* Get type of selection on disk & in memory */ - if ((fm->fsel_type = H5S_GET_SELECT_TYPE(fm->file_space)) < H5S_SEL_NONE) + if ((fm->fsel_type = H5S_GET_SELECT_TYPE(dinfo->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) + if ((fm->msel_type = H5S_GET_SELECT_TYPE(dinfo->mem_space)) < H5S_SEL_NONE) HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to get type of selection") /* If the selection is NONE or POINTS, set the flag to FALSE */ @@ -1248,57 +1237,53 @@ H5D__chunk_io_init_selections(const H5D_io_info_t *io_info, const H5D_type_info_ if (sel_hyper_flag) { /* Build the file selection for each chunk */ if (H5S_SEL_ALL == fm->fsel_type) { - if (H5D__create_chunk_file_map_all(fm, io_info) < 0) + if (H5D__create_piece_file_map_all(dinfo, io_info) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections") } /* end if */ else { /* Sanity check */ HDassert(fm->fsel_type == H5S_SEL_HYPERSLABS); - if (H5D__create_chunk_file_map_hyper(fm, io_info) < 0) + if (H5D__create_piece_file_map_hyper(dinfo, io_info) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections") } /* end else */ } /* end if */ else { - H5S_sel_iter_op_t iter_op; /* Operator for iteration */ - H5D_chunk_file_iter_ud_t udata; /* User data for iteration */ + H5S_sel_iter_op_t iter_op; /* Operator for iteration */ /* Create temporary datatypes for selection iteration */ if (NULL == (file_type = H5T_copy(dataset->shared->type, H5T_COPY_ALL))) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy file datatype") - /* Initialize the user data */ - udata.fm = fm; -#ifdef H5_HAVE_PARALLEL - udata.io_info = io_info; -#endif /* H5_HAVE_PARALLEL */ - - iter_op.op_type = H5S_SEL_ITER_OP_LIB; - iter_op.u.lib_op = H5D__chunk_file_cb; + /* set opdata for H5D__piece_mem_cb */ + io_info_wrap.io_info = io_info; + io_info_wrap.dinfo = dinfo; + iter_op.op_type = H5S_SEL_ITER_OP_LIB; + iter_op.u.lib_op = H5D__piece_file_cb; /* Spaces might not be the same shape, iterate over the file selection directly */ - if (H5S_select_iterate(&bogus, file_type, fm->file_space, &iter_op, &udata) < 0) + if (H5S_select_iterate(&bogus, file_type, dinfo->file_space, &iter_op, &io_info_wrap) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections") - /* Reset "last chunk" info */ + /* Reset "last piece" info */ fm->last_index = (hsize_t)-1; - fm->last_chunk_info = NULL; + fm->last_piece_info = NULL; } /* end else */ /* Build the memory selection for each chunk */ - if (sel_hyper_flag && H5S_SELECT_SHAPE_SAME(fm->file_space, fm->mem_space) == TRUE) { + if (sel_hyper_flag && H5S_SELECT_SHAPE_SAME(dinfo->file_space, dinfo->mem_space) == TRUE) { /* Reset chunk template information */ fm->mchunk_tmpl = NULL; - /* If the selections are the same shape, use the file chunk information - * to generate the memory chunk information quickly. + /* If the selections are the same shape, use the file chunk + * information to generate the memory chunk information quickly. */ - if (H5D__create_chunk_mem_map_hyper(fm) < 0) + if (H5D__create_piece_mem_map_hyper(dinfo) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create memory chunk selections") } /* end if */ 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) + H5S_SELECT_IS_REGULAR(dinfo->mem_space) && H5S_SELECT_IS_SINGLE(dinfo->mem_space)) { + if (H5D__create_piece_mem_map_1d(dinfo) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections") } /* end else-if */ else { @@ -1306,7 +1291,7 @@ H5D__chunk_io_init_selections(const H5D_io_info_t *io_info, const H5D_type_info_ size_t elmt_size; /* Memory datatype size */ /* Make a copy of equivalent memory space */ - if ((tmp_mspace = H5S_copy(fm->mem_space, TRUE, FALSE)) == NULL) + if ((tmp_mspace = H5S_copy(dinfo->mem_space, TRUE, FALSE)) == NULL) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space") /* De-select the mem space copy */ @@ -1324,15 +1309,18 @@ H5D__chunk_io_init_selections(const H5D_io_info_t *io_info, const H5D_type_info_ /* Create selection iterator for memory selection */ 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) + if (H5S_select_iter_init(&(fm->mem_iter), dinfo->mem_space, elmt_size, 0) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") iter_init = TRUE; /* Selection iteration info has been initialized */ - iter_op.op_type = H5S_SEL_ITER_OP_LIB; - iter_op.u.lib_op = H5D__chunk_mem_cb; + /* set opdata for H5D__piece_mem_cb */ + io_info_wrap.io_info = io_info; + io_info_wrap.dinfo = dinfo; + iter_op.op_type = H5S_SEL_ITER_OP_LIB; + iter_op.u.lib_op = H5D__piece_mem_cb; /* Spaces aren't the same shape, iterate over the memory selection directly */ - if (H5S_select_iterate(&bogus, file_type, fm->file_space, &iter_op, fm) < 0) + if (H5S_select_iterate(&bogus, file_type, dinfo->file_space, &iter_op, &io_info_wrap) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create memory chunk selections") } /* end else */ } /* end else */ @@ -1344,7 +1332,7 @@ done: 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) + if (H5D__chunk_io_term(io_info, dinfo) < 0) HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release chunk mapping") } /* end if */ @@ -1466,14 +1454,17 @@ H5D__chunk_mem_realloc(void *chk, size_t size, const H5O_pline_t *pline) /*-------------------------------------------------------------------------- NAME - H5D__free_chunk_info + H5D__free_piece_info PURPOSE - Internal routine to destroy a chunk info node + Performs initialization before any sort of I/O on the raw data + This was derived from H5D__free_chunk_info for multi-dset work. USAGE - void H5D__free_chunk_info(chunk_info) + herr_t H5D__free_piece_info(chunk_info, key, opdata) void *chunk_info; IN: Pointer to chunk info to destroy + void *key; Unused + void *opdata; Unused RETURNS - No return value + Non-negative on success, negative on failure DESCRIPTION Releases all the memory for a chunk info node. Called by H5SL_free GLOBAL VARIABLES @@ -1481,51 +1472,48 @@ H5D__chunk_mem_realloc(void *chk, size_t size, const H5O_pline_t *pline) EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -static herr_t -H5D__free_chunk_info(void *item, void H5_ATTR_UNUSED *key, void H5_ATTR_UNUSED *opdata) +herr_t +H5D__free_piece_info(void *item, void H5_ATTR_UNUSED *key, void H5_ATTR_UNUSED *opdata) { - H5D_chunk_info_t *chunk_info = (H5D_chunk_info_t *)item; + H5D_piece_info_t *piece_info = (H5D_piece_info_t *)item; FUNC_ENTER_PACKAGE_NOERR - HDassert(chunk_info); + HDassert(piece_info); - /* Close the chunk's file dataspace, if it's not shared */ - if (!chunk_info->fspace_shared) - (void)H5S_close(chunk_info->fspace); + /* Close the piece's file dataspace, if it's not shared */ + if (!piece_info->fspace_shared) + (void)H5S_close(piece_info->fspace); else - H5S_select_all(chunk_info->fspace, TRUE); + H5S_select_all(piece_info->fspace, TRUE); - /* Close the chunk's memory dataspace, if it's not shared */ - if (!chunk_info->mspace_shared && chunk_info->mspace) - (void)H5S_close(chunk_info->mspace); + /* Close the piece's memory dataspace, if it's not shared */ + if (!piece_info->mspace_shared && piece_info->mspace) + (void)H5S_close((H5S_t *)piece_info->mspace); - /* Free the actual chunk info */ - chunk_info = H5FL_FREE(H5D_chunk_info_t, chunk_info); + /* Free the actual piece info */ + piece_info = H5FL_FREE(H5D_piece_info_t, piece_info); FUNC_LEAVE_NOAPI(0) -} /* H5D__free_chunk_info() */ +} /* H5D__free_piece_info() */ /*------------------------------------------------------------------------- - * Function: H5D__create_chunk_map_single + * Function: H5D__create_piece_map_single * - * Purpose: Create chunk selections when appending a single record + * Purpose: Create piece selections when appending a single record + * This was derived from H5D__create_chunk_map_single for + * multi-dset work. * * Return: Non-negative on success/Negative on failure * - * Programmer: Quincey Koziol - * Tuesday, November 20, 2007 - * + * Programmer: Jonathan Kim Nov, 2013 *------------------------------------------------------------------------- */ 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 /* H5_HAVE_PARALLEL */ - *io_info) +H5D__create_piece_map_single(H5D_dset_io_info_t *di, H5D_io_info_t *io_info) { - H5D_chunk_info_t *chunk_info; /* Chunk information to insert into skip list */ + H5D_chunk_map_t *fm; /* Convenience pointer to chunk map */ + H5D_piece_info_t *piece_info; /* Piece information to insert into skip list */ hsize_t coords[H5O_LAYOUT_NDIMS]; /* Coordinates of chunk */ hsize_t sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */ hsize_t sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */ @@ -1534,64 +1522,68 @@ H5D__create_chunk_map_single(H5D_chunk_map_t *fm, const H5D_io_info_t FUNC_ENTER_PACKAGE - /* Sanity check */ + /* Set convenience pointer */ + fm = di->layout_io_info.chunk_map; + + /* Sanity checks */ + HDassert(fm); HDassert(fm->f_ndims > 0); /* Get coordinate for selection */ - if (H5S_SELECT_BOUNDS(fm->file_space, sel_start, sel_end) < 0) + if (H5S_SELECT_BOUNDS(di->file_space, sel_start, sel_end) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info") - /* Initialize the 'single chunk' file & memory chunk information */ - chunk_info = fm->single_chunk_info; - chunk_info->chunk_points = 1; + /* Initialize the 'single piece' file & memory piece information */ + piece_info = fm->single_piece_info; + piece_info->piece_points = 1; /* Set chunk location & hyperslab size */ for (u = 0; u < fm->f_ndims; u++) { /* Validate this chunk dimension */ - if (fm->layout->u.chunk.dim[u] == 0) + if (di->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]; + piece_info->scaled[u] = sel_start[u] / di->layout->u.chunk.dim[u]; + coords[u] = piece_info->scaled[u] * di->layout->u.chunk.dim[u]; } /* end for */ - chunk_info->scaled[fm->f_ndims] = 0; + piece_info->scaled[fm->f_ndims] = 0; /* Calculate the index of this chunk */ - chunk_info->index = - H5VM_array_offset_pre(fm->f_ndims, fm->layout->u.chunk.down_chunks, chunk_info->scaled); + piece_info->index = + H5VM_array_offset_pre(fm->f_ndims, di->layout->u.chunk.down_chunks, piece_info->scaled); /* Copy selection for file's dataspace into chunk dataspace */ - if (H5S_select_copy(fm->single_space, fm->file_space, FALSE) < 0) + if (H5S_select_copy(fm->single_space, di->file_space, FALSE) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file selection") /* Move selection back to have correct offset in chunk */ 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 - /* store chunk selection information */ - if (io_info->using_mpi_vfd) - fm->select_chunk[chunk_info->index] = chunk_info; -#endif /* H5_HAVE_PARALLEL */ - /* Set the file dataspace for the chunk to the shared 'single' dataspace */ - chunk_info->fspace = fm->single_space; + piece_info->fspace = fm->single_space; /* Indicate that the chunk's file dataspace is shared */ - chunk_info->fspace_shared = TRUE; + piece_info->fspace_shared = TRUE; /* Just point at the memory dataspace & selection */ - chunk_info->mspace = fm->mem_space; + piece_info->mspace = di->mem_space; /* Indicate that the chunk's memory dataspace is shared */ - chunk_info->mspace_shared = TRUE; + piece_info->mspace_shared = TRUE; + + /* make connection to related dset info from this piece_info */ + piece_info->dset_info = di; + + /* Add piece to global piece_count */ + io_info->piece_count++; done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5D__create_chunk_map_single() */ +} /* end H5D__create_piece_map_single() */ /*------------------------------------------------------------------------- - * Function: H5D__create_chunk_file_map_all + * Function: H5D__create_piece_file_map_all * * Purpose: Create all chunk selections in file, for an "all" selection. * @@ -1603,21 +1595,18 @@ done: *------------------------------------------------------------------------- */ 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 /* H5_HAVE_PARALLEL */ - *io_info) +H5D__create_piece_file_map_all(H5D_dset_io_info_t *di, H5D_io_info_t *io_info) { - H5S_t *tmp_fchunk = NULL; /* Temporary file dataspace */ - hsize_t file_dims[H5S_MAX_RANK]; /* File dataspace dims */ - hsize_t sel_points; /* Number of elements in file selection */ - hsize_t zeros[H5S_MAX_RANK]; /* All zero vector (for start parameter to setting hyperslab on partial - chunks) */ - hsize_t coords[H5S_MAX_RANK]; /* Current coordinates of chunk */ - hsize_t end[H5S_MAX_RANK]; /* Final coordinates of chunk */ - hsize_t scaled[H5S_MAX_RANK]; /* Scaled coordinates for this chunk */ - hsize_t chunk_index; /* "Index" of chunk */ + H5D_chunk_map_t *fm; /* Convenience pointer to chunk map */ + H5S_t *tmp_fchunk = NULL; /* Temporary file dataspace */ + hsize_t file_dims[H5S_MAX_RANK]; /* File dataspace dims */ + hsize_t sel_points; /* Number of elements in file selection */ + hsize_t zeros[H5S_MAX_RANK]; /* All zero vector (for start parameter to setting hyperslab on partial + chunks) */ + hsize_t coords[H5S_MAX_RANK]; /* Current coordinates of chunk */ + hsize_t end[H5S_MAX_RANK]; /* Final coordinates of chunk */ + hsize_t scaled[H5S_MAX_RANK]; /* Scaled coordinates for this chunk */ + hsize_t chunk_index; /* "Index" of chunk */ hsize_t curr_partial_clip[H5S_MAX_RANK]; /* Current partial dimension sizes to clip against */ hsize_t partial_dim_size[H5S_MAX_RANK]; /* Size of a partial dimension */ hbool_t is_partial_dim[H5S_MAX_RANK]; /* Whether a dimension is currently a partial chunk */ @@ -1627,14 +1616,18 @@ H5D__create_chunk_file_map_all(H5D_chunk_map_t *fm, const H5D_io_info_t FUNC_ENTER_PACKAGE - /* Sanity check */ + /* Set convenience pointer */ + fm = di->layout_io_info.chunk_map; + + /* Sanity checks */ + HDassert(fm); HDassert(fm->f_ndims > 0); /* Get number of elements selected in file */ - sel_points = fm->nelmts; + sel_points = di->nelmts; /* Get dataspace dimensions */ - if (H5S_get_simple_extent_dims(fm->file_space, file_dims, NULL) < 0) + if (H5S_get_simple_extent_dims(di->file_space, file_dims, NULL) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info") /* Set initial chunk location, partial dimensions, etc */ @@ -1642,7 +1635,7 @@ H5D__create_chunk_file_map_all(H5D_chunk_map_t *fm, const H5D_io_info_t HDmemset(zeros, 0, sizeof(zeros)); for (u = 0; u < fm->f_ndims; u++) { /* Validate this chunk dimension */ - if (fm->layout->u.chunk.dim[u] == 0) + if (di->layout->u.chunk.dim[u] == 0) HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "chunk size must be > 0, dim = %u ", u) /* Set up start / end coordinates for first chunk */ @@ -1672,54 +1665,54 @@ H5D__create_chunk_file_map_all(H5D_chunk_map_t *fm, const H5D_io_info_t /* Iterate through each chunk in the dataset */ while (sel_points) { - H5D_chunk_info_t *new_chunk_info; /* chunk information to insert into skip list */ + H5D_piece_info_t *new_piece_info; /* Piece information to insert into skip list */ hsize_t chunk_points; /* Number of elements in chunk selection */ - /* Add temporary chunk to the list of chunks */ + /* Add temporary chunk to the list of pieces */ /* Allocate the file & memory chunk information */ - if (NULL == (new_chunk_info = H5FL_MALLOC(H5D_chunk_info_t))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate chunk info") + if (NULL == (new_piece_info = H5FL_MALLOC(H5D_piece_info_t))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate piece info") /* Initialize the chunk information */ /* Set the chunk index */ - new_chunk_info->index = chunk_index; - -#ifdef H5_HAVE_PARALLEL - /* Store chunk selection information, for multi-chunk I/O */ - if (io_info->using_mpi_vfd) - fm->select_chunk[chunk_index] = new_chunk_info; -#endif /* H5_HAVE_PARALLEL */ + new_piece_info->index = chunk_index; /* Set the file chunk dataspace */ - if (NULL == (new_chunk_info->fspace = H5S_copy(tmp_fchunk, TRUE, FALSE))) + if (NULL == (new_piece_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; + new_piece_info->fspace_shared = FALSE; /* If there are partial dimensions for this chunk, set the hyperslab for them */ if (num_partial_dims > 0) - if (H5S_select_hyperslab(new_chunk_info->fspace, H5S_SELECT_SET, zeros, NULL, curr_partial_clip, + if (H5S_select_hyperslab(new_piece_info->fspace, H5S_SELECT_SET, zeros, NULL, curr_partial_clip, NULL) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, FAIL, "can't create chunk selection") /* Set the memory chunk dataspace */ - new_chunk_info->mspace = NULL; - new_chunk_info->mspace_shared = FALSE; + new_piece_info->mspace = NULL; + new_piece_info->mspace_shared = FALSE; /* Copy the chunk's scaled coordinates */ - H5MM_memcpy(new_chunk_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims); - new_chunk_info->scaled[fm->f_ndims] = 0; + H5MM_memcpy(new_piece_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims); + new_piece_info->scaled[fm->f_ndims] = 0; + + /* make connection to related dset info from this piece_info */ + new_piece_info->dset_info = di; /* Insert the new chunk into the skip list */ - if (H5SL_insert(fm->sel_chunks, new_chunk_info, &new_chunk_info->index) < 0) { - H5D__free_chunk_info(new_chunk_info, NULL, NULL); + if (H5SL_insert(fm->dset_sel_pieces, new_piece_info, &new_piece_info->index) < 0) { + H5D__free_piece_info(new_piece_info, NULL, NULL); HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert chunk into skip list") } /* end if */ + /* Add piece to global piece_count*/ + io_info->piece_count++; + /* Get number of elements selected in chunk */ - chunk_points = H5S_GET_SELECT_NPOINTS(new_chunk_info->fspace); - H5_CHECKED_ASSIGN(new_chunk_info->chunk_points, uint32_t, chunk_points, hsize_t); + chunk_points = H5S_GET_SELECT_NPOINTS(new_piece_info->fspace); + new_piece_info->piece_points = chunk_points; /* Decrement # of points left in file selection */ sel_points -= chunk_points; @@ -1796,74 +1789,75 @@ done: } /* end H5D__create_chunk_file_map_all() */ /*------------------------------------------------------------------------- - * Function: H5D__create_chunk_file_map_hyper + * Function: H5D__create_piece_file_map_hyper * - * Purpose: Create all chunk selections in file, for a hyperslab selection. + * Purpose: Create all chunk selections in file. + * This was derived from H5D__create_chunk_file_map_hyper for + * multi-dset work. * * Return: Non-negative on success/Negative on failure * - * Programmer: Quincey Koziol - * Thursday, May 29, 2003 - * + * Programmer: Jonathan Kim Nov, 2013 *------------------------------------------------------------------------- */ 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 /* H5_HAVE_PARALLEL */ - *io_info) +H5D__create_piece_file_map_hyper(H5D_dset_io_info_t *dinfo, H5D_io_info_t *io_info) { - H5S_t *tmp_fchunk = NULL; /* Temporary file dataspace */ - hsize_t sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */ - hsize_t sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */ - hsize_t sel_points; /* Number of elements in file selection */ - hsize_t start_coords[H5O_LAYOUT_NDIMS]; /* Starting coordinates of selection */ - hsize_t coords[H5O_LAYOUT_NDIMS]; /* Current coordinates of chunk */ - hsize_t end[H5O_LAYOUT_NDIMS]; /* Final coordinates of chunk */ - hsize_t chunk_index; /* Index of chunk */ - hsize_t start_scaled[H5S_MAX_RANK]; /* Starting scaled coordinates of selection */ - hsize_t scaled[H5S_MAX_RANK]; /* Scaled coordinates for this chunk */ - int curr_dim; /* Current dimension to increment */ - unsigned u; /* Local index variable */ - herr_t ret_value = SUCCEED; /* Return value */ + H5D_chunk_map_t *fm; /* Convenience pointer to chunk map */ + H5S_t *tmp_fchunk = NULL; /* Temporary file dataspace */ + hsize_t sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */ + hsize_t sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */ + hsize_t sel_points; /* Number of elements in file selection */ + hsize_t start_coords[H5O_LAYOUT_NDIMS]; /* Starting coordinates of selection */ + hsize_t coords[H5O_LAYOUT_NDIMS]; /* Current coordinates of chunk */ + hsize_t end[H5O_LAYOUT_NDIMS]; /* Final coordinates of chunk */ + hsize_t chunk_index; /* Index of chunk */ + hsize_t start_scaled[H5S_MAX_RANK]; /* Starting scaled coordinates of selection */ + hsize_t scaled[H5S_MAX_RANK]; /* Scaled coordinates for this chunk */ + int curr_dim; /* Current dimension to increment */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE - /* Sanity check */ + /* Set convenience pointer */ + fm = dinfo->layout_io_info.chunk_map; + + /* Sanity checks */ + HDassert(fm); HDassert(fm->f_ndims > 0); /* Get number of elements selected in file */ - sel_points = fm->nelmts; + sel_points = dinfo->nelmts; /* Get bounding box for selection (to reduce the number of chunks to iterate over) */ - if (H5S_SELECT_BOUNDS(fm->file_space, sel_start, sel_end) < 0) + if (H5S_SELECT_BOUNDS(dinfo->file_space, sel_start, sel_end) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info") /* Set initial chunk location & hyperslab size */ for (u = 0; u < fm->f_ndims; u++) { /* Validate this chunk dimension */ - if (fm->layout->u.chunk.dim[u] == 0) + if (dinfo->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]; + scaled[u] = start_scaled[u] = sel_start[u] / dinfo->layout->u.chunk.dim[u]; + coords[u] = start_coords[u] = scaled[u] * dinfo->layout->u.chunk.dim[u]; end[u] = (coords[u] + fm->chunk_dim[u]) - 1; } /* end for */ /* Calculate the index of this chunk */ - chunk_index = H5VM_array_offset_pre(fm->f_ndims, fm->layout->u.chunk.down_chunks, scaled); + chunk_index = H5VM_array_offset_pre(fm->f_ndims, dinfo->layout->u.chunk.down_chunks, scaled); /* Iterate through each chunk in the dataset */ while (sel_points) { /* Check for intersection of current chunk and file selection */ - if (TRUE == H5S_SELECT_INTERSECT_BLOCK(fm->file_space, coords, end)) { - H5D_chunk_info_t *new_chunk_info; /* chunk information to insert into skip list */ + if (TRUE == H5S_SELECT_INTERSECT_BLOCK(dinfo->file_space, coords, end)) { + H5D_piece_info_t *new_piece_info; /* chunk information to insert into skip list */ hsize_t chunk_points; /* Number of elements in chunk selection */ /* Create dataspace for chunk, 'AND'ing the overall selection with * the current chunk. */ - if (H5S_combine_hyperslab(fm->file_space, H5S_SELECT_AND, coords, NULL, fm->chunk_dim, NULL, + if (H5S_combine_hyperslab(dinfo->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") @@ -1879,42 +1873,42 @@ H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t /* Add temporary chunk to the list of chunks */ /* Allocate the file & memory chunk information */ - if (NULL == (new_chunk_info = H5FL_MALLOC(H5D_chunk_info_t))) + if (NULL == (new_piece_info = H5FL_MALLOC(H5D_piece_info_t))) HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate chunk info") /* Initialize the chunk information */ /* Set the chunk index */ - new_chunk_info->index = chunk_index; - -#ifdef H5_HAVE_PARALLEL - /* Store chunk selection information, for multi-chunk I/O */ - if (io_info->using_mpi_vfd) - fm->select_chunk[chunk_index] = new_chunk_info; -#endif /* H5_HAVE_PARALLEL */ + new_piece_info->index = chunk_index; /* Set the file chunk dataspace */ - new_chunk_info->fspace = tmp_fchunk; - new_chunk_info->fspace_shared = FALSE; + new_piece_info->fspace = tmp_fchunk; + new_piece_info->fspace_shared = FALSE; tmp_fchunk = NULL; /* Set the memory chunk dataspace */ - new_chunk_info->mspace = NULL; - new_chunk_info->mspace_shared = FALSE; + new_piece_info->mspace = NULL; + new_piece_info->mspace_shared = FALSE; /* Copy the chunk's scaled coordinates */ - H5MM_memcpy(new_chunk_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims); - new_chunk_info->scaled[fm->f_ndims] = 0; + H5MM_memcpy(new_piece_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims); + new_piece_info->scaled[fm->f_ndims] = 0; - /* Insert the new chunk into the skip list */ - 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") + /* make connection to related dset info from this piece_info */ + new_piece_info->dset_info = dinfo; + + /* Add piece to global piece_count */ + io_info->piece_count++; + + /* Insert the new piece into the skip list */ + if (H5SL_insert(fm->dset_sel_pieces, new_piece_info, &new_piece_info->index) < 0) { + H5D__free_piece_info(new_piece_info, NULL, NULL); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert piece into skip list") } /* end if */ /* Get number of elements selected in chunk */ - chunk_points = H5S_GET_SELECT_NPOINTS(new_chunk_info->fspace); - H5_CHECKED_ASSIGN(new_chunk_info->chunk_points, uint32_t, chunk_points, hsize_t); + chunk_points = H5S_GET_SELECT_NPOINTS(new_piece_info->fspace); + new_piece_info->piece_points = chunk_points; /* Decrement # of points left in file selection */ sel_points -= chunk_points; @@ -1957,7 +1951,7 @@ H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t } while (curr_dim >= 0 && (coords[curr_dim] > sel_end[curr_dim])); /* Re-calculate the index of this chunk */ - chunk_index = H5VM_array_offset_pre(fm->f_ndims, fm->layout->u.chunk.down_chunks, scaled); + chunk_index = H5VM_array_offset_pre(fm->f_ndims, dinfo->layout->u.chunk.down_chunks, scaled); } /* end if */ } /* end while */ @@ -1968,28 +1962,29 @@ done: HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't release temporary dataspace") FUNC_LEAVE_NOAPI(ret_value) -} /* end H5D__create_chunk_file_map_hyper() */ +} /* end H5D__create_piece_file_map_hyper() */ /*------------------------------------------------------------------------- - * Function: H5D__create_chunk_mem_map_hyper + * Function: H5D__create_piece_mem_map_hyper * - * Purpose: Create all chunk selections in memory by copying the file + * Purpose: Create all chunk selections in memory by copying the file * chunk selections and adjusting their offsets to be correct - * for the memory. + * or the memory. + * This was derived from H5D__create_chunk_mem_map_hyper for + * multi-dset work. * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success/Negative on failure * - * Programmer: Quincey Koziol - * Thursday, May 29, 2003 + * Programmer: Jonathan Kim Nov, 2013 * * Assumptions: That the file and memory selections are the same shape. - * *------------------------------------------------------------------------- */ static herr_t -H5D__create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm) +H5D__create_piece_mem_map_hyper(const H5D_dset_io_info_t *dinfo) { - H5D_chunk_info_t *chunk_info; /* Pointer to chunk information */ + H5D_chunk_map_t *fm; /* Convenience pointer to chunk map */ + H5D_piece_info_t *piece_info; /* Pointer to piece information */ H5SL_node_t *curr_node; /* Current node in skip list */ hsize_t file_sel_start[H5S_MAX_RANK]; /* Offset of low bound of file selection */ hsize_t file_sel_end[H5S_MAX_RANK]; /* Offset of high bound of file selection */ @@ -2002,30 +1997,33 @@ H5D__create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm) FUNC_ENTER_PACKAGE /* Sanity check */ - HDassert(fm->f_ndims > 0); + HDassert(dinfo->layout_io_info.chunk_map->f_ndims > 0); + + /* Set convenience pointer */ + fm = dinfo->layout_io_info.chunk_map; /* Check for all I/O going to a single chunk */ - if (H5SL_count(fm->sel_chunks) == 1) { + if (H5SL_count(fm->dset_sel_pieces) == 1) { /* Get the node */ - curr_node = H5SL_first(fm->sel_chunks); + curr_node = H5SL_first(fm->dset_sel_pieces); - /* Get pointer to chunk's information */ - chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node); - HDassert(chunk_info); + /* Get pointer to piece's information */ + piece_info = (H5D_piece_info_t *)H5SL_item(curr_node); + HDassert(piece_info); /* Just point at the memory dataspace & selection */ - chunk_info->mspace = fm->mem_space; + piece_info->mspace = dinfo->mem_space; - /* Indicate that the chunk's memory space is shared */ - chunk_info->mspace_shared = TRUE; + /* Indicate that the piece's memory space is shared */ + piece_info->mspace_shared = TRUE; } /* end if */ else { /* Get bounding box for file selection */ - if (H5S_SELECT_BOUNDS(fm->file_space, file_sel_start, file_sel_end) < 0) + if (H5S_SELECT_BOUNDS(dinfo->file_space, file_sel_start, file_sel_end) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info") /* Get bounding box for memory selection */ - if (H5S_SELECT_BOUNDS(fm->mem_space, mem_sel_start, mem_sel_end) < 0) + if (H5S_SELECT_BOUNDS(dinfo->mem_space, mem_sel_start, mem_sel_end) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info") /* Calculate the adjustment for memory selection from file selection */ @@ -2037,28 +2035,29 @@ H5D__create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm) } /* end for */ /* Iterate over each chunk in the chunk list */ - curr_node = H5SL_first(fm->sel_chunks); + HDassert(fm->dset_sel_pieces); + curr_node = H5SL_first(fm->dset_sel_pieces); while (curr_node) { hsize_t coords[H5S_MAX_RANK]; /* Current coordinates of chunk */ - hssize_t chunk_adjust[H5S_MAX_RANK]; /* Adjustment to make to a particular chunk */ + hssize_t piece_adjust[H5S_MAX_RANK]; /* Adjustment to make to a particular chunk */ H5S_sel_type chunk_sel_type; /* Chunk's selection type */ - /* Get pointer to chunk's information */ - chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node); - HDassert(chunk_info); + /* Get pointer to piece's information */ + piece_info = (H5D_piece_info_t *)H5SL_item(curr_node); + HDassert(piece_info); /* Compute the chunk coordinates from the scaled coordinates */ for (u = 0; u < fm->f_ndims; u++) - coords[u] = chunk_info->scaled[u] * fm->layout->u.chunk.dim[u]; + coords[u] = piece_info->scaled[u] * dinfo->layout->u.chunk.dim[u]; /* Copy the information */ /* Copy the memory dataspace */ - if ((chunk_info->mspace = H5S_copy(fm->mem_space, TRUE, FALSE)) == NULL) + if ((piece_info->mspace = H5S_copy(dinfo->mem_space, TRUE, FALSE)) == NULL) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space") /* Get the chunk's selection type */ - if ((chunk_sel_type = H5S_GET_SELECT_TYPE(chunk_info->fspace)) < H5S_SEL_NONE) + if ((chunk_sel_type = H5S_GET_SELECT_TYPE(piece_info->fspace)) < H5S_SEL_NONE) HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to get type of selection") /* Set memory selection for "all" chunk selections */ @@ -2068,7 +2067,7 @@ H5D__create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm) coords[u] = (hsize_t)((hssize_t)coords[u] - adjust[u]); /* Set to same shape as chunk */ - if (H5S_select_hyperslab(chunk_info->mspace, H5S_SELECT_SET, coords, NULL, fm->chunk_dim, + if (H5S_select_hyperslab(piece_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") } /* end if */ @@ -2077,32 +2076,32 @@ H5D__create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm) HDassert(H5S_SEL_HYPERSLABS == chunk_sel_type); /* Copy the file chunk's selection */ - if (H5S_SELECT_COPY(chunk_info->mspace, chunk_info->fspace, FALSE) < 0) + if (H5S_SELECT_COPY(piece_info->mspace, piece_info->fspace, FALSE) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy selection") /* Compute the adjustment for this chunk */ for (u = 0; u < fm->f_ndims; u++) { /* Compensate for the chunk offset */ H5_CHECK_OVERFLOW(coords[u], hsize_t, hssize_t); - chunk_adjust[u] = adjust[u] - (hssize_t)coords[u]; + piece_adjust[u] = adjust[u] - (hssize_t)coords[u]; } /* end for */ /* Adjust the selection */ - if (H5S_SELECT_ADJUST_S(chunk_info->mspace, chunk_adjust) < 0) + if (H5S_SELECT_ADJUST_S(piece_info->mspace, piece_adjust) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to adjust selection") } /* end else */ - /* Get the next chunk node in the skip list */ + /* Get the next piece node in the skip list */ curr_node = H5SL_next(curr_node); } /* end while */ } /* end else */ done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5D__create_chunk_mem_map_hyper() */ +} /* end H5D__create_piece_mem_map_hyper() */ /*------------------------------------------------------------------------- - * Function: H5D__create_mem_map_1d + * Function: H5D__create_piece_mem_map_1d * * Purpose: Create all chunk selections for 1-dimensional regular memory space * that has only one single block in the selection @@ -2115,31 +2114,36 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5D__create_chunk_mem_map_1d(const H5D_chunk_map_t *fm) +H5D__create_piece_mem_map_1d(const H5D_dset_io_info_t *dinfo) { - H5D_chunk_info_t *chunk_info; /* Pointer to chunk information */ + H5D_chunk_map_t *fm; /* Convenience pointer to chunk map */ + H5D_piece_info_t *piece_info; /* Pointer to chunk information */ H5SL_node_t *curr_node; /* Current node in skip list */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity check */ - HDassert(fm->f_ndims > 0); + HDassert(dinfo->layout_io_info.chunk_map->f_ndims > 0); + + /* Set convenience pointer */ + fm = dinfo->layout_io_info.chunk_map; + HDassert(fm); /* Check for all I/O going to a single chunk */ - if (H5SL_count(fm->sel_chunks) == 1) { + if (H5SL_count(fm->dset_sel_pieces) == 1) { /* Get the node */ - curr_node = H5SL_first(fm->sel_chunks); + curr_node = H5SL_first(fm->dset_sel_pieces); /* Get pointer to chunk's information */ - chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node); - HDassert(chunk_info); + piece_info = (H5D_piece_info_t *)H5SL_item(curr_node); + HDassert(piece_info); /* Just point at the memory dataspace & selection */ - chunk_info->mspace = fm->mem_space; + piece_info->mspace = dinfo->mem_space; /* Indicate that the chunk's memory space is shared */ - chunk_info->mspace_shared = TRUE; + piece_info->mspace_shared = TRUE; } /* end if */ else { hsize_t mem_sel_start[H5S_MAX_RANK]; /* Offset of low bound of file selection */ @@ -2147,26 +2151,26 @@ H5D__create_chunk_mem_map_1d(const H5D_chunk_map_t *fm) HDassert(fm->m_ndims == 1); - if (H5S_SELECT_BOUNDS(fm->mem_space, mem_sel_start, mem_sel_end) < 0) + if (H5S_SELECT_BOUNDS(dinfo->mem_space, mem_sel_start, mem_sel_end) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info") /* Iterate over each chunk in the chunk list */ - curr_node = H5SL_first(fm->sel_chunks); + curr_node = H5SL_first(fm->dset_sel_pieces); while (curr_node) { hsize_t chunk_points; /* Number of elements in chunk selection */ hsize_t tmp_count = 1; /* Get pointer to chunk's information */ - chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node); - HDassert(chunk_info); + piece_info = (H5D_piece_info_t *)H5SL_item(curr_node); + HDassert(piece_info); /* Copy the memory dataspace */ - if ((chunk_info->mspace = H5S_copy(fm->mem_space, TRUE, FALSE)) == NULL) + if ((piece_info->mspace = H5S_copy(dinfo->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); + chunk_points = H5S_GET_SELECT_NPOINTS(piece_info->fspace); - if (H5S_select_hyperslab(chunk_info->mspace, H5S_SELECT_SET, mem_sel_start, NULL, &tmp_count, + if (H5S_select_hyperslab(piece_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") @@ -2179,177 +2183,187 @@ H5D__create_chunk_mem_map_1d(const H5D_chunk_map_t *fm) done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5D__create_chunk_mem_map_1d() */ +} /* end H5D__create_piece_mem_map_1d() */ /*------------------------------------------------------------------------- - * Function: H5D__chunk_file_cb + * Function: H5D__piece_file_cb * - * Purpose: Callback routine for file selection iterator. Used when + * Purpose: Callback routine for file selection iterator. Used when * creating selections in file for each point selected. * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success/Negative on failure * - * Programmer: Quincey Koziol - * Wednesday, July 23, 2003 + * Programmer: Jonathan Kim Nov, 2013 * *------------------------------------------------------------------------- */ 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__piece_file_cb(void H5_ATTR_UNUSED *elem, const H5T_t H5_ATTR_UNUSED *type, unsigned ndims, + const hsize_t *coords, void *_opdata) { - H5D_chunk_file_iter_ud_t *udata = (H5D_chunk_file_iter_ud_t *)_udata; /* User data for operation */ - H5D_chunk_map_t *fm = udata->fm; /* File<->memory chunk mapping info */ - H5D_chunk_info_t *chunk_info; /* Chunk information for current chunk */ - hsize_t coords_in_chunk[H5O_LAYOUT_NDIMS]; /* Coordinates of element in chunk */ - hsize_t chunk_index; /* Chunk index */ - hsize_t scaled[H5S_MAX_RANK]; /* Scaled coordinates for this chunk */ - unsigned u; /* Local index variable */ - herr_t ret_value = SUCCEED; /* Return value */ + H5D_io_info_wrap_t *opdata = (H5D_io_info_wrap_t *)_opdata; + H5D_io_info_t *io_info = (H5D_io_info_t *)opdata->io_info; /* io info for multi dset */ + H5D_dset_io_info_t *dinfo = (H5D_dset_io_info_t *)opdata->dinfo; /* File<->memory piece mapping info */ + H5D_chunk_map_t *fm; /* Convenience pointer to chunk map */ + H5D_piece_info_t *piece_info; /* Chunk information for current piece */ + hsize_t coords_in_chunk[H5O_LAYOUT_NDIMS]; /* Coordinates of element in chunk */ + hsize_t chunk_index; /* Chunk index */ + hsize_t scaled[H5S_MAX_RANK]; /* Scaled coordinates for this chunk */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE + /* Set convenience pointer */ + fm = dinfo->layout_io_info.chunk_map; + /* Calculate the index of this chunk */ - chunk_index = H5VM_chunk_index_scaled(ndims, coords, fm->layout->u.chunk.dim, - fm->layout->u.chunk.down_chunks, scaled); + chunk_index = H5VM_chunk_index_scaled(ndims, coords, dinfo->layout->u.chunk.dim, + dinfo->layout->u.chunk.down_chunks, scaled); /* Find correct chunk in file & memory skip list */ if (chunk_index == fm->last_index) { /* If the chunk index is the same as the last chunk index we used, * get the cached info to operate on. */ - chunk_info = fm->last_chunk_info; + piece_info = fm->last_piece_info; } /* end if */ else { /* If the chunk index is not the same as the last chunk index we used, - * find the chunk in the skip list. - */ - /* Get the chunk node from the skip list */ - if (NULL == (chunk_info = (H5D_chunk_info_t *)H5SL_search(fm->sel_chunks, &chunk_index))) { + * find the chunk in the skip list. If we do not find it, create + * a new node. */ + if (NULL == (piece_info = (H5D_piece_info_t *)H5SL_search(fm->dset_sel_pieces, &chunk_index))) { H5S_t *fspace; /* Memory chunk's dataspace */ /* Allocate the file & memory chunk information */ - if (NULL == (chunk_info = H5FL_MALLOC(H5D_chunk_info_t))) + if (NULL == (piece_info = H5FL_MALLOC(H5D_piece_info_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info") /* Initialize the chunk information */ /* Set the chunk index */ - chunk_info->index = chunk_index; + piece_info->index = chunk_index; /* Create a dataspace for the chunk */ if ((fspace = H5S_create_simple(fm->f_ndims, fm->chunk_dim, NULL)) == NULL) { - chunk_info = H5FL_FREE(H5D_chunk_info_t, chunk_info); + piece_info = H5FL_FREE(H5D_piece_info_t, piece_info); HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create dataspace for chunk") } /* end if */ /* De-select the chunk space */ if (H5S_select_none(fspace) < 0) { (void)H5S_close(fspace); - chunk_info = H5FL_FREE(H5D_chunk_info_t, chunk_info); + piece_info = H5FL_FREE(H5D_piece_info_t, piece_info); HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to de-select dataspace") } /* end if */ /* Set the file chunk dataspace */ - chunk_info->fspace = fspace; - chunk_info->fspace_shared = FALSE; + piece_info->fspace = fspace; + piece_info->fspace_shared = FALSE; /* Set the memory chunk dataspace */ - chunk_info->mspace = NULL; - chunk_info->mspace_shared = FALSE; + piece_info->mspace = NULL; + piece_info->mspace_shared = FALSE; /* Set the number of selected elements in chunk to zero */ - chunk_info->chunk_points = 0; + piece_info->piece_points = 0; /* Set the chunk's scaled coordinates */ - H5MM_memcpy(chunk_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims); - chunk_info->scaled[fm->f_ndims] = 0; + H5MM_memcpy(piece_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims); + piece_info->scaled[fm->f_ndims] = 0; + + /* Make connection to related dset info from this piece_info */ + piece_info->dset_info = dinfo; /* Insert the new chunk into the skip list */ - 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") + if (H5SL_insert(fm->dset_sel_pieces, piece_info, &piece_info->index) < 0) { + H5D__free_piece_info(piece_info, NULL, NULL); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert chunk into dataset skip list") } /* end if */ - } /* end if */ -#ifdef H5_HAVE_PARALLEL - /* Store chunk selection information, for collective multi-chunk I/O */ - if (udata->io_info->using_mpi_vfd) - fm->select_chunk[chunk_index] = chunk_info; -#endif /* H5_HAVE_PARALLEL */ + /* Add piece to global piece_count */ + io_info->piece_count++; + } /* end if */ /* Update the "last chunk seen" information */ fm->last_index = chunk_index; - fm->last_chunk_info = chunk_info; + fm->last_piece_info = piece_info; } /* end else */ /* Get the offset of the element within the chunk */ for (u = 0; u < fm->f_ndims; u++) - coords_in_chunk[u] = coords[u] - (scaled[u] * fm->layout->u.chunk.dim[u]); + coords_in_chunk[u] = coords[u] - (scaled[u] * dinfo->layout->u.chunk.dim[u]); /* Add point to file selection for chunk */ - if (H5S_select_elements(chunk_info->fspace, H5S_SELECT_APPEND, (size_t)1, coords_in_chunk) < 0) + if (H5S_select_elements(piece_info->fspace, H5S_SELECT_APPEND, (size_t)1, coords_in_chunk) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element") /* Increment the number of elemented selected in chunk */ - chunk_info->chunk_points++; + piece_info->piece_points++; done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5D__chunk_file_cb() */ +} /* end H5D__piece_file_cb */ /*------------------------------------------------------------------------- - * Function: H5D__chunk_mem_cb + * Function: H5D__piece_mem_cb * - * Purpose: Callback routine for file selection iterator. Used when - * creating selections in memory for each chunk. + * Purpose: Callback routine for file selection iterator. Used when + * creating selections in memory for each piece. + * This was derived from H5D__chunk_mem_cb for multi-dset + * work. * * Return: Non-negative on success/Negative on failure * - * Programmer: Raymond Lu - * Thursday, April 10, 2003 + * Programmer: Jonathan Kim Nov, 2013 * *------------------------------------------------------------------------- */ 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__piece_mem_cb(void H5_ATTR_UNUSED *elem, const H5T_t H5_ATTR_UNUSED *type, unsigned ndims, + const hsize_t *coords, void *_opdata) { - H5D_chunk_map_t *fm = (H5D_chunk_map_t *)_fm; /* File<->memory chunk mapping info */ - H5D_chunk_info_t *chunk_info; /* Chunk information for current chunk */ - hsize_t coords_in_mem[H5S_MAX_RANK]; /* Coordinates of element in memory */ - hsize_t chunk_index; /* Chunk index */ - herr_t ret_value = SUCCEED; /* Return value */ + H5D_io_info_wrap_t *opdata = (H5D_io_info_wrap_t *)_opdata; + H5D_dset_io_info_t *dinfo = (H5D_dset_io_info_t *)opdata->dinfo; /* File<->memory chunk mapping info */ + H5D_piece_info_t *piece_info; /* Chunk information for current chunk */ + H5D_chunk_map_t *fm; /* Convenience pointer to chunk map */ + hsize_t coords_in_mem[H5S_MAX_RANK]; /* Coordinates of element in memory */ + hsize_t chunk_index; /* Chunk index */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE + /* Set convenience pointer */ + fm = dinfo->layout_io_info.chunk_map; + /* Calculate the index of this chunk */ - chunk_index = H5VM_chunk_index(ndims, coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks); + chunk_index = + H5VM_chunk_index(ndims, coords, dinfo->layout->u.chunk.dim, dinfo->layout->u.chunk.down_chunks); /* Find correct chunk in file & memory skip list */ if (chunk_index == fm->last_index) { /* If the chunk index is the same as the last chunk index we used, * get the cached spaces to operate on. */ - chunk_info = fm->last_chunk_info; + piece_info = fm->last_piece_info; } /* end if */ else { /* If the chunk index is not the same as the last chunk index we used, - * find the chunk in the skip list. + * find the chunk in the dataset skip list. */ /* Get the chunk node from the skip list */ - 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 == (piece_info = (H5D_piece_info_t *)H5SL_search(fm->dset_sel_pieces, &chunk_index))) + HGOTO_ERROR(H5E_DATASPACE, H5E_NOTFOUND, H5_ITER_ERROR, "can't locate piece in dataset skip list") /* Check if the chunk already has a memory space */ - if (NULL == chunk_info->mspace) + if (NULL == piece_info->mspace) /* Copy the template memory chunk dataspace */ - if (NULL == (chunk_info->mspace = H5S_copy(fm->mchunk_tmpl, FALSE, FALSE))) + if (NULL == (piece_info->mspace = H5S_copy(fm->mchunk_tmpl, FALSE, FALSE))) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, H5_ITER_ERROR, "unable to copy file space") /* Update the "last chunk seen" information */ fm->last_index = chunk_index; - fm->last_chunk_info = chunk_info; + fm->last_piece_info = piece_info; } /* end else */ /* Get coordinates of selection iterator for memory */ @@ -2358,11 +2372,11 @@ H5D__chunk_mem_cb(void H5_ATTR_UNUSED *elem, const H5T_t H5_ATTR_UNUSED *type, u /* Add point to memory selection for chunk */ if (fm->msel_type == H5S_SEL_POINTS) { - if (H5S_select_elements(chunk_info->mspace, H5S_SELECT_APPEND, (size_t)1, coords_in_mem) < 0) + if (H5S_select_elements(piece_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") } /* end if */ else { - if (H5S_hyper_add_span_element(chunk_info->mspace, fm->m_ndims, coords_in_mem) < 0) + if (H5S_hyper_add_span_element(piece_info->mspace, fm->m_ndims, coords_in_mem) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, H5_ITER_ERROR, "unable to select element") } /* end else */ @@ -2372,7 +2386,62 @@ H5D__chunk_mem_cb(void H5_ATTR_UNUSED *elem, const H5T_t H5_ATTR_UNUSED *type, u done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5D__chunk_mem_cb() */ +} /* end H5D__piece_mem_cb() */ + +/*------------------------------------------------------------------------- + * Function: H5D__chunk_mdio_init + * + * Purpose: Performs second phase of initialization for multi-dataset + * I/O. Currently looks up chunk addresses and adds chunks to + * sel_pieces. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D__chunk_mdio_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo) +{ + H5SL_node_t *piece_node; /* Current node in chunk skip list */ + H5D_piece_info_t *piece_info; /* Piece information for current piece */ + H5D_chunk_ud_t udata; /* Chunk data from index */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Get first node in skip list. Note we don't check for failure since NULL + * simply indicates an empty skip list. */ + piece_node = H5D_CHUNK_GET_FIRST_NODE(dinfo); + + /* Iterate over skip list */ + while (piece_node) { + /* Get piece info */ + if (NULL == (piece_info = (H5D_piece_info_t *)H5D_CHUNK_GET_NODE_INFO(dinfo, piece_node))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "couldn't get piece info from list") + + /* Get the info for the chunk in the file */ + if (H5D__chunk_lookup(dinfo->dset, piece_info->scaled, &udata) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address") + + /* Save chunk file address */ + piece_info->faddr = udata.chunk_block.offset; + + /* Add piece to MDIO operation if it has a file address */ + if (H5F_addr_defined(piece_info->faddr)) { + HDassert(io_info->sel_pieces); + HDassert(io_info->pieces_added < io_info->piece_count); + + /* Add to sel_pieces and update pieces_added */ + io_info->sel_pieces[io_info->pieces_added++] = piece_info; + } + + /* Advance to next skip list node */ + piece_node = H5D_CHUNK_GET_NEXT_NODE(dinfo, piece_node); + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__chunk_mdio_init() */ /*------------------------------------------------------------------------- * Function: H5D__chunk_cacheable @@ -2388,16 +2457,19 @@ done: *------------------------------------------------------------------------- */ htri_t -H5D__chunk_cacheable(const H5D_io_info_t *io_info, haddr_t caddr, hbool_t write_op) +H5D__chunk_cacheable(const H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info, haddr_t caddr, + hbool_t write_op) { - const H5D_t *dataset = io_info->dset; /* Local pointer to dataset info */ - hbool_t has_filters = FALSE; /* Whether there are filters on the chunk or not */ - htri_t ret_value = FAIL; /* Return value */ + const H5D_t *dataset = NULL; /* Local pointer to dataset info */ + hbool_t has_filters = FALSE; /* Whether there are filters on the chunk or not */ + htri_t ret_value = FAIL; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity check */ HDassert(io_info); + HDassert(dset_info); + dataset = dset_info->dset; HDassert(dataset); /* Must bring the whole chunk in if there are any filters on the chunk. @@ -2405,9 +2477,9 @@ H5D__chunk_cacheable(const H5D_io_info_t *io_info, haddr_t caddr, hbool_t write_ * chunk because it is a partial edge chunk. */ 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); + has_filters = + !H5D__chunk_is_partial_edge_chunk(dataset->shared->ndims, dataset->shared->layout.u.chunk.dim, + dset_info->store->chunk.scaled, dataset->shared->curr_dims); } /* end if */ else has_filters = TRUE; @@ -2478,7 +2550,7 @@ done: *------------------------------------------------------------------------- */ static htri_t -H5D__chunk_may_use_select_io(const H5D_io_info_t *io_info) +H5D__chunk_may_use_select_io(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info) { const H5D_t *dataset = NULL; /* Local pointer to dataset info */ htri_t ret_value = FAIL; /* Return value */ @@ -2487,19 +2559,19 @@ H5D__chunk_may_use_select_io(const H5D_io_info_t *io_info) /* Sanity check */ HDassert(io_info); + HDassert(dset_info); - dataset = io_info->dset; + dataset = dset_info->dset; HDassert(dataset); /* Don't use selection I/O if it's globally disabled, there is a type * conversion, or if there are filters on the dataset (for now) */ - if (!H5_use_selection_io_g || io_info->io_ops.single_read != H5D__select_read || - dataset->shared->dcpl_cache.pline.nused > 0) + if (dset_info->io_ops.single_read != H5D__select_read || dataset->shared->dcpl_cache.pline.nused > 0) ret_value = FALSE; else { hbool_t page_buf_enabled; - HDassert(io_info->io_ops.single_write == H5D__select_write); + HDassert(dset_info->io_ops.single_write == H5D__select_write); /* Check if the page buffer is enabled */ if (H5PB_enabled(io_info->f_sh, H5FD_MEM_DRAW, &page_buf_enabled) < 0) @@ -2549,36 +2621,40 @@ done: *------------------------------------------------------------------------- */ 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, - H5S_t H5_ATTR_UNUSED *file_space, H5S_t H5_ATTR_UNUSED *mem_space, H5D_chunk_map_t *fm) +H5D__chunk_read(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info) { - H5SL_node_t *chunk_node; /* Current node in chunk skip list */ - H5D_io_info_t nonexistent_io_info; /* "nonexistent" I/O info object */ - uint32_t src_accessed_bytes = 0; /* Total accessed size in a chunk */ - hbool_t skip_missing_chunks = FALSE; /* Whether to skip missing chunks */ - H5S_t **chunk_mem_spaces = NULL; /* Array of chunk memory spaces */ - H5S_t *chunk_mem_spaces_static[8]; /* Static buffer for chunk_mem_spaces */ - H5S_t **chunk_file_spaces = NULL; /* Array of chunk file spaces */ - H5S_t *chunk_file_spaces_static[8]; /* Static buffer for chunk_file_spaces */ - haddr_t *chunk_addrs = NULL; /* Array of chunk addresses */ - haddr_t chunk_addrs_static[8]; /* Static buffer for chunk_addrs */ - herr_t ret_value = SUCCEED; /*return value */ + H5SL_node_t *chunk_node; /* Current node in chunk skip list */ + H5D_io_info_t nonexistent_io_info; /* "nonexistent" I/O info object */ + H5D_dset_io_info_t nonexistent_dset_info; /* "nonexistent" I/O dset info object */ + H5D_dset_io_info_t ctg_dset_info; /* Contiguous I/O dset info object */ + H5D_dset_io_info_t cpt_dset_info; /* Compact I/O dset info object */ + uint32_t src_accessed_bytes = 0; /* Total accessed size in a chunk */ + hbool_t skip_missing_chunks = FALSE; /* Whether to skip missing chunks */ + H5S_t **chunk_mem_spaces = NULL; /* Array of chunk memory spaces */ + H5S_t *chunk_mem_spaces_local[8]; /* Local buffer for chunk_mem_spaces */ + H5S_t **chunk_file_spaces = NULL; /* Array of chunk file spaces */ + H5S_t *chunk_file_spaces_local[8]; /* Local buffer for chunk_file_spaces */ + haddr_t *chunk_addrs = NULL; /* Array of chunk addresses */ + haddr_t chunk_addrs_local[8]; /* Local buffer for chunk_addrs */ + herr_t ret_value = SUCCEED; /*return value */ FUNC_ENTER_PACKAGE /* Sanity check */ HDassert(io_info); - HDassert(io_info->u.rbuf); - HDassert(type_info); - HDassert(fm); + HDassert(dset_info); + HDassert(dset_info->buf.vp); /* Set up "nonexistent" I/O info object */ H5MM_memcpy(&nonexistent_io_info, io_info, sizeof(nonexistent_io_info)); - nonexistent_io_info.layout_ops = *H5D_LOPS_NONEXISTENT; + H5MM_memcpy(&nonexistent_dset_info, dset_info, sizeof(nonexistent_dset_info)); + nonexistent_dset_info.layout_ops = *H5D_LOPS_NONEXISTENT; + nonexistent_io_info.dsets_info = &nonexistent_dset_info; + nonexistent_io_info.count = 1; { - const H5O_fill_t *fill = &(io_info->dset->shared->dcpl_cache.fill); /* Fill value info */ - H5D_fill_value_t fill_status; /* Fill value status */ + const H5O_fill_t *fill = &(dset_info->dset->shared->dcpl_cache.fill); /* Fill value info */ + H5D_fill_value_t fill_status; /* Fill value status */ /* Check the fill value status */ if (H5P_is_fill_value_defined(fill, &fill_status) < 0) @@ -2596,48 +2672,53 @@ H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_ /* Different blocks depending on whether we're using selection I/O */ if (io_info->use_select_io) { size_t num_chunks; - size_t element_sizes[2] = {type_info->dst_type_size, 0}; - void *bufs[2] = {io_info->u.rbuf, NULL}; - - /* Cache number of chunks */ - num_chunks = H5D_CHUNK_GET_NODE_COUNT(fm); - - /* Allocate arrays of dataspaces and offsets for use with selection I/O, - * or point to static buffers */ - HDassert(sizeof(chunk_mem_spaces_static) / sizeof(chunk_mem_spaces_static[0]) == - sizeof(chunk_file_spaces_static) / sizeof(chunk_file_spaces_static[0])); - HDassert(sizeof(chunk_mem_spaces_static) / sizeof(chunk_mem_spaces_static[0]) == - sizeof(chunk_addrs_static) / sizeof(chunk_addrs_static[0])); - if (num_chunks > (sizeof(chunk_mem_spaces_static) / sizeof(chunk_mem_spaces_static[0]))) { - if (NULL == (chunk_mem_spaces = H5MM_malloc(num_chunks * sizeof(H5S_t *)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, - "memory allocation failed for memory space list") - if (NULL == (chunk_file_spaces = H5MM_malloc(num_chunks * sizeof(H5S_t *)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for file space list") - if (NULL == (chunk_addrs = H5MM_malloc(num_chunks * sizeof(haddr_t)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, - "memory allocation failed for chunk address list") - } /* end if */ - else { - chunk_mem_spaces = chunk_mem_spaces_static; - chunk_file_spaces = chunk_file_spaces_static; - chunk_addrs = chunk_addrs_static; - } /* end else */ + size_t element_sizes[2] = {dset_info->type_info.src_type_size, 0}; + void *bufs[2] = {dset_info->buf.vp, NULL}; + + /* Only create selection I/O arrays if not performing multi dataset I/O, + * otherwise the higher level will handle it */ + if (H5D_LAYOUT_CB_PERFORM_IO(io_info)) { + /* Cache number of chunks */ + num_chunks = H5D_CHUNK_GET_NODE_COUNT(dset_info); + + /* Allocate arrays of dataspaces and offsets for use with selection I/O, + * or point to local buffers */ + HDassert(sizeof(chunk_mem_spaces_local) / sizeof(chunk_mem_spaces_local[0]) == + sizeof(chunk_file_spaces_local) / sizeof(chunk_file_spaces_local[0])); + HDassert(sizeof(chunk_mem_spaces_local) / sizeof(chunk_mem_spaces_local[0]) == + sizeof(chunk_addrs_local) / sizeof(chunk_addrs_local[0])); + if (num_chunks > (sizeof(chunk_mem_spaces_local) / sizeof(chunk_mem_spaces_local[0]))) { + if (NULL == (chunk_mem_spaces = H5MM_malloc(num_chunks * sizeof(H5S_t *)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory allocation failed for memory space list") + if (NULL == (chunk_file_spaces = H5MM_malloc(num_chunks * sizeof(H5S_t *)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory allocation failed for file space list") + if (NULL == (chunk_addrs = H5MM_malloc(num_chunks * sizeof(haddr_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory allocation failed for chunk address list") + } /* end if */ + else { + chunk_mem_spaces = chunk_mem_spaces_local; + chunk_file_spaces = chunk_file_spaces_local; + chunk_addrs = chunk_addrs_local; + } /* end else */ - /* Reset num_chunks */ - num_chunks = 0; + /* Reset num_chunks */ + num_chunks = 0; + } /* end if */ /* Iterate through nodes in chunk skip list */ - chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm); + chunk_node = H5D_CHUNK_GET_FIRST_NODE(dset_info); while (chunk_node) { - H5D_chunk_info_t *chunk_info; /* Chunk information */ + H5D_piece_info_t *chunk_info; /* Chunk information */ H5D_chunk_ud_t udata; /* Chunk index pass-through */ /* Get the actual chunk information from the skip list node */ - chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node); + chunk_info = H5D_CHUNK_GET_NODE_INFO(dset_info, chunk_node); /* Get the info for the chunk in the file */ - if (H5D__chunk_lookup(io_info->dset, chunk_info->scaled, &udata) < 0) + if (H5D__chunk_lookup(dset_info->dset, chunk_info->scaled, &udata) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address") /* There should be no chunks cached */ @@ -2649,45 +2730,66 @@ H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_ /* Check for non-existent chunk & skip it if appropriate */ if (H5F_addr_defined(udata.chunk_block.offset)) { - /* Add chunk to list for selection I/O */ - chunk_mem_spaces[num_chunks] = chunk_info->mspace; - chunk_file_spaces[num_chunks] = chunk_info->fspace; - chunk_addrs[num_chunks] = udata.chunk_block.offset; - num_chunks++; + /* Add chunk to list for selection I/O, if not performing multi dataset I/O */ + if (H5D_LAYOUT_CB_PERFORM_IO(io_info)) { + chunk_mem_spaces[num_chunks] = chunk_info->mspace; + chunk_file_spaces[num_chunks] = chunk_info->fspace; + chunk_addrs[num_chunks] = udata.chunk_block.offset; + num_chunks++; + } /* end if */ + else { + /* Add to mdset selection I/O arrays */ + HDassert(io_info->mem_spaces); + HDassert(io_info->file_spaces); + HDassert(io_info->addrs); + HDassert(io_info->element_sizes); + HDassert(io_info->rbufs); + HDassert(io_info->pieces_added < io_info->piece_count); + + io_info->mem_spaces[io_info->pieces_added] = chunk_info->mspace; + io_info->file_spaces[io_info->pieces_added] = chunk_info->fspace; + io_info->addrs[io_info->pieces_added] = udata.chunk_block.offset; + io_info->element_sizes[io_info->pieces_added] = element_sizes[0]; + io_info->rbufs[io_info->pieces_added] = bufs[0]; + io_info->pieces_added++; + } } /* end if */ else if (!skip_missing_chunks) { /* Perform the actual read operation from the nonexistent chunk */ - if ((io_info->io_ops.single_read)(&nonexistent_io_info, type_info, - (hsize_t)chunk_info->chunk_points, chunk_info->fspace, - chunk_info->mspace) < 0) + nonexistent_dset_info.file_space = chunk_info->fspace; + nonexistent_dset_info.mem_space = chunk_info->mspace; + nonexistent_dset_info.nelmts = chunk_info->piece_points; + if ((dset_info->io_ops.single_read)(&nonexistent_io_info, &nonexistent_dset_info) < 0) HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunked read failed") } /* end if */ /* Advance to next chunk in list */ - chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node); + chunk_node = H5D_CHUNK_GET_NEXT_NODE(dset_info, chunk_node); } /* end while */ - /* Issue selection I/O call (we can skip the page buffer because we've - * already verified it won't be used, and the metadata accumulator - * because this is raw data) */ - if (H5F_shared_select_read(H5F_SHARED(io_info->dset->oloc.file), H5FD_MEM_DRAW, (uint32_t)num_chunks, - chunk_mem_spaces, chunk_file_spaces, chunk_addrs, element_sizes, bufs) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunk selection read failed") - - /* Clean up memory */ - if (chunk_mem_spaces != chunk_mem_spaces_static) { - HDassert(chunk_mem_spaces); - HDassert(chunk_file_spaces != chunk_file_spaces_static); - HDassert(chunk_addrs != chunk_addrs_static); - H5MM_free(chunk_mem_spaces); - chunk_mem_spaces = NULL; - H5MM_free(chunk_file_spaces); - chunk_file_spaces = NULL; - H5MM_free(chunk_addrs); - chunk_addrs = NULL; - } /* end if */ - } /* end if */ + /* Only perform I/O if not performing multi dataset I/O, otherwise the + * higher level will handle it after all datasets have been processed */ + if (H5D_LAYOUT_CB_PERFORM_IO(io_info)) { + /* Issue selection I/O call (we can skip the page buffer because we've + * already verified it won't be used, and the metadata accumulator + * because this is raw data) */ + H5_CHECK_OVERFLOW(num_chunks, size_t, uint32_t) + if (H5F_shared_select_read(H5F_SHARED(dset_info->dset->oloc.file), H5FD_MEM_DRAW, + (uint32_t)num_chunks, chunk_mem_spaces, chunk_file_spaces, chunk_addrs, + element_sizes, bufs) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunk selection read failed") + + /* Clean up memory */ + if (chunk_mem_spaces != chunk_mem_spaces_local) { + HDassert(chunk_file_spaces != chunk_file_spaces_local); + HDassert(chunk_addrs != chunk_addrs_local); + chunk_mem_spaces = H5MM_xfree(chunk_mem_spaces); + chunk_file_spaces = H5MM_xfree(chunk_file_spaces); + chunk_addrs = H5MM_xfree(chunk_addrs); + } /* end if */ + } /* end if */ + } /* end if */ else { H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */ H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */ @@ -2697,33 +2799,39 @@ H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_ /* Set up contiguous I/O info object */ 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; + HDmemcpy(&ctg_dset_info, dset_info, sizeof(ctg_dset_info)); + ctg_dset_info.store = &ctg_store; + ctg_dset_info.layout_ops = *H5D_LOPS_CONTIG; + ctg_io_info.dsets_info = &ctg_dset_info; + ctg_io_info.count = 1; /* Initialize temporary contiguous storage info */ - H5_CHECKED_ASSIGN(ctg_store.contig.dset_size, hsize_t, io_info->dset->shared->layout.u.chunk.size, + H5_CHECKED_ASSIGN(ctg_store.contig.dset_size, hsize_t, dset_info->dset->shared->layout.u.chunk.size, uint32_t); /* Set up compact I/O info object */ 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; + HDmemcpy(&cpt_dset_info, dset_info, sizeof(cpt_dset_info)); + cpt_dset_info.store = &cpt_store; + cpt_dset_info.layout_ops = *H5D_LOPS_COMPACT; + cpt_io_info.dsets_info = &cpt_dset_info; + cpt_io_info.count = 1; /* Initialize temporary compact storage info */ cpt_store.compact.dirty = &cpt_dirty; /* Iterate through nodes in chunk skip list */ - chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm); + chunk_node = H5D_CHUNK_GET_FIRST_NODE(dset_info); while (chunk_node) { - H5D_chunk_info_t *chunk_info; /* Chunk information */ + H5D_piece_info_t *chunk_info; /* Chunk information */ H5D_chunk_ud_t udata; /* Chunk index pass-through */ htri_t cacheable; /* Whether the chunk is cacheable */ /* Get the actual chunk information from the skip list node */ - chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node); + chunk_info = H5D_CHUNK_GET_NODE_INFO(dset_info, chunk_node); /* Get the info for the chunk in the file */ - if (H5D__chunk_lookup(io_info->dset, chunk_info->scaled, &udata) < 0) + if (H5D__chunk_lookup(dset_info->dset, chunk_info->scaled, &udata) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address") /* Sanity check */ @@ -2737,20 +2845,23 @@ H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_ void *chunk = NULL; /* Pointer to locked chunk buffer */ /* Set chunk's [scaled] coordinates */ - io_info->store->chunk.scaled = chunk_info->scaled; + dset_info->store->chunk.scaled = chunk_info->scaled; /* Determine if we should use the chunk cache */ - if ((cacheable = H5D__chunk_cacheable(io_info, udata.chunk_block.offset, FALSE)) < 0) + if ((cacheable = H5D__chunk_cacheable(io_info, dset_info, udata.chunk_block.offset, FALSE)) < + 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't tell if chunk is cacheable") if (cacheable) { /* Load the chunk into cache and lock it. */ /* Compute # of bytes accessed in chunk */ - H5_CHECK_OVERFLOW(type_info->src_type_size, /*From:*/ size_t, /*To:*/ uint32_t); - src_accessed_bytes = chunk_info->chunk_points * (uint32_t)type_info->src_type_size; + H5_CHECK_OVERFLOW(dset_info->type_info.src_type_size, /*From:*/ size_t, /*To:*/ uint32_t); + H5_CHECK_OVERFLOW(chunk_info->piece_points, /*From:*/ size_t, /*To:*/ uint32_t); + src_accessed_bytes = + (uint32_t)chunk_info->piece_points * (uint32_t)dset_info->type_info.src_type_size; /* Lock the chunk into the cache */ - if (NULL == (chunk = H5D__chunk_lock(io_info, &udata, FALSE, FALSE))) + if (NULL == (chunk = H5D__chunk_lock(io_info, dset_info, &udata, FALSE, FALSE))) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk") /* Set up the storage buffer information for this chunk */ @@ -2772,35 +2883,39 @@ H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_ } /* end else */ /* Perform the actual read operation */ - 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) + HDassert(chk_io_info->count == 1); + chk_io_info->dsets_info[0].file_space = chunk_info->fspace; + chk_io_info->dsets_info[0].mem_space = chunk_info->mspace; + chk_io_info->dsets_info[0].nelmts = chunk_info->piece_points; + if ((dset_info->io_ops.single_read)(chk_io_info, &chk_io_info->dsets_info[0]) < 0) HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunked read failed") /* Release the cache lock on the chunk. */ - if (chunk && H5D__chunk_unlock(io_info, &udata, FALSE, chunk, src_accessed_bytes) < 0) + if (chunk && + H5D__chunk_unlock(io_info, dset_info, &udata, FALSE, chunk, src_accessed_bytes) < 0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk") } /* end if */ /* Advance to next chunk in list */ - chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node); + chunk_node = H5D_CHUNK_GET_NEXT_NODE(dset_info, chunk_node); } /* end while */ } /* end else */ done: /* Cleanup on failure */ if (ret_value < 0) { - if (chunk_mem_spaces != chunk_mem_spaces_static) + if (chunk_mem_spaces != chunk_mem_spaces_local) chunk_mem_spaces = H5MM_xfree(chunk_mem_spaces); - if (chunk_file_spaces != chunk_file_spaces_static) + if (chunk_file_spaces != chunk_file_spaces_local) chunk_file_spaces = H5MM_xfree(chunk_file_spaces); - if (chunk_addrs != chunk_addrs_static) + if (chunk_addrs != chunk_addrs_local) chunk_addrs = H5MM_xfree(chunk_addrs); } /* end if */ /* Make sure we cleaned up */ - HDassert(!chunk_mem_spaces || chunk_mem_spaces == chunk_mem_spaces_static); - HDassert(!chunk_file_spaces || chunk_file_spaces == chunk_file_spaces_static); - HDassert(!chunk_addrs || chunk_addrs == chunk_addrs_static); + HDassert(!chunk_mem_spaces || chunk_mem_spaces == chunk_mem_spaces_local); + HDassert(!chunk_file_spaces || chunk_file_spaces == chunk_file_spaces_local); + HDassert(!chunk_addrs || chunk_addrs == chunk_addrs_local); FUNC_LEAVE_NOAPI(ret_value) } /* H5D__chunk_read() */ @@ -2818,45 +2933,51 @@ done: *------------------------------------------------------------------------- */ 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, - H5S_t H5_ATTR_UNUSED *file_space, H5S_t H5_ATTR_UNUSED *mem_space, H5D_chunk_map_t *fm) +H5D__chunk_write(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info) { - H5SL_node_t *chunk_node; /* Current node in chunk skip list */ - H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */ - H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */ - H5D_io_info_t cpt_io_info; /* Compact I/O info object */ - H5D_storage_t cpt_store; /* Chunk storage information as compact dataset */ - hbool_t cpt_dirty; /* Temporary placeholder for compact storage "dirty" flag */ - uint32_t dst_accessed_bytes = 0; /* Total accessed size in a chunk */ - H5S_t **chunk_mem_spaces = NULL; /* Array of chunk memory spaces */ - H5S_t *chunk_mem_spaces_static[8]; /* Static buffer for chunk_mem_spaces */ - H5S_t **chunk_file_spaces = NULL; /* Array of chunk file spaces */ - H5S_t *chunk_file_spaces_static[8]; /* Static buffer for chunk_file_spaces */ - haddr_t *chunk_addrs = NULL; /* Array of chunk addresses */ - haddr_t chunk_addrs_static[8]; /* Static buffer for chunk_addrs */ - herr_t ret_value = SUCCEED; /* Return value */ + H5SL_node_t *chunk_node; /* Current node in chunk skip list */ + H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */ + H5D_dset_io_info_t ctg_dset_info; /* Contiguous I/O dset info object */ + H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */ + H5D_io_info_t cpt_io_info; /* Compact I/O info object */ + H5D_dset_io_info_t cpt_dset_info; /* Compact I/O dset info object */ + H5D_storage_t cpt_store; /* Chunk storage information as compact dataset */ + hbool_t cpt_dirty; /* Temporary placeholder for compact storage "dirty" flag */ + uint32_t dst_accessed_bytes = 0; /* Total accessed size in a chunk */ + H5S_t **chunk_mem_spaces = NULL; /* Array of chunk memory spaces */ + H5S_t *chunk_mem_spaces_local[8]; /* Local buffer for chunk_mem_spaces */ + H5S_t **chunk_file_spaces = NULL; /* Array of chunk file spaces */ + H5S_t *chunk_file_spaces_local[8]; /* Local buffer for chunk_file_spaces */ + haddr_t *chunk_addrs = NULL; /* Array of chunk addresses */ + haddr_t chunk_addrs_local[8]; /* Local buffer for chunk_addrs */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity check */ HDassert(io_info); - HDassert(io_info->u.wbuf); - HDassert(type_info); - HDassert(fm); + HDassert(dset_info); + HDassert(dset_info->buf.cvp); /* Set up contiguous I/O info object */ 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; + HDmemcpy(&ctg_dset_info, dset_info, sizeof(ctg_dset_info)); + ctg_dset_info.store = &ctg_store; + ctg_dset_info.layout_ops = *H5D_LOPS_CONTIG; + ctg_io_info.dsets_info = &ctg_dset_info; + ctg_io_info.count = 1; /* Initialize temporary contiguous storage info */ - H5_CHECKED_ASSIGN(ctg_store.contig.dset_size, hsize_t, io_info->dset->shared->layout.u.chunk.size, + H5_CHECKED_ASSIGN(ctg_store.contig.dset_size, hsize_t, dset_info->dset->shared->layout.u.chunk.size, uint32_t); /* Set up compact I/O info object */ 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; + HDmemcpy(&cpt_dset_info, dset_info, sizeof(cpt_dset_info)); + cpt_dset_info.store = &cpt_store; + cpt_dset_info.layout_ops = *H5D_LOPS_COMPACT; + cpt_io_info.dsets_info = &cpt_dset_info; + cpt_io_info.count = 1; /* Initialize temporary compact storage info */ cpt_store.compact.dirty = &cpt_dirty; @@ -2864,51 +2985,56 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize /* Different blocks depending on whether we're using selection I/O */ if (io_info->use_select_io) { size_t num_chunks; - size_t element_sizes[2] = {type_info->dst_type_size, 0}; - const void *bufs[2] = {io_info->u.wbuf, NULL}; - - /* Cache number of chunks */ - num_chunks = H5D_CHUNK_GET_NODE_COUNT(fm); - - /* Allocate arrays of dataspaces and offsets for use with selection I/O, - * or point to static buffers */ - HDassert(sizeof(chunk_mem_spaces_static) / sizeof(chunk_mem_spaces_static[0]) == - sizeof(chunk_file_spaces_static) / sizeof(chunk_file_spaces_static[0])); - HDassert(sizeof(chunk_mem_spaces_static) / sizeof(chunk_mem_spaces_static[0]) == - sizeof(chunk_addrs_static) / sizeof(chunk_addrs_static[0])); - if (num_chunks > (sizeof(chunk_mem_spaces_static) / sizeof(chunk_mem_spaces_static[0]))) { - if (NULL == (chunk_mem_spaces = H5MM_malloc(num_chunks * sizeof(H5S_t *)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, - "memory allocation failed for memory space list") - if (NULL == (chunk_file_spaces = H5MM_malloc(num_chunks * sizeof(H5S_t *)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for file space list") - if (NULL == (chunk_addrs = H5MM_malloc(num_chunks * sizeof(haddr_t)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, - "memory allocation failed for chunk address list") - } /* end if */ - else { - chunk_mem_spaces = chunk_mem_spaces_static; - chunk_file_spaces = chunk_file_spaces_static; - chunk_addrs = chunk_addrs_static; - } /* end else */ + size_t element_sizes[2] = {dset_info->type_info.dst_type_size, 0}; + const void *bufs[2] = {dset_info->buf.cvp, NULL}; + + /* Only create selection I/O arrays if not performing multi dataset I/O, + * otherwise the higher level will handle it */ + if (H5D_LAYOUT_CB_PERFORM_IO(io_info)) { + /* Cache number of chunks */ + num_chunks = H5D_CHUNK_GET_NODE_COUNT(dset_info); + + /* Allocate arrays of dataspaces and offsets for use with selection I/O, + * or point to local buffers */ + HDassert(sizeof(chunk_mem_spaces_local) / sizeof(chunk_mem_spaces_local[0]) == + sizeof(chunk_file_spaces_local) / sizeof(chunk_file_spaces_local[0])); + HDassert(sizeof(chunk_mem_spaces_local) / sizeof(chunk_mem_spaces_local[0]) == + sizeof(chunk_addrs_local) / sizeof(chunk_addrs_local[0])); + if (num_chunks > (sizeof(chunk_mem_spaces_local) / sizeof(chunk_mem_spaces_local[0]))) { + if (NULL == (chunk_mem_spaces = H5MM_malloc(num_chunks * sizeof(H5S_t *)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory allocation failed for memory space list") + if (NULL == (chunk_file_spaces = H5MM_malloc(num_chunks * sizeof(H5S_t *)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory allocation failed for file space list") + if (NULL == (chunk_addrs = H5MM_malloc(num_chunks * sizeof(haddr_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "memory allocation failed for chunk address list") + } /* end if */ + else { + chunk_mem_spaces = chunk_mem_spaces_local; + chunk_file_spaces = chunk_file_spaces_local; + chunk_addrs = chunk_addrs_local; + } /* end else */ - /* Reset num_chunks */ - num_chunks = 0; + /* Reset num_chunks */ + num_chunks = 0; + } /* end if */ /* Iterate through nodes in chunk skip list */ - chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm); + chunk_node = H5D_CHUNK_GET_FIRST_NODE(dset_info); while (chunk_node) { - H5D_chunk_info_t *chunk_info; /* Chunk information */ + H5D_piece_info_t *chunk_info; /* Chunk information */ H5D_chk_idx_info_t idx_info; /* Chunked index info */ H5D_chunk_ud_t udata; /* Index pass-through */ htri_t cacheable; /* Whether the chunk is cacheable */ hbool_t need_insert = FALSE; /* Whether the chunk needs to be inserted into the index */ /* Get the actual chunk information from the skip list node */ - chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node); + chunk_info = H5D_CHUNK_GET_NODE_INFO(dset_info, chunk_node); /* Get the info for the chunk in the file */ - if (H5D__chunk_lookup(io_info->dset, chunk_info->scaled, &udata) < 0) + if (H5D__chunk_lookup(dset_info->dset, chunk_info->scaled, &udata) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address") /* There should be no chunks cached */ @@ -2919,10 +3045,10 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize (!H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length == 0)); /* Set chunk's [scaled] coordinates */ - io_info->store->chunk.scaled = chunk_info->scaled; + dset_info->store->chunk.scaled = chunk_info->scaled; /* Determine if we should use the chunk cache */ - if ((cacheable = H5D__chunk_cacheable(io_info, udata.chunk_block.offset, TRUE)) < 0) + if ((cacheable = H5D__chunk_cacheable(io_info, dset_info, udata.chunk_block.offset, TRUE)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't tell if chunk is cacheable") if (cacheable) { /* Load the chunk into cache. But if the whole chunk is written, @@ -2931,42 +3057,47 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize hbool_t entire_chunk = TRUE; /* Whether whole chunk is selected */ /* Compute # of bytes accessed in chunk */ - H5_CHECK_OVERFLOW(type_info->dst_type_size, /*From:*/ size_t, /*To:*/ uint32_t); - dst_accessed_bytes = chunk_info->chunk_points * (uint32_t)type_info->dst_type_size; + H5_CHECK_OVERFLOW(dset_info->type_info.dst_type_size, /*From:*/ size_t, /*To:*/ uint32_t); + H5_CHECK_OVERFLOW(chunk_info->piece_points, /*From:*/ size_t, /*To:*/ uint32_t); + dst_accessed_bytes = + (uint32_t)chunk_info->piece_points * (uint32_t)dset_info->type_info.dst_type_size; /* Determine if we will access all the data in the chunk */ 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) + (chunk_info->piece_points * dset_info->type_info.src_type_size) != + ctg_store.contig.dset_size || + dset_info->layout_io_info.chunk_map->fsel_type == H5S_SEL_POINTS) entire_chunk = FALSE; /* Lock the chunk into the cache */ - if (NULL == (chunk = H5D__chunk_lock(io_info, &udata, entire_chunk, FALSE))) + if (NULL == (chunk = H5D__chunk_lock(io_info, dset_info, &udata, entire_chunk, FALSE))) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk") /* Set up the storage buffer information for this chunk */ cpt_store.compact.buf = chunk; /* Perform the actual write operation */ - if ((io_info->io_ops.single_write)(&cpt_io_info, type_info, (hsize_t)chunk_info->chunk_points, - chunk_info->fspace, chunk_info->mspace) < 0) + cpt_dset_info.file_space = chunk_info->fspace; + cpt_dset_info.mem_space = chunk_info->mspace; + cpt_dset_info.nelmts = chunk_info->piece_points; + if ((dset_info->io_ops.single_write)(&cpt_io_info, &cpt_dset_info) < 0) HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunked write failed") /* Release the cache lock on the chunk */ - if (H5D__chunk_unlock(io_info, &udata, TRUE, chunk, dst_accessed_bytes) < 0) + if (H5D__chunk_unlock(io_info, dset_info, &udata, TRUE, chunk, dst_accessed_bytes) < 0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk") } /* end if */ else { /* If the chunk hasn't been allocated on disk, do so now. */ if (!H5F_addr_defined(udata.chunk_block.offset)) { /* Compose chunked index info struct */ - 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); + idx_info.f = dset_info->dset->oloc.file; + idx_info.pline = &(dset_info->dset->shared->dcpl_cache.pline); + idx_info.layout = &(dset_info->dset->shared->layout.u.chunk); + idx_info.storage = &(dset_info->dset->shared->layout.storage.u.chunk); /* Set up the size of chunk for user data */ - udata.chunk_block.length = io_info->dset->shared->layout.u.chunk.size; + udata.chunk_block.length = dset_info->dset->shared->layout.u.chunk.size; /* Allocate the chunk */ if (H5D__chunk_file_alloc(&idx_info, NULL, &udata.chunk_block, &need_insert, @@ -2979,53 +3110,72 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "chunk address isn't defined") /* Cache the new chunk information */ - H5D__chunk_cinfo_cache_update(&io_info->dset->shared->cache.chunk.last, &udata); + H5D__chunk_cinfo_cache_update(&dset_info->dset->shared->cache.chunk.last, &udata); /* Insert chunk into index */ - 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) + if (need_insert && dset_info->dset->shared->layout.storage.u.chunk.ops->insert) + if ((dset_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") } /* end if */ - /* Add chunk to list for selection I/O */ - chunk_mem_spaces[num_chunks] = chunk_info->mspace; - chunk_file_spaces[num_chunks] = chunk_info->fspace; - chunk_addrs[num_chunks] = udata.chunk_block.offset; - num_chunks++; + /* Add chunk to list for selection I/O, if not performing multi dataset I/O */ + if (H5D_LAYOUT_CB_PERFORM_IO(io_info)) { + chunk_mem_spaces[num_chunks] = chunk_info->mspace; + chunk_file_spaces[num_chunks] = chunk_info->fspace; + chunk_addrs[num_chunks] = udata.chunk_block.offset; + num_chunks++; + } /* end if */ + else { + /* Add to mdset selection I/O arrays */ + HDassert(io_info->mem_spaces); + HDassert(io_info->file_spaces); + HDassert(io_info->addrs); + HDassert(io_info->element_sizes); + HDassert(io_info->wbufs); + HDassert(io_info->pieces_added < io_info->piece_count); + + io_info->mem_spaces[io_info->pieces_added] = chunk_info->mspace; + io_info->file_spaces[io_info->pieces_added] = chunk_info->fspace; + io_info->addrs[io_info->pieces_added] = udata.chunk_block.offset; + io_info->element_sizes[io_info->pieces_added] = element_sizes[0]; + io_info->wbufs[io_info->pieces_added] = bufs[0]; + io_info->pieces_added++; + } } /* end else */ /* Advance to next chunk in list */ - chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node); + chunk_node = H5D_CHUNK_GET_NEXT_NODE(dset_info, chunk_node); } /* end while */ - /* Issue selection I/O call (we can skip the page buffer because we've - * already verified it won't be used, and the metadata accumulator - * because this is raw data) */ - if (H5F_shared_select_write(H5F_SHARED(io_info->dset->oloc.file), H5FD_MEM_DRAW, (uint32_t)num_chunks, - chunk_mem_spaces, chunk_file_spaces, chunk_addrs, element_sizes, - bufs) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunk selection read failed") - - /* Clean up memory */ - if (chunk_mem_spaces != chunk_mem_spaces_static) { - HDassert(chunk_mem_spaces); - HDassert(chunk_file_spaces != chunk_file_spaces_static); - HDassert(chunk_addrs != chunk_addrs_static); - H5MM_free(chunk_mem_spaces); - chunk_mem_spaces = NULL; - H5MM_free(chunk_file_spaces); - chunk_file_spaces = NULL; - H5MM_free(chunk_addrs); - chunk_addrs = NULL; - } /* end if */ - } /* end if */ + /* Only perform I/O if not performing multi dataset I/O, otherwise the + * higher level will handle it after all datasets have been processed */ + if (H5D_LAYOUT_CB_PERFORM_IO(io_info)) { + /* Issue selection I/O call (we can skip the page buffer because we've + * already verified it won't be used, and the metadata accumulator + * because this is raw data) */ + H5_CHECK_OVERFLOW(num_chunks, size_t, uint32_t) + if (H5F_shared_select_write(H5F_SHARED(dset_info->dset->oloc.file), H5FD_MEM_DRAW, + (uint32_t)num_chunks, chunk_mem_spaces, chunk_file_spaces, + chunk_addrs, element_sizes, bufs) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "chunk selection write failed") + + /* Clean up memory */ + if (chunk_mem_spaces != chunk_mem_spaces_local) { + HDassert(chunk_file_spaces != chunk_file_spaces_local); + HDassert(chunk_addrs != chunk_addrs_local); + chunk_mem_spaces = H5MM_xfree(chunk_mem_spaces); + chunk_file_spaces = H5MM_xfree(chunk_file_spaces); + chunk_addrs = H5MM_xfree(chunk_addrs); + } /* end if */ + } /* end if */ + } /* end if */ else { /* Iterate through nodes in chunk skip list */ - chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm); + chunk_node = H5D_CHUNK_GET_FIRST_NODE(dset_info); while (chunk_node) { - H5D_chunk_info_t *chunk_info; /* Chunk information */ + H5D_piece_info_t *chunk_info; /* Chunk information */ H5D_chk_idx_info_t idx_info; /* Chunked index info */ H5D_io_info_t *chk_io_info; /* Pointer to I/O info object for this chunk */ void *chunk; /* Pointer to locked chunk buffer */ @@ -3034,10 +3184,10 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize hbool_t need_insert = FALSE; /* Whether the chunk needs to be inserted into the index */ /* Get the actual chunk information from the skip list node */ - chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node); + chunk_info = H5D_CHUNK_GET_NODE_INFO(dset_info, chunk_node); /* Look up the chunk */ - if (H5D__chunk_lookup(io_info->dset, chunk_info->scaled, &udata) < 0) + if (H5D__chunk_lookup(dset_info->dset, chunk_info->scaled, &udata) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address") /* Sanity check */ @@ -3045,10 +3195,10 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize (!H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length == 0)); /* Set chunk's [scaled] coordinates */ - io_info->store->chunk.scaled = chunk_info->scaled; + dset_info->store->chunk.scaled = chunk_info->scaled; /* Determine if we should use the chunk cache */ - if ((cacheable = H5D__chunk_cacheable(io_info, udata.chunk_block.offset, TRUE)) < 0) + if ((cacheable = H5D__chunk_cacheable(io_info, dset_info, udata.chunk_block.offset, TRUE)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't tell if chunk is cacheable") if (cacheable) { /* Load the chunk into cache. But if the whole chunk is written, @@ -3056,17 +3206,20 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize hbool_t entire_chunk = TRUE; /* Whether whole chunk is selected */ /* Compute # of bytes accessed in chunk */ - H5_CHECK_OVERFLOW(type_info->dst_type_size, /*From:*/ size_t, /*To:*/ uint32_t); - dst_accessed_bytes = chunk_info->chunk_points * (uint32_t)type_info->dst_type_size; + H5_CHECK_OVERFLOW(dset_info->type_info.dst_type_size, /*From:*/ size_t, /*To:*/ uint32_t); + H5_CHECK_OVERFLOW(chunk_info->piece_points, /*From:*/ size_t, /*To:*/ uint32_t); + dst_accessed_bytes = + (uint32_t)chunk_info->piece_points * (uint32_t)dset_info->type_info.dst_type_size; /* Determine if we will access all the data in the chunk */ 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) + (chunk_info->piece_points * dset_info->type_info.src_type_size) != + ctg_store.contig.dset_size || + dset_info->layout_io_info.chunk_map->fsel_type == H5S_SEL_POINTS) entire_chunk = FALSE; /* Lock the chunk into the cache */ - if (NULL == (chunk = H5D__chunk_lock(io_info, &udata, entire_chunk, FALSE))) + if (NULL == (chunk = H5D__chunk_lock(io_info, dset_info, &udata, entire_chunk, FALSE))) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk") /* Set up the storage buffer information for this chunk */ @@ -3079,13 +3232,13 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize /* If the chunk hasn't been allocated on disk, do so now. */ if (!H5F_addr_defined(udata.chunk_block.offset)) { /* Compose chunked index info struct */ - 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); + idx_info.f = dset_info->dset->oloc.file; + idx_info.pline = &(dset_info->dset->shared->dcpl_cache.pline); + idx_info.layout = &(dset_info->dset->shared->layout.u.chunk); + idx_info.storage = &(dset_info->dset->shared->layout.storage.u.chunk); /* Set up the size of chunk for user data */ - udata.chunk_block.length = io_info->dset->shared->layout.u.chunk.size; + udata.chunk_block.length = dset_info->dset->shared->layout.u.chunk.size; /* Allocate the chunk */ if (H5D__chunk_file_alloc(&idx_info, NULL, &udata.chunk_block, &need_insert, @@ -3098,7 +3251,7 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "chunk address isn't defined") /* Cache the new chunk information */ - H5D__chunk_cinfo_cache_update(&io_info->dset->shared->cache.chunk.last, &udata); + H5D__chunk_cinfo_cache_update(&dset_info->dset->shared->cache.chunk.last, &udata); } /* end if */ /* Set up the storage address information for this chunk */ @@ -3112,43 +3265,46 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize } /* end else */ /* Perform the actual write operation */ - 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) + HDassert(chk_io_info->count == 1); + chk_io_info->dsets_info[0].file_space = chunk_info->fspace; + chk_io_info->dsets_info[0].mem_space = chunk_info->mspace; + chk_io_info->dsets_info[0].nelmts = chunk_info->piece_points; + if ((dset_info->io_ops.single_write)(chk_io_info, &chk_io_info->dsets_info[0]) < 0) HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunked write failed") /* Release the cache lock on the chunk, or insert chunk into index. */ if (chunk) { - if (H5D__chunk_unlock(io_info, &udata, TRUE, chunk, dst_accessed_bytes) < 0) + if (H5D__chunk_unlock(io_info, dset_info, &udata, TRUE, chunk, dst_accessed_bytes) < 0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk") } /* end if */ 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) + if (need_insert && dset_info->dset->shared->layout.storage.u.chunk.ops->insert) + if ((dset_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") } /* end else */ /* Advance to next chunk in list */ - chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node); + chunk_node = H5D_CHUNK_GET_NEXT_NODE(dset_info, chunk_node); } /* end while */ } /* end else */ done: /* Cleanup on failure */ if (ret_value < 0) { - if (chunk_mem_spaces != chunk_mem_spaces_static) + if (chunk_mem_spaces != chunk_mem_spaces_local) chunk_mem_spaces = H5MM_xfree(chunk_mem_spaces); - if (chunk_file_spaces != chunk_file_spaces_static) + if (chunk_file_spaces != chunk_file_spaces_local) chunk_file_spaces = H5MM_xfree(chunk_file_spaces); - if (chunk_addrs != chunk_addrs_static) + if (chunk_addrs != chunk_addrs_local) chunk_addrs = H5MM_xfree(chunk_addrs); } /* end if */ /* Make sure we cleaned up */ - HDassert(!chunk_mem_spaces || chunk_mem_spaces == chunk_mem_spaces_static); - HDassert(!chunk_file_spaces || chunk_file_spaces == chunk_file_spaces_static); - HDassert(!chunk_addrs || chunk_addrs == chunk_addrs_static); + HDassert(!chunk_mem_spaces || chunk_mem_spaces == chunk_mem_spaces_local); + HDassert(!chunk_file_spaces || chunk_file_spaces == chunk_file_spaces_local); + HDassert(!chunk_addrs || chunk_addrs == chunk_addrs_local); FUNC_LEAVE_NOAPI(ret_value) } /* H5D__chunk_write() */ @@ -3199,44 +3355,56 @@ done: * * Return: Non-negative on success/Negative on failure * - * Programmer: Quincey Koziol - * Saturday, May 17, 2003 + * Programmer: Jonathan Kim Nov, 2013 * *------------------------------------------------------------------------- */ static herr_t -H5D__chunk_io_term(const H5D_chunk_map_t *fm) +H5D__chunk_io_term(H5D_io_info_t H5_ATTR_UNUSED *io_info, H5D_dset_io_info_t *di) { - herr_t ret_value = SUCCEED; /*return value */ + H5D_chunk_map_t *fm; /* Convenience pointer to chunk map */ + herr_t ret_value = SUCCEED; /*return value */ FUNC_ENTER_PACKAGE + HDassert(di); + + /* Set convenience pointer */ + fm = di->layout_io_info.chunk_map; + /* Single element I/O vs. multiple element I/O cleanup */ if (fm->use_single) { /* Sanity checks */ - HDassert(fm->sel_chunks == NULL); - HDassert(fm->single_chunk_info); - HDassert(fm->single_chunk_info->fspace_shared); - HDassert(fm->single_chunk_info->mspace_shared); + HDassert(fm->dset_sel_pieces == NULL); + HDassert(fm->last_piece_info == NULL); + HDassert(fm->single_piece_info); + HDassert(fm->single_piece_info->fspace_shared); + HDassert(fm->single_piece_info->mspace_shared); /* Reset the selection for the single element I/O */ H5S_select_all(fm->single_space, TRUE); } /* end if */ else { - /* Release the nodes on the list of selected chunks */ - 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") - } /* end else */ + /* Release the nodes on the list of selected pieces, or the last (only) + * piece if the skiplist is not available */ + if (fm->dset_sel_pieces) { + if (H5SL_free(fm->dset_sel_pieces, H5D__free_piece_info, NULL) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTNEXT, FAIL, "can't free dataset skip list") + } /* end if */ + else if (fm->last_piece_info) { + if (H5D__free_piece_info(fm->last_piece_info, NULL, NULL) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "can't free piece info") + fm->last_piece_info = NULL; + } /* end if */ + } /* end else */ - /* Free the memory chunk dataspace template */ + /* Free the memory piece dataspace template */ 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 /* H5_HAVE_PARALLEL */ + + /* Free chunk map */ + di->layout_io_info.chunk_map = H5FL_FREE(H5D_chunk_map_t, di->layout_io_info.chunk_map); done: FUNC_LEAVE_NOAPI(ret_value) @@ -4099,20 +4267,19 @@ done: *------------------------------------------------------------------------- */ 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) +H5D__chunk_lock(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info, H5D_chunk_ud_t *udata, + hbool_t relax, hbool_t prev_unfilt_chunk) { - const H5D_t *dset = io_info->dset; /* Local pointer to the dataset info */ - H5O_pline_t *pline = - &(dset->shared->dcpl_cache - .pline); /* I/O pipeline info - always equal to the pline passed to H5D__chunk_mem_alloc */ - H5O_pline_t *old_pline = pline; /* Old pipeline, i.e. pipeline used to read the chunk */ - const H5O_layout_t *layout = &(dset->shared->layout); /* Dataset layout */ - const H5O_fill_t *fill = &(dset->shared->dcpl_cache.fill); /* Fill value info */ - H5D_fill_buf_info_t fb_info; /* Dataset's fill buffer info */ - hbool_t fb_info_init = FALSE; /* Whether the fill value buffer has been initialized */ - H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /*raw data chunk cache*/ - H5D_rdcc_ent_t *ent; /*cache entry */ - size_t chunk_size; /*size of a chunk */ + const H5D_t *dset; /* Convenience pointer to the dataset */ + H5O_pline_t *pline; /* I/O pipeline info - always equal to the pline passed to H5D__chunk_mem_alloc */ + H5O_pline_t *old_pline; /* Old pipeline, i.e. pipeline used to read the chunk */ + const H5O_layout_t *layout; /* Dataset layout */ + const H5O_fill_t *fill; /* Fill value info */ + H5D_fill_buf_info_t fb_info; /* Dataset's fill buffer info */ + hbool_t fb_info_init = FALSE; /* Whether the fill value buffer has been initialized */ + H5D_rdcc_t *rdcc; /*raw data chunk cache*/ + H5D_rdcc_ent_t *ent; /*cache entry */ + size_t chunk_size; /*size of a chunk */ hbool_t disable_filters = FALSE; /* Whether to disable filters (when adding to cache) */ void *chunk = NULL; /*the file chunk */ void *ret_value = NULL; /* Return value */ @@ -4121,10 +4288,20 @@ H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata, hbool_t rel /* Sanity checks */ HDassert(io_info); - HDassert(io_info->store); - HDassert(udata); + HDassert(dset_info); + HDassert(dset_info->store); + dset = dset_info->dset; HDassert(dset); + HDassert(udata); HDassert(!(udata->new_unfilt_chunk && prev_unfilt_chunk)); + + /* Set convenience pointers */ + pline = &(dset->shared->dcpl_cache.pline); + old_pline = pline; + layout = &(dset->shared->layout); + fill = &(dset->shared->dcpl_cache.fill); + rdcc = &(dset->shared->cache.chunk); + HDassert(!rdcc->tmp_head); /* Get the chunk's size */ @@ -4146,7 +4323,7 @@ H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata, hbool_t rel /* Make sure this is the right chunk */ for (u = 0; u < layout->u.chunk.ndims - 1; u++) - HDassert(io_info->store->chunk.scaled[u] == ent->scaled[u]); + HDassert(dset_info->store->chunk.scaled[u] == ent->scaled[u]); } #endif /* NDEBUG */ @@ -4261,9 +4438,9 @@ H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata, hbool_t rel } /* end if */ else if (layout->u.chunk.flags & H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS) { /* Check if this is an edge chunk */ - 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)) { + if (H5D__chunk_is_partial_edge_chunk(dset->shared->ndims, layout->u.chunk.dim, + dset_info->store->chunk.scaled, + dset->shared->curr_dims)) { /* Disable the filters for both writing and reading */ disable_filters = TRUE; old_pline = NULL; @@ -4388,17 +4565,17 @@ H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata, hbool_t rel /* See if the chunk can be cached */ if (rdcc->nslots > 0 && chunk_size <= rdcc->nbytes_max) { /* Calculate the index */ - udata->idx_hint = H5D__chunk_hash_val(io_info->dset->shared, udata->common.scaled); + udata->idx_hint = H5D__chunk_hash_val(dset->shared, udata->common.scaled); /* Add the chunk to the cache only if the slot is not already locked */ ent = rdcc->slot[udata->idx_hint]; if (!ent || !ent->locked) { /* Preempt enough things from the cache to make room */ if (ent) { - if (H5D__chunk_cache_evict(io_info->dset, ent, TRUE) < 0) + if (H5D__chunk_cache_evict(dset, ent, TRUE) < 0) HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "unable to preempt chunk from cache") } /* end if */ - if (H5D__chunk_cache_prune(io_info->dset, chunk_size) < 0) + if (H5D__chunk_cache_prune(dset, chunk_size) < 0) HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "unable to preempt chunk(s) from cache") /* Create a new entry */ @@ -4498,19 +4675,26 @@ done: *------------------------------------------------------------------------- */ 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) +H5D__chunk_unlock(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_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); /* Dataset layout */ - const H5D_rdcc_t *rdcc = &(io_info->dset->shared->cache.chunk); + const H5O_layout_t *layout; /* Dataset layout */ + const H5D_rdcc_t *rdcc; + const H5D_t *dset; /* Local pointer to the dataset info */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity check */ HDassert(io_info); + HDassert(dset_info); HDassert(udata); + /* Set convenience pointers */ + layout = &(dset_info->dset->shared->layout); + rdcc = &(dset_info->dset->shared->cache.chunk); + dset = dset_info->dset; + if (UINT_MAX == udata->idx_hint) { /* * It's not in the cache, probably because it's too big. If it's @@ -4526,9 +4710,9 @@ H5D__chunk_unlock(const H5D_io_info_t *io_info, const H5D_chunk_ud_t *udata, hbo } /* end if */ else if (layout->u.chunk.flags & H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS) { /* Check if the chunk is an edge chunk, and disable filters if so */ - 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); + is_unfiltered_edge_chunk = + H5D__chunk_is_partial_edge_chunk(dset->shared->ndims, layout->u.chunk.dim, + dset_info->store->chunk.scaled, dset->shared->curr_dims); } /* end if */ if (dirty) { @@ -4547,13 +4731,13 @@ H5D__chunk_unlock(const H5D_io_info_t *io_info, const H5D_chunk_ud_t *udata, hbo 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) + if (H5D__chunk_flush_entry(dset, &fake_ent, TRUE) < 0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush indexed storage buffer") } /* end if */ else { if (chunk) chunk = H5D__chunk_mem_xfree( - chunk, (is_unfiltered_edge_chunk ? NULL : &(io_info->dset->shared->dcpl_cache.pline))); + chunk, (is_unfiltered_edge_chunk ? NULL : &(dset->shared->dcpl_cache.pline))); } /* end else */ } /* end if */ else { @@ -4676,9 +4860,8 @@ done: *------------------------------------------------------------------------- */ herr_t -H5D__chunk_allocate(const H5D_io_info_t *io_info, hbool_t full_overwrite, const hsize_t old_dim[]) +H5D__chunk_allocate(const H5D_t *dset, hbool_t full_overwrite, const hsize_t old_dim[]) { - const H5D_t *dset = io_info->dset; /* the dataset pointer */ H5D_chk_idx_info_t idx_info; /* Chunked index info */ const H5D_chunk_ops_t *ops = dset->shared->layout.storage.u.chunk.ops; /* Chunk operations */ hsize_t min_unalloc[H5O_LAYOUT_NDIMS]; /* First chunk in each dimension that is unallocated (in scaled @@ -5170,6 +5353,7 @@ H5D__chunk_update_old_edge_chunks(H5D_t *dset, hsize_t old_dim[]) H5D_io_info_t chk_io_info; /* Chunked I/O info object */ H5D_chunk_ud_t chk_udata; /* User data for locking chunk */ H5D_storage_t chk_store; /* Chunk storage information */ + H5D_dset_io_info_t chk_dset_info; /* Chunked I/O dset info object */ void *chunk; /* The file chunk */ hbool_t carry; /* Flag to indicate that chunk increment carrys to higher dimension (sorta) */ herr_t ret_value = SUCCEED; /* Return value */ @@ -5203,7 +5387,13 @@ H5D__chunk_update_old_edge_chunks(H5D_t *dset, hsize_t old_dim[]) * Note that we only need to set chunk_offset once, as the array's address * will never change. */ chk_store.chunk.scaled = chunk_sc; - H5D_BUILD_IO_INFO_RD(&chk_io_info, dset, &chk_store, NULL); + + chk_io_info.op_type = H5D_IO_OP_READ; + + chk_dset_info.dset = dset; + chk_dset_info.store = &chk_store; + chk_dset_info.buf.vp = NULL; + chk_io_info.dsets_info = &chk_dset_info; /* * Determine the edges of the dataset which need to be modified @@ -5268,11 +5458,12 @@ H5D__chunk_update_old_edge_chunks(H5D_t *dset, hsize_t old_dim[]) if (H5F_addr_defined(chk_udata.chunk_block.offset) || (UINT_MAX != chk_udata.idx_hint)) { /* Lock the chunk into cache. H5D__chunk_lock will take care of * updating the chunk to no longer be an edge chunk. */ - if (NULL == (chunk = (void *)H5D__chunk_lock(&chk_io_info, &chk_udata, FALSE, TRUE))) + if (NULL == + (chunk = (void *)H5D__chunk_lock(&chk_io_info, &chk_dset_info, &chk_udata, FALSE, TRUE))) HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "unable to lock raw data chunk") /* Unlock the chunk */ - if (H5D__chunk_unlock(&chk_io_info, &chk_udata, TRUE, chunk, (uint32_t)0) < 0) + if (H5D__chunk_unlock(&chk_io_info, &chk_dset_info, &chk_udata, TRUE, chunk, (uint32_t)0) < 0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to unlock raw data chunk") } /* end if */ @@ -5603,7 +5794,7 @@ 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; /* Local pointer to I/O info */ - const H5D_t *dset = io_info->dset; /* Local pointer to the dataset info */ + const H5D_t *dset = udata->dset_info->dset; /* Local pointer to the dataset info */ const H5O_layout_t *layout = &(dset->shared->layout); /* Dataset's layout */ unsigned rank = udata->common.layout->ndims - 1; /* Dataset rank */ const hsize_t *scaled = udata->common.scaled; /* Scaled chunk offset */ @@ -5658,7 +5849,7 @@ H5D__chunk_prune_fill(H5D_chunk_it_ud1_t *udata, hbool_t new_unfilt_chunk) HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, FAIL, "unable to select hyperslab") /* Lock the chunk into the cache, to get a pointer to the chunk buffer */ - if (NULL == (chunk = (void *)H5D__chunk_lock(io_info, &chk_udata, FALSE, FALSE))) + if (NULL == (chunk = (void *)H5D__chunk_lock(io_info, udata->dset_info, &chk_udata, FALSE, FALSE))) HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "unable to lock raw data chunk") /* Fill the selection in the memory buffer */ @@ -5695,7 +5886,7 @@ H5D__chunk_prune_fill(H5D_chunk_it_ud1_t *udata, hbool_t new_unfilt_chunk) bytes_accessed = (uint32_t)sel_nelmts * layout->u.chunk.dim[rank]; /* Release lock on chunk */ - if (H5D__chunk_unlock(io_info, &chk_udata, TRUE, chunk, bytes_accessed) < 0) + if (H5D__chunk_unlock(io_info, udata->dset_info, &chk_udata, TRUE, chunk, bytes_accessed) < 0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to unlock raw data chunk") done: @@ -5822,6 +6013,7 @@ H5D__chunk_prune_by_extent(H5D_t *dset, const hsize_t *old_dim) unfiltered */ H5D_chk_idx_info_t idx_info; /* Chunked index info */ H5D_io_info_t chk_io_info; /* Chunked I/O info object */ + H5D_dset_io_info_t chk_dset_info; /* Chunked I/O dset info object */ H5D_storage_t chk_store; /* Chunk storage information */ const H5O_layout_t *layout = &(dset->shared->layout); /* Dataset's layout */ const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /*raw data chunk cache */ @@ -5889,7 +6081,14 @@ H5D__chunk_prune_by_extent(H5D_t *dset, const hsize_t *old_dim) * Note that we only need to set scaled once, as the array's address * will never change. */ chk_store.chunk.scaled = scaled; - H5D_BUILD_IO_INFO_RD(&chk_io_info, dset, &chk_store, NULL); + + chk_io_info.op_type = H5D_IO_OP_READ; + + chk_dset_info.dset = dset; + chk_dset_info.store = &chk_store; + chk_dset_info.buf.vp = NULL; + chk_io_info.dsets_info = &chk_dset_info; + chk_io_info.count = 1; /* Compose chunked index info struct */ idx_info.f = dset->oloc.file; @@ -5903,6 +6102,7 @@ H5D__chunk_prune_by_extent(H5D_t *dset, const hsize_t *old_dim) udata.common.storage = sc; udata.common.scaled = scaled; udata.io_info = &chk_io_info; + udata.dset_info = &chk_dset_info; udata.idx_info = &idx_info; udata.space_dim = space_dim; udata.shrunk_dim = shrunk_dim; @@ -6183,18 +6383,18 @@ H5D__chunk_addrmap_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata) *------------------------------------------------------------------------- */ herr_t -H5D__chunk_addrmap(const H5D_io_info_t *io_info, haddr_t chunk_addr[]) +H5D__chunk_addrmap(const H5D_t *dset, haddr_t chunk_addr[]) { - H5D_chk_idx_info_t idx_info; /* Chunked index info */ - const H5D_t *dset = io_info->dset; /* Local pointer to dataset info */ - H5D_chunk_it_ud2_t udata; /* User data for iteration callback */ - H5O_storage_chunk_t *sc = &(dset->shared->layout.storage.u.chunk); + H5D_chk_idx_info_t idx_info; /* Chunked index info */ + H5D_chunk_it_ud2_t udata; /* User data for iteration callback */ + H5O_storage_chunk_t *sc; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE HDassert(dset); HDassert(dset->shared); + sc = &(dset->shared->layout.storage.u.chunk); H5D_CHUNK_STORAGE_INDEX_CHK(sc); HDassert(chunk_addr); @@ -7254,9 +7454,10 @@ done: *------------------------------------------------------------------------- */ 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__nonexistent_readvv(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_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; /* User data for H5VM_opvv() operator */ ssize_t ret_value = -1; /* Return value */ @@ -7273,8 +7474,8 @@ H5D__nonexistent_readvv(const H5D_io_info_t *io_info, size_t chunk_max_nseq, siz HDassert(mem_off_arr); /* Set up user data for H5VM_opvv() */ - udata.rbuf = (unsigned char *)io_info->u.rbuf; - udata.dset = io_info->dset; + udata.rbuf = (unsigned char *)dset_info->buf.vp; + udata.dset = dset_info->dset; /* Call generic sequence operation routine */ if ((ret_value = H5VM_opvv(chunk_max_nseq, chunk_curr_seq, chunk_len_arr, chunk_off_arr, mem_max_nseq, |