summaryrefslogtreecommitdiffstats
path: root/test/vfd_swmr_bigset_writer.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/vfd_swmr_bigset_writer.c')
-rw-r--r--test/vfd_swmr_bigset_writer.c2557
1 files changed, 2019 insertions, 538 deletions
diff --git a/test/vfd_swmr_bigset_writer.c b/test/vfd_swmr_bigset_writer.c
index 6280af5..14cbedf 100644
--- a/test/vfd_swmr_bigset_writer.c
+++ b/test/vfd_swmr_bigset_writer.c
@@ -38,9 +38,14 @@
* (or the width and height) of a chunk, and writes a test pattern to
* the dataset on chunk boundaries.
*
+ * For 3D dataset, the extension is always along the first dimension.
+ * e.g. the chunk size is `l` x `m` x `n`, after `i` iterations, the
+ * dataset size becomes `i x l` x `m` x `n`.
+ * It does not test VDS for 3D dataset.
+ *
* The reader should be started with the same user-selectable parameters
* as the writer: iterations, number of datasets, chunk width and
- * height, dimensions.
+ * height and depth, dimensions.
*
* The reader opens the same HDF5 file, reads and re-reads it until all
* `n` datasets appear, and then reads and re-reads the datasets until
@@ -72,7 +77,6 @@
#include "H5Cpkg.h"
#include "H5Fpkg.h"
-// #include "H5Iprivate.h"
#include "H5HGprivate.h"
#include "H5VLprivate.h"
@@ -81,29 +85,40 @@
#ifndef H5_HAVE_WIN32_API
-#include <err.h>
-#include <libgen.h>
-
-#define ROWS 256
-#define COLS 512
-#define RANK 2
-
-static const unsigned int hang_back = 3;
+#define MAX_READ_LEN_IN_SECONDS 2
+#define TICK_LEN 4
+#define MAX_LAG 7
+#define FSP_SIZE 4096
+#define PAGE_BUF_SIZE 4096
+#define ROWS 256
+#define COLS 512
+#define DEPTH 1
+#define RANK2 2
+#define RANK3 3
+#define NUM_ATTEMPTS 100
+#define SKIP_CHUNK 0
+
+/* Calculate the time passed in seconds.
+ * X is the beginning time; Y is the ending time.
+ * Expects X, Y to be struct timespec from the function call HDclock_gettime.
+ */
+#define TIME_PASSED(X, Y) \
+ ((double)((Y.tv_sec - X.tv_sec) * 1000000000 + (Y.tv_nsec - X.tv_nsec))) / 1000000000.0
typedef struct _base {
- hsize_t row, col;
+ hsize_t depth, row, col;
} base_t;
typedef struct _mat {
- unsigned rows, cols;
+ unsigned depth, rows, cols;
uint32_t elt[1];
} mat_t;
typedef struct _quadrant {
- hsize_t start[RANK];
- hsize_t stride[RANK];
- hsize_t block[RANK];
- hsize_t count[RANK];
+ hsize_t start[RANK2];
+ hsize_t stride[RANK2];
+ hsize_t block[RANK2];
+ hsize_t count[RANK2];
hid_t space, src_space;
} quadrant_t;
@@ -114,30 +129,69 @@ typedef struct _sources {
#define MANY_FILES 4
typedef struct {
- hid_t * dataset;
- sources_t * sources;
- hid_t file[MANY_FILES];
- hid_t dapl, filetype, memspace, one_by_one_sid, quadrant_dcpl;
- unsigned ndatasets;
- const char * filename[MANY_FILES];
- char progname[PATH_MAX];
- struct timespec update_interval;
+ hid_t * dataset;
+ sources_t * sources;
+ hid_t file[MANY_FILES];
+ hid_t dapl, filetype, memspace, one_by_one_sid, quadrant_dcpl;
+ unsigned ndatasets;
+ const char *filename[MANY_FILES];
+ char progname[PATH_MAX];
struct {
quadrant_t ul, ur, bl, br, src;
} quadrants;
- unsigned int cols, rows;
+ unsigned int depth, cols, rows;
unsigned int asteps;
unsigned int nsteps;
- bool two_dee;
- bool wait_for_signal;
+ unsigned int part_chunk;
+ unsigned int skip_chunk;
+ unsigned int over_extend;
+ bool expand_2d;
+ bool test_3d;
enum { vds_off, vds_single, vds_multi } vds;
- bool use_vfd_swmr;
- bool writer;
- bool fixed_array;
- hsize_t chunk_dims[RANK];
- hsize_t one_dee_max_dims[RANK];
+ bool use_vfd_swmr;
+ bool use_legacy_swmr;
+ bool use_named_pipe;
+ bool do_perf;
+ bool cross_chunk_read;
+ bool writer;
+ bool fixed_array;
+ bool flush_raw_data;
+ hsize_t chunk_dims[RANK2];
+ hsize_t one_dee_max_dims[RANK2];
+ hsize_t fsp_size;
+ size_t page_buf_size;
+ uint32_t tick_len;
+ uint32_t max_lag;
+ unsigned mdc_init_size;
+ size_t chunk_cache_size;
+ unsigned int deflate_level;
+ struct timespec ival;
} state_t;
+/* Structure to hold info for named pipes */
+typedef struct {
+ const char *fifo_writer_to_reader; /* Name of fifo for writer to reader */
+ const char *fifo_reader_to_writer; /* Name of fifo for reader to writer */
+ int fd_writer_to_reader; /* File ID for fifo from writer to reader */
+ int fd_reader_to_writer; /* File ID for fifo from reader to writer */
+ int notify; /* Value to notify between writer and reader */
+ int verify; /* Value to verify between writer and reader */
+} np_state_t;
+
+typedef struct {
+ unsigned step;
+ struct timespec time;
+} exchange_info_t;
+
+/* Initializations for np_state_t */
+#define NP_INITIALIZER \
+ (np_state_t) \
+ { \
+ .fifo_writer_to_reader = "./fifo_bigset_writer_to_reader", \
+ .fifo_reader_to_writer = "./fifo_bigset_reader_to_writer", .fd_writer_to_reader = -1, \
+ .fd_reader_to_writer = -1, .notify = 0, .verify = 0 \
+ }
+
static inline state_t
state_initializer(void)
{
@@ -147,128 +201,153 @@ state_initializer(void)
.filetype = H5T_NATIVE_UINT32,
.one_by_one_sid = H5I_INVALID_HID,
.quadrant_dcpl = H5I_INVALID_HID,
+ .depth = DEPTH,
.rows = ROWS,
.cols = COLS,
.ndatasets = 5,
.asteps = 10,
.nsteps = 100,
+ .part_chunk = 0,
+ .skip_chunk = SKIP_CHUNK,
+ .over_extend = 1,
.filename = {"", "", "", ""},
- .two_dee = false,
- .wait_for_signal = true,
+ .expand_2d = false,
+ .test_3d = false,
.vds = vds_off,
.use_vfd_swmr = true,
+ .use_legacy_swmr = false,
+ .use_named_pipe = true,
+ .do_perf = false,
+ .cross_chunk_read = false,
.writer = true,
.fixed_array = false,
.one_dee_max_dims = {ROWS, H5S_UNLIMITED},
.chunk_dims = {ROWS, COLS},
- .update_interval =
- (struct timespec){.tv_sec = 0, .tv_nsec = 1000000000UL / 30 /* 1/30 second */}};
+ .fsp_size = FSP_SIZE,
+ .page_buf_size = PAGE_BUF_SIZE,
+ .tick_len = TICK_LEN,
+ .max_lag = MAX_LAG,
+ .flush_raw_data = false,
+ .mdc_init_size = 0,
+ .chunk_cache_size = 0,
+ .deflate_level = 0,
+ .ival = (struct timespec){.tv_sec = MAX_READ_LEN_IN_SECONDS, .tv_nsec = 0}};
}
-static void state_init(state_t *, int, char **);
+static bool state_init(state_t *, int, char **);
static const hid_t badhid = H5I_INVALID_HID;
-static hsize_t two_dee_max_dims[RANK];
-
-static uint32_t
-matget(const mat_t *mat, unsigned i, unsigned j)
-{
- assert(i < mat->rows && j < mat->cols);
-
- return mat->elt[i * mat->cols + j];
-}
-
-static void
-matset(mat_t *mat, unsigned i, unsigned j, uint32_t v)
-{
- assert(i < mat->rows && j < mat->cols);
-
- mat->elt[i * mat->cols + j] = v;
-}
-
-static mat_t *
-newmat(unsigned rows, unsigned cols)
-{
- mat_t *mat;
-
- mat = HDmalloc(sizeof(*mat) + (rows * cols - 1) * sizeof(mat->elt[0]));
-
- if (mat == NULL)
- err(EXIT_FAILURE, "%s: HDmalloc", __func__);
-
- mat->rows = rows;
- mat->cols = cols;
-
- return mat;
-}
+static hsize_t two_dee_max_dims[RANK2], three_dee_max_dims[RANK3];
static void
usage(const char *progname)
{
- fprintf(stderr,
- "usage: %s [-F] [-M] [-S] [-V] [-W] [-a steps] [-b] [-c cols]\n"
- " [-d dims]\n"
- " [-n iterations] [-r rows] [-s datasets]\n"
- " [-u milliseconds]\n"
- "\n"
- "-F: fixed maximal dimension for the chunked datasets\n"
- "-M: use virtual datasets and many source\n"
- " files\n"
- "-S: do not use VFD SWMR\n"
- "-V: use virtual datasets and a single\n"
- " source file\n"
- "-W: do not wait for a signal before\n"
- " exiting\n"
- "-a steps: `steps` between adding attributes\n"
- "-b: write data in big-endian byte order\n"
- "-c cols: `cols` columns per chunk\n"
- "-d 1|one|2|two|both: select dataset expansion in one or\n"
- " both dimensions\n"
- "-n iterations: how many times to expand each dataset\n"
- "-r rows: `rows` rows per chunk\n"
- "-s datasets: number of datasets to create\n"
- "-u ms: milliseconds interval between updates\n"
- " to %s.h5\n"
- "\n",
- progname, progname);
+ HDfprintf(
+ stderr,
+ "usage: %s [-C] [-F] [-M] [-P] [-R] [-S] [-V] [-W] [-a steps] [-b] [-c cols]\n"
+ " [-d dims] [-e depth] [-f tick_len] [-g max_lag] [-j skip_chunk] [-k part_chunk]\n"
+ " [-l tick_num] [-n iterations] [-o page_buf_size] [-p fsp_size] [-r rows]\n"
+ " [-s datasets] [-t] [-u over_extend] [-v chunk_cache_size] [-w deflate_level]\n"
+ "\n"
+ "-C: cross-over chunk read during chunk verification\n"
+ "-F: fixed maximal dimension for the chunked datasets\n"
+ "-M: use virtual datasets and many source\n"
+ " files\n"
+ "-N: do not use named pipes\n"
+ "-P: do the performance measurement\n"
+ "-R: flush raw data\n"
+ "-S: do not use VFD SWMR\n"
+ "-T: use legacy SWMR (-S and -N must also be specified)\n"
+ "-V: use virtual datasets and a single\n"
+ " source file\n"
+ "-a steps: `steps` between adding attributes\n"
+ "-b: write data in big-endian byte order\n"
+ "-c cols: `cols` columns of the chunk\n"
+ "-d 1|one|2|two|both: select dataset expansion in one or\n"
+ " both dimensions\n"
+ "-e depth: the first dimension of the 3D chunk\n"
+ "-f tick_len: tick length\n"
+ "-g max_lag: maximal lag\n"
+ "-j skip_chunk: skip the Nth (skip_chunk) chunks during chunk writing\n"
+ "-k part_chunk: the size for partial chunk write (only along the first dimension)\n"
+ "-l tick_num: expected maximal number of ticks from\n"
+ " the writer's finishing creation to the reader's finishing validation\n"
+ "-m mdc_init_size: the initial size of metadata cache in megabytes (must be between 1 and 32MB)\n"
+ "-n iterations: how many times to expand each dataset\n"
+ "-o page_buf_size: page buffer size\n"
+ "-p fsp_size: file space page size\n"
+ "-r rows: `rows` rows of the chunk\n"
+ "-s datasets: number of datasets to create\n"
+ "-t: enable test for 3D datasets (dataset expansion is along one dimension)\n"
+ " currently, 3D datasets isn't tested with VDS\n"
+ "-u over_extend: extend the size of the dataset in multiple chunks or partial chunks\n"
+ "-v chunk_cache_size: the size of raw data chunk cache in bytes\n"
+ "-w deflate_level: the level (0 - 9) of gzip compression\n"
+ "\n",
+ progname);
exit(EXIT_FAILURE);
}
-static void
+static bool
make_quadrant_dataspace(state_t *s, quadrant_t *q)
{
- q->space = H5Screate_simple(NELMTS(s->chunk_dims), s->chunk_dims,
- s->two_dee ? two_dee_max_dims : s->one_dee_max_dims);
+ if ((q->space = H5Screate_simple(NELMTS(s->chunk_dims), s->chunk_dims,
+ s->expand_2d ? two_dee_max_dims : s->one_dee_max_dims)) < 0) {
+ HDfprintf(stderr, "H5Screate_simple failed\n");
+ TEST_ERROR;
+ }
- if (q->space < 0) {
- errx(EXIT_FAILURE, "%s.%d: H5Screate_simple failed", __func__, __LINE__);
+ if (H5Sselect_hyperslab(q->space, H5S_SELECT_SET, q->start, q->stride, q->count, q->block) < 0) {
+ HDfprintf(stderr, "H5Sselect_hyperslab failed\n");
+ TEST_ERROR;
}
- if (H5Sselect_hyperslab(q->space, H5S_SELECT_SET, q->start, q->stride, q->count, q->block) < 0)
- errx(EXIT_FAILURE, "%s: H5Sselect_hyperslab failed", __func__);
+ return true;
+
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Sclose(q->space);
+ }
+ H5E_END_TRY;
+
+ return false;
}
-static void
+static bool
state_init(state_t *s, int argc, char **argv)
{
unsigned long tmp;
int ch;
unsigned i;
- const hsize_t dims = 1;
- char tfile[PATH_MAX];
+ const hsize_t dims = 1;
+ char * tfile = NULL;
char * end;
- unsigned long millis;
+ size_t rdcc_nslots, rdcc_nbytes;
+ double rdcc_w0;
quadrant_t *const ul = &s->quadrants.ul, *const ur = &s->quadrants.ur, *const bl = &s->quadrants.bl,
*const br = &s->quadrants.br, *const src = &s->quadrants.src;
const char *personality;
*s = state_initializer();
- esnprintf(tfile, sizeof(tfile), "%s", argv[0]);
- esnprintf(s->progname, sizeof(s->progname), "%s", basename(tfile));
- while ((ch = getopt(argc, argv, "FMSVWa:bc:d:n:qr:s:u:")) != -1) {
+ if (H5_basename(argv[0], &tfile) < 0) {
+ HDfprintf(stderr, "H5_basename failed\n");
+ TEST_ERROR;
+ }
+
+ esnprintf(s->progname, sizeof(s->progname), "%s", tfile);
+
+ if (tfile)
+ HDfree(tfile);
+
+ while ((ch = getopt(argc, argv, "CFMNPRSTVa:bc:d:e:f:g:j:k:l:m:n:o:p:qr:s:tu:v:w:")) != -1) {
switch (ch) {
+ case 'C':
+ /* This flag indicates cross-over chunk read during data validation */
+ s->cross_chunk_read = true;
+ break;
case 'F':
/* The flag to indicate whether the maximal dimension of the chunked datasets is fixed or
* unlimited */
@@ -277,74 +356,124 @@ state_init(state_t *s, int argc, char **argv)
case 'M':
s->vds = vds_multi;
break;
+ case 'P':
+ s->do_perf = true;
+ break;
+ case 'R':
+ s->flush_raw_data = true;
+ break;
case 'S':
s->use_vfd_swmr = false;
break;
+ case 'T':
+ s->use_legacy_swmr = true;
+ break;
case 'V':
s->vds = vds_single;
break;
- case 'W':
- s->wait_for_signal = false;
+ case 'N':
+ /* Disable named pipes, mainly for running the writer and reader seperately */
+ s->use_named_pipe = false;
break;
case 'd':
if (strcmp(optarg, "1") == 0 || strcmp(optarg, "one") == 0)
- s->two_dee = false;
+ s->expand_2d = false;
else if (strcmp(optarg, "2") == 0 || strcmp(optarg, "two") == 0 ||
strcmp(optarg, "both") == 0)
- s->two_dee = true;
+ s->expand_2d = true;
else {
- errx(EXIT_FAILURE, "bad -d argument \"%s\"", optarg);
+ HDfprintf(stderr, "bad -d argument %s\n", optarg);
+ TEST_ERROR;
}
break;
case 'a':
case 'c':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
case 'n':
+ case 'o':
+ case 'p':
case 'r':
case 's':
+ case 'u':
+ case 'v':
+ case 'w':
errno = 0;
- tmp = strtoul(optarg, &end, 0);
+ tmp = HDstrtoul(optarg, &end, 0);
if (end == optarg || *end != '\0') {
- errx(EXIT_FAILURE, "couldn't parse `-%c` argument `%s`", ch, optarg);
+ HDfprintf(stderr, "couldn't parse -%c argument %s\n", ch, optarg);
+ TEST_ERROR;
}
else if (errno != 0) {
- err(EXIT_FAILURE, "couldn't parse `-%c` argument `%s`", ch, optarg);
+ 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;
}
- else if (tmp > UINT_MAX)
- errx(EXIT_FAILURE, "`-%c` argument `%lu` too large", ch, tmp);
if ((ch == 'c' || ch == 'r') && tmp == 0) {
- errx(EXIT_FAILURE, "`-%c` argument `%lu` must be >= 1", ch, tmp);
+ HDfprintf(stderr, "-%c argument %lu must be >= 1", ch, tmp);
+ TEST_ERROR;
}
if (ch == 'a')
s->asteps = (unsigned)tmp;
else if (ch == 'c')
s->cols = (unsigned)tmp;
+ else if (ch == 'e')
+ s->depth = (unsigned)tmp;
+ else if (ch == 'f')
+ s->tick_len = (unsigned)tmp;
+ else if (ch == 'g')
+ s->max_lag = (unsigned)tmp;
+ else if (ch == 'j')
+ s->skip_chunk = (unsigned)tmp;
+ else if (ch == 'k')
+ s->part_chunk = (unsigned)tmp;
+ else if (ch == 'l') {
+ /* Translate the tick number to time represented by the timespec struct */
+ float time = (float)(((unsigned)tmp * TICK_LEN) / 10.0);
+ unsigned sec = (unsigned)time;
+ unsigned nsec = (unsigned)((time - sec) * 10 * 1000 * 1000);
+
+ s->ival.tv_sec = sec;
+ s->ival.tv_nsec = nsec;
+ }
+ else if (ch == 'm')
+ s->mdc_init_size = (unsigned)tmp;
else if (ch == 'n')
s->nsteps = (unsigned)tmp;
+ else if (ch == 'o')
+ s->page_buf_size = (unsigned)tmp;
+ else if (ch == 'p')
+ s->fsp_size = (unsigned)tmp;
else if (ch == 'r')
s->rows = (unsigned)tmp;
+ else if (ch == 'u')
+ s->over_extend = (unsigned)tmp;
+ else if (ch == 'v')
+ s->chunk_cache_size = (unsigned)tmp;
+ else if (ch == 'w')
+ s->deflate_level = (unsigned)tmp;
else
s->ndatasets = (unsigned)tmp;
break;
+ case 't':
+ s->test_3d = true;
+ break;
case 'b':
s->filetype = H5T_STD_U32BE;
break;
case 'q':
verbosity = 0;
break;
- case 'u':
- errno = 0;
- millis = strtoul(optarg, &end, 0);
- if (millis == ULONG_MAX && errno == ERANGE) {
- err(EXIT_FAILURE, "option -p argument \"%s\"", optarg);
- }
- else if (*end != '\0') {
- errx(EXIT_FAILURE, "garbage after -p argument \"%s\"", optarg);
- }
- s->update_interval.tv_sec = (time_t)(millis / 1000UL);
- s->update_interval.tv_nsec = (long)((millis * 1000000UL) % 1000000000UL);
- break;
case '?':
default:
usage(s->progname);
@@ -354,29 +483,62 @@ state_init(state_t *s, int argc, char **argv)
argc -= optind;
argv += optind;
- if (argc > 0)
- errx(EXIT_FAILURE, "unexpected command-line arguments");
+ if (argc > 0) {
+ HDfprintf(stderr, "unexpected command-line arguments\n");
+ TEST_ERROR;
+ }
- if (s->vds != vds_off && s->two_dee) {
- errx(EXIT_FAILURE, "virtual datasets and 2D datasets are mutually exclusive");
+ if (s->vds != vds_off && s->expand_2d) {
+ HDfprintf(stderr, "virtual datasets and 2D datasets are mutually exclusive\n");
+ TEST_ERROR;
}
- s->chunk_dims[0] = s->rows;
- s->chunk_dims[1] = s->cols;
+ if (s->test_3d) {
+ if (s->depth < 1) {
+ HDfprintf(stderr, "The depth of 3D dataset can't be less than 1\n");
+ TEST_ERROR;
+ }
+
+ if (s->expand_2d) {
+ HDfprintf(stderr, "3D dataset test doesn't support 2D expansion\n");
+ TEST_ERROR;
+ }
+
+ if (s->vds != vds_off) {
+ HDfprintf(stderr, "3D dataset test doesn't support VDS\n");
+ TEST_ERROR;
+ }
+ }
+
+ s->chunk_dims[0] = s->rows;
+ s->chunk_dims[1] = s->cols;
+
s->one_dee_max_dims[0] = s->rows;
if (s->fixed_array) {
s->one_dee_max_dims[1] = s->cols * s->nsteps;
two_dee_max_dims[0] = s->rows * s->nsteps;
two_dee_max_dims[1] = s->cols * s->nsteps;
+
+ if (s->test_3d) {
+ three_dee_max_dims[0] = s->depth * s->nsteps;
+ three_dee_max_dims[1] = s->rows;
+ three_dee_max_dims[2] = s->cols;
+ }
}
else {
s->one_dee_max_dims[1] = H5S_UNLIMITED;
two_dee_max_dims[0] = two_dee_max_dims[1] = H5S_UNLIMITED;
+
+ if (s->test_3d) {
+ three_dee_max_dims[0] = H5S_UNLIMITED;
+ three_dee_max_dims[1] = s->rows;
+ three_dee_max_dims[2] = s->cols;
+ }
}
if (s->vds != vds_off) {
- const hsize_t half_chunk_dims[RANK] = {s->rows / 2, s->cols / 2};
- hsize_t half_max_dims[RANK];
+ const hsize_t half_chunk_dims[RANK2] = {s->rows / 2, s->cols / 2};
+ hsize_t half_max_dims[RANK2];
if (s->fixed_array) {
half_max_dims[0] = s->rows / 2;
@@ -388,11 +550,14 @@ state_init(state_t *s, int argc, char **argv)
}
if ((s->quadrant_dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0) {
- errx(EXIT_FAILURE, "%s.%d: H5Pcreate failed", __func__, __LINE__);
+ HDfprintf(stderr, "H5Pcreate failed\n");
+ TEST_ERROR;
}
- if (H5Pset_chunk(s->quadrant_dcpl, RANK, half_chunk_dims) < 0)
- errx(EXIT_FAILURE, "H5Pset_chunk failed");
+ if (H5Pset_chunk(s->quadrant_dcpl, RANK2, half_chunk_dims) < 0) {
+ HDfprintf(stderr, "H5Pset_chunk failed\n");
+ TEST_ERROR;
+ }
*ul = (quadrant_t){.start = {0, 0},
.stride = {s->rows, s->cols},
@@ -414,72 +579,126 @@ state_init(state_t *s, int argc, char **argv)
.block = {s->rows / 2, s->cols / 2},
.count = {1, H5S_UNLIMITED}};
- make_quadrant_dataspace(s, ul);
- make_quadrant_dataspace(s, ur);
- make_quadrant_dataspace(s, bl);
- make_quadrant_dataspace(s, br);
+ if (!make_quadrant_dataspace(s, ul)) {
+ HDfprintf(stderr, "make_quadrant_dataspace failed\n");
+ TEST_ERROR;
+ }
+
+ if (!make_quadrant_dataspace(s, ur)) {
+ HDfprintf(stderr, "make_quadrant_dataspace failed\n");
+ TEST_ERROR;
+ }
+
+ if (!make_quadrant_dataspace(s, bl)) {
+ HDfprintf(stderr, "make_quadrant_dataspace failed\n");
+ TEST_ERROR;
+ }
+
+ if (!make_quadrant_dataspace(s, br)) {
+ HDfprintf(stderr, "make_quadrant_dataspace failed\n");
+ TEST_ERROR;
+ }
*src = (quadrant_t){.start = {0, 0},
.stride = {s->rows / 2, s->cols / 2},
.block = {s->rows / 2, s->cols / 2},
.count = {1, H5S_UNLIMITED}};
- src->space = H5Screate_simple(RANK, half_chunk_dims, half_max_dims);
-
- if (src->space < 0) {
- errx(EXIT_FAILURE, "%s.%d: H5Screate_simple failed", __func__, __LINE__);
+ if ((src->space = H5Screate_simple(RANK2, half_chunk_dims, half_max_dims)) < 0) {
+ HDfprintf(stderr, "H5Screate_simple failed\n");
+ TEST_ERROR;
}
if (H5Sselect_hyperslab(src->space, H5S_SELECT_SET, src->start, src->stride, src->count, src->block) <
- 0)
- errx(EXIT_FAILURE, "%s: H5Sselect_hyperslab failed", __func__);
-
- ul->src_space = H5Screate_simple(RANK, half_chunk_dims, half_max_dims);
-
- if (ul->src_space < 0) {
- errx(EXIT_FAILURE, "%s.%d: H5Screate_simple failed", __func__, __LINE__);
+ 0) {
+ HDfprintf(stderr, "H5Sselect_hyperslab failed\n");
+ TEST_ERROR;
}
- ur->src_space = H5Screate_simple(RANK, half_chunk_dims, half_max_dims);
-
- if (ur->src_space < 0) {
- errx(EXIT_FAILURE, "%s.%d: H5Screate_simple failed", __func__, __LINE__);
+ if ((ul->src_space = H5Screate_simple(RANK2, half_chunk_dims, half_max_dims)) < 0) {
+ HDfprintf(stderr, "H5Screate_simple failed\n");
+ TEST_ERROR;
}
- bl->src_space = H5Screate_simple(RANK, half_chunk_dims, half_max_dims);
-
- if (bl->src_space < 0) {
- errx(EXIT_FAILURE, "%s.%d: H5Screate_simple failed", __func__, __LINE__);
+ if ((ur->src_space = H5Screate_simple(RANK2, half_chunk_dims, half_max_dims)) < 0) {
+ HDfprintf(stderr, "H5Screate_simple failed\n");
+ TEST_ERROR;
}
- br->src_space = H5Screate_simple(RANK, half_chunk_dims, half_max_dims);
+ if ((bl->src_space = H5Screate_simple(RANK2, half_chunk_dims, half_max_dims)) < 0) {
+ HDfprintf(stderr, "H5Screate_simple failed\n");
+ TEST_ERROR;
+ }
- if (br->src_space < 0) {
- errx(EXIT_FAILURE, "%s.%d: H5Screate_simple failed", __func__, __LINE__);
+ if ((br->src_space = H5Screate_simple(RANK2, half_chunk_dims, half_max_dims)) < 0) {
+ HDfprintf(stderr, "H5Screate_simple failed\n");
+ TEST_ERROR;
}
}
/* space for attributes */
- if ((s->one_by_one_sid = H5Screate_simple(1, &dims, &dims)) < 0)
- errx(EXIT_FAILURE, "H5Screate_simple failed");
+ if ((s->one_by_one_sid = H5Screate_simple(1, &dims, &dims)) < 0) {
+ HDfprintf(stderr, "H5Screate_simple failed\n");
+ TEST_ERROR;
+ }
- s->dataset = HDmalloc(sizeof(*s->dataset) * s->ndatasets);
- if (s->dataset == NULL)
- err(EXIT_FAILURE, "could not allocate dataset handles");
+ if ((s->dataset = HDmalloc(sizeof(hid_t) * s->ndatasets)) == NULL) {
+ HDfprintf(stderr, "HDmalloc failed\n");
+ TEST_ERROR;
+ }
- s->sources = HDmalloc(sizeof(*s->sources) * s->ndatasets);
- if (s->sources == NULL)
- err(EXIT_FAILURE, "could not allocate quadrant dataset handles");
+ if ((s->sources = HDmalloc(sizeof(*s->sources) * s->ndatasets)) == NULL) {
+ HDfprintf(stderr, "HDmalloc failed\n");
+ TEST_ERROR;
+ }
for (i = 0; i < s->ndatasets; i++) {
s->dataset[i] = badhid;
s->sources[i].ul = s->sources[i].ur = s->sources[i].bl = s->sources[i].br = badhid;
}
- s->memspace = H5Screate_simple(RANK, s->chunk_dims, NULL);
+ if (s->test_3d) {
+ hsize_t dims3[RANK3] = {s->depth, s->chunk_dims[0], s->chunk_dims[1]};
+
+ if (s->part_chunk)
+ dims3[0] = s->part_chunk;
- if (s->memspace < 0) {
- errx(EXIT_FAILURE, "%s.%d: H5Screate_simple failed", __func__, __LINE__);
+ if ((s->memspace = H5Screate_simple(RANK3, dims3, NULL)) < 0) {
+ HDfprintf(stderr, "H5Screate_simple failed\n");
+ TEST_ERROR;
+ }
+ }
+ else {
+ hsize_t dims2[RANK2];
+
+ if (s->expand_2d) {
+ dims2[0] = s->chunk_dims[0];
+ dims2[1] = s->chunk_dims[1];
+ }
+ else {
+ dims2[0] = s->chunk_dims[0];
+
+ if (s->part_chunk)
+ dims2[1] = s->part_chunk;
+ else
+ dims2[1] = s->chunk_dims[1];
+ }
+
+ if ((s->memspace = H5Screate_simple(RANK2, dims2, NULL)) < 0) {
+ HDfprintf(stderr, "H5Screate_simple failed\n");
+ TEST_ERROR;
+ }
+ }
+
+ /* The default is zero, meaning no skip */
+ if (s->skip_chunk == 1) {
+ HDfprintf(stderr, "can't skip every chunk\n");
+ TEST_ERROR;
+ }
+
+ if (s->over_extend == 0) {
+ HDfprintf(stderr, "Extension of the dataset can't be zero\n");
+ TEST_ERROR;
}
s->filename[0] = "vfd_swmr_bigset.h5";
@@ -494,52 +713,156 @@ state_init(state_t *s, int argc, char **argv)
s->filename[3] = s->filename[0];
}
- personality = strstr(s->progname, "vfd_swmr_bigset_");
+ personality = HDstrstr(s->progname, "vfd_swmr_bigset_");
- if (personality != NULL && strcmp(personality, "vfd_swmr_bigset_writer") == 0)
+ if (personality != NULL && HDstrcmp(personality, "vfd_swmr_bigset_writer") == 0)
s->writer = true;
- else if (personality != NULL && strcmp(personality, "vfd_swmr_bigset_reader") == 0)
+ else if (personality != NULL && HDstrcmp(personality, "vfd_swmr_bigset_reader") == 0)
s->writer = false;
else {
- errx(EXIT_FAILURE, "unknown personality, expected vfd_swmr_bigset_{reader,writer}");
+ HDfprintf(stderr, "unknown personality, expected vfd_swmr_bigset_{reader,writer}\n");
+ TEST_ERROR;
+ }
+
+ if ((s->dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0) {
+ HDfprintf(stderr, "H5Pcreate failed\n");
+ TEST_ERROR;
+ }
+
+ if (s->chunk_cache_size) {
+ if (H5Pget_chunk_cache(s->dapl, &rdcc_nslots, &rdcc_nbytes, &rdcc_w0) < 0) {
+ HDfprintf(stderr, "H5Pget_chunk_cache failed\n");
+ TEST_ERROR;
+ }
+
+ if (H5Pset_chunk_cache(s->dapl, rdcc_nslots, s->chunk_cache_size, rdcc_w0) < 0) {
+ HDfprintf(stderr, "H5Pset_chunk_cache failed\n");
+ TEST_ERROR;
+ }
+ }
+
+ if (s->deflate_level > 9) {
+ HDfprintf(stderr, "deflation level must be between 0 and 9\n");
+ TEST_ERROR;
+ }
+
+ if (s->vds != vds_off && H5Pset_virtual_view(s->dapl, H5D_VDS_FIRST_MISSING) < 0) {
+ HDfprintf(stderr, "H5Pset_virtual_view failed\n");
+ TEST_ERROR;
+ }
+
+ if (s->use_legacy_swmr) {
+ if (s->use_vfd_swmr) {
+ HDfprintf(stderr, "Can't use both VFD SWMR and Legacy SWMR\n");
+ TEST_ERROR;
+ }
+
+ if (s->use_named_pipe) {
+ HDfprintf(stderr, "Can't use named pipe for the Legacy SWMR\n");
+ TEST_ERROR;
+ }
}
- if ((s->dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
- errx(EXIT_FAILURE, "%s.%d: H5Pcreate failed", __func__, __LINE__);
+ return true;
+
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Pclose(s->quadrant_dcpl);
+ H5Sclose(ul->space);
+ H5Sclose(ur->space);
+ H5Sclose(bl->space);
+ H5Sclose(br->space);
+ H5Sclose(ul->src_space);
+ H5Sclose(ur->src_space);
+ H5Sclose(bl->src_space);
+ H5Sclose(br->src_space);
+ H5Sclose(src->space);
+ H5Sclose(s->one_by_one_sid);
+ H5Sclose(s->memspace);
+ }
+ H5E_END_TRY;
+
+ if (tfile)
+ HDfree(tfile);
+
+ if (s->dataset)
+ HDfree(s->dataset);
- if (H5Pset_chunk_cache(s->dapl, 0, 0, H5D_CHUNK_CACHE_W0_DEFAULT) < 0)
- errx(EXIT_FAILURE, "H5Pset_chunk_cache failed");
+ if (s->sources)
+ HDfree(s->sources);
- if (s->vds != vds_off && H5Pset_virtual_view(s->dapl, H5D_VDS_FIRST_MISSING) < 0)
- errx(EXIT_FAILURE, "H5Pset_virtual_view failed");
+ return false;
}
-static void
+static bool
state_destroy(state_t *s)
{
- size_t i;
-
- if (H5Pclose(s->dapl) < 0)
- errx(EXIT_FAILURE, "H5Pclose(fapl)");
+ size_t i;
+ struct timespec start_time, end_time;
- s->dapl = badhid;
+ if (H5Pclose(s->dapl) < 0) {
+ HDfprintf(stderr, "H5Pclose failed\n");
+ TEST_ERROR;
+ }
if (s->vds != vds_off) {
quadrant_t *const ul = &s->quadrants.ul, *const ur = &s->quadrants.ur, *const bl = &s->quadrants.bl,
*const br = &s->quadrants.br;
if (H5Sclose(ul->src_space) < 0 || H5Sclose(ur->src_space) < 0 || H5Sclose(bl->src_space) < 0 ||
- H5Sclose(br->src_space) < 0)
- errx(EXIT_FAILURE, "H5Sclose failed");
+ H5Sclose(br->src_space) < 0) {
+ HDfprintf(stderr, "H5Sclose failed\n");
+ TEST_ERROR;
+ }
- ul->src_space = ur->src_space = bl->src_space = br->src_space = badhid;
+ if (H5Sclose(ul->space) < 0 || H5Sclose(ur->space) < 0 || H5Sclose(bl->space) < 0 ||
+ H5Sclose(br->space) < 0) {
+ HDfprintf(stderr, "H5Sclose failed\n");
+ TEST_ERROR;
+ }
- if (H5Pclose(s->quadrant_dcpl) < 0)
- errx(EXIT_FAILURE, "H5Pclose(dcpl)");
+ if (H5Pclose(s->quadrant_dcpl) < 0) {
+ HDfprintf(stderr, "H5Pclose failed\n");
+ TEST_ERROR;
+ }
+ }
- s->quadrant_dcpl = badhid;
+ if (H5Sclose(s->one_by_one_sid) < 0) {
+ HDfprintf(stderr, "H5Sclose failed\n");
+ TEST_ERROR;
+ }
- /* TBD destroy spaces belonging to quadrants */
+ if (H5Sclose(s->memspace) < 0) {
+ HDfprintf(stderr, "H5Sclose failed\n");
+ TEST_ERROR;
+ }
+
+ /* The writer ends the tick before closing the file to make the data visible to the reader */
+ if (s->writer && s->use_vfd_swmr) {
+ unsigned long j;
+
+ if (s->vds != vds_multi) {
+ if (H5Fvfd_swmr_end_tick(s->file[0]) < 0) {
+ HDfprintf(stderr, "H5Fvfd_swmr_end_tick failed\n");
+ TEST_ERROR;
+ }
+ }
+ else {
+ for (j = 0; j < NELMTS(s->file); j++)
+ if (H5Fvfd_swmr_end_tick(s->file[j]) < 0) {
+ HDfprintf(stderr, "H5Fvfd_swmr_end_tick failed\n");
+ TEST_ERROR;
+ }
+ }
+ }
+
+ /* For checking the time spent in file close. It's for running the writer alone */
+ if (s->do_perf) {
+ if (HDclock_gettime(CLOCK_MONOTONIC, &start_time) == -1) {
+ HDfprintf(stderr, "HDclock_gettime failed");
+ TEST_ERROR;
+ }
}
for (i = 0; i < NELMTS(s->file); i++) {
@@ -550,12 +873,282 @@ state_destroy(state_t *s)
if (s->vds != vds_multi && i > 0)
continue;
- if (H5Fclose(fid) < 0)
- errx(EXIT_FAILURE, "H5Fclose");
+ if (H5Fclose(fid) < 0) {
+ HDfprintf(stderr, "H5Fclose failed\n");
+ TEST_ERROR;
+ }
+ }
+
+ /* For checking the time spent in file close. It's for running the writer alone */
+ if (s->do_perf) {
+ if (HDclock_gettime(CLOCK_MONOTONIC, &end_time) == -1) {
+ HDfprintf(stderr, "HDclock_gettime failed");
+ TEST_ERROR;
+ }
+
+ HDfprintf(stdout, "File close time (for running the writer alone) = %lf seconds\n",
+ TIME_PASSED(start_time, end_time));
}
+
+ if (s->dataset)
+ HDfree(s->dataset);
+
+ if (s->sources)
+ HDfree(s->sources);
+
+ return true;
+
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Pclose(s->quadrant_dcpl);
+ H5Sclose(s->one_by_one_sid);
+ H5Sclose(s->memspace);
+ }
+ H5E_END_TRY;
+
+ if (s->dataset)
+ HDfree(s->dataset);
+
+ if (s->sources)
+ HDfree(s->sources);
+
+ return false;
}
-static void
+/*
+ * Initialize the named pipes for test synchronization.
+ * (This function can go to vfd_swmr_common.c. It's the same as
+ * the one in vfd_swmr_attrdset_writer.c)
+ */
+static bool
+np_init(np_state_t *np, bool writer)
+{
+ *np = NP_INITIALIZER;
+
+ /*
+ * Use two named pipes(FIFO) to coordinate the writer and reader for
+ * two-way communication so that the two sides can move forward together.
+ * One is for the writer to write to the reader.
+ * The other one is for the reader to signal the writer.
+ */
+ if (writer) {
+ /* If the named pipes are present at the start of the test, remove them */
+ if (HDaccess(np->fifo_writer_to_reader, F_OK) == 0)
+ if (HDremove(np->fifo_writer_to_reader) != 0) {
+ HDfprintf(stderr, "HDremove fifo_writer_to_reader failed\n");
+ TEST_ERROR;
+ }
+
+ if (HDaccess(np->fifo_reader_to_writer, F_OK) == 0)
+ if (HDremove(np->fifo_reader_to_writer) != 0) {
+ HDfprintf(stderr, "HDremove fifo_reader_to_writer failed\n");
+ TEST_ERROR;
+ }
+
+ /* Writer creates two named pipes(FIFO) */
+ if (HDmkfifo(np->fifo_writer_to_reader, 0600) < 0) {
+ HDfprintf(stderr, "HDmkfifo fifo_writer_to_reader failed\n");
+ TEST_ERROR;
+ }
+
+ if (HDmkfifo(np->fifo_reader_to_writer, 0600) < 0) {
+ HDfprintf(stderr, "HDmkfifo fifo_reader_to_writer failed\n");
+ TEST_ERROR;
+ }
+ }
+
+ /* Both the writer and reader open the pipes */
+ if ((np->fd_writer_to_reader = HDopen(np->fifo_writer_to_reader, O_RDWR)) < 0) {
+ HDfprintf(stderr, "HDopen fifo_writer_to_reader failed\n");
+ TEST_ERROR;
+ }
+
+ if ((np->fd_reader_to_writer = HDopen(np->fifo_reader_to_writer, O_RDWR)) < 0) {
+ HDfprintf(stderr, "HDopen fifo_reader_to_writer failed\n");
+ TEST_ERROR;
+ }
+
+ return true;
+
+error:
+ return false;
+} /* np_init() */
+
+/*
+ * Close and remove the named pipes.
+ * (This function can go to vfd_swmr_common.c. It's the same as
+ * the one in vfd_swmr_attrdset_writer.c)
+ */
+static bool
+np_close(np_state_t *np, bool writer)
+{
+ /* Both the writer and reader close the named pipes */
+ if (HDclose(np->fd_writer_to_reader) < 0) {
+ HDfprintf(stderr, "HDclose fd_writer_to_reader failed\n");
+ TEST_ERROR;
+ }
+
+ if (HDclose(np->fd_reader_to_writer) < 0) {
+ HDfprintf(stderr, "HDclose fd_reader_to_writer failed\n");
+ TEST_ERROR;
+ }
+
+ /* Reader finishes last and deletes the named pipes */
+ if (!writer) {
+ if (HDremove(np->fifo_writer_to_reader) != 0) {
+ HDfprintf(stderr, "HDremove fifo_writer_to_reader failed\n");
+ TEST_ERROR;
+ }
+
+ if (HDremove(np->fifo_reader_to_writer) != 0) {
+ HDfprintf(stderr, "HDremove fifo_reader_to_writer failed\n");
+ TEST_ERROR;
+ }
+ }
+ return true;
+
+error:
+ return false;
+} /* np_close() */
+
+/* Wait for the writer's notice before starting validation */
+static int
+reader_verify(np_state_t np, int verify)
+{
+ int notify;
+
+ if (HDread(np.fd_writer_to_reader, &notify, sizeof(int)) < 0) {
+ HDfprintf(stderr, "HDread failed\n");
+ TEST_ERROR;
+ }
+
+ if (notify != verify) {
+ HDfprintf(stderr, "expected %d but read %d\n", verify, notify);
+ TEST_ERROR;
+ }
+
+ return 0;
+
+error:
+ return -1;
+}
+
+/* Notify the reader of finishing creation by sending the timestamp
+ * and wait for the reader to finish validation before proceeding */
+static int
+notify_and_wait_for_reader(state_t *s, np_state_t *np)
+{
+ int notify;
+ unsigned int i;
+ struct timespec last = {0, 0};
+
+ /* Get the time when finishing creation */
+ if (HDclock_gettime(CLOCK_MONOTONIC, &last) < 0) {
+ HDfprintf(stderr, "HDclock_gettime failed\n");
+ TEST_ERROR;
+ }
+
+ /* Notify the reader of finishing creation by sending the timestamp */
+ if (HDwrite(np->fd_writer_to_reader, &last, sizeof(last)) < 0) {
+ HDfprintf(stderr, "HDwrite failed\n");
+ TEST_ERROR;
+ }
+
+ /* During the wait, writer makes repeated HDF5 API calls so as to trigger
+ * EOT at approximately the correct time */
+ for (i = 0; i < MAX_LAG + 1; i++) {
+ decisleep(TICK_LEN);
+
+ H5E_BEGIN_TRY
+ {
+ H5Aexists(s->file[0], "nonexistent");
+ }
+ H5E_END_TRY;
+ }
+
+ /* Wait until the reader finishes validating creation */
+ if (HDread(np->fd_reader_to_writer, &notify, sizeof(int)) < 0) {
+ HDfprintf(stderr, "HDread failed\n");
+ TEST_ERROR;
+ }
+
+ if (notify != np->verify) {
+ HDfprintf(stderr, "expected %d but read %d\n", np->verify, notify);
+ TEST_ERROR;
+ }
+
+ return 0;
+
+error:
+ return -1;
+}
+
+/* Receive the notice of the writer finishing dataset creation (timestamp)
+ * Make sure the dataset validation doesn't take longer than the expected time.
+ * This time period is from the writer finishing dataset creation to the reader finishing
+ * the validation of dataset creation */
+static int
+reader_check_time_and_notify_writer(np_state_t *np, state_t s)
+{
+ struct timespec last = {0, 0};
+
+ /* Receive the notice of the writer finishing creation (timestamp) */
+ if (HDread(np->fd_writer_to_reader, &last, sizeof(last)) < 0) {
+ HDfprintf(stderr, "HDread failed\n");
+ TEST_ERROR;
+ }
+
+ /* If the dataset validation takes longer than the expected time, issue a warning.
+ * This time period is from the writer finishing dataset creation to the reader finishing
+ * the validation of dataset creation */
+ if (below_speed_limit(&last, &(s.ival))) {
+ AT();
+ HDfprintf(stderr, "Warning: dataset validation took too long to finish\n");
+ }
+
+ /* Notify the writer that dataset validation is finished */
+ if (HDwrite(np->fd_reader_to_writer, &(np->notify), sizeof(int)) < 0) {
+ HDfprintf(stderr, "HDwrite failed\n");
+ TEST_ERROR;
+ }
+
+ return 0;
+
+error:
+ return -1;
+}
+
+/* Notify the reader by sending the timestamp and the number of chunks written */
+static int
+notify_reader(np_state_t *np, unsigned step)
+{
+ exchange_info_t *last = HDcalloc(1, sizeof(exchange_info_t));
+
+ /* Get the time */
+ if (HDclock_gettime(CLOCK_MONOTONIC, &(last->time)) < 0) {
+ HDfprintf(stderr, "HDclock_gettime failed\n");
+ TEST_ERROR;
+ }
+
+ last->step = step;
+
+ /* Notify the reader by sending the timestamp and the number of chunks written */
+ if (HDwrite(np->fd_writer_to_reader, last, sizeof(exchange_info_t)) < 0) {
+ HDfprintf(stderr, "HDwrite failed");
+ TEST_ERROR;
+ }
+
+ if (last)
+ HDfree(last);
+
+ return 0;
+
+error:
+ return -1;
+}
+
+static bool
create_extensible_dset(state_t *s, unsigned int which)
{
quadrant_t *const ul = &s->quadrants.ul, *const ur = &s->quadrants.ur, *const bl = &s->quadrants.bl,
@@ -563,19 +1156,47 @@ create_extensible_dset(state_t *s, unsigned int which)
char dname[sizeof("/dataset-9999999999")];
char ul_dname[sizeof("/ul-dataset-9999999999")], ur_dname[sizeof("/ur-dataset-9999999999")],
bl_dname[sizeof("/bl-dataset-9999999999")], br_dname[sizeof("/br-dataset-9999999999")];
- hid_t dcpl, ds, filespace;
-
- assert(which < s->ndatasets);
- assert(s->dataset[which] == badhid);
+ hid_t dcpl = H5I_INVALID_HID, dset_id = H5I_INVALID_HID, filespace = H5I_INVALID_HID;
+ hsize_t dims3[3] = {s->depth, s->chunk_dims[0], s->chunk_dims[1]};
esnprintf(dname, sizeof(dname), "/dataset-%d", which);
if ((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0) {
- errx(EXIT_FAILURE, "%s.%d: H5Pcreate failed", __func__, __LINE__);
+ HDfprintf(stderr, "H5Pcreate failed\n");
+ TEST_ERROR;
}
- if (H5Pset_chunk(dcpl, RANK, s->chunk_dims) < 0)
- errx(EXIT_FAILURE, "H5Pset_chunk failed");
+ if (s->test_3d) {
+ /* The chunk is L x M x N and grows along the first dimension */
+ if (H5Pset_chunk(dcpl, RANK3, dims3) < 0) {
+ HDfprintf(stderr, "H5Pset_chunk for 3D dataset failed\n");
+ TEST_ERROR;
+ }
+ }
+ else {
+ if (H5Pset_chunk(dcpl, RANK2, s->chunk_dims) < 0) {
+ HDfprintf(stderr, "H5Pset_chunk for 2D dataset failed\n");
+ TEST_ERROR;
+ }
+ }
+
+ /* Never write fill value when new chunks are allocated */
+ if (H5Pset_fill_time(dcpl, H5D_FILL_TIME_NEVER) < 0) {
+ HDfprintf(stderr, "H5Pset_fill_time failed\n");
+ TEST_ERROR;
+ }
+
+ /* Early space allocation */
+ if (H5Pset_alloc_time(dcpl, H5D_ALLOC_TIME_EARLY) < 0) {
+ HDfprintf(stderr, "H5Pset_alloc_time failed\n");
+ TEST_ERROR;
+ }
+
+ /* GZIP compression */
+ if (s->deflate_level && H5Pset_deflate(dcpl, s->deflate_level) < 0) {
+ HDfprintf(stderr, "H5Pset_deflate failed\n");
+ TEST_ERROR;
+ }
if (s->vds != vds_off) {
sources_t *const srcs = &s->sources[which];
@@ -585,78 +1206,115 @@ create_extensible_dset(state_t *s, unsigned int which)
esnprintf(bl_dname, sizeof(bl_dname), "/bl-dataset-%d", which);
esnprintf(br_dname, sizeof(br_dname), "/br-dataset-%d", which);
- srcs->ul = H5Dcreate2(s->file[0], ul_dname, s->filetype, ul->src_space, H5P_DEFAULT, s->quadrant_dcpl,
- s->dapl);
-
- if (srcs->ul < 0)
- errx(EXIT_FAILURE, "H5Dcreate(, \"%s\", ) failed", ul_dname);
-
- srcs->ur = H5Dcreate2(s->file[1], ur_dname, s->filetype, ur->src_space, H5P_DEFAULT, s->quadrant_dcpl,
- s->dapl);
-
- if (srcs->ur < 0)
- errx(EXIT_FAILURE, "H5Dcreate(, \"%s\", ) failed", ur_dname);
+ if ((srcs->ul = H5Dcreate2(s->file[0], ul_dname, s->filetype, ul->src_space, H5P_DEFAULT,
+ s->quadrant_dcpl, s->dapl)) < 0) {
+ HDfprintf(stderr, "H5Dcreate2 failed\n");
+ TEST_ERROR;
+ }
- srcs->bl = H5Dcreate2(s->file[2], bl_dname, s->filetype, bl->src_space, H5P_DEFAULT, s->quadrant_dcpl,
- s->dapl);
+ if ((srcs->ur = H5Dcreate2(s->file[1], ur_dname, s->filetype, ur->src_space, H5P_DEFAULT,
+ s->quadrant_dcpl, s->dapl)) < 0) {
+ HDfprintf(stderr, "H5Dcreate2 failed\n");
+ TEST_ERROR;
+ }
- if (srcs->bl < 0)
- errx(EXIT_FAILURE, "H5Dcreate(, \"%s\", ) failed", bl_dname);
+ if ((srcs->bl = H5Dcreate2(s->file[2], bl_dname, s->filetype, bl->src_space, H5P_DEFAULT,
+ s->quadrant_dcpl, s->dapl)) < 0) {
+ HDfprintf(stderr, "H5Dcreate2 failed\n");
+ TEST_ERROR;
+ }
- srcs->br = H5Dcreate2(s->file[3], br_dname, s->filetype, br->src_space, H5P_DEFAULT, s->quadrant_dcpl,
- s->dapl);
+ if ((srcs->br = H5Dcreate2(s->file[3], br_dname, s->filetype, br->src_space, H5P_DEFAULT,
+ s->quadrant_dcpl, s->dapl)) < 0) {
+ HDfprintf(stderr, "H5Dcreate2 failed\n");
+ TEST_ERROR;
+ }
- if (srcs->br < 0)
- errx(EXIT_FAILURE, "H5Dcreate(, \"%s\", ) failed", br_dname);
+ if (H5Pset_virtual(dcpl, ul->space, s->filename[0], ul_dname, src->space) < 0) {
+ HDfprintf(stderr, "H5Pset_virtual failed\n");
+ TEST_ERROR;
+ }
- if (H5Pset_virtual(dcpl, ul->space, s->filename[0], ul_dname, src->space) < 0)
- errx(EXIT_FAILURE, "%s: H5Pset_virtual failed", __func__);
+ if (H5Pset_virtual(dcpl, ur->space, s->filename[1], ur_dname, src->space) < 0) {
+ HDfprintf(stderr, "H5Pset_virtual failed\n");
+ TEST_ERROR;
+ }
- if (H5Pset_virtual(dcpl, ur->space, s->filename[1], ur_dname, src->space) < 0)
- errx(EXIT_FAILURE, "%s: H5Pset_virtual failed", __func__);
+ if (H5Pset_virtual(dcpl, bl->space, s->filename[2], bl_dname, src->space) < 0) {
+ HDfprintf(stderr, "H5Pset_virtual failed\n");
+ TEST_ERROR;
+ }
- if (H5Pset_virtual(dcpl, bl->space, s->filename[2], bl_dname, src->space) < 0)
- errx(EXIT_FAILURE, "%s: H5Pset_virtual failed", __func__);
+ if (H5Pset_virtual(dcpl, br->space, s->filename[3], br_dname, src->space) < 0) {
+ HDfprintf(stderr, "H5Pset_virtual failed\n");
+ TEST_ERROR;
+ }
+ }
- if (H5Pset_virtual(dcpl, br->space, s->filename[3], br_dname, src->space) < 0)
- errx(EXIT_FAILURE, "%s: H5Pset_virtual failed", __func__);
+ if (s->test_3d) {
+ if ((filespace = H5Screate_simple(RANK3, dims3, three_dee_max_dims)) < 0) {
+ HDfprintf(stderr, "H5Screate_simple 3D dataspace failed\n");
+ TEST_ERROR;
+ }
+ }
+ else {
+ if ((filespace = H5Screate_simple(RANK2, s->chunk_dims,
+ s->expand_2d ? two_dee_max_dims : s->one_dee_max_dims)) < 0) {
+ HDfprintf(stderr, "H5Screate_simple 2D dataspace failed\n");
+ TEST_ERROR;
+ }
}
- filespace = H5Screate_simple(NELMTS(s->chunk_dims), s->chunk_dims,
- s->two_dee ? two_dee_max_dims : s->one_dee_max_dims);
+ if ((dset_id = H5Dcreate2(s->file[0], dname, s->filetype, filespace, H5P_DEFAULT, dcpl, s->dapl)) < 0) {
+ HDfprintf(stderr, "H5Dcreate2 failed\n");
+ TEST_ERROR;
+ }
- if (filespace < 0) {
- errx(EXIT_FAILURE, "%s.%d: H5Screate_simple failed", __func__, __LINE__);
+ if (H5Sclose(filespace) < 0) {
+ HDfprintf(stderr, "H5Sclose failed\n");
+ TEST_ERROR;
}
- ds = H5Dcreate2(s->file[0], dname, s->filetype, filespace, H5P_DEFAULT, dcpl, s->dapl);
+ if (H5Pclose(dcpl) < 0) {
+ HDfprintf(stderr, "H5Pclose failed\n");
+ TEST_ERROR;
+ }
- if (ds < 0)
- errx(EXIT_FAILURE, "H5Dcreate(, \"%s\", ) failed", dname);
+ s->dataset[which] = dset_id;
- if (H5Sclose(filespace) < 0)
- errx(EXIT_FAILURE, "%s: H5Sclose failed", __func__);
+ return true;
- if (H5Pclose(dcpl) < 0)
- errx(EXIT_FAILURE, "%s: H5Pclose failed", __func__);
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Dclose(dset_id);
+ H5Pclose(dcpl);
+ H5Sclose(filespace);
+ }
+ H5E_END_TRY;
- s->dataset[which] = ds;
+ return false;
}
-static void
+static bool
close_extensible_dset(state_t *s, unsigned int which)
{
char dname[sizeof("/dataset-9999999999")];
- hid_t ds;
+ hid_t dset_id = H5I_INVALID_HID;
- assert(which < s->ndatasets);
+ if (which >= s->ndatasets) {
+ HDfprintf(stderr, "index is out of range\n");
+ TEST_ERROR;
+ }
esnprintf(dname, sizeof(dname), "/dataset-%d", which);
- ds = s->dataset[which];
+ dset_id = s->dataset[which];
- if (H5Dclose(ds) < 0)
- errx(EXIT_FAILURE, "H5Dclose failed for \"%s\"", dname);
+ if (H5Dclose(dset_id) < 0) {
+ HDfprintf(stderr, "H5Dclose failed\n");
+ TEST_ERROR;
+ }
s->dataset[which] = badhid;
@@ -664,86 +1322,258 @@ close_extensible_dset(state_t *s, unsigned int which)
sources_t *const srcs = &s->sources[which];
if (H5Dclose(srcs->ul) < 0 || H5Dclose(srcs->ur) < 0 || H5Dclose(srcs->bl) < 0 ||
- H5Dclose(srcs->br) < 0)
- errx(EXIT_FAILURE, "H5Dclose failed");
+ H5Dclose(srcs->br) < 0) {
+ HDfprintf(stderr, "H5Dclose failed\n");
+ TEST_ERROR;
+ }
+ }
+
+ return true;
- srcs->ul = srcs->ur = srcs->bl = srcs->br = badhid;
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Dclose(dset_id);
}
+ H5E_END_TRY;
+
+ return false;
}
-static void
-open_extensible_dset(state_t *s, unsigned int which)
+static bool
+open_extensible_dset(state_t *s)
{
- hsize_t dims[RANK], maxdims[RANK];
- char dname[sizeof("/dataset-9999999999")];
- hid_t ds, filespace, ty;
- const int tries = 10000;
- int i;
- struct timespec last = {0, 0};
- static const struct timespec ival = {5, 0};
- estack_state_t es;
-
- assert(which < s->ndatasets);
- assert(s->dataset[which] == badhid);
+ hsize_t dims2[RANK2], maxdims2[RANK2];
+ hsize_t dims3[RANK3], maxdims3[RANK3];
+ char dname[sizeof("/dataset-9999999999")];
+ hid_t dset_id, filespace, dtype;
+ int rank;
+ unsigned int which, i;
+
+ for (which = 0; which < s->ndatasets; which++) {
+ esnprintf(dname, sizeof(dname), "/dataset-%d", which);
+
+ /* 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[0], dname, s->dapl);
+ }
+ H5E_END_TRY;
- esnprintf(dname, sizeof(dname), "/dataset-%d", which);
+ if (dset_id >= 0)
+ break;
+ else
+ decisleep(1);
+ }
- es = disable_estack();
- for (i = 0; i < tries; i++) {
- struct timespec one_tenth = {.tv_sec = 0, .tv_nsec = 1000000000L / 10};
+ if (i == NUM_ATTEMPTS) {
+ HDfprintf(stderr, "chunk verification reached the maximal number of attempts\n");
+ TEST_ERROR;
+ }
- ds = H5Dopen2(s->file[0], dname, s->dapl);
+ if ((dtype = H5Dget_type(dset_id)) < 0) {
+ HDfprintf(stderr, "H5Dget_type failed\n");
+ TEST_ERROR;
+ }
- if (ds >= 0)
- break;
+ if (H5Tequal(dtype, s->filetype) <= 0) {
+ HDfprintf(stderr, "Unexpected data type\n");
+ TEST_ERROR;
+ }
+
+ if ((filespace = H5Dget_space(dset_id)) < 0) {
+ HDfprintf(stderr, "H5Dget_space failed\n");
+ TEST_ERROR;
+ }
+
+ if ((rank = H5Sget_simple_extent_ndims(filespace)) < 0) {
+ HDfprintf(stderr, "H5Sget_simple_extent_ndims failed\n");
+ TEST_ERROR;
+ }
+
+ if ((s->test_3d && rank != RANK3) || (!s->test_3d && rank != RANK2)) {
+ HDfprintf(stderr, "Unexpected data rank: %d\n", rank);
+ TEST_ERROR;
+ }
+
+ if (s->test_3d) {
+ if (H5Sget_simple_extent_dims(filespace, dims3, maxdims3) < 0) {
+ HDfprintf(stderr, "H5Sget_simple_extent_dims failed\n");
+ TEST_ERROR;
+ }
+ }
+ else {
+ if (H5Sget_simple_extent_dims(filespace, dims2, maxdims2) < 0) {
+ HDfprintf(stderr, "H5Sget_simple_extent_dims failed\n");
+ TEST_ERROR;
+ }
+ }
+
+ if (H5Sclose(filespace) < 0) {
+ HDfprintf(stderr, "H5Sclose failed\n");
+ TEST_ERROR;
+ }
+
+ if (H5Tclose(dtype) < 0) {
+ HDfprintf(stderr, "H5Tclose failed\n");
+ TEST_ERROR;
+ }
+
+ if (s->test_3d) {
+ if (maxdims3[0] != three_dee_max_dims[0] || maxdims3[1] != three_dee_max_dims[1] ||
+ maxdims3[2] != three_dee_max_dims[2]) {
+ HDfprintf(stderr,
+ "Unexpected maximum dimensions %" PRIuHSIZE " x %" PRIuHSIZE " x %" PRIuHSIZE,
+ maxdims3[0], maxdims3[1], maxdims3[2]);
+ TEST_ERROR;
+ }
+ }
+ else {
+ if (s->expand_2d) {
+ if (maxdims2[0] != two_dee_max_dims[0] || maxdims2[1] != two_dee_max_dims[1] ||
+ maxdims2[0] != maxdims2[1]) {
+ HDfprintf(stderr, "Unexpected maximum dimensions %" PRIuHSIZE " x %" PRIuHSIZE,
+ maxdims2[0], maxdims2[1]);
+ TEST_ERROR;
+ }
+ }
+ else if (maxdims2[0] != s->one_dee_max_dims[0] || maxdims2[1] != s->one_dee_max_dims[1] ||
+ dims2[0] != s->chunk_dims[0]) {
+ HDfprintf(stderr,
+ "Unexpected maximum dimensions %" PRIuHSIZE " x %" PRIuHSIZE
+ " or columns %" PRIuHSIZE,
+ maxdims2[0], maxdims2[1], dims2[1]);
+ }
+ }
+
+ s->dataset[which] = dset_id;
+ }
+
+ return true;
- if (below_speed_limit(&last, &ival)) {
- warnx("H5Dopen(, \"%s\", ) transient failure, %d retries remain", dname, tries - i - 1);
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Dclose(dset_id);
+ H5Tclose(dtype);
+ H5Sclose(filespace);
+ }
+ H5E_END_TRY;
+
+ return false;
+}
+
+static bool
+create_dsets(state_t s)
+{
+ struct timespec start_time, end_time;
+ unsigned int which;
+
+ /* For checking the time spent in dataset creation. It's for running the writer alone */
+ if (s.do_perf) {
+ if (HDclock_gettime(CLOCK_MONOTONIC, &start_time) == -1) {
+ HDfprintf(stderr, "HDclock_gettime failed");
+ TEST_ERROR;
}
- while (nanosleep(&one_tenth, &one_tenth) == -1 && errno == EINTR)
- ; // do nothing
}
- restore_estack(es);
- if (i == tries) {
- errx(EXIT_FAILURE, "H5Dopen(, \"%s\", ) failed after %d tries", dname, tries);
+ /* Create NDATASETS datasets as the reader is doing verification. So no communication with
+ * the reader during the creation of datasets.
+ */
+ for (which = 0; which < s.ndatasets; which++)
+ if (!create_extensible_dset(&s, which)) {
+ HDfprintf(stderr, "create_extensible_dset failed: number %u\n", which);
+ TEST_ERROR;
+ }
+
+ /* For checking the time spent in dataset creation. It's for running the writer alone */
+ if (s.do_perf) {
+ if (HDclock_gettime(CLOCK_MONOTONIC, &end_time) == -1) {
+ HDfprintf(stderr, "HDclock_gettime failed");
+ TEST_ERROR;
+ }
+
+ HDfprintf(stdout, "Dataset creation time (for running the writer alone) = %lf seconds\n",
+ TIME_PASSED(start_time, end_time));
}
- if ((ty = H5Dget_type(ds)) < 0)
- errx(EXIT_FAILURE, "H5Dget_type failed");
+ return true;
- if (H5Tequal(ty, s->filetype) <= 0)
- errx(EXIT_FAILURE, "Unexpected data type");
+error:
+ return false;
+}
- if ((filespace = H5Dget_space(ds)) < 0)
- errx(EXIT_FAILURE, "H5Dget_space failed");
+static uint32_t
+matget(const mat_t *mat, unsigned k, unsigned i, unsigned j)
+{
+ return mat->elt[k * mat->rows * mat->cols + i * mat->cols + j];
+}
- if (H5Sget_simple_extent_ndims(filespace) != RANK)
- errx(EXIT_FAILURE, "Unexpected rank");
+static bool
+matset(mat_t *mat, unsigned k, unsigned i, unsigned j, uint32_t v)
+{
+ if (k >= mat->depth || i >= mat->rows || j >= mat->cols) {
+ HDfprintf(stderr, "index out of boundary\n");
+ TEST_ERROR;
+ }
- if (H5Sget_simple_extent_dims(filespace, dims, maxdims) < 0)
- errx(EXIT_FAILURE, "H5Sget_simple_extent_dims failed");
+ mat->elt[k * mat->rows * mat->cols + i * mat->cols + j] = v;
- if (H5Sclose(filespace) < 0)
- errx(EXIT_FAILURE, "H5Sclose failed");
+ return true;
- filespace = badhid;
+error:
+ return false;
+}
+
+static mat_t *
+newmat(state_t s)
+{
+ mat_t *mat;
+
+ /*
+ * If partial chunk is enabled, the chunk size along the growing dimension
+ * is replaced with the partial size
+ */
+ if (s.test_3d) {
+ if (s.part_chunk) {
+ mat = HDmalloc(sizeof(*mat) + (s.part_chunk * s.rows * s.cols - 1) * sizeof(mat->elt[0]));
+ mat->depth = s.part_chunk;
+ }
+ else {
+ mat = HDmalloc(sizeof(*mat) + (s.depth * s.rows * s.cols - 1) * sizeof(mat->elt[0]));
+ mat->depth = s.depth;
+ }
- if (s->two_dee) {
- if (maxdims[0] != two_dee_max_dims[0] || maxdims[1] != two_dee_max_dims[1] ||
- maxdims[0] != maxdims[1]) {
- errx(EXIT_FAILURE, "Unexpected maximum dimensions %" PRIuHSIZE " x %" PRIuHSIZE, maxdims[0],
- maxdims[1]);
+ mat->rows = s.rows;
+ mat->cols = s.cols;
+ }
+ else {
+ if (s.part_chunk && !s.expand_2d) {
+ mat = HDmalloc(sizeof(*mat) + (s.rows * s.part_chunk - 1) * sizeof(mat->elt[0]));
+ mat->depth = 1;
+ mat->rows = s.rows;
+ mat->cols = s.part_chunk;
+ }
+ else {
+ mat = HDmalloc(sizeof(*mat) + (s.rows * s.cols - 1) * sizeof(mat->elt[0]));
+ mat->depth = 1;
+ mat->rows = s.rows;
+ mat->cols = s.cols;
}
}
- else if (maxdims[0] != s->one_dee_max_dims[0] || maxdims[1] != s->one_dee_max_dims[1] ||
- dims[0] != s->chunk_dims[0]) {
- errx(EXIT_FAILURE,
- "Unexpected maximum dimensions %" PRIuHSIZE " x %" PRIuHSIZE " or columns %" PRIuHSIZE,
- maxdims[0], maxdims[1], dims[1]);
+
+ if (mat == NULL) {
+ HDfprintf(stderr, "HDmalloc failed\n");
+ TEST_ERROR;
}
- s->dataset[which] = ds;
+ return mat;
+
+error:
+ return NULL;
}
/* Write or verify the dataset test pattern in the matrix `mat`.
@@ -752,7 +1582,7 @@ open_extensible_dset(state_t *s, unsigned int which)
*
* If `do_set` is true, write the pattern; otherwise, verify.
*
- * The basic test pattern consists of increasing
+ * For 2D datasets, the basic test pattern consists of increasing
* integers written in nested corners of the dataset
* starting at element (0, 0):
*
@@ -771,101 +1601,254 @@ open_extensible_dset(state_t *s, unsigned int which)
* 15 14 13 12
*
* In an actual pattern, the dataset number, `which`, is added to each integer.
+ *
+ * For 3D datasets, the increment of chunks is along the first dimension.
*/
-static void
+static bool
set_or_verify_matrix(mat_t *mat, unsigned int which, base_t base, bool do_set)
{
- unsigned row, col;
+ unsigned depth, row, col;
+ bool ret = true;
+
+ /* For 2D datasets, `depth` is one */
+ for (depth = 0; depth < mat->depth; depth++) {
+ for (row = 0; row < mat->rows; row++) {
+ for (col = 0; col < mat->cols; col++) {
+ uint32_t v;
+ hsize_t k = base.depth + depth, i = base.row + row, j = base.col + col, u;
+
+ if (j <= i)
+ u = k * 10 + (i + 1) * (i + 1) - 1 - j;
+ else
+ u = k * 10 + j * j + i;
- for (row = 0; row < mat->rows; row++) {
- for (col = 0; col < mat->cols; col++) {
- uint32_t v;
- hsize_t i = base.row + row, j = base.col + col, u;
+ v = (uint32_t)(u + which);
- if (j <= i)
- u = (i + 1) * (i + 1) - 1 - j;
- else
- u = j * j + i;
-
- assert(UINT32_MAX - u >= which);
- v = (uint32_t)(u + which);
- if (do_set)
- matset(mat, row, col, v);
- else if (matget(mat, row, col) != v) {
- errx(EXIT_FAILURE,
- "matrix mismatch "
- "at %" PRIuHSIZE ", %" PRIuHSIZE " (%u, %u), "
- "read %" PRIu32 " expecting %" PRIu32,
- i, j, row, col, matget(mat, row, col), v);
+ if (do_set) {
+ if (!matset(mat, depth, row, col, v)) {
+ HDfprintf(stderr, "data initialization failed\n");
+ ret = false;
+ break;
+ }
+ }
+ else if (matget(mat, depth, row, col) != v) {
+ /* If the data doesn't match, simply return false and
+ * let the caller repeat this step
+ */
+ ret = false;
+ break;
+ }
}
}
}
+
+ return ret;
}
-static void
+static bool
init_matrix(mat_t *mat, unsigned int which, base_t base)
{
- set_or_verify_matrix(mat, which, base, true);
+ return set_or_verify_matrix(mat, which, base, true);
}
-static void
+static bool
verify_matrix(mat_t *mat, unsigned int which, base_t base)
{
- set_or_verify_matrix(mat, which, base, false);
+ return set_or_verify_matrix(mat, which, base, false);
}
-static void
+static unsigned int
+calc_total_steps(state_t s)
+{
+ unsigned int total_steps = 0;
+
+ /* Calculate the number of steps depending on if partial chunk is enabled.
+ * e.g. the original number of steps is 10 and the size of the chunk along
+ * the growing dimension is 6. The number of elements for this dimension is
+ * 60. When the size of the partial chunk along the growing dimension is 5
+ * (treated as the new chunk size), the number of steps becomes 12.
+ */
+ if (s.test_3d) {
+ if (s.part_chunk)
+ total_steps = s.nsteps * s.depth / s.part_chunk;
+ else
+ total_steps = s.nsteps;
+ }
+ else if (s.expand_2d) {
+ total_steps = s.nsteps;
+ }
+ else {
+ if (s.part_chunk)
+ total_steps = s.nsteps * s.cols / s.part_chunk;
+ else
+ total_steps = s.nsteps;
+ }
+
+ return total_steps;
+}
+
+static bool
verify_chunk(state_t *s, hid_t filespace, mat_t *mat, unsigned which, base_t base)
{
- hsize_t offset[RANK] = {base.row, base.col};
- herr_t status;
- hid_t ds;
+ herr_t status;
+ hid_t dset_id;
- assert(which < s->ndatasets);
+ if (which >= s->ndatasets) {
+ HDfprintf(stderr, "the dataset order is bigger than the number of datasets");
+ TEST_ERROR;
+ }
- dbgf(1, "verifying chunk %" PRIuHSIZE ", %" PRIuHSIZE "\n", base.row, base.col);
+ dset_id = s->dataset[which];
- ds = s->dataset[which];
+ if (s->test_3d) {
+ hsize_t offset3[RANK3] = {base.depth, base.row, base.col};
+ hsize_t count3[RANK3] = {s->depth, s->chunk_dims[0], s->chunk_dims[1]};
- status = H5Sselect_hyperslab(filespace, H5S_SELECT_SET, offset, NULL, s->chunk_dims, NULL);
+ if (s->part_chunk)
+ count3[0] = s->part_chunk;
- if (status < 0)
- errx(EXIT_FAILURE, "H5Sselect_hyperslab failed");
+ if (H5Sselect_hyperslab(filespace, H5S_SELECT_SET, offset3, NULL, count3, NULL) < 0) {
+ HDfprintf(stderr, "H5Sselect_hyperslab failed\n");
+ TEST_ERROR;
+ }
+ }
+ else {
+ hsize_t offset2[RANK2] = {base.row, base.col};
+ hsize_t count2[RANK2];
+
+ if (s->expand_2d) {
+ count2[0] = s->chunk_dims[0];
+ count2[1] = s->chunk_dims[1];
+ }
+ else {
+ count2[0] = s->chunk_dims[0];
+
+ if (s->part_chunk)
+ count2[1] = s->part_chunk;
+ else
+ count2[1] = s->chunk_dims[1];
+ }
- status = H5Dread(ds, H5T_NATIVE_UINT32, s->memspace, filespace, H5P_DEFAULT, mat->elt);
+ if (H5Sselect_hyperslab(filespace, H5S_SELECT_SET, offset2, NULL, count2, NULL) < 0) {
+ HDfprintf(stderr, "H5Sselect_hyperslab failed\n");
+ TEST_ERROR;
+ }
+ }
+
+ /* A failure to read the data may indicate the data isn't ready yet. Instead of displaying the error
+ * stack, simply return false and let the caller repeat this step.
+ */
+ H5E_BEGIN_TRY
+ {
+ status = H5Dread(dset_id, H5T_NATIVE_UINT32, s->memspace, filespace, H5P_DEFAULT, mat->elt);
+ }
+ H5E_END_TRY;
if (status < 0)
- errx(EXIT_FAILURE, "H5Dread failed");
+ TEST_ERROR;
- verify_matrix(mat, which, base);
+ return verify_matrix(mat, which, base);
+
+error:
+ return false;
}
-static void
+/* Try to verify a chunk NUM_ATTEMPTS times until the data is correct */
+static bool
+repeat_verify_chunk(state_t *s, hid_t filespace, mat_t *mat, unsigned which, base_t base)
+{
+ hid_t dset_id = s->dataset[which];
+ unsigned i;
+
+ /* If the chunk data isn't good after reading it NUM_ATTEMPTS times, report it as a failure */
+ for (i = 0; i < NUM_ATTEMPTS; i++) {
+ if (verify_chunk(s, filespace, mat, which, base))
+ break;
+ else {
+ decisleep(1);
+
+ /* Refresh the dataset and try it again */
+ if (H5Drefresh(dset_id) < 0) {
+ HDfprintf(stderr, "H5Drefresh failed\n");
+ TEST_ERROR;
+ }
+ }
+ }
+
+ if (i == NUM_ATTEMPTS) {
+ HDfprintf(stderr, "chunk verification reached the maximal number of attempts\n");
+ TEST_ERROR;
+ }
+
+ return true;
+
+error:
+ return false;
+}
+
+static bool
init_and_write_chunk(state_t *s, hid_t filespace, mat_t *mat, unsigned which, base_t base)
{
- hsize_t offset[RANK] = {base.row, base.col};
- herr_t status;
- hid_t ds;
+ hid_t dset_id;
- assert(which < s->ndatasets);
+ dset_id = s->dataset[which];
- ds = s->dataset[which];
+ if (!init_matrix(mat, which, base)) {
+ HDfprintf(stderr, "data initialization failed\n");
+ TEST_ERROR;
+ }
- init_matrix(mat, which, base);
+ if (s->test_3d) {
+ hsize_t offset3[RANK3] = {base.depth, base.row, base.col};
+ hsize_t count3[RANK3] = {s->depth, s->chunk_dims[0], s->chunk_dims[1]};
- status = H5Sselect_hyperslab(filespace, H5S_SELECT_SET, offset, NULL, s->chunk_dims, NULL);
+ /* Handling partial chunk */
+ if (s->part_chunk)
+ count3[0] = s->part_chunk;
- if (status < 0)
- errx(EXIT_FAILURE, "H5Sselect_hyperslab failed");
+ /* The chunk dimensions are L x M x N. It grows along the first dimension */
+ if (H5Sselect_hyperslab(filespace, H5S_SELECT_SET, offset3, NULL, count3, NULL) < 0) {
+ HDfprintf(stderr, "H5Sselect_hyperslab for 2D dataset failed\n");
+ TEST_ERROR;
+ }
+ }
+ else {
+ hsize_t offset2[RANK2] = {base.row, base.col};
+ hsize_t count2[RANK2];
- status = H5Dwrite(ds, H5T_NATIVE_UINT32, s->memspace, filespace, H5P_DEFAULT, mat->elt);
+ if (s->expand_2d) {
+ count2[0] = s->chunk_dims[0];
+ count2[1] = s->chunk_dims[1];
+ }
+ else {
+ count2[0] = s->chunk_dims[0];
- if (status < 0)
- errx(EXIT_FAILURE, "H5Dwrite failed");
+ /* Handling partial chunk */
+ if (s->part_chunk)
+ count2[1] = s->part_chunk;
+ else
+ count2[1] = s->chunk_dims[1];
+ }
+
+ if (H5Sselect_hyperslab(filespace, H5S_SELECT_SET, offset2, NULL, count2, NULL) < 0) {
+ HDfprintf(stderr, "H5Sselect_hyperslab for 2D dataset failed\n");
+ TEST_ERROR;
+ }
+ }
+
+ if (H5Dwrite(dset_id, H5T_NATIVE_UINT32, s->memspace, filespace, H5P_DEFAULT, mat->elt) < 0) {
+ HDfprintf(stderr, "H5Dwrite failed\n");
+ TEST_ERROR;
+ }
+
+ return true;
+
+error:
+ return false;
}
-static void
-verify_dset_attribute(hid_t ds, unsigned int which, unsigned int step)
+static bool
+verify_dset_attribute(hid_t dset_id, unsigned int which, unsigned int step)
{
unsigned int read_step;
hid_t aid;
@@ -875,100 +1858,284 @@ verify_dset_attribute(hid_t ds, unsigned int which, unsigned int step)
dbgf(1, "verifying attribute %s on dataset %u equals %u\n", name, which, step);
- if ((aid = H5Aopen(ds, name, H5P_DEFAULT)) < 0)
- errx(EXIT_FAILURE, "H5Aopen failed");
+ if ((aid = H5Aopen(dset_id, name, H5P_DEFAULT)) < 0) {
+ HDfprintf(stderr, "H5Aopen failed\n");
+ TEST_ERROR;
+ }
+
+ if (H5Aread(aid, H5T_NATIVE_UINT, &read_step) < 0) {
+ HDfprintf(stderr, "H5Aread failed\n");
+ TEST_ERROR;
+ }
+
+ if (H5Aclose(aid) < 0) {
+ HDfprintf(stderr, "H5Aclose failed\n");
+ TEST_ERROR;
+ }
+
+ if (read_step != step) {
+ HDfprintf(stderr, "expected %u read %u\n", step, read_step);
+ TEST_ERROR;
+ }
- if (H5Aread(aid, H5T_NATIVE_UINT, &read_step) < 0)
- errx(EXIT_FAILURE, "H5Aread failed");
+ return true;
- if (H5Aclose(aid) < 0)
- errx(EXIT_FAILURE, "H5Aclose failed");
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Aclose(aid);
+ }
+ H5E_END_TRY;
- if (read_step != step)
- errx(EXIT_FAILURE, "expected %u read %u", step, read_step);
+ return false;
}
-static void
-verify_extensible_dset(state_t *s, unsigned int which, mat_t *mat, unsigned *stepp)
+static bool
+verify_extensible_dset(state_t *s, unsigned int which, mat_t *mat, unsigned finished_step, unsigned last_step)
{
- hid_t ds, filespace;
- hsize_t size[RANK];
+ hid_t dset_id = H5I_INVALID_HID, filespace = H5I_INVALID_HID;
+ hsize_t size2[RANK2], size3[RANK3];
base_t base, last;
- unsigned int ncols, last_step, step;
+ unsigned int nchunks, step, ofs;
+ int i;
- assert(which < s->ndatasets);
+ if (which >= s->ndatasets) {
+ HDfprintf(stderr, "the dataset order is bigger than the number of datasets");
+ TEST_ERROR;
+ }
- ds = s->dataset[which];
+ dset_id = s->dataset[which];
- if (H5Drefresh(ds) < 0)
- errx(EXIT_FAILURE, "H5Drefresh failed");
+ /* Attempt to check the availablity of the chunks for a number times
+ * (NUM_ATTEMPTS) before reporting it as a failure */
+ for (i = 0; i < NUM_ATTEMPTS; i++) {
+ if (H5Drefresh(dset_id) < 0) {
+ HDfprintf(stderr, "H5Drefresh failed\n");
+ TEST_ERROR;
+ }
- filespace = H5Dget_space(ds);
+ if ((filespace = H5Dget_space(dset_id)) < 0) {
+ HDfprintf(stderr, "H5Dget_space failed\n");
+ TEST_ERROR;
+ }
- if (filespace == badhid)
- errx(EXIT_FAILURE, "H5Dget_space failed");
+ if (s->test_3d) {
+ if (H5Sget_simple_extent_dims(filespace, size3, NULL) < 0) {
+ HDfprintf(stderr, "H5Sget_simple_extent_dims failed\n");
+ TEST_ERROR;
+ }
- if (H5Sget_simple_extent_dims(filespace, size, NULL) < 0)
- errx(EXIT_FAILURE, "H5Sget_simple_extent_dims failed");
+ /* Handling partial chunks */
+ if (s->part_chunk)
+ nchunks = (unsigned)size3[0] / s->part_chunk;
+ else
+ nchunks = (unsigned)size3[0] / s->depth;
+ }
+ else {
+ if (H5Sget_simple_extent_dims(filespace, size2, NULL) < 0) {
+ HDfprintf(stderr, "H5Sget_simple_extent_dims failed\n");
+ TEST_ERROR;
+ }
- ncols = (unsigned)(size[1] / s->chunk_dims[1]);
- if (ncols < hang_back)
- goto out;
+ /* Handling partial chunks */
+ if (s->part_chunk)
+ nchunks = (unsigned)(size2[1] / s->part_chunk);
+ else
+ nchunks = (unsigned)(size2[1] / s->chunk_dims[1]);
+ }
- last_step = ncols - hang_back;
+ /* Make sure the chunks show up on the reader side. Otherwise sleep a while and try again */
+ if (nchunks >= last_step)
+ break;
+ else
+ decisleep(1);
+ }
- for (step = *stepp; step <= last_step; step++) {
- const unsigned ofs = step % 2;
+ if (i == NUM_ATTEMPTS) {
+ HDfprintf(stderr, "chunk verification reached the maximal number of attempts");
+ TEST_ERROR;
+ }
+ for (step = finished_step; step < last_step; step++) {
dbgf(1, "%s: which %u step %u\n", __func__, which, step);
- if (s->two_dee) {
- size[0] = s->chunk_dims[0] * (1 + step);
- size[1] = s->chunk_dims[1] * (1 + step);
- last.row = s->chunk_dims[0] * step + ofs;
- last.col = s->chunk_dims[1] * step + ofs;
+ if (s->skip_chunk && step % s->skip_chunk == 0)
+ continue;
+
+ /* Read data that randomly crosses over chunks. But it should not happen to
+ * the last chunk being written
+ */
+ if (s->cross_chunk_read) {
+ if (step == last_step - 1)
+ ofs = 0;
+ else
+ ofs = step % 2;
}
- else {
- size[0] = s->chunk_dims[0];
- size[1] = s->chunk_dims[1] * (1 + step);
+ else
+ ofs = 0;
+
+ if (s->test_3d) {
+ if (s->part_chunk) {
+ last.depth = s->part_chunk * step + ofs;
+ }
+ else {
+ last.depth = s->depth * step + ofs;
+ }
+
last.row = 0;
- last.col = s->chunk_dims[1] * step + ofs;
+ last.col = 0;
}
+ else {
+ last.depth = 0;
- dbgf(1, "new size %" PRIuHSIZE ", %" PRIuHSIZE "\n", size[0], size[1]);
- dbgf(1, "last row %" PRIuHSIZE " col %" PRIuHSIZE "\n", last.row, last.col);
+ if (s->expand_2d) {
+ last.row = s->chunk_dims[0] * step + ofs;
+ last.col = s->chunk_dims[1] * step + ofs;
+ }
+ else {
+ last.row = 0;
+
+ if (s->part_chunk) {
+ last.col = s->part_chunk * step + ofs;
+ }
+ else {
+ last.col = s->chunk_dims[1] * step + ofs;
+ }
+ }
+ }
- if (s->two_dee) {
+ if (s->test_3d)
+ dbgf(1, "last row %" PRIuHSIZE " col %" PRIuHSIZE " depth %" PRIuHSIZE "\n", last.row, last.col,
+ last.depth);
+ else
+ dbgf(1, "last row %" PRIuHSIZE " col %" PRIuHSIZE "\n", last.row, last.col);
+ if (s->test_3d || !s->expand_2d) {
+ if (!repeat_verify_chunk(s, filespace, mat, which, last)) {
+ HDfprintf(stderr, "chunk verification failed\n");
+ TEST_ERROR;
+ }
+ }
+ else {
/* Down the right side, intersecting the bottom row. */
- base.col = last.col;
- for (base.row = ofs; base.row <= last.row; base.row += s->chunk_dims[0]) {
- verify_chunk(s, filespace, mat, which, base);
+ base.col = last.col;
+ base.depth = 0;
+ for (base.row = 0; base.row <= last.row; base.row += s->chunk_dims[0]) {
+ if (!repeat_verify_chunk(s, filespace, mat, which, base)) {
+ HDfprintf(stderr, "chunk verification failed\n");
+ TEST_ERROR;
+ }
}
/* Across the bottom, stopping before the last column to
* avoid re-reading the bottom-right chunk.
*/
base.row = last.row;
- for (base.col = ofs; base.col < last.col; base.col += s->chunk_dims[1]) {
- verify_chunk(s, filespace, mat, which, base);
+ for (base.col = 0; base.col < last.col; base.col += s->chunk_dims[1]) {
+ if (!repeat_verify_chunk(s, filespace, mat, which, base)) {
+ HDfprintf(stderr, "chunk verification failed\n");
+ TEST_ERROR;
+ }
}
}
- else {
- verify_chunk(s, filespace, mat, which, last);
+
+ if (s->asteps != 0 && step % s->asteps == 0) {
+ if (!verify_dset_attribute(dset_id, which, step)) {
+ HDfprintf(stderr, "verify_dset_attribute failed\n");
+ TEST_ERROR;
+ }
}
- if (s->asteps != 0 && step % s->asteps == 0)
- verify_dset_attribute(ds, which, step);
}
- *stepp = step;
+ return true;
-out:
- if (H5Sclose(filespace) < 0)
- errx(EXIT_FAILURE, "H5Sclose failed");
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Sclose(filespace);
+ }
+ H5E_END_TRY;
+
+ return false;
}
-static void
+static bool
+verify_dsets(state_t s, np_state_t *np, mat_t *mat)
+{
+ unsigned finished_step = 0;
+ unsigned which;
+ unsigned counter = 0;
+ unsigned total_steps = 0;
+ double passed_time = 0.0, total_time = 0.0, min_time = 1000000.0, max_time = 0.0;
+ exchange_info_t last;
+ struct timespec end_time;
+
+ total_steps = calc_total_steps(s);
+
+ do {
+ /* Receive the notice of the writer finishing creation,
+ * including the number of chunks finished and the timestamp
+ */
+ if (s.use_named_pipe && HDread(np->fd_writer_to_reader, &last, sizeof(last)) < 0) {
+ HDfprintf(stderr, "HDread failed\n");
+ TEST_ERROR;
+ }
+
+ for (which = 0; which < s.ndatasets; which++) {
+ /* Verify the chunks starting from the finished one in last round
+ * to the ones written in this round
+ */
+ if (!verify_extensible_dset(&s, which, mat, finished_step, last.step)) {
+ HDfprintf(stderr, "verify_extensible_dset failed\n");
+ TEST_ERROR;
+ }
+
+ /* Reset the finished one */
+ finished_step = last.step;
+ }
+
+ /* Make sure the chunk verification doesn't take longer than the expected time.
+ * This time period is from the writer finishing chunks to the reader finishing
+ * the validation of the chunks */
+ if (s.use_named_pipe && below_speed_limit(&(last.time), &(s.ival))) {
+ AT();
+ HDfprintf(stderr, "Warning: verify_extensible_dset took too long to finish\n");
+ }
+
+ /* For checking the time lapse between the writer's finishing writing a batch of chunks
+ * within a tick and the reader's finishing verifying those chunks
+ */
+ if (s.use_named_pipe && s.do_perf) {
+ if (HDclock_gettime(CLOCK_MONOTONIC, &end_time) == -1) {
+ HDfprintf(stderr, "HDclock_gettime failed");
+ TEST_ERROR;
+ }
+
+ counter++;
+ passed_time = TIME_PASSED(last.time, end_time);
+
+ total_time += passed_time;
+
+ if (passed_time > max_time)
+ max_time = passed_time;
+
+ if (passed_time < min_time)
+ min_time = passed_time;
+ }
+ } while (finished_step < total_steps);
+
+ /* Print out the performance information */
+ if (s.use_named_pipe && s.do_perf && counter)
+ HDfprintf(stdout, "Dataset verification: mean time = %lf, max time = %lf, min time = %lf\n",
+ total_time / (double)counter, max_time, min_time);
+
+ return true;
+
+error:
+ return false;
+}
+
+static bool
add_dset_attribute(const state_t *s, hid_t ds, hid_t sid, unsigned int which, unsigned int step)
{
hid_t aid;
@@ -978,210 +2145,524 @@ add_dset_attribute(const state_t *s, hid_t ds, hid_t sid, unsigned int which, un
dbgf(1, "setting attribute %s on dataset %u to %u\n", name, which, step);
- if ((aid = H5Acreate2(ds, name, s->filetype, sid, H5P_DEFAULT, H5P_DEFAULT)) < 0)
- errx(EXIT_FAILURE, "H5Acreate2 failed");
+ if ((aid = H5Acreate2(ds, name, s->filetype, sid, H5P_DEFAULT, H5P_DEFAULT)) < 0) {
+ HDfprintf(stderr, "H5Acreate2 failed\n");
+ TEST_ERROR;
+ }
+
+ if (H5Awrite(aid, H5T_NATIVE_UINT, &step) < 0) {
+ HDfprintf(stderr, "H5Awrite failed\n");
+ TEST_ERROR;
+ }
+
+ if (H5Aclose(aid) < 0) {
+ HDfprintf(stderr, "H5Aclose failed\n");
+ TEST_ERROR;
+ }
- if (H5Awrite(aid, H5T_NATIVE_UINT, &step) < 0)
- errx(EXIT_FAILURE, "H5Awrite failed");
- if (H5Aclose(aid) < 0)
- errx(EXIT_FAILURE, "H5Aclose failed");
+ return true;
+
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Aclose(aid);
+ }
+ H5E_END_TRY;
+
+ return false;
}
-static void
+static bool
write_extensible_dset(state_t *s, unsigned int which, unsigned int step, mat_t *mat)
{
- hid_t ds, filespace;
- hsize_t size[RANK];
+ hid_t dset_id = H5I_INVALID_HID, filespace = H5I_INVALID_HID;
+ hsize_t size2[RANK2], size3[RANK3];
base_t base, last;
+ char dname[sizeof("/dataset-9999999999")];
+
+ esnprintf(dname, sizeof(dname), "/dataset-%d", which);
dbgf(1, "%s: which %u step %u\n", __func__, which, step);
- assert(which < s->ndatasets);
+ if (which >= s->ndatasets) {
+ HDfprintf(stderr, "index is out of range\n");
+ TEST_ERROR;
+ }
+
+ dset_id = s->dataset[which];
+
+ if (s->asteps != 0 && step % s->asteps == 0) {
+ if (!add_dset_attribute(s, dset_id, s->one_by_one_sid, which, step)) {
+ HDfprintf(stderr, "add_dset_attribute failed\n");
+ TEST_ERROR;
+ }
+ }
- ds = s->dataset[which];
+ /* Handling both over extension of the datasets and partial chunks. Datasets
+ * can be extended multiple chunks instead of one chunk at a time.
+ * e.g. if the over extension is set to 10 chunks, the datasets are extended
+ * 10 chunks along the growing dimension after every 10 chunks are written.
+ */
+ if (s->test_3d) {
+ if (s->part_chunk) {
+ size3[0] = s->over_extend * s->part_chunk * (1 + step / s->over_extend);
+ last.depth = s->part_chunk * step;
+ }
+ else {
+ size3[0] = s->over_extend * s->depth * (1 + step / s->over_extend);
+ last.depth = s->depth * step;
+ }
- if (s->asteps != 0 && step % s->asteps == 0)
- add_dset_attribute(s, ds, s->one_by_one_sid, which, step);
+ size3[1] = s->chunk_dims[0];
+ size3[2] = s->chunk_dims[1];
- if (s->two_dee) {
- size[0] = s->chunk_dims[0] * (1 + step);
- size[1] = s->chunk_dims[1] * (1 + step);
- last.row = s->chunk_dims[0] * step;
- last.col = s->chunk_dims[1] * step;
+ last.row = 0;
+ last.col = 0;
}
else {
- size[0] = s->chunk_dims[0];
- size[1] = s->chunk_dims[1] * (1 + step);
- last.row = 0;
- last.col = s->chunk_dims[1] * step;
+ if (s->expand_2d) {
+ size2[0] = s->over_extend * s->chunk_dims[0] * (1 + step / s->over_extend);
+ size2[1] = s->over_extend * s->chunk_dims[1] * (1 + step / s->over_extend);
+
+ last.row = s->chunk_dims[0] * step;
+ last.col = s->chunk_dims[1] * step;
+ }
+ else {
+ size2[0] = s->chunk_dims[0];
+ last.row = 0;
+
+ if (s->part_chunk) {
+ size2[1] = s->over_extend * s->part_chunk * (1 + step / s->over_extend);
+ last.col = s->part_chunk * step;
+ }
+ else {
+ size2[1] = s->over_extend * s->chunk_dims[1] * (1 + step / s->over_extend);
+ last.col = s->chunk_dims[1] * step;
+ }
+ }
+ last.depth = 0;
}
- dbgf(1, "new size %" PRIuHSIZE ", %" PRIuHSIZE "\n", size[0], size[1]);
+ if (s->test_3d)
+ dbgf(1, "new size %" PRIuHSIZE ", %" PRIuHSIZE ", %" PRIuHSIZE "\n", size3[0], size3[1], size3[2]);
+ else
+ dbgf(1, "new size %" PRIuHSIZE ", %" PRIuHSIZE "\n", size2[0], size2[1]);
if (s->vds != vds_off) {
- const hsize_t half_size[RANK] = {size[0] / 2, size[1] / 2};
- sources_t *const srcs = &s->sources[which];
+ const hsize_t half_size[RANK2] = {size2[0] / 2, size2[1] / 2};
+ sources_t *const srcs = &s->sources[which];
if (H5Dset_extent(srcs->ul, half_size) < 0) {
- errx(EXIT_FAILURE, "%s.%d: H5Dset_extent failed", __func__, __LINE__);
+ HDfprintf(stderr, "H5Dset_extent failed\n");
+ TEST_ERROR;
}
+
if (H5Dset_extent(srcs->ur, half_size) < 0) {
- errx(EXIT_FAILURE, "%s.%d: H5Dset_extent failed", __func__, __LINE__);
+ HDfprintf(stderr, "H5Dset_extent failed\n");
+ TEST_ERROR;
}
+
if (H5Dset_extent(srcs->bl, half_size) < 0) {
- errx(EXIT_FAILURE, "%s.%d: H5Dset_extent failed", __func__, __LINE__);
+ HDfprintf(stderr, "H5Dset_extent failed\n");
+ TEST_ERROR;
}
+
if (H5Dset_extent(srcs->br, half_size) < 0) {
- errx(EXIT_FAILURE, "%s.%d: H5Dset_extent failed", __func__, __LINE__);
+ HDfprintf(stderr, "H5Dset_extent failed\n");
+ TEST_ERROR;
+ }
+ }
+ else {
+ /* Handling over extension. Making sure the dataset size doesn't exceed the fixed maximal size */
+ if (step % s->over_extend == 0) {
+ if (s->test_3d) {
+ if (size3[0] <= three_dee_max_dims[0] && H5Dset_extent(dset_id, size3) < 0) {
+ HDfprintf(stderr, "H5Dset_extent for 3D dataset failed\n");
+ TEST_ERROR;
+ }
+ }
+ else {
+ if ((s->expand_2d && size2[0] <= two_dee_max_dims[0] && size2[0] <= two_dee_max_dims[0]) ||
+ (!s->expand_2d && size2[1] <= two_dee_max_dims[1])) {
+ if (H5Dset_extent(dset_id, size2) < 0) {
+ HDfprintf(stderr, "H5Dset_extent for 2D dataset failed\n");
+ TEST_ERROR;
+ }
+ }
+ }
}
}
- else if (H5Dset_extent(ds, size) < 0)
- errx(EXIT_FAILURE, "H5Dset_extent failed");
-
- filespace = H5Dget_space(ds);
- if (filespace == badhid)
- errx(EXIT_FAILURE, "H5Dget_space failed");
+ if ((filespace = H5Dget_space(dset_id)) < 0) {
+ HDfprintf(stderr, "H5Dget_space failed\n");
+ TEST_ERROR;
+ }
- if (s->two_dee) {
- base.col = last.col;
+ if (s->test_3d || !s->expand_2d) {
+ if (!init_and_write_chunk(s, filespace, mat, which, last)) {
+ HDfprintf(stderr, "init_and_write_chunk failed\n");
+ TEST_ERROR;
+ }
+ }
+ else if (s->expand_2d) {
+ base.col = last.col;
+ base.depth = 0;
for (base.row = 0; base.row <= last.row; base.row += s->chunk_dims[0]) {
dbgf(1, "writing chunk %" PRIuHSIZE ", %" PRIuHSIZE "\n", base.row, base.col);
- init_and_write_chunk(s, filespace, mat, which, base);
+ if (!init_and_write_chunk(s, filespace, mat, which, base)) {
+ HDfprintf(stderr, "init_and_write_chunk failed\n");
+ TEST_ERROR;
+ }
}
base.row = last.row;
for (base.col = 0; base.col < last.col; base.col += s->chunk_dims[1]) {
dbgf(1, "writing chunk %" PRIuHSIZE ", %" PRIuHSIZE "\n", base.row, base.col);
- init_and_write_chunk(s, filespace, mat, which, base);
+ if (!init_and_write_chunk(s, filespace, mat, which, base)) {
+ HDfprintf(stderr, "init_and_write_chunk failed\n");
+ TEST_ERROR;
+ }
}
}
- else {
- init_and_write_chunk(s, filespace, mat, which, last);
+
+ if (H5Sclose(filespace) < 0) {
+ HDfprintf(stderr, "H5Sclose failed\n");
+ TEST_ERROR;
}
- if (H5Sclose(filespace) < 0)
- errx(EXIT_FAILURE, "H5Sclose failed");
+ return true;
+
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Sclose(filespace);
+ }
+ H5E_END_TRY;
+
+ return false;
+}
+
+static bool
+write_dsets(state_t s, np_state_t *np, mat_t *mat)
+{
+ unsigned last_step, step, total_steps, which;
+ unsigned long long old_tick_num;
+ H5F_t * f = NULL;
+ struct timespec start_time, end_time;
+
+ if (NULL == (f = (H5F_t *)H5VL_object(s.file[0]))) {
+ HDfprintf(stderr, "H5VL_object failed\n");
+ TEST_ERROR;
+ }
+
+ /* For checking the time spent in writing data. It's for running the writer alone */
+ if (s.do_perf) {
+ if (HDclock_gettime(CLOCK_MONOTONIC, &start_time) == -1) {
+ HDfprintf(stderr, "HDclock_gettime failed");
+ TEST_ERROR;
+ }
+ }
+
+ old_tick_num = f->shared->tick_num;
+
+ /* Write as many as chunks within the same tick number before notifying
+ * the reader to verify them. Take account of partial chunk write
+ * here by multiplying the dividing factor for partial chunk. Treat each
+ * partial chunk as if it's a chunk.
+ */
+ total_steps = calc_total_steps(s);
+
+ for (step = 0; step < total_steps; step++) {
+ /* Write as many as chunks before the tick number changes */
+ if (f->shared->tick_num == old_tick_num) {
+ if (!s.skip_chunk || (s.skip_chunk && step % s.skip_chunk != 0)) {
+ for (which = 0; which < s.ndatasets; which++) {
+ dbgf(2, "step %d which %d\n", step, which);
+ if (!write_extensible_dset(&s, which, step, mat)) {
+ HDfprintf(stderr, "write_extensible_dset failed\n");
+ TEST_ERROR;
+ }
+ }
+ }
+ }
+
+ /* Notify the reader to start verification by
+ * sending the timestamp and the number of chunks written
+ */
+ if (f->shared->tick_num > old_tick_num || step == (total_steps - 1)) {
+ last_step = step + 1;
+ if (s.use_named_pipe && notify_reader(np, last_step) < 0) {
+ HDfprintf(stderr, "notify_reader failed\n");
+ TEST_ERROR;
+ }
+
+ old_tick_num = f->shared->tick_num;
+ }
+ }
+
+ /* For checking the time spent in writing data. It's for running the writer alone */
+ if (s.do_perf) {
+ double throughput;
+ double time_passed;
+
+ if (HDclock_gettime(CLOCK_MONOTONIC, &end_time) == -1) {
+ HDfprintf(stderr, "HDclock_gettime failed");
+ TEST_ERROR;
+ }
+
+ time_passed = TIME_PASSED(start_time, end_time);
+
+ /* Calculate the write speed */
+ if (s.test_3d)
+ throughput =
+ ((double)(sizeof(unsigned int) * s.depth * s.rows * s.cols * s.nsteps * s.ndatasets)) /
+ time_passed;
+ else
+ throughput =
+ ((double)(sizeof(unsigned int) * s.rows * s.cols * s.nsteps * s.ndatasets)) / time_passed;
+
+ /* Print out the performance information */
+ HDfprintf(stdout,
+ "Dataset write time (for running the writer alone) = %lf seconds, write speed = %.2lf "
+ "bytes/second\n",
+ time_passed, throughput);
+ }
+
+ return true;
+
+error:
+ return false;
}
int
main(int argc, char **argv)
{
- mat_t * mat;
- hid_t fcpl;
- sigset_t oldsigs;
- herr_t ret;
- unsigned step, which;
- state_t s;
- size_t i;
-
- state_init(&s, argc, argv);
+ mat_t * mat;
+ hid_t fcpl = H5I_INVALID_HID;
+ unsigned which;
+ state_t s;
+ np_state_t np;
+ size_t i;
+
+ if (!state_init(&s, argc, argv)) {
+ HDfprintf(stderr, "state_init failed\n");
+ TEST_ERROR;
+ }
- if ((mat = newmat(s.rows, s.cols)) == NULL)
- err(EXIT_FAILURE, "%s: could not allocate matrix", __func__);
+ if ((mat = newmat(s)) == NULL) {
+ HDfprintf(stderr, "could not allocate matrix\n");
+ TEST_ERROR;
+ }
/* Set fs_strategy (file space strategy) and fs_page_size (file space page size) */
- if ((fcpl = vfd_swmr_create_fcpl(H5F_FSPACE_STRATEGY_PAGE, 4096)) < 0)
- errx(EXIT_FAILURE, "H5Pcreate");
+ if ((fcpl = vfd_swmr_create_fcpl(H5F_FSPACE_STRATEGY_PAGE, s.fsp_size)) < 0) {
+ HDfprintf(stderr, "vfd_swmr_create_fcpl failed\n");
+ TEST_ERROR;
+ }
for (i = 0; i < NELMTS(s.file); i++) {
hid_t fapl;
H5F_vfd_swmr_config_t config;
+ H5AC_cache_config_t mdc_config;
if (s.vds != vds_multi && i > 0) {
s.file[i] = s.file[0];
continue;
}
- /* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */
- init_vfd_swmr_config(&config, 4, 7, s.writer, TRUE, 128, "./bigset-shadow-%zu", i);
+ /* config, tick_len, max_lag, writer, maintain_metadata_file, generate_updater_files,
+ * flush_raw_data, md_pages_reserved, md_file_path, updater_file_path */
+ init_vfd_swmr_config(&config, s.tick_len, s.max_lag, s.writer, TRUE, FALSE, s.flush_raw_data, 128,
+ "./bigset-shadow-%zu", NULL, i);
/* use_latest_format, use_vfd_swmr, only_meta_page, page_buf_size, config */
- fapl = vfd_swmr_create_fapl(true, s.use_vfd_swmr, true, 4096, &config);
+ if ((fapl = vfd_swmr_create_fapl(true, s.use_vfd_swmr, true, s.page_buf_size, &config)) < 0) {
+ HDfprintf(stderr, "vfd_swmr_create_fapl failed");
+ TEST_ERROR;
+ }
+
+ /* Set the initial size for the metadata cache between 1 and 32 in megabytes.
+ * Zero means using the default value, which is no-op.
+ */
+ if (s.mdc_init_size) {
+ mdc_config.version = H5AC__CURR_CACHE_CONFIG_VERSION;
+
+ if (H5Pget_mdc_config(fapl, &mdc_config) < 0) {
+ HDfprintf(stderr, "H5Pget_mdc_config failed");
+ TEST_ERROR;
+ }
- if (fapl < 0)
- errx(EXIT_FAILURE, "vfd_swmr_create_fapl");
+ /* Convert the value to megabytes */
+ mdc_config.set_initial_size = TRUE;
+ mdc_config.initial_size = s.mdc_init_size * 1024 * 1024;
+
+ if (H5Pset_mdc_config(fapl, &mdc_config) < 0) {
+ HDfprintf(stderr, "H5Pset_mdc_config failed");
+ TEST_ERROR;
+ }
+ }
s.file[i] = s.writer ? H5Fcreate(s.filename[i], H5F_ACC_TRUNC, fcpl, fapl)
: H5Fopen(s.filename[i], H5F_ACC_RDONLY, fapl);
- if (s.file[i] == badhid)
- errx(EXIT_FAILURE, s.writer ? "H5Fcreate" : "H5Fopen");
+ if (s.file[i] == badhid) {
+ HDfprintf(stderr, s.writer ? "H5Fcreate failed" : "H5Fopen failed");
+ TEST_ERROR;
+ }
- if (H5Pclose(fapl) < 0)
- errx(EXIT_FAILURE, "H5Pclose(fapl)");
+ if (H5Pclose(fapl) < 0) {
+ HDfprintf(stderr, "H5Pclose failed\n");
+ TEST_ERROR;
+ }
}
- block_signals(&oldsigs);
+ /* Initiailze named pipes */
+ if (s.use_named_pipe && !np_init(&np, s.writer)) {
+ HDfprintf(stderr, "np_init() failed\n");
+ TEST_ERROR;
+ }
if (s.writer) {
- for (which = 0; which < s.ndatasets; which++)
- create_extensible_dset(&s, which);
-
- for (step = 0; step < s.nsteps; step++) {
- for (which = 0; which < s.ndatasets; which++) {
- dbgf(2, "step %d which %d\n", step, which);
- write_extensible_dset(&s, which, step, mat);
- if (s.ndatasets <= s.nsteps)
- nanosleep(&s.update_interval, NULL);
+ /* Writer tells reader to start */
+ np.notify = 1;
+ if (s.use_named_pipe && HDwrite(np.fd_writer_to_reader, &np.notify, sizeof(int)) < 0) {
+ HDfprintf(stderr, "HDwrite failed\n");
+ TEST_ERROR;
+ }
+
+ /* Creates multiple datasets */
+ if (!create_dsets(s)) {
+ HDfprintf(stderr, "create_dsets failed");
+ TEST_ERROR;
+ }
+
+ /* Call H5Fvfd_swmr_end_tick to end the tick. No communication with the reader in this step */
+ if (s.use_vfd_swmr && s.use_named_pipe) {
+ unsigned long j;
+
+ if (s.vds != vds_multi) {
+ if (H5Fvfd_swmr_end_tick(s.file[0]) < 0) {
+ HDfprintf(stderr, "H5Fvfd_swmr_end_tick failed\n");
+ TEST_ERROR;
+ }
+ }
+ else {
+ for (j = 0; j < NELMTS(s.file); j++)
+ if (H5Fvfd_swmr_end_tick(s.file[j]) < 0) {
+ HDfprintf(stderr, "H5Fvfd_swmr_end_tick failed\n");
+ TEST_ERROR;
+ }
}
- if (s.ndatasets > s.nsteps)
- nanosleep(&s.update_interval, NULL);
+ }
+
+ /* Notify the reader of finishing dataset creation by sending the timestamp
+ * and wait for the reader to finish validation before proceeding */
+ np.verify = 2;
+ if (s.use_named_pipe && notify_and_wait_for_reader(&s, &np) < 0) {
+ HDfprintf(stderr, "notify_and_wait_for_reader failed\n");
+ TEST_ERROR;
+ }
+
+ /* Enable the Legacy SWMR writing mode if specified */
+ if (s.use_legacy_swmr && H5Fstart_swmr_write(s.file[0]) < 0) {
+ HDfprintf(stderr, "failed to start the Legacy SWMR writing mode\n");
+ TEST_ERROR;
+ }
+
+ /* Start to write chunks. The writer writes as many chunks as possible within a tick, then
+ * notify the reader. But it doesn't receive back the reader's notice. */
+ if (!write_dsets(s, &np, mat)) {
+ fprintf(stderr, "write_dsets failed");
+ TEST_ERROR;
}
}
else {
- unsigned *nextstep = calloc(s.ndatasets, sizeof(*nextstep));
- unsigned finished_step;
-
- if (nextstep == NULL)
- err(EXIT_FAILURE, "could not allocate `nextstep` array");
-
- for (which = s.ndatasets; which > 0; which--)
- open_extensible_dset(&s, which - 1);
-
- do {
- finished_step = UINT_MAX; /* the greatest step finished on
- * *all* datasets
- */
-
- for (which = s.ndatasets; which-- > 0;) {
- dbgf(2, "step %d which %d\n", nextstep[which], which);
- verify_extensible_dset(&s, which, mat, &nextstep[which]);
- if (nextstep[which] < finished_step)
- finished_step = nextstep[which];
- if (s.ndatasets <= s.nsteps)
- nanosleep(&s.update_interval, NULL);
- }
- if (s.ndatasets > s.nsteps)
- nanosleep(&s.update_interval, NULL);
- } while (hang_back + finished_step < s.nsteps);
+ /* Wait for the writer's notice before starting the validation of dataset creation */
+ np.verify = 1;
+ if (s.use_named_pipe && reader_verify(np, np.verify) < 0) {
+ HDfprintf(stderr, "reader_verify failed\n");
+ TEST_ERROR;
+ }
+
+ /* Open all the datasets as the writer is creating them. No communication with
+ * the writer during this step.
+ */
+ if (!open_extensible_dset(&s)) {
+ HDfprintf(stderr, "open_extensible_dset failed\n");
+ TEST_ERROR;
+ }
+
+ /* Receive the notice of the writer finishing dataset creation (timestamp)
+ * Make sure the dataset creation doesn't take longer than the expected time.
+ * This time period is from the writer finishing dataset creation to the reader finishing
+ * the validation of dataset creation */
+ np.notify = 2;
+ if (s.use_named_pipe && reader_check_time_and_notify_writer(&np, s) < 0) {
+ HDfprintf(stderr, "reader_check_time_and_notify_writer failed\n");
+ TEST_ERROR;
+ }
- free(nextstep);
+ /* Once the reader starts to verify the datasets, it doesn't notify the writer any info.
+ * Both the reader and writer finish by themselves.
+ */
+ if (!verify_dsets(s, &np, mat)) {
+ HDfprintf(stderr, "verify_dsets failed\n");
+ TEST_ERROR;
+ }
}
for (which = 0; which < s.ndatasets; which++)
- close_extensible_dset(&s, which);
+ if (!close_extensible_dset(&s, which)) {
+ HDfprintf(stderr, "close_extensible_dset failed\n");
+ TEST_ERROR;
+ }
+
+ if (H5Pclose(fcpl) < 0) {
+ HDfprintf(stderr, "H5Pclose failed\n");
+ TEST_ERROR;
+ }
+
+ if (s.use_named_pipe && !np_close(&np, s.writer)) {
+ HDfprintf(stderr, "np_close() failed\n");
+ TEST_ERROR;
+ }
- if (s.use_vfd_swmr && s.wait_for_signal)
- await_signal(s.file[0]);
+ if (!state_destroy(&s)) {
+ HDfprintf(stderr, "state_destroy failed\n");
+ TEST_ERROR;
+ }
- restore_signals(&oldsigs);
+ if (mat)
+ HDfree(mat);
- if (H5Pclose(fcpl) < 0)
- errx(EXIT_FAILURE, "H5Pclose(fcpl)");
+ return EXIT_SUCCESS;
- state_destroy(&s);
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Pclose(fcpl);
- free(mat);
+ for (i = 0; i < NELMTS(s.file); i++)
+ H5Fclose(s.file[i]);
+ }
+ H5E_END_TRY;
- if (s.dataset)
- HDfree(s.dataset);
- if (s.sources)
- HDfree(s.sources);
+ if (s.use_named_pipe && np.fd_writer_to_reader >= 0)
+ HDclose(np.fd_writer_to_reader);
- return EXIT_SUCCESS;
-}
+ if (s.use_named_pipe && np.fd_reader_to_writer >= 0)
+ HDclose(np.fd_reader_to_writer);
+ if (s.use_named_pipe && !s.writer) {
+ HDremove(np.fifo_writer_to_reader);
+ HDremove(np.fifo_reader_to_writer);
+ }
+
+ if (mat)
+ HDfree(mat);
+
+ return EXIT_FAILURE;
+}
#else /* H5_HAVE_WIN32_API */
int