mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-03-07 16:37:56 +08:00
Implementation of the mpio driver with selection I/O. (#3222)
* This changes the default selection I/O to on for MPIO.
This commit is contained in:
parent
fb38a8b924
commit
291b2f7ae4
30
src/H5Dio.c
30
src/H5Dio.c
@ -415,8 +415,14 @@ H5D__read(size_t count, H5D_dset_io_info_t *dset_info)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get MPI-I/O transfer mode");
|
||||
|
||||
/* Only report the collective I/O mode if we're actually performing collective I/O */
|
||||
if (xfer_mode == H5FD_MPIO_COLLECTIVE)
|
||||
if (xfer_mode == H5FD_MPIO_COLLECTIVE) {
|
||||
H5CX_set_mpio_actual_io_mode(io_info.actual_io_mode);
|
||||
|
||||
/* If we did selection I/O, report that we used "link chunk" mode, since that's the most
|
||||
* analogous to what selection I/O does */
|
||||
if (io_info.use_select_io == H5D_SELECTION_IO_MODE_ON)
|
||||
H5CX_set_mpio_actual_chunk_opt(H5D_MPIO_LINK_CHUNK);
|
||||
}
|
||||
}
|
||||
#endif /* H5_HAVE_PARALLEL */
|
||||
}
|
||||
@ -1131,20 +1137,16 @@ H5D__typeinfo_init_phase2(H5D_io_info_t *io_info)
|
||||
assert(io_info);
|
||||
|
||||
/* If selection I/O mode is default (auto), enable it here if the VFD supports it (it will be turned off
|
||||
* later if something else conflicts), otherwise disable it. If we're using the MPIO VFD, the automatic
|
||||
* selection will happen in H5D__mpio_opt_possible() inside H5D__ioinfo_adjust(). */
|
||||
#ifdef H5_HAVE_PARALLEL
|
||||
if (!io_info->using_mpi_vfd)
|
||||
#endif /* H5_HAVE_PARALLEL */
|
||||
if (io_info->use_select_io == H5D_SELECTION_IO_MODE_DEFAULT) {
|
||||
if (H5F_has_vector_select_io(io_info->dsets_info[0].dset->oloc.file,
|
||||
io_info->op_type == H5D_IO_OP_WRITE))
|
||||
io_info->use_select_io = H5D_SELECTION_IO_MODE_ON;
|
||||
else {
|
||||
io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF;
|
||||
io_info->no_selection_io_cause |= H5D_SEL_IO_DEFAULT_OFF;
|
||||
}
|
||||
* later if something else conflicts), otherwise disable it */
|
||||
if (io_info->use_select_io == H5D_SELECTION_IO_MODE_DEFAULT) {
|
||||
if (H5F_has_vector_select_io(io_info->dsets_info[0].dset->oloc.file,
|
||||
io_info->op_type == H5D_IO_OP_WRITE))
|
||||
io_info->use_select_io = H5D_SELECTION_IO_MODE_ON;
|
||||
else {
|
||||
io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF;
|
||||
io_info->no_selection_io_cause |= H5D_SEL_IO_DEFAULT_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're doing type conversion and we might be doing selection I/O, check if the buffers are large
|
||||
* enough to handle the whole I/O */
|
||||
|
@ -622,6 +622,9 @@ 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;
|
||||
|
||||
/* Decision on whether to use selection I/O should have been made by now */
|
||||
assert(io_info->use_select_io != H5D_SELECTION_IO_MODE_DEFAULT);
|
||||
|
||||
/* Datatype conversions and transformations are allowed with selection I/O. If the selection I/O mode
|
||||
* is auto (default), disable collective for now and re-enable later if we can */
|
||||
if (io_info->use_select_io != H5D_SELECTION_IO_MODE_ON) {
|
||||
@ -731,25 +734,6 @@ H5D__mpio_opt_possible(H5D_io_info_t *io_info)
|
||||
HMPI_GOTO_ERROR(FAIL, "MPI_Allreduce failed", mpi_code)
|
||||
} /* end else */
|
||||
|
||||
/* If the selection I/O mode is default (auto), decide here whether it should be on or off */
|
||||
if (io_info->use_select_io == H5D_SELECTION_IO_MODE_DEFAULT) {
|
||||
/* If the only reason(s) we've disabled collective are type conversions and/or transforms, enable
|
||||
* selection I/O and re-enable collective I/O since it's supported by selection I/O */
|
||||
if (global_cause[0] && !(global_cause[0] & ~((unsigned)H5D_MPIO_DATATYPE_CONVERSION |
|
||||
(unsigned)H5D_MPIO_DATA_TRANSFORMS))) {
|
||||
assert(!(local_cause[0] &
|
||||
~((unsigned)H5D_MPIO_DATATYPE_CONVERSION | (unsigned)H5D_MPIO_DATA_TRANSFORMS)));
|
||||
local_cause[0] = 0;
|
||||
global_cause[0] = 0;
|
||||
io_info->use_select_io = H5D_SELECTION_IO_MODE_ON;
|
||||
}
|
||||
else {
|
||||
/* Otherwise, there's currently no benefit to selection I/O, so leave it off */
|
||||
io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF;
|
||||
io_info->no_selection_io_cause |= H5D_SEL_IO_DEFAULT_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the local & global values of no-collective-cause in the API context */
|
||||
H5CX_set_mpio_local_no_coll_cause(local_cause[0]);
|
||||
H5CX_set_mpio_global_no_coll_cause(global_cause[0]);
|
||||
|
402
src/H5FD.c
402
src/H5FD.c
@ -1723,8 +1723,8 @@ H5FDread_selection(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count,
|
||||
|
||||
/* Call private function */
|
||||
/* (Note compensating for base address addition in internal routine) */
|
||||
if (H5FD_read_selection_id(file, type, count, mem_space_ids, file_space_ids, offsets, element_sizes,
|
||||
bufs) < 0)
|
||||
if (H5FD_read_selection_id(SKIP_NO_CB, file, type, count, mem_space_ids, file_space_ids, offsets,
|
||||
element_sizes, bufs) < 0)
|
||||
HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "file selection read request failed");
|
||||
|
||||
done:
|
||||
@ -1820,14 +1820,408 @@ H5FDwrite_selection(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count
|
||||
|
||||
/* Call private function */
|
||||
/* (Note compensating for base address addition in internal routine) */
|
||||
if (H5FD_write_selection_id(file, type, count, mem_space_ids, file_space_ids, offsets, element_sizes,
|
||||
bufs) < 0)
|
||||
|
||||
if (H5FD_write_selection_id(SKIP_NO_CB, file, type, count, mem_space_ids, file_space_ids, offsets,
|
||||
element_sizes, bufs) < 0)
|
||||
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file selection write request failed");
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_API(ret_value)
|
||||
} /* end H5FDwrite_selection() */
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Purpose: This is similar to H5FDread_selection() with the
|
||||
* exception noted below.
|
||||
*
|
||||
* Perform count reads from the specified file at the
|
||||
* locations selected in the dataspaces in the file_spaces
|
||||
* array, with each of those dataspaces starting at the file
|
||||
* address specified by the corresponding element of the
|
||||
* offsets array, and with the size of each element in the
|
||||
* dataspace specified by the corresponding element of the
|
||||
* element_sizes array. The memory type provided by type is
|
||||
* the same for all selections. Data read is returned in
|
||||
* the locations selected in the dataspaces in the
|
||||
* mem_spaces array, within the buffers provided in the
|
||||
* corresponding elements of the bufs array.
|
||||
*
|
||||
* If i > 0 and element_sizes[i] == 0, presume
|
||||
* element_sizes[n] = element_sizes[i-1] for all n >= i and
|
||||
* < count.
|
||||
*
|
||||
* Note:
|
||||
* It will skip selection read call whether the underlying VFD
|
||||
* supports selection reads or not.
|
||||
*
|
||||
* It will translate the selection read to a vector read call
|
||||
* if vector reads are supported, or a series of scalar read
|
||||
* calls otherwise.
|
||||
*
|
||||
* All reads are done according to the data transfer property
|
||||
* list dxpl_id (which may be the constant H5P_DEFAULT).
|
||||
*
|
||||
* Return: Success: SUCCEED
|
||||
* All reads have completed successfully, and
|
||||
* the results have been written into the supplied
|
||||
* buffers.
|
||||
*
|
||||
* Failure: FAIL
|
||||
* The contents of supplied buffers are undefined.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5FDread_vector_from_selection(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count,
|
||||
hid_t mem_space_ids[], hid_t file_space_ids[], haddr_t offsets[],
|
||||
size_t element_sizes[], void *bufs[] /* out */)
|
||||
{
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_API(FAIL)
|
||||
H5TRACE9("e", "*#MtiIu*i*i*a*zx", file, type, dxpl_id, count, mem_space_ids, file_space_ids, offsets,
|
||||
element_sizes, bufs);
|
||||
|
||||
/* Check arguments */
|
||||
if (!file)
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file pointer cannot be NULL");
|
||||
|
||||
if (!file->cls)
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file class pointer cannot be NULL");
|
||||
|
||||
if ((!mem_space_ids) && (count > 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "mem_spaces parameter can't be NULL if count is positive");
|
||||
|
||||
if ((!file_space_ids) && (count > 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file_spaces parameter can't be NULL if count is positive");
|
||||
|
||||
if ((!offsets) && (count > 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "offsets parameter can't be NULL if count is positive");
|
||||
|
||||
if ((!element_sizes) && (count > 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
|
||||
"element_sizes parameter can't be NULL if count is positive");
|
||||
|
||||
if ((!bufs) && (count > 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bufs parameter can't be NULL if count is positive");
|
||||
|
||||
if ((count > 0) && (element_sizes[0] == 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "sizes[0] can't be 0");
|
||||
|
||||
if ((count > 0) && (bufs[0] == NULL))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bufs[0] can't be NULL");
|
||||
|
||||
/* Get the default dataset transfer property list if the user didn't provide one */
|
||||
if (H5P_DEFAULT == dxpl_id) {
|
||||
dxpl_id = H5P_DATASET_XFER_DEFAULT;
|
||||
}
|
||||
else {
|
||||
if (TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list");
|
||||
}
|
||||
|
||||
/* Call private function */
|
||||
/* (Note compensating for base address addition in internal routine) */
|
||||
if (H5FD_read_vector_from_selection(file, type, count, mem_space_ids, file_space_ids, offsets,
|
||||
element_sizes, bufs) < 0)
|
||||
HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "file selection read request failed");
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_API(ret_value)
|
||||
} /* end H5FDread_vector_from_selection() */
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Purpose: This is similar to H5FDwrite_selection() with the
|
||||
* exception noted below.
|
||||
*
|
||||
* Perform count writes to the specified file at the
|
||||
* locations selected in the dataspaces in the file_spaces
|
||||
* array, with each of those dataspaces starting at the file
|
||||
* address specified by the corresponding element of the
|
||||
* offsets array, and with the size of each element in the
|
||||
* dataspace specified by the corresponding element of the
|
||||
* element_sizes array. The memory type provided by type is
|
||||
* the same for all selections. Data write is from
|
||||
* the locations selected in the dataspaces in the
|
||||
* mem_spaces array, within the buffers provided in the
|
||||
* corresponding elements of the bufs array.
|
||||
*
|
||||
* If i > 0 and element_sizes[i] == 0, presume
|
||||
* element_sizes[n] = element_sizes[i-1] for all n >= i and
|
||||
* < count.
|
||||
*
|
||||
* Note:
|
||||
* It will skip selection write call whether the underlying VFD
|
||||
* supports selection writes or not.
|
||||
*
|
||||
* It will translate the selection write to a vector write call
|
||||
* if vector writes are supported, or a series of scalar write
|
||||
* calls otherwise.
|
||||
*
|
||||
* All writes are done according to the data transfer property
|
||||
* list dxpl_id (which may be the constant H5P_DEFAULT).
|
||||
*
|
||||
* Return: Success: SUCCEED
|
||||
* All writes have completed successfully
|
||||
*
|
||||
* Failure: FAIL
|
||||
* One or more of the writes failed.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5FDwrite_vector_from_selection(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count,
|
||||
hid_t mem_space_ids[], hid_t file_space_ids[], haddr_t offsets[],
|
||||
size_t element_sizes[], const void *bufs[])
|
||||
{
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_API(FAIL)
|
||||
H5TRACE9("e", "*#MtiIu*i*i*a*z**x", file, type, dxpl_id, count, mem_space_ids, file_space_ids, offsets,
|
||||
element_sizes, bufs);
|
||||
|
||||
/* Check arguments */
|
||||
if (!file)
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file pointer cannot be NULL");
|
||||
|
||||
if (!file->cls)
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file class pointer cannot be NULL");
|
||||
|
||||
if ((!mem_space_ids) && (count > 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "mem_spaces parameter can't be NULL if count is positive");
|
||||
|
||||
if ((!file_space_ids) && (count > 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file_spaces parameter can't be NULL if count is positive");
|
||||
|
||||
if ((!offsets) && (count > 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "offsets parameter can't be NULL if count is positive");
|
||||
|
||||
if ((!element_sizes) && (count > 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
|
||||
"element_sizes parameter can't be NULL if count is positive");
|
||||
|
||||
if ((!bufs) && (count > 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bufs parameter can't be NULL if count is positive");
|
||||
|
||||
if ((count > 0) && (element_sizes[0] == 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "sizes[0] can't be 0");
|
||||
|
||||
if ((count > 0) && (bufs[0] == NULL))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bufs[0] can't be NULL");
|
||||
|
||||
/* Get the default dataset transfer property list if the user didn't provide one */
|
||||
if (H5P_DEFAULT == dxpl_id) {
|
||||
dxpl_id = H5P_DATASET_XFER_DEFAULT;
|
||||
}
|
||||
else {
|
||||
if (TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list");
|
||||
}
|
||||
|
||||
/* Call private function */
|
||||
/* (Note compensating for base address addition in internal routine) */
|
||||
if (H5FD_write_vector_from_selection(file, type, count, mem_space_ids, file_space_ids, offsets,
|
||||
element_sizes, bufs) < 0)
|
||||
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file selection write request failed");
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_API(ret_value)
|
||||
} /* end H5FDwrite_vector_from_selection() */
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Purpose: This is similar to H5FDread_selection() with the
|
||||
* exception noted below.
|
||||
*
|
||||
* Perform count reads from the specified file at the
|
||||
* locations selected in the dataspaces in the file_spaces
|
||||
* array, with each of those dataspaces starting at the file
|
||||
* address specified by the corresponding element of the
|
||||
* offsets array, and with the size of each element in the
|
||||
* dataspace specified by the corresponding element of the
|
||||
* element_sizes array. The memory type provided by type is
|
||||
* the same for all selections. Data read is returned in
|
||||
* the locations selected in the dataspaces in the
|
||||
* mem_spaces array, within the buffers provided in the
|
||||
* corresponding elements of the bufs array.
|
||||
*
|
||||
* If i > 0 and element_sizes[i] == 0, presume
|
||||
* element_sizes[n] = element_sizes[i-1] for all n >= i and
|
||||
* < count.
|
||||
*
|
||||
* Note:
|
||||
* It will skip selection and vector read calls whether the underlying
|
||||
* VFD supports selection and vector reads or not.
|
||||
*
|
||||
* It will translate the selection read to a series of
|
||||
* scalar read calls.
|
||||
*
|
||||
* All reads are done according to the data transfer property
|
||||
* list dxpl_id (which may be the constant H5P_DEFAULT).
|
||||
*
|
||||
* Return: Success: SUCCEED
|
||||
* All reads have completed successfully, and
|
||||
* the results have been written into the supplied
|
||||
* buffers.
|
||||
*
|
||||
* Failure: FAIL
|
||||
* The contents of supplied buffers are undefined.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5FDread_from_selection(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count, hid_t mem_space_ids[],
|
||||
hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[], void *bufs[])
|
||||
{
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_API(FAIL)
|
||||
H5TRACE9("e", "*#MtiIu*i*i*a*z**x", file, type, dxpl_id, count, mem_space_ids, file_space_ids, offsets,
|
||||
element_sizes, bufs);
|
||||
|
||||
/* Check arguments */
|
||||
if (!file)
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file pointer cannot be NULL");
|
||||
|
||||
if (!file->cls)
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file class pointer cannot be NULL");
|
||||
|
||||
if ((!mem_space_ids) && (count > 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "mem_spaces parameter can't be NULL if count is positive");
|
||||
|
||||
if ((!file_space_ids) && (count > 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file_spaces parameter can't be NULL if count is positive");
|
||||
|
||||
if ((!offsets) && (count > 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "offsets parameter can't be NULL if count is positive");
|
||||
|
||||
if ((!element_sizes) && (count > 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
|
||||
"element_sizes parameter can't be NULL if count is positive");
|
||||
|
||||
if ((!bufs) && (count > 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bufs parameter can't be NULL if count is positive");
|
||||
|
||||
if ((count > 0) && (element_sizes[0] == 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "sizes[0] can't be 0");
|
||||
|
||||
if ((count > 0) && (bufs[0] == NULL))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bufs[0] can't be NULL");
|
||||
|
||||
/* Get the default dataset transfer property list if the user didn't provide one */
|
||||
if (H5P_DEFAULT == dxpl_id) {
|
||||
dxpl_id = H5P_DATASET_XFER_DEFAULT;
|
||||
}
|
||||
else {
|
||||
if (TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list");
|
||||
}
|
||||
|
||||
/* Call private function */
|
||||
/* (Note compensating for base address addition in internal routine) */
|
||||
if (H5FD_read_from_selection(file, type, count, mem_space_ids, file_space_ids, offsets, element_sizes,
|
||||
bufs) < 0)
|
||||
HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "file selection read request failed");
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_API(ret_value)
|
||||
} /* end H5FDread_from_selection() */
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Purpose: This is similar to H5FDwrite_selection() with the
|
||||
* exception noted below.
|
||||
*
|
||||
* Perform count writes to the specified file at the
|
||||
* locations selected in the dataspaces in the file_spaces
|
||||
* array, with each of those dataspaces starting at the file
|
||||
* address specified by the corresponding element of the
|
||||
* offsets array, and with the size of each element in the
|
||||
* dataspace specified by the corresponding element of the
|
||||
* element_sizes array. The memory type provided by type is
|
||||
* the same for all selections. Data write is from
|
||||
* the locations selected in the dataspaces in the
|
||||
* mem_spaces array, within the buffers provided in the
|
||||
* corresponding elements of the bufs array.
|
||||
*
|
||||
* If i > 0 and element_sizes[i] == 0, presume
|
||||
* element_sizes[n] = element_sizes[i-1] for all n >= i and
|
||||
* < count.
|
||||
*
|
||||
* Note:
|
||||
* It will skip selection and vector write calls whether the underlying
|
||||
* VFD supports selection and vector writes or not.
|
||||
*
|
||||
* It will translate the selection write to a series of
|
||||
* scalar write calls.
|
||||
*
|
||||
* All writes are done according to the data transfer property
|
||||
* list dxpl_id (which may be the constant H5P_DEFAULT).
|
||||
*
|
||||
* Return: Success: SUCCEED
|
||||
* All writes have completed successfully
|
||||
*
|
||||
* Failure: FAIL
|
||||
* One or more of the writes failed.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5FDwrite_from_selection(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count, hid_t mem_space_ids[],
|
||||
hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[],
|
||||
const void *bufs[])
|
||||
{
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_API(FAIL)
|
||||
H5TRACE9("e", "*#MtiIu*i*i*a*z**x", file, type, dxpl_id, count, mem_space_ids, file_space_ids, offsets,
|
||||
element_sizes, bufs);
|
||||
|
||||
/* Check arguments */
|
||||
if (!file)
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file pointer cannot be NULL");
|
||||
|
||||
if (!file->cls)
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file class pointer cannot be NULL");
|
||||
|
||||
if ((!mem_space_ids) && (count > 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "mem_spaces parameter can't be NULL if count is positive");
|
||||
|
||||
if ((!file_space_ids) && (count > 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file_spaces parameter can't be NULL if count is positive");
|
||||
|
||||
if ((!offsets) && (count > 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "offsets parameter can't be NULL if count is positive");
|
||||
|
||||
if ((!element_sizes) && (count > 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
|
||||
"element_sizes parameter can't be NULL if count is positive");
|
||||
|
||||
if ((!bufs) && (count > 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bufs parameter can't be NULL if count is positive");
|
||||
|
||||
if ((count > 0) && (element_sizes[0] == 0))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "sizes[0] can't be 0");
|
||||
|
||||
if ((count > 0) && (bufs[0] == NULL))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bufs[0] can't be NULL");
|
||||
|
||||
/* Get the default dataset transfer property list if the user didn't provide one */
|
||||
if (H5P_DEFAULT == dxpl_id) {
|
||||
dxpl_id = H5P_DATASET_XFER_DEFAULT;
|
||||
}
|
||||
else {
|
||||
if (TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list");
|
||||
}
|
||||
|
||||
/* Call private function */
|
||||
/* (Note compensating for base address addition in internal routine) */
|
||||
if (H5FD_write_from_selection(file, type, count, mem_space_ids, file_space_ids, offsets, element_sizes,
|
||||
bufs) < 0)
|
||||
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file selection write request failed");
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_API(ret_value)
|
||||
} /* end H5FDwrite_from_selection() */
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5FDflush
|
||||
*
|
||||
|
@ -281,6 +281,18 @@ H5_DLL herr_t H5FDread_selection(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id,
|
||||
H5_DLL herr_t H5FDwrite_selection(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count,
|
||||
hid_t mem_spaces[], hid_t file_spaces[], haddr_t offsets[],
|
||||
size_t element_sizes[], const void *bufs[]);
|
||||
H5_DLL herr_t H5FDread_vector_from_selection(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count,
|
||||
hid_t mem_spaces[], hid_t file_spaces[], haddr_t offsets[],
|
||||
size_t element_sizes[], void *bufs[] /* out */);
|
||||
H5_DLL herr_t H5FDwrite_vector_from_selection(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count,
|
||||
hid_t mem_spaces[], hid_t file_spaces[], haddr_t offsets[],
|
||||
size_t element_sizes[], const void *bufs[] /* in */);
|
||||
H5_DLL herr_t H5FDread_from_selection(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count,
|
||||
hid_t mem_space_ids[], hid_t file_space_ids[], haddr_t offsets[],
|
||||
size_t element_sizes[], void *bufs[] /* out */);
|
||||
H5_DLL herr_t H5FDwrite_from_selection(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count,
|
||||
hid_t mem_space_ids[], hid_t file_space_ids[], haddr_t offsets[],
|
||||
size_t element_sizes[], const void *bufs[] /* in */);
|
||||
H5_DLL herr_t H5FDflush(H5FD_t *file, hid_t dxpl_id, hbool_t closing);
|
||||
H5_DLL herr_t H5FDtruncate(H5FD_t *file, hid_t dxpl_id, hbool_t closing);
|
||||
H5_DLL herr_t H5FDlock(H5FD_t *file, hbool_t rw);
|
||||
|
700
src/H5FDint.c
700
src/H5FDint.c
@ -62,17 +62,17 @@
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* H5FD_vsrt_tmp_t
|
||||
* H5FD_srt_tmp_t
|
||||
*
|
||||
* Structure used to store vector I/O request addresses and the associated
|
||||
* Structure used to store I/O request addresses and the associated
|
||||
* indexes in the addrs[] array for the purpose of determine the sorted
|
||||
* order.
|
||||
*
|
||||
* This is done by allocating an array of H5FD_vsrt_tmp_t of length
|
||||
* This is done by allocating an array of H5FD_srt_tmp_t of length
|
||||
* count, loading it with the contents of the addrs[] array and the
|
||||
* associated indices, and then sorting it.
|
||||
*
|
||||
* This sorted array of H5FD_vsrt_tmp_t is then used to populate sorted
|
||||
* This sorted array of H5FD_srt_tmp_t is then used to populate sorted
|
||||
* versions of the types[], addrs[], sizes[] and bufs[] vectors.
|
||||
*
|
||||
* addr: haddr_t containing the value of addrs[i],
|
||||
@ -82,10 +82,10 @@
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
typedef struct H5FD_vsrt_tmp_t {
|
||||
typedef struct H5FD_srt_tmp_t {
|
||||
haddr_t addr;
|
||||
size_t index;
|
||||
} H5FD_vsrt_tmp_t;
|
||||
} H5FD_srt_tmp_t;
|
||||
|
||||
/* Information needed for iterating over the registered VFD hid_t IDs.
|
||||
* The name or value of the new VFD that is being registered is stored
|
||||
@ -109,12 +109,14 @@ typedef struct H5FD_get_driver_ud_t {
|
||||
/* Local Prototypes */
|
||||
/********************/
|
||||
static int H5FD__get_driver_cb(void *obj, hid_t id, void *_op_data);
|
||||
static herr_t H5FD__read_selection_translate(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count,
|
||||
H5S_t **mem_spaces, H5S_t **file_spaces, haddr_t offsets[],
|
||||
size_t element_sizes[], void *bufs[] /* out */);
|
||||
static herr_t H5FD__write_selection_translate(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count,
|
||||
H5S_t **mem_spaces, H5S_t **file_spaces, haddr_t offsets[],
|
||||
size_t element_sizes[], const void *bufs[]);
|
||||
static herr_t H5FD__read_selection_translate(uint32_t skip_vector_cb, H5FD_t *file, H5FD_mem_t type,
|
||||
hid_t dxpl_id, uint32_t count, H5S_t **mem_spaces,
|
||||
H5S_t **file_spaces, haddr_t offsets[], size_t element_sizes[],
|
||||
void *bufs[] /* out */);
|
||||
static herr_t H5FD__write_selection_translate(uint32_t skip_vector_cb, H5FD_t *file, H5FD_mem_t type,
|
||||
hid_t dxpl_id, uint32_t count, H5S_t **mem_spaces,
|
||||
H5S_t **file_spaces, haddr_t offsets[], size_t element_sizes[],
|
||||
const void *bufs[]);
|
||||
|
||||
/*********************/
|
||||
/* Package Variables */
|
||||
@ -734,8 +736,8 @@ done:
|
||||
* Function: H5FD__read_selection_translate
|
||||
*
|
||||
* Purpose: Translates a selection read call to a vector read call if
|
||||
* vector reads are supported, or a series of scalar read
|
||||
* calls otherwise.
|
||||
* vector reads are supported and !skip_vector_cb,
|
||||
* or a series of scalar read calls otherwise.
|
||||
*
|
||||
* Return: Success: SUCCEED
|
||||
* All reads have completed successfully, and
|
||||
@ -748,8 +750,8 @@ done:
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5FD__read_selection_translate(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count,
|
||||
H5S_t **mem_spaces, H5S_t **file_spaces, haddr_t offsets[],
|
||||
H5FD__read_selection_translate(uint32_t skip_vector_cb, H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id,
|
||||
uint32_t count, H5S_t **mem_spaces, H5S_t **file_spaces, haddr_t offsets[],
|
||||
size_t element_sizes[], void *bufs[] /* out */)
|
||||
{
|
||||
hbool_t extend_sizes = FALSE;
|
||||
@ -797,7 +799,7 @@ H5FD__read_selection_translate(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uin
|
||||
assert((bufs) || (count == 0));
|
||||
|
||||
/* Check if we're using vector I/O */
|
||||
use_vector = file->cls->read_vector != NULL;
|
||||
use_vector = (file->cls->read_vector != NULL) && (!skip_vector_cb);
|
||||
|
||||
if (count > 0) {
|
||||
/* Verify that the first elements of the element_sizes and bufs arrays are
|
||||
@ -1063,8 +1065,8 @@ done:
|
||||
* If the underlying VFD supports selection reads, pass the
|
||||
* call through directly.
|
||||
*
|
||||
* If it doesn't, convert the vector read into a sequence
|
||||
* of individual reads.
|
||||
* If it doesn't, convert the selection read into a sequence
|
||||
* of vector or scalar reads.
|
||||
*
|
||||
* Return: Success: SUCCEED
|
||||
* All reads have completed successfully, and
|
||||
@ -1189,8 +1191,8 @@ H5FD_read_selection(H5FD_t *file, H5FD_mem_t type, uint32_t count, H5S_t **mem_s
|
||||
/* Otherwise, implement the selection read as a sequence of regular
|
||||
* or vector read calls.
|
||||
*/
|
||||
if (H5FD__read_selection_translate(file, type, dxpl_id, count, mem_spaces, file_spaces, offsets,
|
||||
element_sizes, bufs) < 0)
|
||||
if (H5FD__read_selection_translate(SKIP_NO_CB, file, type, dxpl_id, count, mem_spaces, file_spaces,
|
||||
offsets, element_sizes, bufs) < 0)
|
||||
HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "translation to vector or scalar read failed");
|
||||
|
||||
done:
|
||||
@ -1228,6 +1230,15 @@ done:
|
||||
* Purpose: Like H5FD_read_selection(), but takes hid_t arrays instead
|
||||
* of H5S_t * arrays for the dataspaces.
|
||||
*
|
||||
* Depending on the parameter skip_cb which is translated into
|
||||
* skip_selection_cb and skip_vector_cb:
|
||||
*
|
||||
* --If the underlying VFD supports selection reads and !skip_selection_cb,
|
||||
* pass the call through directly.
|
||||
*
|
||||
* --If it doesn't, convert the selection reads into a sequence of vector or
|
||||
* scalar reads depending on skip_vector_cb.
|
||||
*
|
||||
* Return: Success: SUCCEED
|
||||
* All reads have completed successfully, and
|
||||
* the results havce been into the supplied
|
||||
@ -1239,7 +1250,7 @@ done:
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5FD_read_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_space_ids[],
|
||||
H5FD_read_selection_id(uint32_t skip_cb, H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_space_ids[],
|
||||
hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[],
|
||||
void *bufs[] /* out */)
|
||||
{
|
||||
@ -1250,6 +1261,8 @@ H5FD_read_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_
|
||||
H5S_t **file_spaces = file_spaces_local;
|
||||
hid_t dxpl_id = H5I_INVALID_HID; /* DXPL for operation */
|
||||
uint32_t i;
|
||||
uint32_t skip_selection_cb;
|
||||
uint32_t skip_vector_cb;
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI(FAIL)
|
||||
@ -1282,6 +1295,9 @@ H5FD_read_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_
|
||||
}
|
||||
#endif /* H5_HAVE_PARALLEL */
|
||||
|
||||
skip_selection_cb = skip_cb & SKIP_SELECTION_CB;
|
||||
skip_vector_cb = skip_cb & SKIP_VECTOR_CB;
|
||||
|
||||
if (file->base_addr > 0) {
|
||||
|
||||
/* apply the base_addr offset to the offsets array. Must undo before
|
||||
@ -1320,7 +1336,7 @@ H5FD_read_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_
|
||||
}
|
||||
|
||||
/* if the underlying VFD supports selection read, make the call */
|
||||
if (file->cls->read_selection) {
|
||||
if (!skip_selection_cb && file->cls->read_selection) {
|
||||
if ((file->cls->read_selection)(file, type, dxpl_id, count, mem_space_ids, file_space_ids, offsets,
|
||||
element_sizes, bufs) < 0)
|
||||
HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read selection request failed");
|
||||
@ -1348,8 +1364,9 @@ H5FD_read_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_
|
||||
}
|
||||
|
||||
/* Translate to vector or scalar I/O */
|
||||
if (H5FD__read_selection_translate(file, type, dxpl_id, count, mem_spaces, file_spaces, offsets,
|
||||
element_sizes, bufs) < 0)
|
||||
|
||||
if (H5FD__read_selection_translate(skip_vector_cb, file, type, dxpl_id, count, mem_spaces,
|
||||
file_spaces, offsets, element_sizes, bufs) < 0)
|
||||
HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "translation to vector or scalar read failed");
|
||||
}
|
||||
|
||||
@ -1378,8 +1395,8 @@ done:
|
||||
* Function: H5FD__write_selection_translate
|
||||
*
|
||||
* Purpose: Translates a selection write call to a vector write call
|
||||
* if vector writes are supported, or a series of scalar
|
||||
* write calls otherwise.
|
||||
* if vector writes are supported and !skip_vector_cb,
|
||||
* or a series of scalar write calls otherwise.
|
||||
*
|
||||
* Return: Success: SUCCEED
|
||||
* All writes have completed successfully.
|
||||
@ -1390,8 +1407,8 @@ done:
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5FD__write_selection_translate(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count,
|
||||
H5S_t **mem_spaces, H5S_t **file_spaces, haddr_t offsets[],
|
||||
H5FD__write_selection_translate(uint32_t skip_vector_cb, H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id,
|
||||
uint32_t count, H5S_t **mem_spaces, H5S_t **file_spaces, haddr_t offsets[],
|
||||
size_t element_sizes[], const void *bufs[])
|
||||
{
|
||||
hbool_t extend_sizes = FALSE;
|
||||
@ -1439,7 +1456,7 @@ H5FD__write_selection_translate(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, ui
|
||||
assert((bufs) || (count == 0));
|
||||
|
||||
/* Check if we're using vector I/O */
|
||||
use_vector = file->cls->write_vector != NULL;
|
||||
use_vector = (file->cls->write_vector != NULL) && (!skip_vector_cb);
|
||||
|
||||
if (count > 0) {
|
||||
/* Verify that the first elements of the element_sizes and bufs arrays are
|
||||
@ -1705,8 +1722,8 @@ done:
|
||||
* If the underlying VFD supports selection writes, pass the
|
||||
* call through directly.
|
||||
*
|
||||
* If it doesn't, convert the vector write into a sequence
|
||||
* of individual writes.
|
||||
* If it doesn't, convert the selection write into a sequence
|
||||
* of vector or scalar writes.
|
||||
*
|
||||
* Return: Success: SUCCEED
|
||||
* All writes have completed successfully.
|
||||
@ -1823,8 +1840,9 @@ H5FD_write_selection(H5FD_t *file, H5FD_mem_t type, uint32_t count, H5S_t **mem_
|
||||
/* Otherwise, implement the selection write as a sequence of regular
|
||||
* or vector write calls.
|
||||
*/
|
||||
if (H5FD__write_selection_translate(file, type, dxpl_id, count, mem_spaces, file_spaces, offsets,
|
||||
element_sizes, bufs) < 0)
|
||||
|
||||
if (H5FD__write_selection_translate(SKIP_NO_CB, file, type, dxpl_id, count, mem_spaces, file_spaces,
|
||||
offsets, element_sizes, bufs) < 0)
|
||||
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "translation to vector or scalar write failed");
|
||||
|
||||
done:
|
||||
@ -1862,6 +1880,15 @@ done:
|
||||
* Purpose: Like H5FD_write_selection(), but takes hid_t arrays
|
||||
* instead of H5S_t * arrays for the dataspaces.
|
||||
*
|
||||
* Depending on the parameter skip_cb which is translated into
|
||||
* skip_selection_cb and skip_vector_cb:
|
||||
*
|
||||
* --If the underlying VFD supports selection writes and !skip_selection_cb,
|
||||
* pass the call through directly.
|
||||
*
|
||||
* --If it doesn't, convert the selection writes into a sequence of vector or
|
||||
* scalar reads depending on skip_vector_cb.
|
||||
*
|
||||
* Return: Success: SUCCEED
|
||||
* All writes have completed successfully.
|
||||
*
|
||||
@ -1871,8 +1898,9 @@ done:
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5FD_write_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_space_ids[],
|
||||
hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[], const void *bufs[])
|
||||
H5FD_write_selection_id(uint32_t skip_cb, H5FD_t *file, H5FD_mem_t type, uint32_t count,
|
||||
hid_t mem_space_ids[], hid_t file_space_ids[], haddr_t offsets[],
|
||||
size_t element_sizes[], const void *bufs[])
|
||||
{
|
||||
hbool_t offsets_cooked = FALSE;
|
||||
H5S_t *mem_spaces_local[H5FD_LOCAL_SEL_ARR_LEN];
|
||||
@ -1881,6 +1909,8 @@ H5FD_write_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem
|
||||
H5S_t **file_spaces = file_spaces_local;
|
||||
hid_t dxpl_id = H5I_INVALID_HID; /* DXPL for operation */
|
||||
uint32_t i;
|
||||
uint32_t skip_selection_cb;
|
||||
uint32_t skip_vector_cb;
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI(FAIL)
|
||||
@ -1913,6 +1943,9 @@ H5FD_write_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem
|
||||
}
|
||||
#endif /* H5_HAVE_PARALLEL */
|
||||
|
||||
skip_selection_cb = skip_cb & SKIP_SELECTION_CB;
|
||||
skip_vector_cb = skip_cb & SKIP_VECTOR_CB;
|
||||
|
||||
if (file->base_addr > 0) {
|
||||
|
||||
/* apply the base_addr offset to the offsets array. Must undo before
|
||||
@ -1945,7 +1978,7 @@ H5FD_write_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem
|
||||
}
|
||||
|
||||
/* if the underlying VFD supports selection write, make the call */
|
||||
if (file->cls->write_selection) {
|
||||
if (!skip_selection_cb && file->cls->write_selection) {
|
||||
if ((file->cls->write_selection)(file, type, dxpl_id, count, mem_space_ids, file_space_ids, offsets,
|
||||
element_sizes, bufs) < 0)
|
||||
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "driver write selection request failed");
|
||||
@ -1973,8 +2006,9 @@ H5FD_write_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem
|
||||
}
|
||||
|
||||
/* Translate to vector or scalar I/O */
|
||||
if (H5FD__write_selection_translate(file, type, dxpl_id, count, mem_spaces, file_spaces, offsets,
|
||||
element_sizes, bufs) < 0)
|
||||
|
||||
if (H5FD__write_selection_translate(skip_vector_cb, file, type, dxpl_id, count, mem_spaces,
|
||||
file_spaces, offsets, element_sizes, bufs) < 0)
|
||||
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "translation to vector or scalar write failed");
|
||||
}
|
||||
|
||||
@ -1999,6 +2033,209 @@ done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5FD_write_selection_id() */
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5FD_read_vector_from_selection
|
||||
*
|
||||
* Purpose: Internal routine for H5FDread_vector_from_selection()
|
||||
*
|
||||
* It will translate the selection read to a vector read call
|
||||
* if vector reads are supported, or a series of scalar read
|
||||
* calls otherwise.
|
||||
*
|
||||
* Return: Success: SUCCEED
|
||||
* All writes have completed successfully.
|
||||
*
|
||||
* Failure: FAIL
|
||||
* One or more writes failed.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5FD_read_vector_from_selection(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_space_ids[],
|
||||
hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[],
|
||||
void *bufs[])
|
||||
{
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI(FAIL)
|
||||
|
||||
/* Sanity checks */
|
||||
assert(file);
|
||||
assert(file->cls);
|
||||
assert((mem_space_ids) || (count == 0));
|
||||
assert((file_space_ids) || (count == 0));
|
||||
assert((offsets) || (count == 0));
|
||||
assert((element_sizes) || (count == 0));
|
||||
assert((bufs) || (count == 0));
|
||||
|
||||
/* Verify that the first elements of the element_sizes and bufs arrays are
|
||||
* valid. */
|
||||
assert((count == 0) || (element_sizes[0] != 0));
|
||||
assert((count == 0) || (bufs[0] != NULL));
|
||||
|
||||
/* Call private function */
|
||||
/* (Note compensating for base address addition in internal routine) */
|
||||
if (H5FD_read_selection_id(SKIP_SELECTION_CB, file, type, count, mem_space_ids, file_space_ids, offsets,
|
||||
element_sizes, bufs) < 0)
|
||||
HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "file selection read request failed");
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
|
||||
} /* end H5FD_read_vector_from_selection() */
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5FD_write_vector_from_selection
|
||||
*
|
||||
* Purpose: Internal routine for H5FDwrite_vector_from_selection()
|
||||
*
|
||||
* It will translate the selection write to a vector write call
|
||||
* if vector writes are supported, or a series of scalar write
|
||||
* calls otherwise.
|
||||
*
|
||||
* Return: Success: SUCCEED
|
||||
* All writes have completed successfully.
|
||||
*
|
||||
* Failure: FAIL
|
||||
* One or more writes failed.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5FD_write_vector_from_selection(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_space_ids[],
|
||||
hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[],
|
||||
const void *bufs[])
|
||||
{
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI(FAIL)
|
||||
|
||||
/* Sanity checks */
|
||||
assert(file);
|
||||
assert(file->cls);
|
||||
assert((mem_space_ids) || (count == 0));
|
||||
assert((file_space_ids) || (count == 0));
|
||||
assert((offsets) || (count == 0));
|
||||
assert((element_sizes) || (count == 0));
|
||||
assert((bufs) || (count == 0));
|
||||
|
||||
/* Verify that the first elements of the element_sizes and bufs arrays are
|
||||
* valid. */
|
||||
assert((count == 0) || (element_sizes[0] != 0));
|
||||
assert((count == 0) || (bufs[0] != NULL));
|
||||
|
||||
/* Call private function */
|
||||
/* (Note compensating for base address addition in internal routine) */
|
||||
if (H5FD_write_selection_id(SKIP_SELECTION_CB, file, type, count, mem_space_ids, file_space_ids, offsets,
|
||||
element_sizes, bufs) < 0)
|
||||
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file selection write request failed");
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
|
||||
} /* end H5FD_write_vector_from_selection() */
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5FD_read_from_selection
|
||||
*
|
||||
* Purpose: Internal routine for H5FDread_from_selection()
|
||||
*
|
||||
* It will translate the selection read to a series of
|
||||
* scalar read calls.
|
||||
*
|
||||
* Return: Success: SUCCEED
|
||||
* All writes have completed successfully.
|
||||
*
|
||||
* Failure: FAIL
|
||||
* One or more writes failed.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5FD_read_from_selection(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_space_ids[],
|
||||
hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[], void *bufs[])
|
||||
{
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI(FAIL)
|
||||
|
||||
/* Sanity checks */
|
||||
assert(file);
|
||||
assert(file->cls);
|
||||
assert((mem_space_ids) || (count == 0));
|
||||
assert((file_space_ids) || (count == 0));
|
||||
assert((offsets) || (count == 0));
|
||||
assert((element_sizes) || (count == 0));
|
||||
assert((bufs) || (count == 0));
|
||||
|
||||
/* Verify that the first elements of the element_sizes and bufs arrays are
|
||||
* valid. */
|
||||
assert((count == 0) || (element_sizes[0] != 0));
|
||||
assert((count == 0) || (bufs[0] != NULL));
|
||||
|
||||
/* Call private function */
|
||||
/* (Note compensating for base address addition in internal routine) */
|
||||
if (H5FD_read_selection_id(SKIP_SELECTION_CB | SKIP_VECTOR_CB, file, type, count, mem_space_ids,
|
||||
file_space_ids, offsets, element_sizes, bufs) < 0)
|
||||
HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "file selection read request failed");
|
||||
|
||||
done:
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
|
||||
} /* end H5FD_read_from_selection() */
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5FD_write_from_selection
|
||||
*
|
||||
* Purpose: Internal routine for H5FDwrite_from_selection()
|
||||
*
|
||||
* It will translate the selection write to a series of
|
||||
* scalar write calls.
|
||||
*
|
||||
* Return: Success: SUCCEED
|
||||
* All writes have completed successfully.
|
||||
*
|
||||
* Failure: FAIL
|
||||
* One or more writes failed.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5FD_write_from_selection(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_space_ids[],
|
||||
hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[],
|
||||
const void *bufs[])
|
||||
{
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI(FAIL)
|
||||
|
||||
/* Sanity checks */
|
||||
assert(file);
|
||||
assert(file->cls);
|
||||
assert((mem_space_ids) || (count == 0));
|
||||
assert((file_space_ids) || (count == 0));
|
||||
assert((offsets) || (count == 0));
|
||||
assert((element_sizes) || (count == 0));
|
||||
assert((bufs) || (count == 0));
|
||||
|
||||
/* Verify that the first elements of the element_sizes and bufs arrays are
|
||||
* valid. */
|
||||
assert((count == 0) || (element_sizes[0] != 0));
|
||||
assert((count == 0) || (bufs[0] != NULL));
|
||||
|
||||
/* Call private function */
|
||||
/* (Note compensating for base address addition in internal routine) */
|
||||
if (H5FD_write_selection_id(SKIP_SELECTION_CB | SKIP_VECTOR_CB, file, type, count, mem_space_ids,
|
||||
file_space_ids, offsets, element_sizes, bufs) < 0)
|
||||
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file selection write request failed");
|
||||
|
||||
done:
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
|
||||
} /* end H5FD_write_from_selection() */
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5FD_set_eoa
|
||||
*
|
||||
@ -2138,6 +2375,119 @@ H5FD_driver_query(const H5FD_class_t *driver, unsigned long *flags /*out*/)
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5FD_driver_query() */
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* Function: H5FD__vstr_tmp_cmp()
|
||||
*
|
||||
* Purpose: This is the comparison callback function used by qsort()
|
||||
* in H5FD__sort_io_req_real( )
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static int
|
||||
H5FD__srt_tmp_cmp(const void *element_1, const void *element_2)
|
||||
{
|
||||
haddr_t addr_1 = ((const H5FD_srt_tmp_t *)element_1)->addr;
|
||||
haddr_t addr_2 = ((const H5FD_srt_tmp_t *)element_2)->addr;
|
||||
int ret_value = 0; /* Return value */
|
||||
|
||||
FUNC_ENTER_PACKAGE_NOERR
|
||||
|
||||
/* Sanity checks */
|
||||
assert(H5_addr_defined(addr_1));
|
||||
assert(H5_addr_defined(addr_2));
|
||||
|
||||
/* Compare the addresses */
|
||||
if (H5_addr_gt(addr_1, addr_2))
|
||||
ret_value = 1;
|
||||
else if (H5_addr_lt(addr_1, addr_2))
|
||||
ret_value = -1;
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* H5FD__srt_tmp_cmp() */
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5FD__sort_io_req_real()
|
||||
*
|
||||
* Purpose: Scan the addrs array to see if it is sorted.
|
||||
*
|
||||
* If sorted, return TRUE in *was_sorted.
|
||||
*
|
||||
* If not sorted, use qsort() to sort the array.
|
||||
* Do this by allocating an array of struct H5FD_srt_tmp_t,
|
||||
* where each instance of H5FD_srt_tmp_t has two fields,
|
||||
* addr and index. Load the array with the contents of the
|
||||
* addrs array and the index of the associated entry.
|
||||
* Then sort the array using qsort().
|
||||
* Return *FALSE in was_sorted.
|
||||
*
|
||||
* This is a common routine used by:
|
||||
* --H5FD_sort_vector_io_req ()
|
||||
* --H5FD_sort_selection_io_req()
|
||||
*
|
||||
* Return: SUCCEED/FAIL
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5FD__sort_io_req_real(size_t count, haddr_t *addrs, hbool_t *was_sorted, struct H5FD_srt_tmp_t **srt_tmp)
|
||||
{
|
||||
size_t i;
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_PACKAGE
|
||||
|
||||
/* Sanity checks */
|
||||
|
||||
/* scan the offsets array to see if it is sorted */
|
||||
for (i = 1; i < count; i++) {
|
||||
assert(H5_addr_defined(addrs[i - 1]));
|
||||
|
||||
if (H5_addr_gt(addrs[i - 1], addrs[i]))
|
||||
break;
|
||||
else if (H5_addr_eq(addrs[i - 1], addrs[i]))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "duplicate addr in selections");
|
||||
}
|
||||
|
||||
/* if we traversed the entire array without breaking out, then
|
||||
* the array was already sorted */
|
||||
if (i >= count)
|
||||
*was_sorted = TRUE;
|
||||
else
|
||||
*was_sorted = FALSE;
|
||||
|
||||
if (!(*was_sorted)) {
|
||||
size_t srt_tmp_size;
|
||||
|
||||
srt_tmp_size = (count * sizeof(struct H5FD_srt_tmp_t));
|
||||
|
||||
if (NULL == (*srt_tmp = (H5FD_srt_tmp_t *)malloc(srt_tmp_size)))
|
||||
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't alloc srt_tmp");
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
(*srt_tmp)[i].addr = addrs[i];
|
||||
(*srt_tmp)[i].index = i;
|
||||
}
|
||||
|
||||
/* sort the srt_tmp array */
|
||||
qsort(*srt_tmp, count, sizeof(struct H5FD_srt_tmp_t), H5FD__srt_tmp_cmp);
|
||||
|
||||
/* verify no duplicate entries */
|
||||
i = 1;
|
||||
|
||||
for (i = 1; i < count; i++) {
|
||||
assert(H5_addr_lt((*srt_tmp)[i - 1].addr, (*srt_tmp)[i].addr));
|
||||
|
||||
if (H5_addr_eq(addrs[i - 1], addrs[i]))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "duplicate addrs in array");
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
|
||||
} /* H5FD__sort_io_req_real() */
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5FD_sort_vector_io_req
|
||||
*
|
||||
@ -2169,38 +2519,15 @@ H5FD_driver_query(const H5FD_class_t *driver, unsigned long *flags /*out*/)
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
H5FD__vsrt_tmp_cmp(const void *element_1, const void *element_2)
|
||||
{
|
||||
haddr_t addr_1 = ((const H5FD_vsrt_tmp_t *)element_1)->addr;
|
||||
haddr_t addr_2 = ((const H5FD_vsrt_tmp_t *)element_2)->addr;
|
||||
int ret_value = 0; /* Return value */
|
||||
|
||||
FUNC_ENTER_PACKAGE_NOERR
|
||||
|
||||
/* Sanity checks */
|
||||
assert(H5_addr_defined(addr_1));
|
||||
assert(H5_addr_defined(addr_2));
|
||||
|
||||
/* Compare the addresses */
|
||||
if (H5_addr_gt(addr_1, addr_2))
|
||||
ret_value = 1;
|
||||
else if (H5_addr_lt(addr_1, addr_2))
|
||||
ret_value = -1;
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* H5FD__vsrt_tmp_cmp() */
|
||||
|
||||
herr_t
|
||||
H5FD_sort_vector_io_req(hbool_t *vector_was_sorted, uint32_t _count, H5FD_mem_t types[], haddr_t addrs[],
|
||||
size_t sizes[], H5_flexible_const_ptr_t bufs[], H5FD_mem_t **s_types_ptr,
|
||||
haddr_t **s_addrs_ptr, size_t **s_sizes_ptr, H5_flexible_const_ptr_t **s_bufs_ptr)
|
||||
{
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
size_t count = (size_t)_count;
|
||||
size_t i;
|
||||
struct H5FD_vsrt_tmp_t *srt_tmp = NULL;
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
size_t count = (size_t)_count;
|
||||
size_t i;
|
||||
struct H5FD_srt_tmp_t *srt_tmp = NULL;
|
||||
|
||||
FUNC_ENTER_NOAPI(FAIL)
|
||||
|
||||
@ -2224,22 +2551,12 @@ H5FD_sort_vector_io_req(hbool_t *vector_was_sorted, uint32_t _count, H5FD_mem_t
|
||||
assert((count == 0) || ((s_sizes_ptr) && (NULL == *s_sizes_ptr)));
|
||||
assert((count == 0) || ((s_bufs_ptr) && (NULL == *s_bufs_ptr)));
|
||||
|
||||
/* scan the addrs array to see if it is sorted */
|
||||
for (i = 1; i < count; i++) {
|
||||
assert(H5_addr_defined(addrs[i - 1]));
|
||||
|
||||
if (H5_addr_gt(addrs[i - 1], addrs[i]))
|
||||
break;
|
||||
else if (H5_addr_eq(addrs[i - 1], addrs[i]))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "duplicate addr in vector");
|
||||
}
|
||||
|
||||
/* if we traversed the entire array without breaking out, then
|
||||
* the array was already sorted */
|
||||
if (i >= count)
|
||||
*vector_was_sorted = TRUE;
|
||||
else
|
||||
*vector_was_sorted = FALSE;
|
||||
/* Sort the addrs array in increasing addr order, while
|
||||
* maintaining the association between each addr, and the
|
||||
* sizes[], types[], and bufs[] values at the same index.
|
||||
*/
|
||||
if (H5FD__sort_io_req_real(count, addrs, vector_was_sorted, &srt_tmp) < 0)
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "sorting error in selection offsets");
|
||||
|
||||
if (*vector_was_sorted) {
|
||||
|
||||
@ -2250,46 +2567,14 @@ H5FD_sort_vector_io_req(hbool_t *vector_was_sorted, uint32_t _count, H5FD_mem_t
|
||||
}
|
||||
else {
|
||||
|
||||
/* must sort the addrs array in increasing addr order, while
|
||||
* maintaining the association between each addr, and the
|
||||
* sizes[], types[], and bufs[] values at the same index.
|
||||
*
|
||||
* Do this by allocating an array of struct H5FD_vsrt_tmp_t, where
|
||||
* each instance of H5FD_vsrt_tmp_t has two fields, addr and index.
|
||||
* Load the array with the contents of the addrs array and
|
||||
* the index of the associated entry. Sort the array, allocate
|
||||
* the s_types_ptr, s_addrs_ptr, s_sizes_ptr, and s_bufs_ptr
|
||||
/*
|
||||
* Allocate the s_types_ptr, s_addrs_ptr, s_sizes_ptr, and s_bufs_ptr
|
||||
* arrays and populate them using the mapping provided by
|
||||
* the sorted array of H5FD_vsrt_tmp_t.
|
||||
* the sorted array of H5FD_srt_tmp_t.
|
||||
*/
|
||||
size_t j;
|
||||
size_t fixed_size_index = count;
|
||||
size_t fixed_type_index = count;
|
||||
size_t srt_tmp_size;
|
||||
|
||||
srt_tmp_size = (count * sizeof(struct H5FD_vsrt_tmp_t));
|
||||
|
||||
if (NULL == (srt_tmp = (H5FD_vsrt_tmp_t *)malloc(srt_tmp_size)))
|
||||
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't alloc srt_tmp");
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
srt_tmp[i].addr = addrs[i];
|
||||
srt_tmp[i].index = i;
|
||||
}
|
||||
|
||||
/* sort the srt_tmp array */
|
||||
qsort(srt_tmp, count, sizeof(struct H5FD_vsrt_tmp_t), H5FD__vsrt_tmp_cmp);
|
||||
|
||||
/* verify no duplicate entries */
|
||||
i = 1;
|
||||
|
||||
for (i = 1; i < count; i++) {
|
||||
assert(H5_addr_lt(srt_tmp[i - 1].addr, srt_tmp[i].addr));
|
||||
|
||||
if (H5_addr_eq(addrs[i - 1], addrs[i]))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "duplicate addr in vector");
|
||||
}
|
||||
|
||||
if ((NULL == (*s_types_ptr = (H5FD_mem_t *)malloc(count * sizeof(H5FD_mem_t)))) ||
|
||||
(NULL == (*s_addrs_ptr = (haddr_t *)malloc(count * sizeof(haddr_t)))) ||
|
||||
@ -2378,6 +2663,187 @@ done:
|
||||
|
||||
} /* end H5FD_sort_vector_io_req() */
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Purpose: Determine whether the supplied selection I/O request is
|
||||
* sorted.
|
||||
*
|
||||
* if is is, set *selection_was_sorted to TRUE, set:
|
||||
*
|
||||
* *s_mem_space_ids_ptr = mem_space_ids;
|
||||
* *s_file_space_ids_ptr = file_space_ids;
|
||||
* *s_offsets_ptr = offsets;
|
||||
* *s_element_sizes_ptr = element_sizes;
|
||||
* *s_bufs_ptr = bufs;
|
||||
*
|
||||
* and return.
|
||||
*
|
||||
* If it is not sorted, duplicate the mem_space_ids, file_space_ids,
|
||||
* offsets, element_sizes and bufs arrays, storing the base
|
||||
* addresses of the new arrays in *s_mem_space_ids_ptr,
|
||||
* s_file_space_ids_ptr, s_offsets_ptr, *s_element_sizes_ptr,
|
||||
* and s_bufs_ptr respectively. Determine the sorted order
|
||||
* of the selection I/O request, and load it into the new
|
||||
* selections in sorted order.
|
||||
*
|
||||
* Note that in this case, it is the caller's responsibility
|
||||
* to free the sorted vectors.
|
||||
*
|
||||
* Return: SUCCEED/FAIL
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5FD_sort_selection_io_req(hbool_t *selection_was_sorted, size_t count, hid_t mem_space_ids[],
|
||||
hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[],
|
||||
H5_flexible_const_ptr_t bufs[], hid_t **s_mem_space_ids_ptr,
|
||||
hid_t **s_file_space_ids_ptr, haddr_t **s_offsets_ptr,
|
||||
size_t **s_element_sizes_ptr, H5_flexible_const_ptr_t **s_bufs_ptr)
|
||||
{
|
||||
size_t i;
|
||||
struct H5FD_srt_tmp_t *srt_tmp = NULL;
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI(FAIL)
|
||||
|
||||
/* Sanity checks */
|
||||
|
||||
assert(selection_was_sorted);
|
||||
|
||||
assert((mem_space_ids) || (count == 0));
|
||||
assert((file_space_ids) || (count == 0));
|
||||
assert((offsets) || (count == 0));
|
||||
assert((element_sizes) || (count == 0));
|
||||
assert((bufs) || (count == 0));
|
||||
|
||||
/* verify that the first elements of the element_sizes and bufs arrays are
|
||||
* valid.
|
||||
*/
|
||||
assert((count == 0) || (element_sizes[0] != 0));
|
||||
assert((count == 0) || (bufs[0].cvp != NULL));
|
||||
|
||||
assert((count == 0) || ((s_mem_space_ids_ptr) && (NULL == *s_mem_space_ids_ptr)));
|
||||
assert((count == 0) || ((s_file_space_ids_ptr) && (NULL == *s_file_space_ids_ptr)));
|
||||
assert((count == 0) || ((s_offsets_ptr) && (NULL == *s_offsets_ptr)));
|
||||
assert((count == 0) || ((s_element_sizes_ptr) && (NULL == *s_element_sizes_ptr)));
|
||||
assert((count == 0) || ((s_bufs_ptr) && (NULL == *s_bufs_ptr)));
|
||||
|
||||
/* Sort the offsets array in increasing offset order, while
|
||||
* maintaining the association between each offset, and the
|
||||
* mem_space_ids[], file_space_ids[], element_sizes and bufs[]
|
||||
* values at the same index.
|
||||
*/
|
||||
if (H5FD__sort_io_req_real(count, offsets, selection_was_sorted, &srt_tmp) < 0)
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "sorting error in selection offsets");
|
||||
|
||||
if (*selection_was_sorted) {
|
||||
|
||||
*s_mem_space_ids_ptr = mem_space_ids;
|
||||
*s_file_space_ids_ptr = file_space_ids;
|
||||
*s_offsets_ptr = offsets;
|
||||
*s_element_sizes_ptr = element_sizes;
|
||||
*s_bufs_ptr = bufs;
|
||||
}
|
||||
else {
|
||||
|
||||
/*
|
||||
* Allocate the s_mem_space_ids_ptr, s_file_space_ids_ptr, s_offsets_ptr,
|
||||
* s_element_sizes_ptr and s_bufs_ptr arrays and populate them using the
|
||||
* mapping provided by the sorted array of H5FD_srt_tmp_t.
|
||||
*/
|
||||
size_t j;
|
||||
size_t fixed_element_sizes_index = count;
|
||||
size_t fixed_bufs_index = count;
|
||||
|
||||
if ((NULL == (*s_mem_space_ids_ptr = (hid_t *)malloc(count * sizeof(hid_t)))) ||
|
||||
(NULL == (*s_file_space_ids_ptr = (hid_t *)malloc(count * sizeof(hid_t)))) ||
|
||||
(NULL == (*s_offsets_ptr = (haddr_t *)malloc(count * sizeof(haddr_t)))) ||
|
||||
(NULL == (*s_element_sizes_ptr = (size_t *)malloc(count * sizeof(size_t)))) ||
|
||||
(NULL ==
|
||||
(*s_bufs_ptr = (H5_flexible_const_ptr_t *)malloc(count * sizeof(H5_flexible_const_ptr_t))))) {
|
||||
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't alloc sorted selection(s)");
|
||||
}
|
||||
|
||||
assert(element_sizes[0] != 0);
|
||||
assert(bufs[0].cvp != NULL);
|
||||
|
||||
/* Scan the element_sizes and bufs array to determine if the fixed
|
||||
* element_sizes / bufs optimization is in use, and if so, to determine
|
||||
* the index of the last valid value on each array.
|
||||
* We have already verified that the first
|
||||
* elements of these arrays are valid so we can start at the second
|
||||
* element (if it exists).
|
||||
*/
|
||||
for (i = 1; i < count && ((fixed_element_sizes_index == count) || (fixed_bufs_index == count)); i++) {
|
||||
if ((fixed_element_sizes_index == count) && (element_sizes[i] == 0))
|
||||
fixed_element_sizes_index = i - 1;
|
||||
if ((fixed_bufs_index == count) && (bufs[i].cvp == NULL))
|
||||
fixed_bufs_index = i - 1;
|
||||
}
|
||||
|
||||
assert(fixed_element_sizes_index <= count);
|
||||
assert(fixed_bufs_index <= count);
|
||||
|
||||
/* Populate the sorted arrays. Note that the index stored in srt_tmp
|
||||
* refers to the index in the unsorted array, while the position of
|
||||
* srt_tmp within the sorted array is the index in the sorted arrays */
|
||||
for (i = 0; i < count; i++) {
|
||||
|
||||
j = srt_tmp[i].index;
|
||||
|
||||
(*s_mem_space_ids_ptr)[i] = mem_space_ids[j];
|
||||
(*s_file_space_ids_ptr)[i] = file_space_ids[j];
|
||||
(*s_offsets_ptr)[i] = offsets[j];
|
||||
(*s_element_sizes_ptr)[i] = element_sizes[MIN(j, fixed_element_sizes_index)];
|
||||
(*s_bufs_ptr)[i] = bufs[MIN(j, fixed_bufs_index)];
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if (srt_tmp) {
|
||||
free(srt_tmp);
|
||||
srt_tmp = NULL;
|
||||
}
|
||||
|
||||
/* On failure, free the sorted arrays if they were allocated.
|
||||
* Note that we only allocate these arrays if the original array
|
||||
* was not sorted -- thus we check both for failure, and for
|
||||
* the flag indicating that the original array was not sorted
|
||||
* in increasing address order.
|
||||
*/
|
||||
if ((ret_value != SUCCEED) && (!(*selection_was_sorted))) {
|
||||
|
||||
/* free space allocated for sorted arrays */
|
||||
if (*s_mem_space_ids_ptr) {
|
||||
free(*s_mem_space_ids_ptr);
|
||||
*s_mem_space_ids_ptr = NULL;
|
||||
}
|
||||
|
||||
if (*s_file_space_ids_ptr) {
|
||||
free(*s_file_space_ids_ptr);
|
||||
*s_file_space_ids_ptr = NULL;
|
||||
}
|
||||
|
||||
if (*s_offsets_ptr) {
|
||||
free(*s_offsets_ptr);
|
||||
*s_offsets_ptr = NULL;
|
||||
}
|
||||
|
||||
if (*s_element_sizes_ptr) {
|
||||
free(*s_element_sizes_ptr);
|
||||
*s_element_sizes_ptr = NULL;
|
||||
}
|
||||
|
||||
if (*s_bufs_ptr) {
|
||||
free(*s_bufs_ptr);
|
||||
*s_bufs_ptr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
|
||||
} /* end H5FD_sort_selection_io_req() */
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5FD_delete
|
||||
*
|
||||
|
1026
src/H5FDmpio.c
1026
src/H5FDmpio.c
File diff suppressed because it is too large
Load Diff
@ -77,6 +77,10 @@ typedef struct {
|
||||
} \
|
||||
}
|
||||
|
||||
#define SKIP_NO_CB 0x00u
|
||||
#define SKIP_SELECTION_CB 0x01u
|
||||
#define SKIP_VECTOR_CB 0x02u
|
||||
|
||||
/* Define structure to hold driver ID, info & configuration string for FAPLs */
|
||||
typedef struct {
|
||||
hid_t driver_id; /* Driver's ID */
|
||||
@ -149,12 +153,27 @@ H5_DLL herr_t H5FD_read_selection(H5FD_t *file, H5FD_mem_t type, uint32_t count
|
||||
H5_DLL herr_t H5FD_write_selection(H5FD_t *file, H5FD_mem_t type, uint32_t count, struct H5S_t **mem_spaces,
|
||||
struct H5S_t **file_spaces, haddr_t offsets[], size_t element_sizes[],
|
||||
const void *bufs[]);
|
||||
H5_DLL herr_t H5FD_read_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_space_ids[],
|
||||
hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[],
|
||||
void *bufs[] /* out */);
|
||||
H5_DLL herr_t H5FD_write_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_space_ids[],
|
||||
H5_DLL herr_t H5FD_read_selection_id(uint32_t skip_cb, H5FD_t *file, H5FD_mem_t type, uint32_t count,
|
||||
hid_t mem_space_ids[], hid_t file_space_ids[], haddr_t offsets[],
|
||||
size_t element_sizes[], void *bufs[] /* out */);
|
||||
H5_DLL herr_t H5FD_write_selection_id(uint32_t skip_cb, H5FD_t *file, H5FD_mem_t type, uint32_t count,
|
||||
hid_t mem_space_ids[], hid_t file_space_ids[], haddr_t offsets[],
|
||||
size_t element_sizes[], const void *bufs[]);
|
||||
H5_DLL herr_t H5FD_read_vector_from_selection(H5FD_t *file, H5FD_mem_t type, uint32_t count,
|
||||
hid_t mem_space_ids[], hid_t file_space_ids[],
|
||||
haddr_t offsets[], size_t element_sizes[], void *bufs[]);
|
||||
|
||||
H5_DLL herr_t H5FD_write_vector_from_selection(H5FD_t *file, H5FD_mem_t type, uint32_t count,
|
||||
hid_t mem_space_ids[], hid_t file_space_ids[],
|
||||
haddr_t offsets[], size_t element_sizes[], const void *bufs[]);
|
||||
|
||||
H5_DLL herr_t H5FD_read_from_selection(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_space_ids[],
|
||||
hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[],
|
||||
const void *bufs[]);
|
||||
void *bufs[]);
|
||||
|
||||
H5_DLL herr_t H5FD_write_from_selection(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_space_ids[],
|
||||
hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[],
|
||||
const void *bufs[]);
|
||||
H5_DLL herr_t H5FD_flush(H5FD_t *file, hbool_t closing);
|
||||
H5_DLL herr_t H5FD_truncate(H5FD_t *file, hbool_t closing);
|
||||
H5_DLL herr_t H5FD_lock(H5FD_t *file, hbool_t rw);
|
||||
@ -171,6 +190,12 @@ H5_DLL herr_t H5FD_sort_vector_io_req(hbool_t *vector_was_sorted, uint32_t count
|
||||
haddr_t addrs[], size_t sizes[], H5_flexible_const_ptr_t bufs[],
|
||||
H5FD_mem_t **s_types_ptr, haddr_t **s_addrs_ptr, size_t **s_sizes_ptr,
|
||||
H5_flexible_const_ptr_t **s_bufs_ptr);
|
||||
|
||||
H5_DLL herr_t H5FD_sort_selection_io_req(hbool_t *selection_was_sorted, size_t count, hid_t mem_space_ids[],
|
||||
hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[],
|
||||
H5_flexible_const_ptr_t bufs[], hid_t **s_mem_space_ids,
|
||||
hid_t **s_file_space_ids, haddr_t **s_offsets_ptr,
|
||||
size_t **s_element_sizes_ptr, H5_flexible_const_ptr_t **s_bufs_ptr);
|
||||
H5_DLL herr_t H5FD_init(void);
|
||||
|
||||
/* Function prototypes for MPI based VFDs*/
|
||||
|
@ -2751,9 +2751,6 @@ test_set_get_select_io_mode(hid_t fid)
|
||||
if (H5Pget_selection_io(dxpl, &selection_io_mode) < 0)
|
||||
TEST_ERROR;
|
||||
|
||||
if (selection_io_mode != H5D_SELECTION_IO_MODE_DEFAULT)
|
||||
TEST_ERROR;
|
||||
|
||||
/* Disable case */
|
||||
if (H5Pset_selection_io(dxpl, H5D_SELECTION_IO_MODE_OFF) < 0)
|
||||
TEST_ERROR;
|
||||
@ -3063,11 +3060,29 @@ static herr_t
|
||||
test_get_no_selection_io_cause(const char *filename, hid_t fapl)
|
||||
{
|
||||
|
||||
int errs = 0;
|
||||
hid_t dxpl = H5I_INVALID_HID;
|
||||
H5D_selection_io_mode_t selection_io_mode;
|
||||
int errs = 0;
|
||||
|
||||
printf("\n");
|
||||
TESTING("H5Pget_no_selection_io_cause()");
|
||||
|
||||
if ((dxpl = H5Pcreate(H5P_DATASET_XFER)) < 0)
|
||||
FAIL_STACK_ERROR;
|
||||
|
||||
if (H5Pget_selection_io(dxpl, &selection_io_mode) < 0)
|
||||
TEST_ERROR;
|
||||
|
||||
if (H5Pclose(dxpl) < 0)
|
||||
FAIL_STACK_ERROR;
|
||||
|
||||
/* The following tests are based on H5D_SELECTION_IO_MODE_DEFAULT as the
|
||||
default setting in the library; skip the tests if that is not true */
|
||||
if (selection_io_mode != H5D_SELECTION_IO_MODE_DEFAULT) {
|
||||
SKIPPED();
|
||||
return SUCCEED;
|
||||
}
|
||||
|
||||
errs += test_no_selection_io_cause_mode(filename, fapl, TEST_DISABLE_BY_API);
|
||||
errs += test_no_selection_io_cause_mode(filename, fapl, TEST_NOT_CONTIGUOUS_OR_CHUNKED_DATASET);
|
||||
errs += test_no_selection_io_cause_mode(filename, fapl, TEST_CONTIGUOUS_SIEVE_BUFFER);
|
||||
@ -3083,6 +3098,7 @@ test_get_no_selection_io_cause(const char *filename, hid_t fapl)
|
||||
errs += test_no_selection_io_cause_mode(filename, fapl, TEST_PAGE_BUFFER);
|
||||
#endif
|
||||
|
||||
error:
|
||||
if (errs) {
|
||||
printf(" FAILED\n");
|
||||
return FAIL;
|
||||
|
@ -782,7 +782,7 @@ coll_chunktest(const char *filename, int chunk_factor, int select_factor, int ap
|
||||
status = H5Pget_selection_io(xfer_plist, &selection_io_mode);
|
||||
VRFY((status >= 0), "testing property list get succeeded");
|
||||
|
||||
if (facc_type == FACC_MPIO && (selection_io_mode != H5D_SELECTION_IO_MODE_ON)) {
|
||||
if (facc_type == FACC_MPIO && (selection_io_mode == H5D_SELECTION_IO_MODE_OFF)) {
|
||||
switch (api_option) {
|
||||
case API_LINK_HARD:
|
||||
status = H5Pget(xfer_plist, H5D_XFER_COLL_CHUNK_LINK_HARD_NAME, &prop_value);
|
||||
|
@ -3356,7 +3356,7 @@ actual_io_mode_tests(void)
|
||||
ret = H5Pclose(dxpl_id);
|
||||
VRFY((ret >= 0), "H5Pclose succeeded");
|
||||
|
||||
if (selection_io_mode != H5D_SELECTION_IO_MODE_ON) {
|
||||
if (selection_io_mode == H5D_SELECTION_IO_MODE_OFF) {
|
||||
test_actual_io_mode(TEST_ACTUAL_IO_NO_COLLECTIVE);
|
||||
|
||||
/*
|
||||
|
@ -128,6 +128,11 @@ typedef enum {
|
||||
#define TEST_TCONV_BUF_TOO_SMALL 0x008
|
||||
#define TEST_IN_PLACE_TCONV 0x010
|
||||
|
||||
/* Definitions used by test_bug_optimized_bufs() and test_bug_api_library() */
|
||||
#define DIMS 10000
|
||||
#define BIG_X_FACTOR 1048576
|
||||
#define BIG_Y_FACTOR 32
|
||||
|
||||
/*
|
||||
* Helper routine to set dxpl
|
||||
* --selection I/O mode
|
||||
@ -2960,6 +2965,8 @@ test_multi_dsets_all(int niter, hid_t fid, unsigned chunked, unsigned mwbuf)
|
||||
const void *wbufs[MULTI_NUM_DSETS];
|
||||
void *rbufs[MULTI_NUM_DSETS];
|
||||
|
||||
curr_nerrors = nerrors;
|
||||
|
||||
/* for n niter to ensure that all randomized dset_types with multi_dset_type_t will be covered */
|
||||
for (n = 0; n < niter; n++) {
|
||||
|
||||
@ -3434,6 +3441,19 @@ test_no_selection_io_cause_mode(const char *filename, hid_t fapl, uint32_t test_
|
||||
|
||||
/* Datatype conversion */
|
||||
if (test_mode & TEST_DATATYPE_CONVERSION) {
|
||||
|
||||
/* With one exception, all will land at H5FD__mpio_read/write_selection().
|
||||
* As the xfer mode is H5FD_MPIO_INDEPENDENT, this will call
|
||||
* H5FD__read/write_from_selection() triggering H5D_SEL_IO_NO_VECTOR_OR_SELECTION_IO_CB.
|
||||
*/
|
||||
no_selection_io_cause_read_expected |= H5D_SEL_IO_NO_VECTOR_OR_SELECTION_IO_CB;
|
||||
|
||||
/* Exception case: This will turn off selection I/O landing at H5FD__mpio_write() */
|
||||
if ((test_mode & TEST_TCONV_BUF_TOO_SMALL) && !(test_mode & TEST_IN_PLACE_TCONV))
|
||||
no_selection_io_cause_write_expected |= H5D_SEL_IO_TCONV_BUF_TOO_SMALL;
|
||||
else
|
||||
no_selection_io_cause_write_expected |= H5D_SEL_IO_NO_VECTOR_OR_SELECTION_IO_CB;
|
||||
|
||||
if (H5Pset_selection_io(dxpl, H5D_SELECTION_IO_MODE_ON) < 0)
|
||||
P_TEST_ERROR;
|
||||
tid = H5T_NATIVE_UINT;
|
||||
@ -3443,18 +3463,12 @@ test_no_selection_io_cause_mode(const char *filename, hid_t fapl, uint32_t test_
|
||||
if (H5Pset_buffer(dxpl, sizeof(int), NULL, NULL) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
/* If we're using in-place type conversion sel io will succeed */
|
||||
if (test_mode & TEST_IN_PLACE_TCONV) {
|
||||
if (H5Pset_modify_write_buf(dxpl, TRUE) < 0)
|
||||
P_TEST_ERROR;
|
||||
}
|
||||
else
|
||||
no_selection_io_cause_write_expected |= H5D_SEL_IO_TCONV_BUF_TOO_SMALL;
|
||||
|
||||
/* In-place type conversion for read doesn't require modify_write_buf */
|
||||
}
|
||||
|
||||
/* If the tconv buf is largge enough sel io will succeed */
|
||||
}
|
||||
|
||||
/* Create 1d data space */
|
||||
@ -3521,6 +3535,31 @@ test_no_selection_io_cause_mode(const char *filename, hid_t fapl, uint32_t test_
|
||||
static void
|
||||
test_get_no_selection_io_cause(const char *filename, hid_t fapl)
|
||||
{
|
||||
hid_t dxpl = H5I_INVALID_HID;
|
||||
H5D_selection_io_mode_t selection_io_mode;
|
||||
|
||||
if (MAINPROCESS) {
|
||||
printf("\n");
|
||||
TESTING("for H5Pget_no_selection_io_cause()");
|
||||
}
|
||||
|
||||
curr_nerrors = nerrors;
|
||||
|
||||
if ((dxpl = H5Pcreate(H5P_DATASET_XFER)) < 0)
|
||||
P_TEST_ERROR;
|
||||
if (H5Pget_selection_io(dxpl, &selection_io_mode) < 0)
|
||||
P_TEST_ERROR;
|
||||
if (H5Pclose(dxpl) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
/* The following tests are based on H5D_SELECTION_IO_MODE_DEFAULT as the
|
||||
* default setting in the library; skip the tests if that is not true */
|
||||
if (selection_io_mode != H5D_SELECTION_IO_MODE_DEFAULT) {
|
||||
if (MAINPROCESS)
|
||||
SKIPPED();
|
||||
return;
|
||||
}
|
||||
|
||||
test_no_selection_io_cause_mode(filename, fapl, TEST_DISABLE_BY_API);
|
||||
test_no_selection_io_cause_mode(filename, fapl, TEST_NOT_CONTIGUOUS_OR_CHUNKED_DATASET);
|
||||
test_no_selection_io_cause_mode(filename, fapl, TEST_DATATYPE_CONVERSION);
|
||||
@ -3533,6 +3572,366 @@ test_get_no_selection_io_cause(const char *filename, hid_t fapl)
|
||||
return;
|
||||
} /* test_get_no_selection_io_cause() */
|
||||
|
||||
/*
|
||||
* This bug is exposed when running testpar/t_coll_md.c via testphdf5.
|
||||
*
|
||||
* Optimized bufs (bufs[1] is NULL) is used when passing as a parameter to the mpio driver
|
||||
* for selection I/O. When computing mpi_bufs_base in that routine, it is not accounted
|
||||
* for and therefore causing segmentation fault when running the test.
|
||||
*
|
||||
* Fix:
|
||||
* Check for optimized bufs when computing mpi_bufs_base.
|
||||
*/
|
||||
static void
|
||||
test_bug_optimized_bufs(const char *filename, hid_t fapl)
|
||||
{
|
||||
hid_t dxpl = H5I_INVALID_HID;
|
||||
hid_t dcpl = H5I_INVALID_HID;
|
||||
hid_t fid = H5I_INVALID_HID;
|
||||
hid_t did = H5I_INVALID_HID;
|
||||
hid_t fspace_id = H5I_INVALID_HID;
|
||||
hid_t mspace_id = H5I_INVALID_HID;
|
||||
hsize_t dims[1];
|
||||
hsize_t cdims[1];
|
||||
hsize_t start[1];
|
||||
hsize_t stride[1];
|
||||
hsize_t count[1];
|
||||
hsize_t block[1];
|
||||
int *wbuf;
|
||||
|
||||
if ((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if ((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
dims[0] = (hsize_t)mpi_size * (hsize_t)DIMS;
|
||||
|
||||
fspace_id = H5Screate_simple(1, dims, NULL);
|
||||
|
||||
cdims[0] = (hsize_t)mpi_size;
|
||||
|
||||
if (H5Pset_chunk(dcpl, 1, cdims) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if ((did = H5Dcreate2(fid, "bug_optimized_bufs", H5T_NATIVE_INT, fspace_id, H5P_DEFAULT, dcpl,
|
||||
H5P_DEFAULT)) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
start[0] = (hsize_t)mpi_rank;
|
||||
stride[0] = (hsize_t)mpi_size;
|
||||
count[0] = DIMS;
|
||||
block[0] = 1;
|
||||
|
||||
if (H5Sselect_hyperslab(fspace_id, H5S_SELECT_SET, start, stride, count, block) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if ((mspace_id = H5Screate_simple(1, count, NULL)) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if ((wbuf = calloc(1, count[0] * sizeof(int))) == NULL)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if ((dxpl = H5Pcreate(H5P_DATASET_XFER)) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
/* Enable collection transfer mode */
|
||||
if (H5Pset_dxpl_mpio(dxpl, H5FD_MPIO_COLLECTIVE) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
/* Enable selection I/O */
|
||||
if (H5Pset_selection_io(dxpl, H5D_SELECTION_IO_MODE_ON) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if (H5Dwrite(did, H5T_NATIVE_INT, mspace_id, fspace_id, dxpl, wbuf) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if (H5Dclose(did) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if (H5Pclose(dcpl) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if (H5Pclose(dxpl) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if (H5Sclose(fspace_id) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if (H5Sclose(mspace_id) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if (H5Fclose(fid) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
return;
|
||||
|
||||
} /* test_bug_optimized_bufs() */
|
||||
|
||||
/*
|
||||
* The bug is exposed when running testpar/t_pread.c.
|
||||
*
|
||||
* The file is created with userblock. Before passing down to the mpio driver for
|
||||
* selection I/O, the parameter offsets[] is added by base_addr (size of the uesrblock).
|
||||
* For the independent case in the mpio driver for selection I/O,
|
||||
* the intermediate routine for the API H5FDread/write_vector_from_selection() is called.
|
||||
* The parameter offsets[] is passed as is to the intermediate routine which will
|
||||
* be added again by base_addr causing incorrect data retrieval.
|
||||
*
|
||||
* Fix:
|
||||
* The parameter offsets[] needs to be adjusted by the base_addr addition before calling
|
||||
* the intermediate routine.
|
||||
*/
|
||||
static void
|
||||
test_bug_base_addr(const char *filename, hid_t fapl)
|
||||
{
|
||||
hid_t dxpl = H5I_INVALID_HID;
|
||||
hid_t dxpl_read = H5I_INVALID_HID;
|
||||
hid_t fid = H5I_INVALID_HID;
|
||||
hid_t did = H5I_INVALID_HID;
|
||||
hid_t sid = H5I_INVALID_HID;
|
||||
hid_t fcpl = H5I_INVALID_HID;
|
||||
hsize_t dims[1];
|
||||
hid_t tid = H5T_NATIVE_INT;
|
||||
int wbuf[DSET_SELECT_DIM];
|
||||
int rbuf[DSET_SELECT_DIM];
|
||||
int i;
|
||||
|
||||
/* Create user block */
|
||||
if ((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if (H5Pset_userblock(fcpl, 512) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if ((dxpl = H5Pcreate(H5P_DATASET_XFER)) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
/* Create the file with userblock */
|
||||
if ((fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl)) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
/* Create 1d data space */
|
||||
dims[0] = DSET_SELECT_DIM;
|
||||
|
||||
if ((sid = H5Screate_simple(1, dims, NULL)) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if ((did = H5Dcreate2(fid, "bug_base_addr", H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) <
|
||||
0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
/* Initialize data */
|
||||
for (i = 0; i < DSET_SELECT_DIM; i++)
|
||||
wbuf[i] = i;
|
||||
|
||||
if ((dxpl = H5Pcreate(H5P_DATASET_XFER)) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
/* Enable selection I/O */
|
||||
if (H5Pset_selection_io(dxpl, H5D_SELECTION_IO_MODE_ON) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
/* Independent by default and with selection I/O ON for reading */
|
||||
if ((dxpl_read = H5Pcopy(dxpl)) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
/* Enable collective and with selection I/O ON for writing */
|
||||
if (H5Pset_dxpl_mpio(dxpl, H5FD_MPIO_COLLECTIVE) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if (H5Dwrite(did, tid, H5S_ALL, H5S_ALL, dxpl, wbuf) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if (H5Dread(did, tid, H5S_ALL, H5S_ALL, dxpl_read, rbuf) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if (H5Dclose(did) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if (H5Pclose(dxpl) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if (H5Pclose(dxpl_read) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if (H5Sclose(sid) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if (H5Pclose(fcpl) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if (H5Fclose(fid) < 0)
|
||||
P_TEST_ERROR;
|
||||
return;
|
||||
|
||||
} /* test_bug_base_addr() */
|
||||
|
||||
/*
|
||||
* This bug is exposed when running testpar/t_2Gio.c with at least 2 processes.
|
||||
*
|
||||
* The root problem is from calling an API function from within the library i.e.
|
||||
* calling H5FDread/write_vector_from_selection() for independent access in the
|
||||
* mpio driver for selection I/O.
|
||||
*
|
||||
* The test scenario is described below with the test writing to a dataset
|
||||
* via H5Dwrite():
|
||||
* --running with 2 processes
|
||||
* --with selection I/O on
|
||||
* --with COLLECTIVE xfer mode
|
||||
*
|
||||
* For process 1:
|
||||
* The library internal calls H5D__write():
|
||||
* --io_info.use_select_io is ON
|
||||
* --io_info.use_select_io is OFF after calling H5D__typeinfo_init_phase2()
|
||||
* due to H5D_SEL_IO_TCONV_BUF_TOO_SMALL
|
||||
* --H5D__mpio_opt_possible() returns 0 so xfer mode is set to
|
||||
* H5FD_MPIO_INDEPENDENT
|
||||
* The library eventually calls H5FD__mpio_write() performing scalar calls for the writes
|
||||
*
|
||||
* For process 0:
|
||||
* The library internal calls H5D__write():
|
||||
* --io_info.use_select_io is ON
|
||||
* --H5D__mpio_opt_possible() returns 0 so xfer mode is set to
|
||||
* H5FD_MPIO_INDEPENDENT
|
||||
* The library eventually calls H5FD__mpio_write_selection():
|
||||
* --since the xfer mode is INDEPENDENT it calls the API
|
||||
* H5FDwrite_vector_from_selection(), which eventually calls
|
||||
* H5FD__mpio_write_vector(). This routine obtains the
|
||||
* xfer mode via API context which returns COLLECTIVE.
|
||||
* Then the test hangs when trying to do MPI_File_set_view().
|
||||
*
|
||||
* Fix:
|
||||
* Create wrapper functions for the API H5FDread/write_vector_from_selection() and
|
||||
* they will be called by H5FD__mpio_read/write_selection() for independent access.
|
||||
*
|
||||
*/
|
||||
static void
|
||||
test_bug_api_library(const char *filename, hid_t fapl)
|
||||
{
|
||||
hid_t dxpl = H5I_INVALID_HID;
|
||||
hid_t fid = H5I_INVALID_HID;
|
||||
hid_t did = H5I_INVALID_HID;
|
||||
hid_t sid = H5I_INVALID_HID;
|
||||
hid_t fspace_id = H5I_INVALID_HID;
|
||||
hid_t mspace_id = H5I_INVALID_HID;
|
||||
hsize_t dims[2];
|
||||
hsize_t start[2];
|
||||
hsize_t stride[2];
|
||||
hsize_t count[2];
|
||||
hsize_t block[2];
|
||||
int *wbuf;
|
||||
hsize_t i, j;
|
||||
|
||||
if ((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
dims[0] = (hsize_t)BIG_X_FACTOR;
|
||||
dims[1] = (hsize_t)BIG_Y_FACTOR;
|
||||
|
||||
if ((sid = H5Screate_simple(2, dims, NULL)) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if ((did = H5Dcreate2(fid, "bug_coll_to_ind", H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT,
|
||||
H5P_DEFAULT)) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if ((wbuf = malloc((size_t)dims[0] * (size_t)dims[1] * sizeof(int))) == NULL)
|
||||
P_TEST_ERROR;
|
||||
|
||||
/* Each process takes a slabs of rows. */
|
||||
block[0] = (hsize_t)dims[0] / (hsize_t)mpi_size;
|
||||
block[1] = (hsize_t)dims[1];
|
||||
stride[0] = block[0];
|
||||
stride[1] = block[1];
|
||||
count[0] = 1;
|
||||
count[1] = 1;
|
||||
start[0] = (hsize_t)mpi_rank * block[0];
|
||||
start[1] = 0;
|
||||
|
||||
if ((fspace_id = H5Dget_space(did)) < 0)
|
||||
P_TEST_ERROR;
|
||||
if (MAINPROCESS) {
|
||||
if (H5Sselect_none(fspace_id) < 0)
|
||||
P_TEST_ERROR;
|
||||
} /* end if */
|
||||
else {
|
||||
if (H5Sselect_hyperslab(fspace_id, H5S_SELECT_SET, start, stride, count, block) < 0)
|
||||
P_TEST_ERROR;
|
||||
} /* end else */
|
||||
|
||||
if ((mspace_id = H5Screate_simple(2, block, NULL)) < 0)
|
||||
P_TEST_ERROR;
|
||||
if (MAINPROCESS) {
|
||||
if (H5Sselect_none(mspace_id) < 0)
|
||||
P_TEST_ERROR;
|
||||
} /* end if */
|
||||
|
||||
if ((dxpl = H5Pcreate(H5P_DATASET_XFER)) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
/* Enable collective transfer */
|
||||
if (H5Pset_dxpl_mpio(dxpl, H5FD_MPIO_COLLECTIVE) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
/* Enable selection I/O */
|
||||
if (H5Pset_selection_io(dxpl, H5D_SELECTION_IO_MODE_ON) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
/* Put some trivial data in wbuf */
|
||||
for (i = 0; i < block[0]; i++) {
|
||||
for (j = 0; j < block[1]; j++) {
|
||||
*wbuf = (int)((i + start[0]) * 100 + (j + start[1] + 1));
|
||||
wbuf++;
|
||||
}
|
||||
}
|
||||
|
||||
/* With datatype conversion */
|
||||
if (H5Dwrite(did, H5T_NATIVE_UCHAR, mspace_id, fspace_id, dxpl, wbuf) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if (H5Dclose(did) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if (H5Pclose(dxpl) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if (H5Sclose(fspace_id) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if (H5Sclose(mspace_id) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if (H5Fclose(fid) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
return;
|
||||
|
||||
} /* test_bug_api_library() */
|
||||
|
||||
/*
|
||||
* Verify bugs exposed when H5D_SELECTION_IO_MODE_ON is set as the
|
||||
* default in the library.
|
||||
*/
|
||||
static void
|
||||
test_bugs_select_on(const char *filename, hid_t fapl)
|
||||
{
|
||||
if (MAINPROCESS) {
|
||||
printf("\n");
|
||||
TESTING("to verify bugs exposed when H5D_SELECTION_IO_MODE_ON is set as library default");
|
||||
}
|
||||
|
||||
curr_nerrors = nerrors;
|
||||
|
||||
test_bug_optimized_bufs(filename, fapl);
|
||||
test_bug_base_addr(filename, fapl);
|
||||
test_bug_api_library(filename, fapl);
|
||||
|
||||
CHECK_PASSED();
|
||||
return;
|
||||
|
||||
} /* test_bugs_select_on() */
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: main
|
||||
*
|
||||
@ -3740,12 +4139,10 @@ main(int argc, char *argv[])
|
||||
if (H5Fclose(fid) < 0)
|
||||
P_TEST_ERROR;
|
||||
|
||||
if (MAINPROCESS) {
|
||||
printf("\n");
|
||||
TESTING("Testing for H5Pget_no_selection_io_cause()");
|
||||
}
|
||||
test_get_no_selection_io_cause(FILENAME, fapl);
|
||||
|
||||
test_bugs_select_on(FILENAME, fapl);
|
||||
|
||||
/* Barrier to make sure all ranks are done before deleting the file, and
|
||||
* also to clean up output (make sure PASSED is printed before any of the
|
||||
* following messages) */
|
||||
|
1805
testpar/t_vfd.c
1805
testpar/t_vfd.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user