Compare commits
5 Commits
develop
...
feature/se
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b6a360acd | ||
|
|
87dbb64233 | ||
|
|
896288e49c | ||
|
|
f7e9b183a1 | ||
|
|
3aa43dc6b4 |
@@ -2749,6 +2749,8 @@ H5D__chunk_read(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info)
|
||||
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];
|
||||
if (io_info->sel_pieces)
|
||||
io_info->sel_pieces[io_info->pieces_added] = chunk_info;
|
||||
io_info->pieces_added++;
|
||||
}
|
||||
} /* end if */
|
||||
@@ -3139,6 +3141,8 @@ H5D__chunk_write(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info)
|
||||
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];
|
||||
if (io_info->sel_pieces)
|
||||
io_info->sel_pieces[io_info->pieces_added] = chunk_info;
|
||||
io_info->pieces_added++;
|
||||
}
|
||||
} /* end else */
|
||||
|
||||
@@ -757,18 +757,15 @@ H5D__contig_may_use_select_io(const H5D_io_info_t *io_info, const H5D_dset_io_in
|
||||
|
||||
dataset = dset_info->dset;
|
||||
|
||||
/* Don't use selection I/O if it's globally disabled, if there is a type
|
||||
* conversion, or if it's not a contiguous dataset, or if the sieve buffer
|
||||
* exists (write) or is dirty (read) */
|
||||
if (dset_info->io_ops.single_read != H5D__select_read ||
|
||||
dset_info->layout_ops.readvv != H5D__contig_readvv ||
|
||||
/* Don't use selection I/O if it's globally disabled, if it's not a contiguous dataset, or if the sieve
|
||||
* buffer exists (write) or is dirty (read) */
|
||||
if (dset_info->layout_ops.readvv != H5D__contig_readvv ||
|
||||
(op_type == H5D_IO_OP_READ && dataset->shared->cache.contig.sieve_dirty) ||
|
||||
(op_type == H5D_IO_OP_WRITE && dataset->shared->cache.contig.sieve_buf))
|
||||
ret_value = FALSE;
|
||||
else {
|
||||
hbool_t page_buf_enabled;
|
||||
|
||||
HDassert(dset_info->io_ops.single_write == H5D__select_write);
|
||||
HDassert(dset_info->layout_ops.writevv == H5D__contig_writevv);
|
||||
|
||||
/* Check if the page buffer is enabled */
|
||||
@@ -841,6 +838,8 @@ H5D__contig_read(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
|
||||
io_info->addrs[io_info->pieces_added] = dinfo->store->contig.dset_addr;
|
||||
io_info->element_sizes[io_info->pieces_added] = dinfo->type_info.src_type_size;
|
||||
io_info->rbufs[io_info->pieces_added] = dinfo->buf.vp;
|
||||
if (io_info->sel_pieces)
|
||||
io_info->sel_pieces[io_info->pieces_added] = dinfo->layout_io_info.contig_piece_info;
|
||||
io_info->pieces_added++;
|
||||
}
|
||||
}
|
||||
@@ -911,6 +910,8 @@ H5D__contig_write(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
|
||||
io_info->addrs[io_info->pieces_added] = dinfo->store->contig.dset_addr;
|
||||
io_info->element_sizes[io_info->pieces_added] = dinfo->type_info.dst_type_size;
|
||||
io_info->wbufs[io_info->pieces_added] = dinfo->buf.cvp;
|
||||
if (io_info->sel_pieces)
|
||||
io_info->sel_pieces[io_info->pieces_added] = dinfo->layout_io_info.contig_piece_info;
|
||||
io_info->pieces_added++;
|
||||
}
|
||||
}
|
||||
|
||||
301
src/H5Dio.c
301
src/H5Dio.c
@@ -292,16 +292,16 @@ H5D__read(size_t count, H5D_dset_io_info_t *dset_info)
|
||||
if (io_op_init == 0)
|
||||
HGOTO_DONE(SUCCEED)
|
||||
|
||||
/* Perform second phase of type info initialization */
|
||||
if (H5D__typeinfo_init_phase2(&io_info) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up type info (second phase)")
|
||||
|
||||
#ifdef H5_HAVE_PARALLEL
|
||||
/* Adjust I/O info for any parallel I/O */
|
||||
if (H5D__ioinfo_adjust(&io_info) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to adjust I/O info for parallel I/O")
|
||||
#endif /*H5_HAVE_PARALLEL*/
|
||||
|
||||
/* Perform second phase of type info initialization */
|
||||
if (H5D__typeinfo_init_phase2(&io_info) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up type info (second phase)")
|
||||
|
||||
/* If multi dataset I/O callback is not provided, perform read IO via
|
||||
* single-dset path with looping */
|
||||
if (io_info.md_io_ops.multi_read_md) {
|
||||
@@ -339,6 +339,7 @@ H5D__read(size_t count, H5D_dset_io_info_t *dset_info)
|
||||
else {
|
||||
haddr_t prev_tag = HADDR_UNDEF;
|
||||
|
||||
/* Allocate selection I/O parameter arrays if necessary */
|
||||
if (!H5D_LAYOUT_CB_PERFORM_IO(&io_info) && io_info.piece_count > 0) {
|
||||
if (NULL == (io_info.mem_spaces = H5MM_malloc(io_info.piece_count * sizeof(H5S_t *))))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
|
||||
@@ -354,6 +355,11 @@ H5D__read(size_t count, H5D_dset_io_info_t *dset_info)
|
||||
if (NULL == (io_info.rbufs = H5MM_malloc(io_info.piece_count * sizeof(void *))))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
|
||||
"memory allocation failed for read buffer list")
|
||||
if (io_info.tconv_buf)
|
||||
if (NULL ==
|
||||
(io_info.sel_pieces = H5MM_malloc(io_info.piece_count * sizeof(io_info.sel_pieces[0]))))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
|
||||
"unable to allocate array of selected pieces")
|
||||
}
|
||||
|
||||
/* Loop with serial & single-dset read IO path */
|
||||
@@ -373,15 +379,24 @@ H5D__read(size_t count, H5D_dset_io_info_t *dset_info)
|
||||
H5AC_tag(prev_tag, NULL);
|
||||
}
|
||||
|
||||
/* Make final multi dataset selection I/O call if we are using both
|
||||
* features - in this case the multi_read callbacks did not perform the
|
||||
* actual I/O */
|
||||
H5_CHECK_OVERFLOW(io_info.pieces_added, size_t, uint32_t)
|
||||
if (!H5D_LAYOUT_CB_PERFORM_IO(&io_info))
|
||||
if (H5F_shared_select_read(io_info.f_sh, H5FD_MEM_DRAW, (uint32_t)io_info.pieces_added,
|
||||
io_info.mem_spaces, io_info.file_spaces, io_info.addrs,
|
||||
io_info.element_sizes, io_info.rbufs) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "selection read failed")
|
||||
/* Make final selection I/O call if the multi_read callbacks did not perform the actual I/O
|
||||
* (if using selection I/O and either multi dataset or type conversion) */
|
||||
if (!H5D_LAYOUT_CB_PERFORM_IO(&io_info)) {
|
||||
/* Check for type conversion */
|
||||
if (io_info.tconv_buf) {
|
||||
/* Type conversion pathway */
|
||||
if (H5D__scatgath_read_select(&io_info) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "type conversion selection read failed")
|
||||
}
|
||||
else {
|
||||
/* Call selection I/O directly */
|
||||
H5_CHECK_OVERFLOW(io_info.pieces_added, size_t, uint32_t)
|
||||
if (H5F_shared_select_read(io_info.f_sh, H5FD_MEM_DRAW, (uint32_t)io_info.pieces_added,
|
||||
io_info.mem_spaces, io_info.file_spaces, io_info.addrs,
|
||||
io_info.element_sizes, io_info.rbufs) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "selection read failed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
@@ -663,16 +678,16 @@ H5D__write(size_t count, H5D_dset_io_info_t *dset_info)
|
||||
HDassert(type_info_init == count);
|
||||
HDassert(io_op_init == count);
|
||||
|
||||
/* Perform second phase of type info initialization */
|
||||
if (H5D__typeinfo_init_phase2(&io_info) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up type info (second phase)")
|
||||
|
||||
#ifdef H5_HAVE_PARALLEL
|
||||
/* Adjust I/O info for any parallel I/O */
|
||||
if (H5D__ioinfo_adjust(&io_info) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to adjust I/O info for parallel I/O")
|
||||
#endif /*H5_HAVE_PARALLEL*/
|
||||
|
||||
/* Perform second phase of type info initialization */
|
||||
if (H5D__typeinfo_init_phase2(&io_info) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up type info (second phase)")
|
||||
|
||||
/* If multi dataset I/O callback is not provided, perform write IO via
|
||||
* single-dset path with looping */
|
||||
if (io_info.md_io_ops.multi_write_md) {
|
||||
@@ -710,6 +725,7 @@ H5D__write(size_t count, H5D_dset_io_info_t *dset_info)
|
||||
else {
|
||||
haddr_t prev_tag = HADDR_UNDEF;
|
||||
|
||||
/* Allocate selection I/O parameter arrays if necessary */
|
||||
if (!H5D_LAYOUT_CB_PERFORM_IO(&io_info) && io_info.piece_count > 0) {
|
||||
if (NULL == (io_info.mem_spaces = H5MM_malloc(io_info.piece_count * sizeof(H5S_t *))))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
|
||||
@@ -724,7 +740,12 @@ H5D__write(size_t count, H5D_dset_io_info_t *dset_info)
|
||||
"memory allocation failed for element size list")
|
||||
if (NULL == (io_info.wbufs = H5MM_malloc(io_info.piece_count * sizeof(const void *))))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
|
||||
"memory allocation failed for read buffer list")
|
||||
"memory allocation failed for write buffer list")
|
||||
if (io_info.tconv_buf)
|
||||
if (NULL ==
|
||||
(io_info.sel_pieces = H5MM_malloc(io_info.piece_count * sizeof(io_info.sel_pieces[0]))))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
|
||||
"unable to allocate array of selected pieces")
|
||||
}
|
||||
|
||||
/* loop with serial & single-dset write IO path */
|
||||
@@ -742,15 +763,24 @@ H5D__write(size_t count, H5D_dset_io_info_t *dset_info)
|
||||
H5AC_tag(prev_tag, NULL);
|
||||
}
|
||||
|
||||
/* Make final multi dataset selection I/O call if we are using both
|
||||
* features - in this case the multi_write callbacks did not perform the
|
||||
* actual I/O */
|
||||
H5_CHECK_OVERFLOW(io_info.pieces_added, size_t, uint32_t)
|
||||
if (!H5D_LAYOUT_CB_PERFORM_IO(&io_info))
|
||||
if (H5F_shared_select_write(io_info.f_sh, H5FD_MEM_DRAW, (uint32_t)io_info.pieces_added,
|
||||
io_info.mem_spaces, io_info.file_spaces, io_info.addrs,
|
||||
io_info.element_sizes, io_info.wbufs) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "selection write failed")
|
||||
/* Make final selection I/O call if the multi_write callbacks did not perform the actual I/O
|
||||
* (if using selection I/O and either multi dataset or type conversion) */
|
||||
if (!H5D_LAYOUT_CB_PERFORM_IO(&io_info)) {
|
||||
/* Check for type conversion */
|
||||
if (io_info.tconv_buf) {
|
||||
/* Type conversion pathway */
|
||||
if (H5D__scatgath_write_select(&io_info) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "type conversion selection write failed")
|
||||
}
|
||||
else {
|
||||
/* Call selection I/O directly */
|
||||
H5_CHECK_OVERFLOW(io_info.pieces_added, size_t, uint32_t)
|
||||
if (H5F_shared_select_write(io_info.f_sh, H5FD_MEM_DRAW, (uint32_t)io_info.pieces_added,
|
||||
io_info.mem_spaces, io_info.file_spaces, io_info.addrs,
|
||||
io_info.element_sizes, io_info.wbufs) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "selection write failed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef OLD_WAY
|
||||
@@ -998,9 +1028,9 @@ H5D__typeinfo_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info, hid_t
|
||||
/* Check if the datatypes are compound subsets of one another */
|
||||
type_info->cmpd_subset = H5T_path_compound_subset(type_info->tpath);
|
||||
|
||||
/* Update io_info->max_type_size */
|
||||
io_info->max_type_size =
|
||||
MAX3(io_info->max_type_size, type_info->src_type_size, type_info->dst_type_size);
|
||||
/* Update io_info->max_tconv_type_size */
|
||||
io_info->max_tconv_type_size =
|
||||
MAX3(io_info->max_tconv_type_size, type_info->src_type_size, type_info->dst_type_size);
|
||||
|
||||
/* Check if we need a background buffer */
|
||||
if ((io_info->op_type == H5D_IO_OP_WRITE) && H5T_detect_class(dset->shared->type, H5T_VLEN, FALSE))
|
||||
@@ -1026,7 +1056,8 @@ done:
|
||||
* Function: H5D__typeinfo_init_phase2
|
||||
*
|
||||
* Purpose: Finish initializing type info for all datasets after
|
||||
* calculating the max type size across all datasets.
|
||||
* calculating the max type size across all datasets. And
|
||||
* after H5D__ioinfo_adjust().
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
@@ -1043,88 +1074,154 @@ H5D__typeinfo_init_phase2(H5D_io_info_t *io_info)
|
||||
HDassert(io_info);
|
||||
|
||||
/* Check if we need to allocate a shared type conversion buffer */
|
||||
if (io_info->max_type_size) {
|
||||
void *tconv_buf; /* Temporary conversion buffer pointer */
|
||||
void *bkgr_buf; /* Background conversion buffer pointer */
|
||||
size_t max_temp_buf; /* Maximum temporary buffer size */
|
||||
size_t target_size; /* Desired buffer size */
|
||||
size_t i; /* Local index variable */
|
||||
if (io_info->max_tconv_type_size) {
|
||||
H5FD_mpio_xfer_t xfer_mode; /* Parallel transfer for this request */
|
||||
size_t i; /* Local index variable */
|
||||
|
||||
/* Get info from API context */
|
||||
if (H5CX_get_max_temp_buf(&max_temp_buf) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve max. temp. buf size")
|
||||
if (H5CX_get_tconv_buf(&tconv_buf) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve temp. conversion buffer pointer")
|
||||
if (H5CX_get_bkgr_buf(&bkgr_buf) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve background conversion buffer pointer")
|
||||
/* Get the original state of parallel I/O transfer mode */
|
||||
if (H5CX_get_io_xfer_mode(&xfer_mode) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get MPI-I/O transfer mode")
|
||||
|
||||
/* Set up datatype conversion/background buffers */
|
||||
target_size = max_temp_buf;
|
||||
/* Check if we're doing collective I/O */
|
||||
if (xfer_mode == H5FD_MPIO_COLLECTIVE) {
|
||||
size_t tconv_buf_size = 0; /* Size of shared type conversion buffer */
|
||||
|
||||
/* If the buffer is too small to hold even one element (in the dataset with the largest , try to make
|
||||
* it bigger */
|
||||
if (target_size < io_info->max_type_size) {
|
||||
hbool_t default_buffer_info; /* Whether the buffer information are the defaults */
|
||||
/* Only implemented for selection I/O */
|
||||
HDassert(io_info->use_select_io);
|
||||
|
||||
/* Detect if we have all default settings for buffers */
|
||||
default_buffer_info =
|
||||
(hbool_t)((H5D_TEMP_BUF_SIZE == max_temp_buf) && (NULL == tconv_buf) && (NULL == bkgr_buf));
|
||||
/* Collective I/O, conversion buffer must be large enough for entire I/O (for now).
|
||||
* Stick with individual background buffers */
|
||||
|
||||
/* Check if we are using the default buffer info */
|
||||
if (default_buffer_info)
|
||||
/* OK to get bigger for library default settings */
|
||||
target_size = io_info->max_type_size;
|
||||
else
|
||||
/* Don't get bigger than the application has requested */
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small")
|
||||
} /* end if */
|
||||
/* Calculate size of buffers */
|
||||
for (i = 0; i < io_info->count; i++) {
|
||||
H5D_type_info_t *type_info = &io_info->dsets_info[i].type_info;
|
||||
|
||||
/* Get a temporary buffer for type conversion unless the app has already
|
||||
* supplied one through the xfer properties. Instead of allocating a
|
||||
* buffer which is the exact size, we allocate the target size. This
|
||||
* buffer is shared among all datasets in the operation, unlike for the
|
||||
* background buffer, where each dataset gets its own. */
|
||||
if (NULL == (io_info->tconv_buf = (uint8_t *)tconv_buf)) {
|
||||
/* Allocate temporary buffer */
|
||||
if (NULL == (io_info->tconv_buf = H5FL_BLK_MALLOC(type_conv, target_size)))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
|
||||
io_info->tconv_buf_allocated = TRUE;
|
||||
} /* end if */
|
||||
/* Check if type conversion buffer is needed for this dataset */
|
||||
if (!type_info->is_conv_noop || !type_info->is_xform_noop) {
|
||||
/* Calculate location and size of this dataset's portion of the global type
|
||||
* conversion buffer */
|
||||
tconv_buf_size += io_info->dsets_info[i].nelmts *
|
||||
MAX(type_info->src_type_size, type_info->dst_type_size);
|
||||
|
||||
/* Don't use API provided background buffer if there's more than one dataset, since each
|
||||
* dataset needs its own */
|
||||
if (io_info->count > 1)
|
||||
bkgr_buf = NULL;
|
||||
/* Allocate background buffer, if necessary */
|
||||
if (type_info->need_bkg) {
|
||||
if (NULL ==
|
||||
(type_info->bkg_buf = H5FL_BLK_CALLOC(type_conv, io_info->dsets_info[i].nelmts *
|
||||
type_info->dst_type_size)))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
|
||||
"memory allocation failed for type conversion")
|
||||
type_info->bkg_buf_allocated = TRUE;
|
||||
|
||||
/* Iterate over datasets */
|
||||
for (i = 0; i < io_info->count; i++) {
|
||||
H5D_type_info_t *type_info = &io_info->dsets_info[i].type_info;
|
||||
/* Check if we need to fill the background buffer with the destination contents */
|
||||
if (type_info->need_bkg == H5T_BKG_YES)
|
||||
io_info->must_fill_bkg = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute the number of elements that will fit into buffer */
|
||||
type_info->request_nelmts = target_size / MAX(type_info->src_type_size, type_info->dst_type_size);
|
||||
;
|
||||
|
||||
/* Sanity check elements in temporary buffer */
|
||||
if (type_info->request_nelmts == 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small")
|
||||
|
||||
/* Allocate background buffer if necessary */
|
||||
if (type_info->need_bkg && NULL == (type_info->bkg_buf = (uint8_t *)bkgr_buf)) {
|
||||
size_t bkg_size; /* Desired background buffer size */
|
||||
|
||||
/* Compute the background buffer size */
|
||||
/* (don't try to use buffers smaller than the default size) */
|
||||
bkg_size = type_info->request_nelmts * type_info->dst_type_size;
|
||||
if (bkg_size < max_temp_buf)
|
||||
bkg_size = max_temp_buf;
|
||||
|
||||
/* Allocate background buffer */
|
||||
/* (Need calloc()-like call since memory needs to be initialized) */
|
||||
if (NULL == (type_info->bkg_buf = H5FL_BLK_CALLOC(type_conv, bkg_size)))
|
||||
/* Allocate global type conversion buffer (if any, could be none if datasets in this
|
||||
* I/O have 0 elements selected) */
|
||||
/* Allocating large buffers here will blow out all other type conversion buffers
|
||||
* on the free list. Should we change this to a regular malloc? Would require
|
||||
* keeping track of which version of free() to call. -NAF */
|
||||
if (tconv_buf_size > 0) {
|
||||
if (NULL == (io_info->tconv_buf = H5FL_BLK_MALLOC(type_conv, tconv_buf_size)))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
|
||||
"memory allocation failed for background conversion")
|
||||
type_info->bkg_buf_allocated = TRUE;
|
||||
"memory allocation failed for type conversion")
|
||||
io_info->tconv_buf_allocated = TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* No collective I/O, only need to make sure it's big enough for one element */
|
||||
void *tconv_buf; /* Temporary conversion buffer pointer */
|
||||
void *bkgr_buf; /* Background conversion buffer pointer */
|
||||
size_t max_temp_buf; /* Maximum temporary buffer size */
|
||||
size_t target_size; /* Desired buffer size */
|
||||
|
||||
/* Disable selection I/O (for now) since the selection I/O type conversion code path
|
||||
* assumes the tconv buf is large enough to hold all data in the I/O, and we don't want
|
||||
* to impose this when there's no benefit */
|
||||
io_info->use_select_io = FALSE;
|
||||
|
||||
/* Get info from API context */
|
||||
if (H5CX_get_max_temp_buf(&max_temp_buf) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve max. temp. buf size")
|
||||
if (H5CX_get_tconv_buf(&tconv_buf) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve temp. conversion buffer pointer")
|
||||
if (H5CX_get_bkgr_buf(&bkgr_buf) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL,
|
||||
"can't retrieve background conversion buffer pointer")
|
||||
|
||||
/* Set up datatype conversion/background buffers */
|
||||
target_size = max_temp_buf;
|
||||
|
||||
/* If the buffer is too small to hold even one element (in the dataset with the largest , try to
|
||||
* make it bigger */
|
||||
if (target_size < io_info->max_tconv_type_size) {
|
||||
hbool_t default_buffer_info; /* Whether the buffer information are the defaults */
|
||||
|
||||
/* Detect if we have all default settings for buffers */
|
||||
default_buffer_info = (hbool_t)((H5D_TEMP_BUF_SIZE == max_temp_buf) && (NULL == tconv_buf) &&
|
||||
(NULL == bkgr_buf));
|
||||
|
||||
/* Check if we are using the default buffer info */
|
||||
if (default_buffer_info)
|
||||
/* OK to get bigger for library default settings */
|
||||
target_size = io_info->max_tconv_type_size;
|
||||
else
|
||||
/* Don't get bigger than the application has requested */
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small")
|
||||
} /* end if */
|
||||
|
||||
/* Get a temporary buffer for type conversion unless the app has already
|
||||
* supplied one through the xfer properties. Instead of allocating a
|
||||
* buffer which is the exact size, we allocate the target size. This
|
||||
* buffer is shared among all datasets in the operation, unlike for the
|
||||
* background buffer, where each dataset gets its own. */
|
||||
if (NULL == (io_info->tconv_buf = (uint8_t *)tconv_buf)) {
|
||||
/* Allocate temporary buffer */
|
||||
if (NULL == (io_info->tconv_buf = H5FL_BLK_MALLOC(type_conv, target_size)))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
|
||||
"memory allocation failed for type conversion")
|
||||
io_info->tconv_buf_allocated = TRUE;
|
||||
} /* end if */
|
||||
|
||||
/* Don't use API provided background buffer if there's more than one dataset, since each
|
||||
* dataset needs its own */
|
||||
if (io_info->count > 1)
|
||||
bkgr_buf = NULL;
|
||||
|
||||
/* Iterate over datasets */
|
||||
for (i = 0; i < io_info->count; i++) {
|
||||
H5D_type_info_t *type_info = &io_info->dsets_info[i].type_info;
|
||||
|
||||
/* Compute the number of elements that will fit into buffer */
|
||||
type_info->request_nelmts =
|
||||
target_size / MAX(type_info->src_type_size, type_info->dst_type_size);
|
||||
;
|
||||
|
||||
/* Sanity check elements in temporary buffer */
|
||||
if (type_info->request_nelmts == 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small")
|
||||
|
||||
/* Allocate background buffer if necessary */
|
||||
if (type_info->need_bkg && NULL == (type_info->bkg_buf = (uint8_t *)bkgr_buf)) {
|
||||
size_t bkg_size; /* Desired background buffer size */
|
||||
|
||||
/* Compute the background buffer size */
|
||||
/* (don't try to use buffers smaller than the default size) */
|
||||
bkg_size = type_info->request_nelmts * type_info->dst_type_size;
|
||||
if (bkg_size < max_temp_buf)
|
||||
bkg_size = max_temp_buf;
|
||||
|
||||
/* Allocate background buffer */
|
||||
/* (Need calloc()-like call since memory needs to be initialized) */
|
||||
if (NULL == (type_info->bkg_buf = H5FL_BLK_CALLOC(type_conv, bkg_size)))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
|
||||
"memory allocation failed for background conversion")
|
||||
type_info->bkg_buf_allocated = TRUE;
|
||||
} /* end if */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -626,13 +626,16 @@ H5D__mpio_opt_possible(H5D_io_info_t *io_info)
|
||||
if (!H5FD_mpi_opt_types_g)
|
||||
local_cause[0] |= H5D_MPIO_MPI_OPT_TYPES_ENV_VAR_DISABLED;
|
||||
|
||||
/* Don't allow collective operations if datatype conversions need to happen */
|
||||
if (!type_info->is_conv_noop)
|
||||
local_cause[0] |= H5D_MPIO_DATATYPE_CONVERSION;
|
||||
/* Datatype conversions and transformations are allowed with selection I/O */
|
||||
if (!io_info->use_select_io) {
|
||||
/* Don't allow collective operations if datatype conversions need to happen */
|
||||
if (!type_info->is_conv_noop)
|
||||
local_cause[0] |= H5D_MPIO_DATATYPE_CONVERSION;
|
||||
|
||||
/* Don't allow collective operations if data transform operations should occur */
|
||||
if (!type_info->is_xform_noop)
|
||||
local_cause[0] |= H5D_MPIO_DATA_TRANSFORMS;
|
||||
/* Don't allow collective operations if data transform operations should occur */
|
||||
if (!type_info->is_xform_noop)
|
||||
local_cause[0] |= H5D_MPIO_DATA_TRANSFORMS;
|
||||
}
|
||||
|
||||
/* Check whether these are both simple or scalar dataspaces */
|
||||
if (!((H5S_SIMPLE == H5S_GET_EXTENT_TYPE(mem_space) ||
|
||||
|
||||
12
src/H5Dpkg.h
12
src/H5Dpkg.h
@@ -70,7 +70,8 @@
|
||||
#define H5D_BT2_MERGE_PERC 40
|
||||
|
||||
/* Macro to determine if the layout I/O callback should perform I/O */
|
||||
#define H5D_LAYOUT_CB_PERFORM_IO(IO_INFO) (!(IO_INFO)->use_select_io || (IO_INFO)->count == 1)
|
||||
#define H5D_LAYOUT_CB_PERFORM_IO(IO_INFO) \
|
||||
(!(IO_INFO)->use_select_io || ((IO_INFO)->count == 1 && !(IO_INFO)->tconv_buf))
|
||||
|
||||
/****************************/
|
||||
/* Package Private Typedefs */
|
||||
@@ -269,7 +270,10 @@ typedef struct H5D_io_info_t {
|
||||
hbool_t use_select_io; /* Whether to use selection I/O */
|
||||
uint8_t *tconv_buf; /* Datatype conv buffer */
|
||||
hbool_t tconv_buf_allocated; /* Whether the type conversion buffer was allocated */
|
||||
size_t max_type_size; /* Largest of all source and destination type sizes */
|
||||
size_t max_tconv_type_size; /* Largest of all source and destination type sizes involved in type
|
||||
conversion */
|
||||
hbool_t
|
||||
must_fill_bkg; /* Whether any datasets need a background buffer filled with destination contents */
|
||||
} H5D_io_info_t;
|
||||
|
||||
/* Created to pass both at once for callback func */
|
||||
@@ -623,12 +627,14 @@ H5_DLL herr_t H5D__select_write(const H5D_io_info_t *io_info, const H5D_dset_io_
|
||||
H5_DLL herr_t H5D_select_io_mem(void *dst_buf, H5S_t *dst_space, const void *src_buf, H5S_t *src_space,
|
||||
size_t elmt_size, size_t nelmts);
|
||||
|
||||
/* Functions that perform scatter-gather serial I/O operations */
|
||||
/* Functions that perform scatter-gather I/O operations */
|
||||
H5_DLL herr_t H5D__scatter_mem(const void *_tscat_buf, H5S_sel_iter_t *iter, size_t nelmts, void *_buf);
|
||||
H5_DLL size_t H5D__gather_mem(const void *_buf, H5S_sel_iter_t *iter, size_t nelmts,
|
||||
void *_tgath_buf /*out*/);
|
||||
H5_DLL herr_t H5D__scatgath_read(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info);
|
||||
H5_DLL herr_t H5D__scatgath_write(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info);
|
||||
H5_DLL herr_t H5D__scatgath_read_select(H5D_io_info_t *io_info);
|
||||
H5_DLL herr_t H5D__scatgath_write_select(H5D_io_info_t *io_info);
|
||||
|
||||
/* Functions that operate on dataset's layout information */
|
||||
H5_DLL herr_t H5D__layout_set_io_ops(const H5D_t *dataset);
|
||||
|
||||
@@ -726,6 +726,528 @@ done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5D__scatgath_write() */
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5D__scatgath_read_select
|
||||
*
|
||||
* Purpose: Perform scatter/gather read from a list of dataset pieces
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5D__scatgath_read_select(H5D_io_info_t *io_info)
|
||||
{
|
||||
H5S_t **tmp_mem_spaces = NULL; /* Memory spaces to use for read from disk */
|
||||
H5S_sel_iter_t *mem_iter = NULL; /* Memory selection iteration info */
|
||||
hbool_t mem_iter_init = FALSE; /* Memory selection iteration info has been initialized */
|
||||
void **tmp_bufs = NULL; /* Buffers to use for read from disk */
|
||||
size_t buf_bytes_used = 0; /* Number of bytes used so far in conversion/background buffer */
|
||||
H5D_dset_io_info_t *last_bkg_buf_dset = NULL; /* Index of last dset that used a background buffer */
|
||||
size_t i; /* Local index variable */
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_PACKAGE
|
||||
|
||||
/* Sanity check */
|
||||
HDassert(io_info);
|
||||
HDassert(io_info->count > 0);
|
||||
HDassert(io_info->mem_spaces || io_info->pieces_added == 0);
|
||||
HDassert(io_info->file_spaces || io_info->pieces_added == 0);
|
||||
HDassert(io_info->addrs || io_info->pieces_added == 0);
|
||||
HDassert(io_info->element_sizes || io_info->pieces_added == 0);
|
||||
HDassert(io_info->rbufs || io_info->pieces_added == 0);
|
||||
|
||||
/* Allocate list of buffers (within the tconv buf) */
|
||||
if (NULL == (tmp_bufs = H5MM_malloc(io_info->pieces_added * sizeof(void *))))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for temporary buffer list")
|
||||
|
||||
/* Allocate the iterator */
|
||||
if (NULL == (mem_iter = H5FL_MALLOC(H5S_sel_iter_t)))
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate memory iterator")
|
||||
|
||||
/* Allocate list of block memory spaces */
|
||||
/*!FIXME delay doing this until we find the first mem space that is non-contiguous or doesn't start at 0
|
||||
*/
|
||||
if (NULL == (tmp_mem_spaces = H5MM_malloc(io_info->pieces_added * sizeof(H5S_t *))))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
|
||||
"memory allocation failed for temporary memory space list")
|
||||
|
||||
/* Build read operation to tconv buffer */
|
||||
for (i = 0; i < io_info->pieces_added; i++) {
|
||||
H5D_dset_io_info_t *dset_info = io_info->sel_pieces[i]->dset_info;
|
||||
|
||||
HDassert(io_info->sel_pieces[i]->piece_points > 0);
|
||||
|
||||
/* Check if this piece is involved in type conversion */
|
||||
if (dset_info->type_info.is_xform_noop && dset_info->type_info.is_conv_noop) {
|
||||
/* No type conversion, just copy the mem space and buffer */
|
||||
tmp_mem_spaces[i] = io_info->mem_spaces[i];
|
||||
tmp_bufs[i] = io_info->rbufs[i];
|
||||
}
|
||||
else {
|
||||
/* Create block memory space */
|
||||
if (NULL ==
|
||||
(tmp_mem_spaces[i] = H5S_create_simple(1, &io_info->sel_pieces[i]->piece_points, NULL))) {
|
||||
HDmemset(&tmp_mem_spaces[i], 0, (io_info->pieces_added - i) * sizeof(tmp_mem_spaces[0]));
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "unable to create simple memory dataspace")
|
||||
}
|
||||
|
||||
/* Set buffer to point into type conversion buffer */
|
||||
tmp_bufs[i] = io_info->tconv_buf + buf_bytes_used;
|
||||
buf_bytes_used += io_info->sel_pieces[i]->piece_points *
|
||||
MAX(dset_info->type_info.src_type_size, dset_info->type_info.dst_type_size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read data from all pieces */
|
||||
H5_CHECK_OVERFLOW(io_info->pieces_added, size_t, uint32_t)
|
||||
if (H5F_shared_select_read(io_info->f_sh, H5FD_MEM_DRAW, (uint32_t)io_info->pieces_added, tmp_mem_spaces,
|
||||
io_info->file_spaces, io_info->addrs, io_info->element_sizes, tmp_bufs) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "selection read failed")
|
||||
|
||||
/* Perform type conversion and scatter data to memory buffers for datasets that need this */
|
||||
for (i = 0; i < io_info->pieces_added; i++) {
|
||||
H5D_dset_io_info_t *dset_info = io_info->sel_pieces[i]->dset_info;
|
||||
|
||||
HDassert(tmp_mem_spaces[i]);
|
||||
|
||||
/* Check if this piece is involved in type conversion */
|
||||
if (tmp_mem_spaces[i] != io_info->mem_spaces[i]) {
|
||||
H5_CHECK_OVERFLOW(io_info->sel_pieces[i]->piece_points, hsize_t, size_t);
|
||||
|
||||
/* Initialize memory iterator */
|
||||
HDassert(!mem_iter_init);
|
||||
if (H5S_select_iter_init(mem_iter, io_info->mem_spaces[i], dset_info->type_info.dst_type_size,
|
||||
0) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL,
|
||||
"unable to initialize memory selection information")
|
||||
mem_iter_init = TRUE; /* Memory selection iteration info has been initialized */
|
||||
|
||||
/* If the source and destination are compound types and subset of each other
|
||||
* and no conversion is needed, copy the data directly into user's buffer and
|
||||
* bypass the rest of steps.
|
||||
*/
|
||||
if (dset_info->type_info.cmpd_subset &&
|
||||
H5T_SUBSET_FALSE != dset_info->type_info.cmpd_subset->subset) {
|
||||
if (H5D__compound_opt_read((size_t)io_info->sel_pieces[i]->piece_points, mem_iter,
|
||||
&dset_info->type_info, tmp_bufs[i], io_info->rbufs[i] /*out*/) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
|
||||
}
|
||||
else {
|
||||
void *tmp_bkg_buf = NULL;
|
||||
|
||||
/* Check for background buffer */
|
||||
if (dset_info->type_info.need_bkg) {
|
||||
HDassert(dset_info->type_info.bkg_buf);
|
||||
|
||||
/* Check if we moved to a new background buffer */
|
||||
if (dset_info != last_bkg_buf_dset) {
|
||||
/* Reset buf_bytes_used */
|
||||
buf_bytes_used = 0;
|
||||
last_bkg_buf_dset = dset_info;
|
||||
}
|
||||
|
||||
/* Calculate background buffer position */
|
||||
tmp_bkg_buf = dset_info->type_info.bkg_buf + buf_bytes_used;
|
||||
buf_bytes_used +=
|
||||
io_info->sel_pieces[i]->piece_points * dset_info->type_info.dst_type_size;
|
||||
|
||||
/* Gather data from read buffer to background buffer if necessary */
|
||||
if (H5T_BKG_YES == dset_info->type_info.need_bkg) {
|
||||
if ((size_t)io_info->sel_pieces[i]->piece_points !=
|
||||
H5D__gather_mem(io_info->rbufs[i], mem_iter,
|
||||
(size_t)io_info->sel_pieces[i]->piece_points,
|
||||
tmp_bkg_buf /*out*/))
|
||||
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "mem gather failed")
|
||||
|
||||
/* Reset selection iterator */
|
||||
HDassert(mem_iter_init);
|
||||
if (H5S_SELECT_ITER_RELEASE(mem_iter) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
|
||||
mem_iter_init = FALSE;
|
||||
|
||||
if (H5S_select_iter_init(mem_iter, io_info->mem_spaces[i],
|
||||
dset_info->type_info.dst_type_size, 0) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL,
|
||||
"unable to initialize memory selection information")
|
||||
mem_iter_init = TRUE; /* Memory selection iteration info has been initialized */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform datatype conversion.
|
||||
*/
|
||||
if (H5T_convert(dset_info->type_info.tpath, dset_info->type_info.src_type_id,
|
||||
dset_info->type_info.dst_type_id,
|
||||
(size_t)io_info->sel_pieces[i]->piece_points, (size_t)0, (size_t)0,
|
||||
tmp_bufs[i], tmp_bkg_buf) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
|
||||
|
||||
/* Do the data transform after the conversion (since we're using type mem_type) */
|
||||
if (!dset_info->type_info.is_xform_noop) {
|
||||
H5Z_data_xform_t *data_transform; /* Data transform info */
|
||||
|
||||
/* Retrieve info from API context */
|
||||
if (H5CX_get_data_transform(&data_transform) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get data transform info")
|
||||
|
||||
if (H5Z_xform_eval(data_transform, tmp_bufs[i],
|
||||
(size_t)io_info->sel_pieces[i]->piece_points,
|
||||
dset_info->type_info.mem_type) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "Error performing data transform")
|
||||
}
|
||||
|
||||
/* Scatter the data into memory */
|
||||
if (H5D__scatter_mem(tmp_bufs[i], mem_iter, (size_t)io_info->sel_pieces[i]->piece_points,
|
||||
io_info->rbufs[i] /*out*/) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "scatter failed")
|
||||
}
|
||||
|
||||
/* Release selection iterator */
|
||||
HDassert(mem_iter_init);
|
||||
if (H5S_SELECT_ITER_RELEASE(mem_iter) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
|
||||
mem_iter_init = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
/* Release and free selection iterator */
|
||||
if (mem_iter_init && H5S_SELECT_ITER_RELEASE(mem_iter) < 0)
|
||||
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
|
||||
if (mem_iter)
|
||||
mem_iter = H5FL_FREE(H5S_sel_iter_t, mem_iter);
|
||||
|
||||
/* Free tmp_bufs */
|
||||
H5MM_free(tmp_bufs);
|
||||
tmp_bufs = NULL;
|
||||
|
||||
/* Clear and free tmp_mem_spaces */
|
||||
if (tmp_mem_spaces) {
|
||||
for (i = 0; i < io_info->pieces_added; i++)
|
||||
if (tmp_mem_spaces[i] != io_info->mem_spaces[i] && tmp_mem_spaces[i] &&
|
||||
H5S_close(tmp_mem_spaces[i]) < 0)
|
||||
HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "Can't close dataspace")
|
||||
H5MM_free(tmp_mem_spaces);
|
||||
tmp_mem_spaces = NULL;
|
||||
}
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5D__scatgath_read_select() */
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5D__scatgath_write_select
|
||||
*
|
||||
* Purpose: Perform scatter/gather write to a list of dataset pieces.
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5D__scatgath_write_select(H5D_io_info_t *io_info)
|
||||
{
|
||||
H5S_t **write_mem_spaces = NULL; /* Memory spaces to use for write to disk */
|
||||
size_t spaces_added = 0; /* Number of spaces added to write_mem_spaces */
|
||||
H5S_sel_iter_t *mem_iter = NULL; /* Memory selection iteration info */
|
||||
hbool_t mem_iter_init = FALSE; /* Memory selection iteration info has been initialized */
|
||||
const void **write_bufs = NULL; /* Buffers to use for write to disk */
|
||||
size_t tconv_bytes_used = 0; /* Number of bytes used so far in conversion buffer */
|
||||
size_t bkg_bytes_used = 0; /* Number of bytes used so far in background buffer */
|
||||
H5D_dset_io_info_t *last_bkg_buf_dset = NULL; /* Index of last dset that used a background buffer */
|
||||
H5S_t **bkg_mem_spaces = NULL; /* Array of memory spaces for read to background buffer */
|
||||
H5S_t **bkg_file_spaces = NULL; /* Array of file spaces for read to background buffer */
|
||||
haddr_t *bkg_addrs = NULL; /* Array of file addresses for read to background buffer */
|
||||
size_t *bkg_element_sizes = NULL; /* Array of element sizes for read to background buffer */
|
||||
void **bkg_bufs = NULL; /* Array background buffers for read of existing file contents */
|
||||
size_t bkg_pieces = 0; /* Number of pieces that need to read the background data from disk */
|
||||
size_t i; /* Local index variable */
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_PACKAGE
|
||||
|
||||
/* Sanity check */
|
||||
HDassert(io_info);
|
||||
HDassert(io_info->count > 0);
|
||||
HDassert(io_info->mem_spaces || io_info->pieces_added == 0);
|
||||
HDassert(io_info->file_spaces || io_info->pieces_added == 0);
|
||||
HDassert(io_info->addrs || io_info->pieces_added == 0);
|
||||
HDassert(io_info->element_sizes || io_info->pieces_added == 0);
|
||||
HDassert(io_info->wbufs || io_info->pieces_added == 0);
|
||||
|
||||
/* Allocate list of buffers (within the tconv buf) */
|
||||
if (NULL == (write_bufs = (const void **)H5MM_malloc(io_info->pieces_added * sizeof(const void *))))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for temporary buffer list")
|
||||
|
||||
/* Allocate the iterator */
|
||||
if (NULL == (mem_iter = H5FL_MALLOC(H5S_sel_iter_t)))
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate memory iterator")
|
||||
|
||||
/* Allocate list of block memory spaces */
|
||||
/*!FIXME delay doing this until we find the first mem space that is non-contiguous or doesn't start at 0
|
||||
*/
|
||||
if (NULL == (write_mem_spaces = H5MM_malloc(io_info->pieces_added * sizeof(H5S_t *))))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
|
||||
"memory allocation failed for temporary memory space list")
|
||||
|
||||
/* Build operations to read data to background buffer and to write data */
|
||||
for (i = 0; i < io_info->pieces_added; i++) {
|
||||
H5D_dset_io_info_t *dset_info = io_info->sel_pieces[i]->dset_info;
|
||||
|
||||
HDassert(io_info->sel_pieces[i]->piece_points > 0);
|
||||
|
||||
/* Check if this piece is involved in type conversion */
|
||||
if (dset_info->type_info.is_xform_noop && dset_info->type_info.is_conv_noop) {
|
||||
/* No type conversion, just copy the mem space and buffer */
|
||||
write_mem_spaces[i] = io_info->mem_spaces[i];
|
||||
spaces_added++;
|
||||
write_bufs[i] = io_info->wbufs[i];
|
||||
}
|
||||
else {
|
||||
void *tmp_write_buf; /* To sidestep const warnings */
|
||||
void *tmp_bkg_buf = NULL;
|
||||
|
||||
H5_CHECK_OVERFLOW(io_info->sel_pieces[i]->piece_points, hsize_t, size_t);
|
||||
|
||||
/* Initialize memory iterator */
|
||||
HDassert(!mem_iter_init);
|
||||
if (H5S_select_iter_init(mem_iter, io_info->mem_spaces[i], dset_info->type_info.src_type_size,
|
||||
0) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL,
|
||||
"unable to initialize memory selection information")
|
||||
mem_iter_init = TRUE; /* Memory selection iteration info has been initialized */
|
||||
|
||||
/* Create block memory space */
|
||||
if (NULL ==
|
||||
(write_mem_spaces[i] = H5S_create_simple(1, &io_info->sel_pieces[i]->piece_points, NULL)))
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "unable to create simple memory dataspace")
|
||||
spaces_added++;
|
||||
|
||||
/* Set buffer to point into type conversion buffer */
|
||||
tmp_write_buf = io_info->tconv_buf + tconv_bytes_used;
|
||||
write_bufs[i] = (const void *)tmp_write_buf;
|
||||
tconv_bytes_used += io_info->sel_pieces[i]->piece_points *
|
||||
MAX(dset_info->type_info.src_type_size, dset_info->type_info.dst_type_size);
|
||||
|
||||
/* Gather data from application buffer into the datatype conversion buffer */
|
||||
if ((size_t)io_info->sel_pieces[i]->piece_points !=
|
||||
H5D__gather_mem(io_info->wbufs[i], mem_iter, (size_t)io_info->sel_pieces[i]->piece_points,
|
||||
tmp_write_buf /*out*/))
|
||||
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "mem gather failed")
|
||||
|
||||
/* If the source and destination are compound types and the destination is
|
||||
* is a subset of the source and no conversion is needed, copy the data
|
||||
* directly into user's buffer and bypass the rest of steps. If the source
|
||||
* is a subset of the destination, the optimization is done in conversion
|
||||
* function H5T_conv_struct_opt to protect the background data.
|
||||
*/
|
||||
if (dset_info->type_info.cmpd_subset &&
|
||||
H5T_SUBSET_DST == dset_info->type_info.cmpd_subset->subset &&
|
||||
dset_info->type_info.dst_type_size == dset_info->type_info.cmpd_subset->copy_size) {
|
||||
if (H5D__compound_opt_write((size_t)io_info->sel_pieces[i]->piece_points,
|
||||
&dset_info->type_info, tmp_write_buf) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
|
||||
|
||||
/* No background buffer necessary, prevent this element from being considered in the second
|
||||
* loop */
|
||||
/* Add this to H5Tconv.c? -NAF */
|
||||
dset_info->type_info.need_bkg = H5T_BKG_NO;
|
||||
} /* end if */
|
||||
else {
|
||||
/* Check for background buffer */
|
||||
if (dset_info->type_info.need_bkg) {
|
||||
HDassert(dset_info->type_info.bkg_buf);
|
||||
|
||||
/* Check if we moved to a new background buffer */
|
||||
if (dset_info != last_bkg_buf_dset) {
|
||||
/* Reset bkg_bytes_used */
|
||||
bkg_bytes_used = 0;
|
||||
last_bkg_buf_dset = dset_info;
|
||||
}
|
||||
|
||||
/* Calculate background buffer position */
|
||||
tmp_bkg_buf = dset_info->type_info.bkg_buf + bkg_bytes_used;
|
||||
bkg_bytes_used +=
|
||||
io_info->sel_pieces[i]->piece_points * dset_info->type_info.dst_type_size;
|
||||
}
|
||||
|
||||
/* Set up background buffer read operation if necessary */
|
||||
if (H5T_BKG_YES == dset_info->type_info.need_bkg) {
|
||||
HDassert(io_info->must_fill_bkg);
|
||||
|
||||
/* Allocate arrays of parameters for selection read to background buffer if necessary */
|
||||
if (!bkg_mem_spaces) {
|
||||
HDassert(!bkg_file_spaces && !bkg_addrs && !bkg_element_sizes && !bkg_bufs);
|
||||
if (NULL == (bkg_mem_spaces = H5MM_malloc(io_info->pieces_added * sizeof(H5S_t *))))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
|
||||
"memory allocation failed for memory space list")
|
||||
if (NULL == (bkg_file_spaces = H5MM_malloc(io_info->pieces_added * sizeof(H5S_t *))))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
|
||||
"memory allocation failed for file space list")
|
||||
if (NULL == (bkg_addrs = H5MM_malloc(io_info->pieces_added * sizeof(haddr_t))))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
|
||||
"memory allocation failed for piece address list")
|
||||
if (NULL == (bkg_element_sizes = H5MM_malloc(io_info->pieces_added * sizeof(size_t))))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
|
||||
"memory allocation failed for element size list")
|
||||
if (NULL == (bkg_bufs = H5MM_malloc(io_info->pieces_added * sizeof(const void *))))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
|
||||
"memory allocation failed for write buffer list")
|
||||
}
|
||||
|
||||
/* Use same (block) memory space, file space, address, and element size as write operation
|
||||
*/
|
||||
HDassert(bkg_mem_spaces && bkg_file_spaces && bkg_addrs && bkg_element_sizes && bkg_bufs);
|
||||
bkg_mem_spaces[bkg_pieces] = write_mem_spaces[i];
|
||||
bkg_file_spaces[bkg_pieces] = io_info->file_spaces[i];
|
||||
bkg_addrs[bkg_pieces] = io_info->addrs[i];
|
||||
bkg_element_sizes[bkg_pieces] = io_info->element_sizes[i];
|
||||
|
||||
/* Use previously calculated background buffer position */
|
||||
bkg_bufs[bkg_pieces] = tmp_bkg_buf;
|
||||
|
||||
/* Add piece */
|
||||
bkg_pieces++;
|
||||
}
|
||||
else {
|
||||
/* Perform type conversion here to avoid second loop if no dsets use the background buffer
|
||||
*/
|
||||
/* Do the data transform before the type conversion (since
|
||||
* transforms must be done in the memory type). */
|
||||
if (!dset_info->type_info.is_xform_noop) {
|
||||
H5Z_data_xform_t *data_transform; /* Data transform info */
|
||||
|
||||
/* Retrieve info from API context */
|
||||
if (H5CX_get_data_transform(&data_transform) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get data transform info")
|
||||
|
||||
if (H5Z_xform_eval(data_transform, tmp_write_buf,
|
||||
(size_t)io_info->sel_pieces[i]->piece_points,
|
||||
dset_info->type_info.mem_type) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "Error performing data transform")
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform datatype conversion.
|
||||
*/
|
||||
if (H5T_convert(dset_info->type_info.tpath, dset_info->type_info.src_type_id,
|
||||
dset_info->type_info.dst_type_id,
|
||||
(size_t)io_info->sel_pieces[i]->piece_points, (size_t)0, (size_t)0,
|
||||
tmp_write_buf, tmp_bkg_buf) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
|
||||
}
|
||||
}
|
||||
|
||||
/* Release selection iterator */
|
||||
HDassert(mem_iter_init);
|
||||
if (H5S_SELECT_ITER_RELEASE(mem_iter) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
|
||||
mem_iter_init = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
HDassert(spaces_added == io_info->pieces_added);
|
||||
|
||||
/* Gather data to background buffer if necessary */
|
||||
if (io_info->must_fill_bkg) {
|
||||
size_t j = 0; /* Index into array of background buffers */
|
||||
|
||||
/* Read data */
|
||||
H5_CHECK_OVERFLOW(bkg_pieces, size_t, uint32_t)
|
||||
if (H5F_shared_select_read(io_info->f_sh, H5FD_MEM_DRAW, (uint32_t)bkg_pieces, bkg_mem_spaces,
|
||||
bkg_file_spaces, bkg_addrs, bkg_element_sizes, bkg_bufs) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "selection read to background buffer failed")
|
||||
|
||||
/* Perform type conversion on pieces with background buffers that were just read */
|
||||
for (i = 0; i < io_info->pieces_added; i++) {
|
||||
H5D_dset_io_info_t *dset_info = io_info->sel_pieces[i]->dset_info;
|
||||
|
||||
if (H5T_BKG_YES == dset_info->type_info.need_bkg) {
|
||||
/* Non-const write_buf[i]. Use pointer math here to avoid const warnings. When
|
||||
* there's a background buffer write_buf[i] always points inside the non-const tconv
|
||||
* buf so this is OK. */
|
||||
void *tmp_write_buf =
|
||||
(void *)((uint8_t *)io_info->tconv_buf +
|
||||
((const uint8_t *)write_bufs[i] - (const uint8_t *)io_info->tconv_buf));
|
||||
|
||||
/* Do the data transform before the type conversion (since
|
||||
* transforms must be done in the memory type). */
|
||||
if (!dset_info->type_info.is_xform_noop) {
|
||||
H5Z_data_xform_t *data_transform; /* Data transform info */
|
||||
|
||||
/* Retrieve info from API context */
|
||||
if (H5CX_get_data_transform(&data_transform) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get data transform info")
|
||||
|
||||
if (H5Z_xform_eval(data_transform, tmp_write_buf,
|
||||
(size_t)io_info->sel_pieces[i]->piece_points,
|
||||
dset_info->type_info.mem_type) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "Error performing data transform")
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform datatype conversion.
|
||||
*/
|
||||
HDassert(j < bkg_pieces);
|
||||
if (H5T_convert(dset_info->type_info.tpath, dset_info->type_info.src_type_id,
|
||||
dset_info->type_info.dst_type_id,
|
||||
(size_t)io_info->sel_pieces[i]->piece_points, (size_t)0, (size_t)0,
|
||||
tmp_write_buf, bkg_bufs[j]) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
|
||||
|
||||
/* Advance to next background buffer */
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
HDassert(j == bkg_pieces);
|
||||
}
|
||||
|
||||
/* Write data to disk */
|
||||
H5_CHECK_OVERFLOW(io_info->pieces_added, size_t, uint32_t)
|
||||
if (H5F_shared_select_write(io_info->f_sh, H5FD_MEM_DRAW, (uint32_t)io_info->pieces_added,
|
||||
write_mem_spaces, io_info->file_spaces, io_info->addrs,
|
||||
io_info->element_sizes, write_bufs) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "selection write failed")
|
||||
|
||||
done:
|
||||
/* Release and free selection iterator */
|
||||
if (mem_iter_init && H5S_SELECT_ITER_RELEASE(mem_iter) < 0)
|
||||
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
|
||||
if (mem_iter)
|
||||
mem_iter = H5FL_FREE(H5S_sel_iter_t, mem_iter);
|
||||
|
||||
/* Free write_bufs */
|
||||
H5MM_free(write_bufs);
|
||||
write_bufs = NULL;
|
||||
|
||||
/* Clear and free write_mem_spaces */
|
||||
if (write_mem_spaces) {
|
||||
for (i = 0; i < spaces_added; i++) {
|
||||
HDassert(write_mem_spaces[i]);
|
||||
if (write_mem_spaces[i] != io_info->mem_spaces[i] && H5S_close(write_mem_spaces[i]) < 0)
|
||||
HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "Can't close dataspace")
|
||||
}
|
||||
H5MM_free(write_mem_spaces);
|
||||
write_mem_spaces = NULL;
|
||||
}
|
||||
|
||||
/* Free bakcground buffer parameter arrays */
|
||||
H5MM_free(bkg_mem_spaces);
|
||||
bkg_mem_spaces = NULL;
|
||||
H5MM_free(bkg_file_spaces);
|
||||
bkg_file_spaces = NULL;
|
||||
H5MM_free(bkg_addrs);
|
||||
bkg_addrs = NULL;
|
||||
H5MM_free(bkg_element_sizes);
|
||||
bkg_element_sizes = NULL;
|
||||
H5MM_free(bkg_bufs);
|
||||
bkg_bufs = NULL;
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5D__scatgath_write_select() */
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5D__compound_opt_read
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user