2023-05-03 03:52:39 +08:00
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
|
|
* Copyright by The HDF Group. *
|
|
|
|
* All rights reserved. *
|
|
|
|
* *
|
|
|
|
* This file is part of HDF5. The full HDF5 copyright notice, including *
|
|
|
|
* terms governing use, modification, and redistribution, is contained in *
|
|
|
|
* the COPYING file, which can be found at the root of the source code *
|
2023-07-13 06:33:58 +08:00
|
|
|
* distribution tree, or in https://www.hdfgroup.org/licenses. *
|
2023-05-03 03:52:39 +08:00
|
|
|
* If you do not have access to either file, you may request a copy from *
|
|
|
|
* help@hdfgroup.org. *
|
|
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
|
|
|
|
#include "H5_api_file_test_parallel.h"
|
|
|
|
|
|
|
|
static int test_create_file(void);
|
|
|
|
static int test_open_file(void);
|
|
|
|
static int test_split_comm_file_access(void);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The array of parallel file tests to be performed.
|
|
|
|
*/
|
|
|
|
static int (*par_file_tests[])(void) = {
|
|
|
|
test_create_file,
|
|
|
|
test_open_file,
|
|
|
|
test_split_comm_file_access,
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* A test to ensure that a file can be created in parallel.
|
|
|
|
*/
|
|
|
|
#define FILE_CREATE_TEST_FILENAME "test_file_parallel.h5"
|
|
|
|
static int
|
|
|
|
test_create_file(void)
|
|
|
|
{
|
|
|
|
hid_t file_id = H5I_INVALID_HID;
|
|
|
|
hid_t fapl_id = H5I_INVALID_HID;
|
|
|
|
|
|
|
|
TESTING("H5Fcreate");
|
|
|
|
|
|
|
|
/* Make sure the connector supports the API functions being tested */
|
|
|
|
if (!(vol_cap_flags_g & H5VL_CAP_FLAG_FILE_BASIC)) {
|
|
|
|
SKIPPED();
|
2023-06-28 23:31:32 +08:00
|
|
|
printf(" API functions for basic file aren't supported with this connector\n");
|
2023-05-03 03:52:39 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-09-06 02:49:37 +08:00
|
|
|
if ((fapl_id = create_mpi_fapl(MPI_COMM_WORLD, MPI_INFO_NULL, true)) < 0)
|
2023-05-03 03:52:39 +08:00
|
|
|
TEST_ERROR;
|
|
|
|
|
|
|
|
if ((file_id = H5Fcreate(FILE_CREATE_TEST_FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id)) < 0) {
|
|
|
|
H5_FAILED();
|
2023-06-28 23:31:32 +08:00
|
|
|
printf(" couldn't create file '%s'\n", FILE_CREATE_TEST_FILENAME);
|
2023-05-03 03:52:39 +08:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (H5Pclose(fapl_id) < 0)
|
|
|
|
TEST_ERROR;
|
|
|
|
if (H5Fclose(file_id) < 0)
|
|
|
|
TEST_ERROR;
|
|
|
|
|
|
|
|
PASSED();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
H5E_BEGIN_TRY
|
|
|
|
{
|
|
|
|
H5Pclose(fapl_id);
|
|
|
|
H5Fclose(file_id);
|
|
|
|
}
|
2023-08-03 06:46:26 +08:00
|
|
|
H5E_END_TRY
|
2023-05-03 03:52:39 +08:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* A test to ensure that a file can be opened in parallel.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
test_open_file(void)
|
|
|
|
{
|
|
|
|
hid_t file_id = H5I_INVALID_HID;
|
|
|
|
hid_t fapl_id = H5I_INVALID_HID;
|
|
|
|
|
|
|
|
TESTING_MULTIPART("H5Fopen");
|
|
|
|
|
|
|
|
/* Make sure the connector supports the API functions being tested */
|
|
|
|
if (!(vol_cap_flags_g & H5VL_CAP_FLAG_FILE_BASIC)) {
|
|
|
|
SKIPPED();
|
2023-06-28 23:31:32 +08:00
|
|
|
printf(" API functions for basic file aren't supported with this connector\n");
|
2023-05-03 03:52:39 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
TESTING_2("test setup");
|
|
|
|
|
2023-09-06 02:49:37 +08:00
|
|
|
if ((fapl_id = create_mpi_fapl(MPI_COMM_WORLD, MPI_INFO_NULL, true)) < 0)
|
2023-05-03 03:52:39 +08:00
|
|
|
TEST_ERROR;
|
|
|
|
|
|
|
|
PASSED();
|
|
|
|
|
|
|
|
BEGIN_MULTIPART
|
|
|
|
{
|
|
|
|
PART_BEGIN(H5Fopen_rdonly)
|
|
|
|
{
|
|
|
|
TESTING_2("H5Fopen in read-only mode");
|
|
|
|
|
|
|
|
if ((file_id = H5Fopen(H5_api_test_parallel_filename, H5F_ACC_RDONLY, fapl_id)) < 0) {
|
|
|
|
H5_FAILED();
|
2023-06-28 23:31:32 +08:00
|
|
|
printf(" unable to open file '%s' in read-only mode\n", H5_api_test_parallel_filename);
|
2023-05-03 03:52:39 +08:00
|
|
|
PART_ERROR(H5Fopen_rdonly);
|
|
|
|
}
|
|
|
|
|
|
|
|
PASSED();
|
|
|
|
}
|
|
|
|
PART_END(H5Fopen_rdonly);
|
|
|
|
|
|
|
|
if (file_id >= 0) {
|
|
|
|
H5E_BEGIN_TRY
|
|
|
|
{
|
|
|
|
H5Fclose(file_id);
|
|
|
|
}
|
2023-08-03 06:46:26 +08:00
|
|
|
H5E_END_TRY
|
2023-05-03 03:52:39 +08:00
|
|
|
file_id = H5I_INVALID_HID;
|
|
|
|
}
|
|
|
|
|
|
|
|
PART_BEGIN(H5Fopen_rdwrite)
|
|
|
|
{
|
|
|
|
TESTING_2("H5Fopen in read-write mode");
|
|
|
|
|
|
|
|
if ((file_id = H5Fopen(H5_api_test_parallel_filename, H5F_ACC_RDWR, fapl_id)) < 0) {
|
|
|
|
H5_FAILED();
|
2023-06-28 23:31:32 +08:00
|
|
|
printf(" unable to open file '%s' in read-write mode\n", H5_api_test_parallel_filename);
|
2023-05-03 03:52:39 +08:00
|
|
|
PART_ERROR(H5Fopen_rdwrite);
|
|
|
|
}
|
|
|
|
|
|
|
|
PASSED();
|
|
|
|
}
|
|
|
|
PART_END(H5Fopen_rdwrite);
|
|
|
|
|
|
|
|
if (file_id >= 0) {
|
|
|
|
H5E_BEGIN_TRY
|
|
|
|
{
|
|
|
|
H5Fclose(file_id);
|
|
|
|
}
|
2023-08-03 06:46:26 +08:00
|
|
|
H5E_END_TRY
|
2023-05-03 03:52:39 +08:00
|
|
|
file_id = H5I_INVALID_HID;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX: SWMR open flags
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
END_MULTIPART;
|
|
|
|
|
|
|
|
TESTING_2("test cleanup");
|
|
|
|
|
|
|
|
if (H5Pclose(fapl_id) < 0)
|
|
|
|
TEST_ERROR;
|
|
|
|
|
|
|
|
PASSED();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
H5E_BEGIN_TRY
|
|
|
|
{
|
|
|
|
H5Pclose(fapl_id);
|
|
|
|
H5Fclose(file_id);
|
|
|
|
}
|
2023-08-03 06:46:26 +08:00
|
|
|
H5E_END_TRY
|
2023-05-03 03:52:39 +08:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Tests file access by a communicator other than MPI_COMM_WORLD.
|
|
|
|
*
|
|
|
|
* Splits MPI_COMM_WORLD into two groups, where one (even_comm) contains
|
|
|
|
* the original processes of even ranks. The other (odd_comm) contains
|
|
|
|
* the original processes of odd ranks. Processes in even_comm create a
|
|
|
|
* file, then close it, using even_comm. Processes in old_comm just do
|
|
|
|
* a barrier using odd_comm. Then they all do a barrier using MPI_COMM_WORLD.
|
|
|
|
* If the file creation and close does not do correct collective action
|
|
|
|
* according to the communicator argument, the processes will freeze up
|
|
|
|
* sooner or later due to MPI_Barrier calls being mixed up.
|
|
|
|
*/
|
|
|
|
#define SPLIT_FILE_COMM_TEST_FILE_NAME "split_comm_file.h5"
|
|
|
|
static int
|
|
|
|
test_split_comm_file_access(void)
|
|
|
|
{
|
|
|
|
MPI_Comm comm;
|
|
|
|
MPI_Info info = MPI_INFO_NULL;
|
|
|
|
hid_t file_id = H5I_INVALID_HID;
|
|
|
|
hid_t fapl_id = H5I_INVALID_HID;
|
|
|
|
int is_old;
|
|
|
|
int newrank;
|
|
|
|
int err_occurred = 0;
|
|
|
|
|
|
|
|
TESTING("file access with a split communicator");
|
|
|
|
|
|
|
|
/* Make sure the connector supports the API functions being tested */
|
|
|
|
if (!(vol_cap_flags_g & H5VL_CAP_FLAG_FILE_BASIC)) {
|
|
|
|
SKIPPED();
|
2023-06-28 23:31:32 +08:00
|
|
|
printf(" API functions for basic file aren't supported with this connector\n");
|
2023-05-03 03:52:39 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set up MPI parameters */
|
|
|
|
MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
|
|
|
|
is_old = mpi_rank % 2;
|
|
|
|
if (MPI_SUCCESS != MPI_Comm_split(MPI_COMM_WORLD, is_old, mpi_rank, &comm)) {
|
|
|
|
H5_FAILED();
|
2023-06-28 23:31:32 +08:00
|
|
|
printf(" failed to split communicator!\n");
|
2023-05-03 03:52:39 +08:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
MPI_Comm_rank(comm, &newrank);
|
|
|
|
|
|
|
|
if (is_old) {
|
|
|
|
/* odd-rank processes */
|
|
|
|
if (MPI_SUCCESS != MPI_Barrier(comm)) {
|
|
|
|
err_occurred = 1;
|
|
|
|
goto access_end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* even-rank processes */
|
|
|
|
int sub_mpi_rank; /* rank in the sub-comm */
|
|
|
|
|
|
|
|
MPI_Comm_rank(comm, &sub_mpi_rank);
|
|
|
|
|
|
|
|
/* setup file access template */
|
2023-09-06 02:49:37 +08:00
|
|
|
if ((fapl_id = create_mpi_fapl(comm, info, true)) < 0) {
|
2023-05-03 03:52:39 +08:00
|
|
|
err_occurred = 1;
|
|
|
|
goto access_end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create the file collectively */
|
|
|
|
if ((file_id = H5Fcreate(SPLIT_FILE_COMM_TEST_FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id)) < 0) {
|
|
|
|
H5_FAILED();
|
2023-06-28 23:31:32 +08:00
|
|
|
printf(" couldn't create file '%s'\n", SPLIT_FILE_COMM_TEST_FILE_NAME);
|
2023-05-03 03:52:39 +08:00
|
|
|
err_occurred = 1;
|
|
|
|
goto access_end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* close the file */
|
|
|
|
if (H5Fclose(file_id) < 0) {
|
|
|
|
H5_FAILED();
|
2023-06-28 23:31:32 +08:00
|
|
|
printf(" failed to close file '%s'\n", SPLIT_FILE_COMM_TEST_FILE_NAME);
|
2023-05-03 03:52:39 +08:00
|
|
|
err_occurred = 1;
|
|
|
|
goto access_end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* delete the test file */
|
|
|
|
if (H5Fdelete(SPLIT_FILE_COMM_TEST_FILE_NAME, fapl_id) < 0) {
|
|
|
|
H5_FAILED();
|
2023-06-28 23:31:32 +08:00
|
|
|
printf(" failed to delete file '%s'\n", SPLIT_FILE_COMM_TEST_FILE_NAME);
|
2023-05-03 03:52:39 +08:00
|
|
|
err_occurred = 1;
|
|
|
|
goto access_end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Release file-access template */
|
|
|
|
if (H5Pclose(fapl_id) < 0) {
|
|
|
|
err_occurred = 1;
|
|
|
|
goto access_end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
access_end:
|
|
|
|
|
|
|
|
/* Get the collective results about whether an error occurred */
|
|
|
|
if (MPI_SUCCESS != MPI_Allreduce(MPI_IN_PLACE, &err_occurred, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD)) {
|
|
|
|
H5_FAILED();
|
2023-06-28 23:31:32 +08:00
|
|
|
printf(" MPI_Allreduce failed\n");
|
2023-05-03 03:52:39 +08:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (err_occurred) {
|
|
|
|
H5_FAILED();
|
2023-06-28 23:31:32 +08:00
|
|
|
printf(" an error occurred on only some ranks during split-communicator file access! - "
|
|
|
|
"collectively failing\n");
|
2023-05-03 03:52:39 +08:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MPI_SUCCESS != MPI_Comm_free(&comm)) {
|
|
|
|
H5_FAILED();
|
2023-06-28 23:31:32 +08:00
|
|
|
printf(" MPI_Comm_free failed\n");
|
2023-05-03 03:52:39 +08:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MPI_SUCCESS != MPI_Barrier(MPI_COMM_WORLD)) {
|
|
|
|
H5_FAILED();
|
2023-06-28 23:31:32 +08:00
|
|
|
printf(" MPI_Barrier on MPI_COMM_WORLD failed\n");
|
2023-05-03 03:52:39 +08:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
PASSED();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
H5E_BEGIN_TRY
|
|
|
|
{
|
|
|
|
H5Pclose(fapl_id);
|
|
|
|
H5Fclose(file_id);
|
|
|
|
}
|
2023-08-03 06:46:26 +08:00
|
|
|
H5E_END_TRY
|
2023-05-03 03:52:39 +08:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Cleanup temporary test files
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
cleanup_files(void)
|
|
|
|
{
|
|
|
|
hid_t fapl_id = H5I_INVALID_HID;
|
|
|
|
|
2023-09-06 02:49:37 +08:00
|
|
|
if ((fapl_id = create_mpi_fapl(MPI_COMM_WORLD, MPI_INFO_NULL, true)) < 0) {
|
2023-05-03 03:52:39 +08:00
|
|
|
if (MAINPROCESS)
|
2023-06-28 23:31:32 +08:00
|
|
|
printf(" failed to create FAPL for deleting test files\n");
|
2023-05-03 03:52:39 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
H5Fdelete(FILE_CREATE_TEST_FILENAME, fapl_id);
|
|
|
|
|
|
|
|
/* The below file is deleted as part of the test */
|
|
|
|
/* H5Fdelete(SPLIT_FILE_COMM_TEST_FILE_NAME, H5P_DEFAULT); */
|
|
|
|
|
|
|
|
if (H5Pclose(fapl_id) < 0) {
|
|
|
|
if (MAINPROCESS)
|
2023-06-28 23:31:32 +08:00
|
|
|
printf(" failed to close FAPL used for deleting test files\n");
|
2023-05-03 03:52:39 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
H5_api_file_test_parallel(void)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
int nerrors;
|
|
|
|
|
|
|
|
if (MAINPROCESS) {
|
2023-06-28 23:31:32 +08:00
|
|
|
printf("**********************************************\n");
|
|
|
|
printf("* *\n");
|
|
|
|
printf("* API Parallel File Tests *\n");
|
|
|
|
printf("* *\n");
|
|
|
|
printf("**********************************************\n\n");
|
2023-05-03 03:52:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0, nerrors = 0; i < ARRAY_LENGTH(par_file_tests); i++) {
|
|
|
|
nerrors += (*par_file_tests[i])() ? 1 : 0;
|
|
|
|
|
|
|
|
if (MPI_SUCCESS != MPI_Barrier(MPI_COMM_WORLD)) {
|
|
|
|
if (MAINPROCESS)
|
2023-06-28 23:31:32 +08:00
|
|
|
printf(" MPI_Barrier() failed!\n");
|
2023-05-03 03:52:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MAINPROCESS) {
|
2023-06-28 23:31:32 +08:00
|
|
|
printf("\n");
|
|
|
|
printf("Cleaning up testing files\n");
|
2023-05-03 03:52:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
cleanup_files();
|
|
|
|
|
|
|
|
return nerrors;
|
|
|
|
}
|