/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 * * distribution tree, or in https://www.hdfgroup.org/licenses. * * If you do not have access to either file, you may request a copy from * * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * Purpose: This is the first half of a two-part test that makes sure * that a file can be read after a parallel application crashes * as long as the file was flushed first. We simulate a crash by * calling _exit() since this doesn't flush HDF5 caches but * still exits with success. */ #include "h5test.h" static const char *FILENAME[] = {"flush", "noflush", NULL}; static int *data_g = NULL; #define N_GROUPS 100 /*------------------------------------------------------------------------- * Function: create_test_file * * Purpose: Creates the file used in part 1 of the test * * Return: Success: A valid file ID * Failure: H5I_INVALID_HID *------------------------------------------------------------------------- */ static hid_t create_test_file(char *name, size_t name_length, hid_t fapl_id) { hid_t fid = H5I_INVALID_HID; hid_t dcpl_id = H5I_INVALID_HID; hid_t sid = H5I_INVALID_HID; hid_t did = H5I_INVALID_HID; hid_t top_level_gid = H5I_INVALID_HID; hid_t gid = H5I_INVALID_HID; hid_t dxpl_id = H5I_INVALID_HID; hsize_t dims[2] = {100, 100}; hsize_t chunk_dims[2] = {5, 5}; hsize_t i, j; if ((fid = H5Fcreate(name, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id)) < 0) goto error; /* Create a chunked dataset */ if ((dcpl_id = H5Pcreate(H5P_DATASET_CREATE)) < 0) goto error; if (H5Pset_chunk(dcpl_id, 2, chunk_dims) < 0) goto error; if ((sid = H5Screate_simple(2, dims, NULL)) < 0) goto error; if ((did = H5Dcreate2(fid, "dset", H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) goto error; if ((dxpl_id = H5Pcreate(H5P_DATASET_XFER)) < 0) goto error; if (H5Pset_dxpl_mpio(dxpl_id, H5FD_MPIO_COLLECTIVE) < 0) goto error; /* Write some data */ for (i = 0; i < dims[0]; i++) for (j = 0; j < dims[1]; j++) data_g[(i * 100) + j] = (int)(i + (i * j) + j); if (H5Dwrite(did, H5T_NATIVE_INT, sid, sid, dxpl_id, data_g) < 0) goto error; /* Create some groups */ if ((top_level_gid = H5Gcreate2(fid, "some_groups", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) goto error; for (i = 0; i < N_GROUPS; i++) { snprintf(name, name_length, "grp%02u", (unsigned)i); if ((gid = H5Gcreate2(top_level_gid, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) goto error; if (H5Gclose(gid) < 0) goto error; } return fid; error: return H5I_INVALID_HID; } /* end create_test_file() */ /*------------------------------------------------------------------------- * Function: main * * Purpose: Part 1 of a two-part parallel H5Fflush() test. * * Return: EXIT_FAILURE (always) *------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { hid_t fid1 = H5I_INVALID_HID; hid_t fid2 = H5I_INVALID_HID; hid_t fapl_id = H5I_INVALID_HID; MPI_File *mpifh_p = NULL; char name[1024]; const char *driver_name; int mpi_size; int mpi_rank; MPI_Comm comm = MPI_COMM_WORLD; MPI_Info info = MPI_INFO_NULL; MPI_Init(&argc, &argv); MPI_Comm_size(comm, &mpi_size); MPI_Comm_rank(comm, &mpi_rank); if (mpi_rank == 0) TESTING("H5Fflush (part1)"); /* Don't run using the split VFD */ driver_name = h5_get_test_driver_name(); if (!strcmp(driver_name, "split")) { if (mpi_rank == 0) { SKIPPED(); puts(" Test not compatible with current Virtual File Driver"); } MPI_Finalize(); exit(EXIT_FAILURE); } if (NULL == (data_g = malloc(100 * 100 * sizeof(*data_g)))) goto error; if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) goto error; if (H5Pset_fapl_mpio(fapl_id, comm, info) < 0) goto error; /* Create the file */ h5_fixname(FILENAME[0], fapl_id, name, sizeof(name)); if ((fid1 = create_test_file(name, sizeof(name), fapl_id)) < 0) goto error; /* Flush and exit without closing the library */ if (H5Fflush(fid1, H5F_SCOPE_GLOBAL) < 0) goto error; /* Create the other file which will not be flushed */ h5_fixname(FILENAME[1], fapl_id, name, sizeof(name)); if ((fid2 = create_test_file(name, sizeof(name), fapl_id)) < 0) goto error; if (mpi_rank == 0) PASSED(); fflush(stdout); fflush(stderr); /* Some systems like AIX do not like files not being closed when MPI_Finalize * is called. So, we need to get the MPI file handles, close them by hand. * Then the _exit is still needed to stop at_exit from happening in some systems. * Note that MPIO VFD returns the address of the file-handle in the VFD struct * because MPI_File_close wants to modify the file-handle variable. */ /* Close file 1 */ if (H5Fget_vfd_handle(fid1, fapl_id, (void **)&mpifh_p) < 0) goto error; if (MPI_File_close(mpifh_p) != MPI_SUCCESS) goto error; /* Close file 2 */ if (H5Fget_vfd_handle(fid2, fapl_id, (void **)&mpifh_p) < 0) goto error; if (MPI_File_close(mpifh_p) != MPI_SUCCESS) goto error; fflush(stdout); fflush(stderr); if (data_g) { free(data_g); data_g = NULL; } /* Always exit with a failure code! * * In accordance with the standard, not having all processes * call MPI_Finalize() can be considered an error, so mpiexec * et al. may indicate failure on return. It's much easier to * always ignore the failure condition than to handle some * platforms returning success and others failure. */ _exit(EXIT_FAILURE); error: fflush(stdout); fflush(stderr); printf("*** ERROR ***\n"); printf("THERE WAS A REAL ERROR IN t_pflush1.\n"); fflush(stdout); if (data_g) free(data_g); _exit(EXIT_FAILURE); } /* end main() */