/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 LICENSE 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 second 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(0) since this doesn't flush HDF5 caches but * still exits with success. */ #include "h5test.h" static const char *FLUSH_FILENAME[] = {"flush", NULL}; static const char *NOFLUSH_FILENAME[] = {"noflush", NULL}; static int *data_g = NULL; #define N_GROUPS 100 /*------------------------------------------------------------------------- * Function: check_test_file * * Purpose: Part 2 of a two-part H5Fflush() test. * * Return: SUCCEED/FAIL *------------------------------------------------------------------------- */ static herr_t check_test_file(char *name, size_t name_length, hid_t fapl_id) { hid_t fid = 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]; int val; hsize_t i, j; if ((dxpl_id = H5Pcreate(H5P_DATASET_XFER)) < 0) goto error; if (H5Pset_dxpl_mpio(dxpl_id, H5FD_MPIO_COLLECTIVE) < 0) goto error; if ((fid = H5Fopen(name, H5F_ACC_RDONLY, fapl_id)) < 0) goto error; /* Open the dataset */ if ((did = H5Dopen2(fid, "dset", H5P_DEFAULT)) < 0) goto error; if ((sid = H5Dget_space(did)) < 0) goto error; if (H5Sget_simple_extent_dims(sid, dims, NULL) < 0) goto error; assert(100 == dims[0] && 100 == dims[1]); /* Read some data */ if (H5Dread(did, H5T_NATIVE_INT, sid, sid, dxpl_id, data_g) < 0) goto error; for (i = 0; i < dims[0]; i++) { for (j = 0; j < dims[1]; j++) { val = (int)(i + (i * j) + j); if (data_g[(i * 100) + j] != val) { H5_FAILED(); printf(" data_g[%lu][%lu] = %d\n", (unsigned long)i, (unsigned long)j, data_g[(i * 100) + j]); printf(" should be %d\n", val); } } } /* Open some groups */ if ((top_level_gid = H5Gopen2(fid, "some_groups", H5P_DEFAULT)) < 0) goto error; for (i = 0; i < N_GROUPS; i++) { snprintf(name, name_length, "grp%02u", (unsigned)i); if ((gid = H5Gopen2(top_level_gid, name, H5P_DEFAULT)) < 0) goto error; if (H5Gclose(gid) < 0) goto error; } if (H5Gclose(top_level_gid) < 0) goto error; if (H5Dclose(did) < 0) goto error; if (H5Fclose(fid) < 0) goto error; if (H5Pclose(dxpl_id) < 0) goto error; if (H5Sclose(sid) < 0) goto error; return SUCCEED; error: H5E_BEGIN_TRY { H5Pclose(dxpl_id); H5Gclose(top_level_gid); H5Dclose(did); H5Fclose(fid); H5Sclose(sid); H5Gclose(gid); } H5E_END_TRY return FAIL; } /* end check_test_file() */ /*------------------------------------------------------------------------- * Function: main * * Purpose: Part 2 of a two-part H5Fflush() test. * * Return: EXIT_SUCCESS/EXIT_FAIL *------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { hid_t fapl_id1 = H5I_INVALID_HID; hid_t fapl_id2 = H5I_INVALID_HID; H5E_auto2_t func; 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 (part2 with flush)"); /* 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_SUCCESS); } if (NULL == (data_g = malloc(100 * 100 * sizeof(*data_g)))) goto error; if ((fapl_id1 = H5Pcreate(H5P_FILE_ACCESS)) < 0) goto error; if (H5Pset_fapl_mpio(fapl_id1, comm, info) < 0) goto error; if ((fapl_id2 = H5Pcreate(H5P_FILE_ACCESS)) < 0) goto error; if (H5Pset_fapl_mpio(fapl_id2, comm, info) < 0) goto error; /* Check the case where the file was flushed */ h5_fixname(FLUSH_FILENAME[0], fapl_id1, name, sizeof(name)); if (check_test_file(name, sizeof(name), fapl_id1)) { H5_FAILED(); goto error; } else if (mpi_rank == 0) { PASSED(); } /* Check the case where the file was not flushed. This should give an error * so we turn off the error stack temporarily. */ if (mpi_rank == 0) TESTING("H5Fflush (part2 without flush)"); H5Eget_auto2(H5E_DEFAULT, &func, NULL); H5Eset_auto2(H5E_DEFAULT, NULL, NULL); h5_fixname(NOFLUSH_FILENAME[0], fapl_id2, name, sizeof(name)); if (check_test_file(name, sizeof(name), fapl_id2)) { if (mpi_rank == 0) PASSED(); } else { H5_FAILED(); goto error; } H5Eset_auto2(H5E_DEFAULT, func, NULL); h5_delete_all_test_files(FLUSH_FILENAME, fapl_id1); H5Pclose(fapl_id1); h5_delete_all_test_files(NOFLUSH_FILENAME, fapl_id2); H5Pclose(fapl_id2); if (data_g) { free(data_g); data_g = NULL; } MPI_Finalize(); exit(EXIT_SUCCESS); error: if (data_g) free(data_g); exit(EXIT_FAILURE); } /* end main() */