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:
vchoi-hdfgroup 2023-08-06 22:12:07 -05:00 committed by GitHub
parent fb38a8b924
commit 291b2f7ae4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 4182 additions and 295 deletions

View File

@ -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 */

View File

@ -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]);

View File

@ -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
*

View File

@ -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);

View File

@ -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
*

File diff suppressed because it is too large Load Diff

View File

@ -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*/

View File

@ -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;

View File

@ -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);

View File

@ -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);
/*

View File

@ -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) */

File diff suppressed because it is too large Load Diff