summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkyang2014 <kyang2014@users.noreply.github.com>2021-12-08 18:09:10 (GMT)
committerGitHub <noreply@github.com>2021-12-08 18:09:10 (GMT)
commit63f084bc8d56c607f570a56cb9e2c188acb4bb62 (patch)
tree0c0dff561e6b73fecec9bcb9b9a7ff5be51b895a
parent0247538fc5226b0899f00c45adab2a454627de02 (diff)
parent4b4c7c4b73038545e29de1608a82cee551b97d82 (diff)
downloadhdf5-63f084bc8d56c607f570a56cb9e2c188acb4bb62.zip
hdf5-63f084bc8d56c607f570a56cb9e2c188acb4bb62.tar.gz
hdf5-63f084bc8d56c607f570a56cb9e2c188acb4bb62.tar.bz2
Merge pull request #1247 from kyang2014/feature/vfd_swmr
Feature/vfd swmr
-rw-r--r--MANIFEST1
-rw-r--r--test/Makefile.am5
-rw-r--r--test/testvfdswmr.sh.in26
-rw-r--r--test/vfd_swmr_indep_rw_writer.c811
4 files changed, 840 insertions, 3 deletions
diff --git a/MANIFEST b/MANIFEST
index cbb4a32..bad97be 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -1441,6 +1441,7 @@
./test/vfd_swmr_group_writer.c
./test/vfd_swmr_gperf_writer.c
./test/vfd_swmr_gfail_writer.c
+./test/vfd_swmr_indep_rw_writer.c
./test/vfd_swmr_reader.c
./test/vfd_swmr_remove_reader.c
./test/vfd_swmr_remove_writer.c
diff --git a/test/Makefile.am b/test/Makefile.am
index 87b2925..f7ed4c6 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -56,6 +56,7 @@ SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) links_env$(EXEEXT) \
vfd_swmr_zoo_reader$(EXEEXT) vfd_swmr_zoo_writer$(EXEEXT) \
vfd_swmr_gperf_reader$(EXEEXT) vfd_swmr_gperf_writer$(EXEEXT) \
vfd_swmr_gfail_reader$(EXEEXT) vfd_swmr_gfail_writer$(EXEEXT) \
+ vfd_swmr_indep_wr_p0$(EXEEXT) vfd_swmr_indep_wr_p1$(EXEEXT) \
vds_env$(EXEEXT) \
vds_swmr_gen$(EXEEXT) vds_swmr_reader$(EXEEXT) vds_swmr_writer$(EXEEXT)
if HAVE_SHARED_CONDITIONAL
@@ -115,6 +116,7 @@ check_PROGRAMS=$(TEST_PROG) error_test err_compat tcheck_version \
vfd_swmr_attrdset_reader vfd_swmr_attrdset_writer \
vfd_swmr_gperf_reader vfd_swmr_gperf_writer \
vfd_swmr_gfail_reader vfd_swmr_gfail_writer \
+ vfd_swmr_indep_wr_p0 vfd_swmr_indep_wr_p1 \
vfd_swmr_check_compat \
vfd_swmr_dsetchks_reader vfd_swmr_dsetchks_writer \
swmr_check_compat_vfd vds_env vds_swmr_gen vds_swmr_reader vds_swmr_writer \
@@ -184,6 +186,9 @@ vfd_swmr_bigset_reader_SOURCES=vfd_swmr_bigset_writer.c
vfd_swmr_group_reader_SOURCES=vfd_swmr_group_writer.c
vfd_swmr_gperf_reader_SOURCES=vfd_swmr_gperf_writer.c
vfd_swmr_gfail_reader_SOURCES=vfd_swmr_gfail_writer.c
+vfd_swmr_indep_wr_p0_SOURCES=vfd_swmr_indep_rw_writer.c
+vfd_swmr_indep_wr_p1_SOURCES=vfd_swmr_indep_rw_writer.c
+
vfd_swmr_dsetops_reader_SOURCES=vfd_swmr_dsetops_writer.c
vfd_swmr_attrdset_writer_SOURCES=vfd_swmr_attrdset_writer.c
diff --git a/test/testvfdswmr.sh.in b/test/testvfdswmr.sh.in
index 535aafa..d52527b 100644
--- a/test/testvfdswmr.sh.in
+++ b/test/testvfdswmr.sh.in
@@ -143,13 +143,14 @@ fi
all_tests="generator expand shrink expand_shrink sparse vlstr_null vlstr_oob zoo"
all_tests="${all_tests} groups groups_attrs groups_ops few_big many_small attrdset"
-tests=${all_tests}
-# For exhaustive run, add: os_groups_attrs, os_groups_ops, os_groups_seg, dsetops, dsetchks
+# For exhaustive run, add: os_groups_attrs, os_groups_ops, os_groups_seg, dsetops, dsetchks,independ_wr
if [[ "$HDF5TestExpress" -eq 0 ]] ; then # exhaustive run
- all_tests="${all_tests} os_groups_attrs os_groups_ops os_groups_seg dsetops dsetchks"
+ all_tests="${all_tests} os_groups_attrs os_groups_ops os_groups_seg dsetops dsetchks independ_wr"
fi
+tests=${all_tests}
+
if [ $# -gt 0 ]; then
tests=
fi
@@ -1367,6 +1368,25 @@ for flush in "" "-U"; do
done
done
+if [ ${do_independ_wr:-no} = yes ]; then
+ echo launch vfd_swmr_indep_wr_p0 ..... process 0 ......
+ echo launch vfd_swmr_indep_wr_p1 ..... process 1 ......
+ catch_out_err_and_rc vfd_swmr_indep_wr_p0 \
+ ../vfd_swmr_indep_wr_p0 &
+ pid_writer=$!
+
+ catch_out_err_and_rc vfd_swmr_group_reader \
+ ../vfd_swmr_indep_wr_p1 &
+ pid_reader=$!
+
+ wait $pid_reader
+ wait $pid_writer
+ # Clean up output files
+ rm -f vfd_swmr_indep_wr_p0.{out,rc}
+ rm -f vfd_swmr_indep_wr_p1.{out,rc}
+fi
+
+
###############################################################################
## Report and exit
###############################################################################
diff --git a/test/vfd_swmr_indep_rw_writer.c b/test/vfd_swmr_indep_rw_writer.c
new file mode 100644
index 0000000..678ccb2
--- /dev/null
+++ b/test/vfd_swmr_indep_rw_writer.c
@@ -0,0 +1,811 @@
+/*
+ * Copyright by The HDF Group.
+ * Copyright by the Board of Trustees of the University of Illinois.
+ * 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://support.hdfgroup.org/ftp/HDF5/releases.
+ * If you do not have access to either file, you may request a copy from
+ * help@hdfgroup.org.
+ */
+
+/* This program checks independence of writer and reader for VFD SWMR.
+ * A writer can also be a reader of another writer. A reader can also be a
+ * writer. The program adapts from the "many small" and the "few big" tests.
+ * One can test the program as follows:
+ * Run ./vfd_swmr_indep_wr_p0 at one terminal
+ * Run ./vfd_swmr_indep_wr_p1 at another terminal
+ * You should see something like:
+ * Successfully write the dataset /dataset-0 for file vfd_swmr_indep_wr_p0.h5.
+ * Successfully open the dataset /dataset-1 for file vfd_swmr_indep_wr_p1.h5.
+ * Successfully verify a dataset.
+ * and
+ * Successfully open the dataset /dataset-0 for file vfd_swmr_indep_wr_p0.h5.
+ * Successfully verify a dataset.
+ * Successfully write the dataset /dataset-1 for file vfd_swmr_indep_wr_p1.h5.
+ */
+
+#define H5C_FRIEND /*suppress error about including H5Cpkg */
+#define H5F_FRIEND /*suppress error about including H5Fpkg */
+
+#include "hdf5.h"
+#include "H5Cpkg.h"
+#include "H5Fpkg.h"
+#include "H5HGprivate.h"
+#include "H5VLprivate.h"
+
+#include "testhdf5.h"
+#include "vfd_swmr_common.h"
+
+#ifndef H5_HAVE_WIN32_API
+
+#define DATA_ROWS 256
+#define DATA_COLS 512
+#define DATA_RANK 2
+#define NUM_ATTEMPTS 100
+
+/* Structure for filling the dataset values. Adapted from vfd_swmr_bigset_writer.c. */
+typedef struct _mat {
+ unsigned rows, cols;
+ uint32_t elt[1];
+} mat_t;
+
+/* Structure to hold the information of various parameters used in the program. */
+typedef struct {
+ hid_t file[2];
+ const char * filename[2];
+ char progname[PATH_MAX];
+ hid_t r_dsetid;
+ hid_t dtype, fapl, fcpl;
+ unsigned int rows, cols;
+ int rank;
+ hsize_t dims[DATA_RANK];
+ uint32_t max_lag;
+ uint32_t tick_len;
+ uint32_t ps;
+ uint32_t pbs;
+ uint32_t check_interval;
+ bool use_vfd_swmr;
+ bool first_proc;
+} state_t;
+
+/* Assign the initialized values to struct state_t declared above */
+static inline state_t
+state_initializer(void)
+{
+ return (state_t){.file = {H5I_INVALID_HID, H5I_INVALID_HID},
+ .filename = {"", ""},
+ .r_dsetid = H5I_INVALID_HID,
+ .dtype = H5T_NATIVE_UINT32,
+ .fapl = H5I_INVALID_HID,
+ .fcpl = H5I_INVALID_HID,
+ .rows = DATA_ROWS,
+ .cols = DATA_COLS,
+ .rank = DATA_RANK,
+ .dims = {DATA_ROWS, DATA_COLS},
+ .max_lag = 7,
+ .tick_len = 4,
+ .ps = 4096,
+ .pbs = 4096,
+ .check_interval = 1,
+ .use_vfd_swmr = true,
+ .first_proc = true};
+}
+
+/* Obtain the data value at index [i][j] for the 2D matrix.
+ All the routines related to the matrix are adapted from the vfd_swmr_bigset_writer.c. */
+static uint32_t
+matget(const mat_t *mat, unsigned i, unsigned j)
+{
+ return mat->elt[i * mat->cols + j];
+}
+
+/* Set the data value at index [i][j] for the 2D matrix. */
+static bool
+matset(mat_t *mat, unsigned i, unsigned j, uint32_t v)
+{
+ if (i >= mat->rows || j >= mat->cols) {
+ HDfprintf(stderr, "index out of boundary\n");
+ TEST_ERROR;
+ }
+
+ mat->elt[i * mat->cols + j] = v;
+
+ return true;
+
+error:
+ return false;
+}
+
+/* Allocate memory for the 2-D matrix. */
+static mat_t *
+newmat(state_t s)
+{
+ mat_t *mat;
+
+ mat = HDmalloc(sizeof(*mat) + (s.rows * s.cols - 1) * sizeof(mat->elt[0]));
+ if (mat == NULL) {
+ HDfprintf(stderr, "HDmalloc failed\n");
+ TEST_ERROR;
+ }
+
+ mat->rows = s.rows;
+ mat->cols = s.cols;
+
+ return mat;
+
+error:
+ return NULL;
+}
+
+/* Write or verify the dataset test pattern in the matrix `mat`.
+ * If `do_set` is true, write the pattern; otherwise, verify.
+ *
+ * The basic test pattern consists of increasing
+ * integers written in nested corners of the dataset
+ * starting at element (0, 0):
+ *
+ * 0
+ *
+ * 0 1
+ * 3 2
+ *
+ * 0 1 4
+ * 3 2 5
+ * 8 7 6
+ *
+ * 0 1 4 9
+ * 3 2 5 10
+ * 8 7 6 11
+ * 15 14 13 12
+ *
+ * In an actual pattern, the dataset number, `which`, is added to each integer.
+ *
+ */
+static bool
+set_or_verify_matrix(mat_t *mat, unsigned int which, bool do_set)
+{
+ unsigned row, col;
+ bool ret = true;
+
+ for (row = 0; row < mat->rows; row++) {
+ for (col = 0; col < mat->cols; col++) {
+ uint32_t v;
+ hsize_t i = row, j = col, u;
+ if (j <= i)
+ u = (i + 1) * (i + 1) - 1 - j;
+ else
+ u = j * j + i;
+
+ v = (uint32_t)(u + which);
+
+ if (do_set) {
+ if (!matset(mat, row, col, v)) {
+ HDfprintf(stderr, "data initialization failed\n");
+ ret = false;
+ break;
+ }
+ }
+ else if (matget(mat, row, col) != v) {
+ /* If the data doesn't match, return false
+ */
+ dbgf(1, "vrfy_matrix failed at row %u,col %u\n", row, col);
+ dbgf(1, "real value is %u\n", matget(mat, row, col));
+ dbgf(1, "expected value is %u\n", v);
+ ret = false;
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+/* Initialize the matrix values. The parameter 'which' determines the data value. */
+static bool
+init_matrix(mat_t *mat, unsigned int which)
+{
+ return set_or_verify_matrix(mat, which, true);
+}
+
+/* Verify the matrix values at each point. The parameter 'which" determines the data value. */
+static bool
+verify_matrix(mat_t *mat, unsigned int which)
+{
+ return set_or_verify_matrix(mat, which, false);
+}
+
+/* Usage of this program when running with the -h option */
+static void
+usage(const char *progname)
+{
+ fprintf(stderr,
+ "usage: %s [-S] [-c cols] [-r rows] [-t tick_len] [-m max_lag] \n"
+ " [-B page_buffer_size] [-s page_size] [-u reader wait interval] [-q silent output] \n"
+ "\n"
+ "-S: do not use VFD SWMR\n"
+ "-c cols: `cols` columns for the dataset\n"
+ " The default value is 512.\n"
+ "-r rows: `rows` rows for the dataset\n"
+ " The default value is 256.\n"
+ "-t tick_len: length of a tick in tenths of a second.\n"
+ "-m max_lag: maximum expected lag(in ticks) between writer and readers\n"
+ "-B pbs: page buffer size in bytes:\n"
+ " The default value is 4K(4096).\n"
+ "-s ps: page size used by page aggregation, page buffer and \n"
+ " the metadata file. The default value is 4K(4096).\n"
+ "-u 0.1s: interval in tenth of seconds to check if a dataset is ready for the reader.\n"
+ "-q: silence printouts, few messages\n"
+ "\n",
+ progname);
+ exit(EXIT_FAILURE);
+}
+
+/* Initialize the state_t with different options specified by the user. */
+static bool
+state_init(state_t *s, int argc, char **argv)
+{
+ unsigned long tmp;
+ int ch;
+ char * tfile = NULL;
+ char * end;
+ const char * personality;
+
+ *s = state_initializer();
+
+ if (H5_basename(argv[0], &tfile) < 0) {
+ HDprintf("H5_basename failed\n");
+ TEST_ERROR;
+ }
+
+ esnprintf(s->progname, sizeof(s->progname), "%s", tfile);
+
+ if (tfile) {
+ HDfree(tfile);
+ tfile = NULL;
+ }
+
+ while ((ch = getopt(argc, argv, "Sqc:r:t:m:B:s:u:")) != -1) {
+ switch (ch) {
+ case 'S':
+ s->use_vfd_swmr = false;
+ break;
+ case 'c':
+ case 'r':
+ case 't':
+ case 'm':
+ case 'B':
+ case 's':
+ case 'u':
+ errno = 0;
+ tmp = HDstrtoul(optarg, &end, 0);
+ if (end == optarg || *end != '\0') {
+ HDfprintf(stderr, "couldn't parse -%c argument %s\n", ch, optarg);
+ TEST_ERROR;
+ }
+ else if (errno != 0) {
+ HDfprintf(stderr, "couldn't parse -%c argument %s\n", ch, optarg);
+ TEST_ERROR;
+ }
+ else if (tmp > UINT_MAX) {
+ HDfprintf(stderr, "-%c argument %lu too large", ch, tmp);
+ TEST_ERROR;
+ }
+ if ((ch == 'c' || ch == 'r') && tmp == 0) {
+ HDfprintf(stderr, "-%c argument %lu must be >= 1", ch, tmp);
+ TEST_ERROR;
+ }
+
+ if (ch == 'c')
+ s->cols = (unsigned)tmp;
+ else if (ch == 'r')
+ s->rows = (unsigned)tmp;
+ else if (ch == 't')
+ s->tick_len = (unsigned)tmp;
+ else if (ch == 'm')
+ s->max_lag = (unsigned)tmp;
+ else if (ch == 'B')
+ s->pbs = (unsigned)tmp;
+ else if (ch == 's')
+ s->ps = (unsigned)tmp;
+ else if (ch == 'u')
+ s->check_interval = (unsigned)tmp;
+ break;
+ case 'q':
+ verbosity = 0;
+ break;
+ case '?':
+ default:
+ usage(s->progname);
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0) {
+ HDprintf("unexpected command-line arguments\n");
+ TEST_ERROR;
+ }
+
+ s->filename[0] = "vfd_swmr_indep_wr_p0.h5";
+ s->filename[1] = "vfd_swmr_indep_wr_p1.h5";
+ s->dims[0] = s->rows;
+ s->dims[1] = s->cols;
+
+ personality = HDstrstr(s->progname, "vfd_swmr_indep_wr");
+
+ if (personality != NULL && HDstrcmp(personality, "vfd_swmr_indep_wr_p0") == 0)
+ s->first_proc = true;
+ else if (personality != NULL && HDstrcmp(personality, "vfd_swmr_indep_wr_p1") == 0)
+ s->first_proc = false;
+ else {
+ HDprintf("unknown personality, expected vfd_swmr_indep_wr_{p0,p1}\n");
+ TEST_ERROR;
+ }
+
+ return true;
+
+error:
+ if (tfile)
+ HDfree(tfile);
+ return false;
+}
+
+/* Initialize the configuration and the file creation and access property lists
+ * for the VFD SMWR independence of the reader/writer test.
+ */
+static bool
+indep_init_vfd_swmr_config_plist(state_t *s, bool writer, const char *mdf_path)
+{
+
+ H5F_vfd_swmr_config_t config;
+
+ /* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */
+ init_vfd_swmr_config(&config, s->tick_len, s->max_lag, writer, TRUE, 128, mdf_path);
+
+ /* Pass the use_vfd_swmr, only_meta_page, page buffer size, config to vfd_swmr_create_fapl().*/
+ if ((s->fapl = vfd_swmr_create_fapl(true, s->use_vfd_swmr, true, s->pbs, &config)) < 0) {
+ printf("vfd_swmr_create_fapl failed\n");
+ TEST_ERROR;
+ }
+
+ /* Set fs_strategy (file space strategy) and fs_page_size (file space page size) */
+ if ((s->fcpl = vfd_swmr_create_fcpl(H5F_FSPACE_STRATEGY_PAGE, s->ps)) < 0) {
+ HDprintf("vfd_swmr_create_fcpl() failed");
+ TEST_ERROR;
+ }
+
+ return true;
+
+error:
+ return false;
+}
+
+/* Write the matrix mat to a dataset. The dataset name depends on the process it runs. */
+static bool
+write_dataset(const state_t *s, mat_t *mat)
+{
+
+ char dname[sizeof("/dataset-?")];
+ hid_t dset_id = H5I_INVALID_HID;
+ hid_t filespace = H5I_INVALID_HID;
+ unsigned int which = 0;
+
+ if (s->first_proc)
+ esnprintf(dname, sizeof(dname), "/dataset-%d", 0);
+ else {
+ esnprintf(dname, sizeof(dname), "/dataset-%d", 1);
+ which = 1;
+ }
+
+ filespace = H5Screate_simple(s->rank, s->dims, NULL);
+ if (filespace < 0) {
+ HDfprintf(stderr, "H5Screate_simple failed\n");
+ TEST_ERROR;
+ }
+
+ if ((dset_id = H5Dcreate2(s->file[which], dname, s->dtype, filespace, H5P_DEFAULT, H5P_DEFAULT,
+ H5P_DEFAULT)) < 0) {
+ HDfprintf(stderr, "H5Dcreate2 failed\n");
+ TEST_ERROR;
+ }
+
+ if (H5Sclose(filespace) < 0) {
+ HDfprintf(stderr, "H5Sclose failed\n");
+ TEST_ERROR;
+ }
+
+ if (!init_matrix(mat, which)) {
+ HDfprintf(stderr, "data initialization failed\n");
+ TEST_ERROR;
+ }
+
+ if (H5Dwrite(dset_id, H5T_NATIVE_UINT32, H5S_ALL, H5S_ALL, H5P_DEFAULT, mat->elt) < 0) {
+ HDfprintf(stderr, "H5Dwrite failed\n");
+ TEST_ERROR;
+ }
+
+ if (H5Dclose(dset_id) < 0) {
+ HDfprintf(stderr, "H5Dclose failed\n");
+ TEST_ERROR;
+ }
+
+ if (s->first_proc)
+ dbgf(1, "Process 0: Successfully write the dataset %s for file %s.\n", dname, s->filename[which]);
+ else
+ dbgf(1, "Process 1: Successfully write the dataset %s for file %s.\n", dname, s->filename[which]);
+
+ return true;
+
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Sclose(filespace);
+ H5Dclose(dset_id);
+ }
+ H5E_END_TRY;
+
+ return false;
+}
+
+/* Open the dataset according to the dataset name related to the process.
+ The dataset ID is saved in the state_t s */
+static bool
+open_dset(state_t *s)
+{
+
+ char dname[sizeof("/dataset-?")];
+ hid_t dset_id;
+ unsigned int i;
+ unsigned int fopen_idx = 0;
+
+ /* The first process reads the dataset from the second process
+ * The second process reads the dataset from the first process
+ */
+ if (s->first_proc) {
+ esnprintf(dname, sizeof(dname), "/dataset-%d", 1);
+ fopen_idx = 1;
+ }
+ else {
+ esnprintf(dname, sizeof(dname), "/dataset-%d", 0);
+ fopen_idx = 0;
+ }
+
+ /* Same as the big dset test, tries to open the dataset repeatedly until successful. After trying
+ * NUM_ATTEMPTS times without success, report it as a failure
+ */
+ for (i = 0; i < NUM_ATTEMPTS; i++) {
+ H5E_BEGIN_TRY
+ {
+ dset_id = H5Dopen2(s->file[fopen_idx], dname, H5P_DEFAULT);
+ }
+ H5E_END_TRY;
+
+ if (dset_id >= 0)
+ break;
+ else
+ decisleep(s->check_interval);
+ }
+
+ s->r_dsetid = dset_id;
+ if (i == NUM_ATTEMPTS) {
+ HDfprintf(stderr, "dataset opening reachs the maximal number of attempts\n");
+ TEST_ERROR;
+ }
+
+ if (s->first_proc)
+ dbgf(1, "Process 0: Successfully open the dataset %s for file %s.\n", dname, s->filename[fopen_idx]);
+ else
+ dbgf(1, "Process 1: Successfully open the dataset %s for file %s.\n", dname, s->filename[fopen_idx]);
+ return true;
+
+error:
+ return false;
+}
+
+/* Verify a dataset, this routine must be called after the open_dset().
+ * It will use the dataset ID assigned by open_dset().
+ */
+static bool
+vrfy_dset(const state_t *s, mat_t *mat)
+{
+
+ unsigned int i;
+ unsigned int which = 0;
+ herr_t status;
+
+ /* The approach is adapted from the big set test. A failure to read the data may indicate the data isn't
+ * ready yet. For this case, we will not display the error stack, instead sleeping for one tenth of a
+ * second, call H5Drefresh and try to call H5Dread again. After NUM_ATTEMPTS times, issue an error.
+ */
+
+ for (i = 0; i < NUM_ATTEMPTS; i++) {
+ H5E_BEGIN_TRY
+ {
+ status = H5Dread(s->r_dsetid, H5T_NATIVE_UINT32, H5S_ALL, H5S_ALL, H5P_DEFAULT, mat->elt);
+ }
+ H5E_END_TRY;
+ if (status < 0) {
+ decisleep(1);
+ /* Refresh the dataset and try it again */
+ if (H5Drefresh(s->r_dsetid) < 0) {
+ HDfprintf(stderr, "H5Drefresh failed\n");
+ TEST_ERROR;
+ }
+ }
+ else
+ break;
+ }
+ if (i == NUM_ATTEMPTS) {
+ HDfprintf(stderr, "dataset verification reached the maximal number of attempts\n");
+ TEST_ERROR;
+ }
+ if (s->first_proc)
+ which = 1;
+
+ if (verify_matrix(mat, which) == false) {
+ HDfprintf(stderr, "dataset verification failed\n");
+ TEST_ERROR;
+ }
+
+ if (s->first_proc)
+ dbgf(1, "Process 0: Successfully verify a dataset.\n");
+ else
+ dbgf(1, "Process 1: Successfully verify a dataset.\n");
+
+ return true;
+
+error:
+ return false;
+}
+
+/* The wrapper routine of open_dset() and vrfy_dset() for readers to verify a dataset. */
+static bool
+read_vrfy_dataset(state_t *s, mat_t *mat)
+{
+
+ if (false == open_dset(s)) {
+ HDfprintf(stderr, "Reader: open_dataset() failed\n");
+ TEST_ERROR;
+ }
+ if (false == vrfy_dset(s, mat)) {
+ HDfprintf(stderr, "Reader: vrfy_dataset() failed\n");
+ TEST_ERROR;
+ }
+
+ if (H5Dclose(s->r_dsetid) < 0) {
+ HDfprintf(stderr, "Reader: H5Dclose() failed\n");
+ TEST_ERROR;
+ }
+ return true;
+
+error:
+
+ H5E_BEGIN_TRY
+ {
+ H5Dclose(s->r_dsetid);
+ }
+ H5E_END_TRY;
+ return false;
+}
+
+/* Close the file access and creation property lists. */
+static bool
+close_pl(const state_t *s)
+{
+
+ if (H5Pclose(s->fapl) < 0) {
+ printf("H5Pclose failed\n");
+ TEST_ERROR;
+ }
+
+ if (H5Pclose(s->fcpl) < 0) {
+ printf("H5Pclose failed\n");
+ TEST_ERROR;
+ }
+
+ return true;
+
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Pclose(s->fapl);
+ H5Pclose(s->fcpl);
+ }
+ H5E_END_TRY;
+
+ return false;
+}
+
+int
+main(int argc, char **argv)
+{
+ bool writer = true;
+ state_t s;
+ bool ret = false;
+ unsigned i;
+ mat_t * mat = NULL;
+
+ if (!state_init(&s, argc, argv)) {
+ HDfprintf(stderr, "state_init failed\n");
+ TEST_ERROR;
+ }
+
+ if ((mat = newmat(s)) == NULL) {
+ HDfprintf(stderr, "could not allocate memory for dataset \n");
+ TEST_ERROR;
+ }
+
+ /* The first process writes a dataset in the first file and then reads a dataset from the second file.*/
+ if (s.first_proc) {
+
+ writer = true;
+ if (false == indep_init_vfd_swmr_config_plist(&s, writer, "./file1-shadow")) {
+ HDfprintf(stderr, "Writer: Cannot initialize file property lists for file %s\n", s.filename[0]);
+ TEST_ERROR;
+ }
+ s.file[0] = H5Fcreate(s.filename[0], H5F_ACC_TRUNC, s.fcpl, s.fapl);
+ if (s.file[0] < 0) {
+ HDfprintf(stderr, "H5Fcreate failed for the file %s\n", s.filename[0]);
+ TEST_ERROR;
+ }
+
+ ret = write_dataset(&s, mat);
+ if (ret == false) {
+ HDfprintf(stderr, "write_dataset failed for the file %s\n", s.filename[0]);
+ TEST_ERROR;
+ }
+
+ /* writer makes repeated HDF5 API calls
+ * to trigger EOT at approximately the correct time */
+ for (i = 0; i < s.max_lag + 1; i++) {
+ decisleep(s.tick_len);
+ H5E_BEGIN_TRY
+ {
+ H5Aexists(s.file[0], "nonexistent");
+ }
+ H5E_END_TRY;
+ }
+
+ if (false == close_pl(&s)) {
+ HDfprintf(stderr, "Fail to close file property lists for writing the file %s.\n", s.filename[0]);
+ TEST_ERROR;
+ }
+
+ writer = false;
+ if (false == indep_init_vfd_swmr_config_plist(&s, writer, "./file2-shadow")) {
+ HDfprintf(stderr, "Reader: Cannot initialize file property lists for file %s\n", s.filename[1]);
+ TEST_ERROR;
+ }
+ s.file[1] = H5Fopen(s.filename[1], H5F_ACC_RDONLY, s.fapl);
+ if (s.file[1] < 0) {
+ HDfprintf(stderr, "H5Fopen failed for the file %s\n", s.filename[1]);
+ TEST_ERROR;
+ }
+
+ ret = read_vrfy_dataset(&s, mat);
+ if (ret == false) {
+ HDfprintf(stderr, "read and verify dataset failed for file %s\n", s.filename[1]);
+ TEST_ERROR;
+ }
+
+ if (false == close_pl(&s)) {
+ HDfprintf(stderr, "Fail to close file property lists for reading the file %s.\n", s.filename[1]);
+ TEST_ERROR;
+ }
+
+ if (H5Fclose(s.file[0]) < 0) {
+ HDfprintf(stderr, "fail to close HDF5 file %s \n", s.filename[0]);
+ TEST_ERROR;
+ }
+
+ if (H5Fclose(s.file[1]) < 0) {
+ HDfprintf(stderr, "fail to close HDF5 file %s \n", s.filename[1]);
+ TEST_ERROR;
+ }
+ }
+ else {
+
+ /* The second process reads the dataset of the first file generated by the first process,
+ * then writes a dataset in the second file for the first process to read.
+ */
+ writer = false;
+ if (false == indep_init_vfd_swmr_config_plist(&s, writer, "./file1-shadow")) {
+ HDfprintf(stderr, "Reader: Cannot initialize file property lists for file %s\n", s.filename[0]);
+ TEST_ERROR;
+ }
+
+ s.file[0] = H5Fopen(s.filename[0], H5F_ACC_RDONLY, s.fapl);
+ if (s.file[0] < 0) {
+ HDfprintf(stderr, "H5Fopen failed for the file %s\n", s.filename[0]);
+ TEST_ERROR;
+ }
+ ret = read_vrfy_dataset(&s, mat);
+ if (ret == false) {
+ HDfprintf(stderr, "read and verify dataset failed for file %s\n", s.filename[0]);
+ TEST_ERROR;
+ }
+
+ if (false == close_pl(&s)) {
+ HDfprintf(stderr, "Fail to close file property lists for reading the file %s.\n", s.filename[0]);
+ TEST_ERROR;
+ }
+
+ writer = true;
+ if (false == indep_init_vfd_swmr_config_plist(&s, writer, "./file2-shadow")) {
+ HDfprintf(stderr, "writer: Cannot initialize file property lists for file %s\n", s.filename[1]);
+ TEST_ERROR;
+ }
+
+ s.file[1] = H5Fcreate(s.filename[1], H5F_ACC_TRUNC, s.fcpl, s.fapl);
+ if (s.file[1] < 0) {
+ HDfprintf(stderr, "H5Fcreate failed for the file %s\n", s.filename[1]);
+ TEST_ERROR;
+ }
+ ret = write_dataset(&s, mat);
+ if (ret == false) {
+ HDfprintf(stderr, "write_dataset failed for the file %s\n", s.filename[1]);
+ TEST_ERROR;
+ }
+
+ /* writer makes repeated HDF5 API calls
+ * to trigger EOT at approximately the correct time */
+ for (i = 0; i < s.max_lag + 1; i++) {
+ decisleep(s.tick_len);
+ H5E_BEGIN_TRY
+ {
+ H5Aexists(s.file[1], "nonexistent");
+ }
+ H5E_END_TRY;
+ }
+
+ if (false == close_pl(&s)) {
+ HDfprintf(stderr, "Fail to close file property lists for writing the file %s.\n", s.filename[1]);
+ TEST_ERROR;
+ }
+
+ if (H5Fclose(s.file[0]) < 0) {
+ HDfprintf(stderr, "fail to close HDF5 file %s \n", s.filename[0]);
+ TEST_ERROR;
+ }
+
+ if (H5Fclose(s.file[1]) < 0) {
+ HDfprintf(stderr, "fail to close HDF5 file %s \n", s.filename[1]);
+ TEST_ERROR;
+ }
+ }
+
+ if (mat)
+ HDfree(mat);
+
+ return EXIT_SUCCESS;
+
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Pclose(s.fapl);
+ H5Pclose(s.fcpl);
+ H5Fclose(s.file[0]);
+ H5Fclose(s.file[1]);
+ }
+ H5E_END_TRY;
+
+ if (mat)
+ HDfree(mat);
+
+ return EXIT_FAILURE;
+}
+
+#else /* H5_HAVE_WIN32_API */
+
+int
+main(void)
+{
+ HDfprintf(stderr, "Non-POSIX platform. Skipping.\n");
+ return EXIT_SUCCESS;
+} /* end main() */
+
+#endif /* H5_HAVE_WIN32_API */