summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--test/genall5.c17
-rw-r--r--test/testvfdswmr.sh.in14
-rw-r--r--test/vfd_swmr.c9
-rw-r--r--test/vfd_swmr_common.c9
-rw-r--r--test/vfd_swmr_common.h3
-rw-r--r--test/vfd_swmr_group_writer.c59
-rw-r--r--test/vfd_swmr_zoo_writer.c731
7 files changed, 543 insertions, 299 deletions
diff --git a/test/genall5.c b/test/genall5.c
index 39e25ac..70190c6 100644
--- a/test/genall5.c
+++ b/test/genall5.c
@@ -19,6 +19,7 @@
* of the same name.
*/
+#include <err.h>
#include "cache_common.h"
#include "vfd_swmr_common.h" /* for below_speed_limit() */
#include "genall5.h"
@@ -412,7 +413,7 @@ vrfy_ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks)
gid = H5Gopen2(fid, group_name, H5P_DEFAULT);
if (gid <= 0) {
- failure_mssg = "vrfy_ns_grp_c: H5Gopen2() failed";
+ failure_mssg = "vrfy_ns_grp_c: H5Gopen2 failed";
return false;
}
@@ -2753,12 +2754,14 @@ tend_zoo(hid_t fid, const char *base_path, struct timespec *lastmsgtime, zoo_con
}
out:
if (!ok) {
- if (HDstrcmp(failure_mssg, last_failure_mssg) != 0)
- *lastmsgtime = (struct timespec){.tv_sec = 0, .tv_nsec = 0};
-
- if (below_speed_limit(lastmsgtime, &config.msgival)) {
- last_failure_mssg = failure_mssg;
- HDfprintf(stderr, "%s: %s", __func__, failure_mssg);
+ /* Currently not used: this step makes sure the operation doesn't take too long.
+ * Any test that sets config.msgival or lastmsgtime to 0 will skip this step */
+ if (strcmp(failure_mssg, last_failure_mssg) != 0 && ((config.msgival.tv_sec || config.msgival.tv_nsec))
+ && (lastmsgtime->tv_sec || lastmsgtime->tv_nsec)) {
+ if (below_speed_limit(lastmsgtime, &config.msgival)) {
+ last_failure_mssg = failure_mssg;
+ warnx("%s: %s", __func__, failure_mssg);
+ }
}
}
return ok;
diff --git a/test/testvfdswmr.sh.in b/test/testvfdswmr.sh.in
index 42932b0..c64f9de 100644
--- a/test/testvfdswmr.sh.in
+++ b/test/testvfdswmr.sh.in
@@ -582,16 +582,16 @@ done
# read and written by VFD SWMR.
#
if [ ${do_zoo:-no} = yes ]; then
- [ -e ./fifo ] && rm -f ./fifo
- mkfifo -m 0600 ./fifo
rm -f ./shared_tick_num
echo launch vfd_swmr_zoo_writer
- STDIN_PATH="./fifo" catch_out_err_and_rc vfd_swmr_zoo_writer \
- ../vfd_swmr_zoo_writer -m 1000 -q &
+ catch_out_err_and_rc vfd_swmr_zoo_writer \
+ ../vfd_swmr_zoo_writer -q &
pid_writer=$!
- STDOUT_PATH="./fifo" catch_out_err_and_rc vfd_swmr_zoo_reader \
- ../vfd_swmr_zoo_reader -q -W &
+ # -l is the expected maximal number of ticks from the writer's finishing zoo creation or deletion
+ # to the reader's finishing validation of zoo creation or deletion
+ catch_out_err_and_rc vfd_swmr_zoo_reader \
+ ../vfd_swmr_zoo_reader -l 4 -q &
pid_reader=$!
# Wait for the reader to finish before signalling the
@@ -599,7 +599,6 @@ if [ ${do_zoo:-no} = yes ]; then
# reader will find the shadow file when it opens
# the .h5 file.
wait $pid_reader
- kill -USR1 $(cat vfd_swmr_zoo_writer.pid)
wait $pid_writer
# Collect exit code of the reader
@@ -615,7 +614,6 @@ if [ ${do_zoo:-no} = yes ]; then
fi
# Clean up output files
- rm -f ./fifo
rm -f vfd_swmr_zoo_writer.{out,rc}
rm -f vfd_swmr_zoo_reader.*.{out,rc}
fi
diff --git a/test/vfd_swmr.c b/test/vfd_swmr.c
index 9c5899e..2d34ebd 100644
--- a/test/vfd_swmr.c
+++ b/test/vfd_swmr.c
@@ -848,15 +848,6 @@ error:
return 1;
} /* test_writer_create_open_flush() */
-/* Sleep for `tenths` tenths of a second */
-static void
-decisleep(uint32_t tenths)
-{
- uint64_t nsec = tenths * 100 * 1000 * 1000;
-
- H5_nanosleep(nsec);
-}
-
/*-------------------------------------------------------------------------
* Function: test_writer_md()
*
diff --git a/test/vfd_swmr_common.c b/test/vfd_swmr_common.c
index dad9e3d..68e0b9c 100644
--- a/test/vfd_swmr_common.c
+++ b/test/vfd_swmr_common.c
@@ -72,6 +72,15 @@ below_speed_limit(struct timespec *last, const struct timespec *ival)
return result;
}
+/* Sleep for `tenths` tenths of a second. */
+void
+decisleep(uint32_t tenths)
+{
+ uint64_t nsec = tenths * 100 * 1000 * 1000;
+
+ H5_nanosleep(nsec);
+}
+
/* Like vsnprintf(3), but abort the program with an error message on
* `stderr` if the buffer is too small or some other error occurs.
*/
diff --git a/test/vfd_swmr_common.h b/test/vfd_swmr_common.h
index e70c316..fee0725 100644
--- a/test/vfd_swmr_common.h
+++ b/test/vfd_swmr_common.h
@@ -57,7 +57,8 @@ H5TEST_DLLVAR int verbosity;
extern "C" {
#endif
-H5TEST_DLL hbool_t below_speed_limit(struct timespec *, const struct timespec *);
+H5TEST_DLL bool below_speed_limit(struct timespec *, const struct timespec *);
+H5TEST_DLL void decisleep(uint32_t tenths);
H5TEST_DLL estack_state_t estack_get_state(void);
H5TEST_DLL estack_state_t disable_estack(void);
diff --git a/test/vfd_swmr_group_writer.c b/test/vfd_swmr_group_writer.c
index b9dbb42..25ee8c5 100644
--- a/test/vfd_swmr_group_writer.c
+++ b/test/vfd_swmr_group_writer.c
@@ -34,6 +34,7 @@ typedef struct {
unsigned int nsteps;
unsigned int update_interval;
bool use_vfd_swmr;
+ bool use_named_pipes;
} state_t;
#define ALL_HID_INITIALIZER \
@@ -41,21 +42,24 @@ typedef struct {
{ \
.file = H5I_INVALID_HID, .one_by_one_sid = H5I_INVALID_HID, .filename = "", \
.filetype = H5T_NATIVE_UINT32, .asteps = 10, .csteps = 10, .nsteps = 100, .update_interval = READER_WAIT_TICKS, \
- .use_vfd_swmr = true \
+ .use_vfd_swmr = true, \
+ .use_named_pipes = true \
}
static void
usage(const char *progname)
{
fprintf(stderr, "usage: %s [-S] [-a steps] [-b] [-c]\n"
- " [-n iterations] [-u numb_ticks]\n"
+ " [-n iterations] [-N] [-q] [-u numb_ticks]\n"
"\n"
"-S: do not use VFD SWMR\n"
"-a steps: `steps` between adding attributes\n"
"-b: write data in big-endian byte order\n"
"-c steps: `steps` between communication between the writer and reader\n"
"-n ngroups: the number of groups\n"
+ "-N: do not use named pipes, mainly for running the writer and reader seperately\n"
"-u numb_tcks: `numb_ticks` for the reader to wait before verification\n"
+ "-q: silence printouts, few messages\n"
"\n",
progname);
exit(EXIT_FAILURE);
@@ -83,7 +87,7 @@ state_init(state_t *s, int argc, char **argv)
if (tfile)
HDfree(tfile);
- while ((ch = getopt(argc, argv, "SWa:bc:n:qu:")) != -1) {
+ while ((ch = getopt(argc, argv, "Sa:bc:n:Nqu:")) != -1) {
switch (ch) {
case 'S':
s->use_vfd_swmr = false;
@@ -120,6 +124,9 @@ state_init(state_t *s, int argc, char **argv)
case 'b':
s->filetype = H5T_STD_U32BE;
break;
+ case 'N':
+ s->use_named_pipes = false;
+ break;
case 'q':
verbosity = 0;
break;
@@ -334,15 +341,6 @@ error:
return false;
}
-/* Sleep for `tenths` tenths of a second */
-static void
-decisleep(uint32_t tenths)
-{
- uint64_t nsec = tenths * 100 * 1000 * 1000;
-
- H5_nanosleep(nsec);
-}
-
int
main(int argc, char **argv)
{
@@ -413,7 +411,7 @@ main(int argc, char **argv)
* 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 (s.use_named_pipes && writer) {
/* Writer creates two named pipes(FIFO) */
if (HDmkfifo(fifo_writer_to_reader, 0600) < 0) {
H5_FAILED(); AT();
@@ -430,13 +428,13 @@ main(int argc, char **argv)
}
/* Both the writer and reader open the pipes */
- if ((fd_writer_to_reader = HDopen(fifo_writer_to_reader, O_RDWR)) < 0) {
+ if (s.use_named_pipes && (fd_writer_to_reader = HDopen(fifo_writer_to_reader, O_RDWR)) < 0) {
H5_FAILED(); AT();
printf("HDopen failed\n");
goto error;
}
- if ((fd_reader_to_writer = HDopen(fifo_reader_to_writer, O_RDWR)) < 0) {
+ if (s.use_named_pipes && (fd_reader_to_writer = HDopen(fifo_reader_to_writer, O_RDWR)) < 0) {
H5_FAILED(); AT();
printf("HDopen failed\n");
goto error;
@@ -451,14 +449,15 @@ main(int argc, char **argv)
printf("write_group failed\n");
/* At communication interval, notifies the reader about the failture and quit */
- if (step % s.csteps == 0) {
+ if (s.use_named_pipes && (step % s.csteps == 0)) {
notify = -1;
HDwrite(fd_writer_to_reader, &notify, sizeof(int));
- goto error;
}
+
+ goto error;
} else {
/* At communication interval, notifies the reader and waits for its response */
- if (step % s.csteps == 0) {
+ if (s.use_named_pipes && (step % s.csteps == 0)) {
/* Bump up the value of notify to notice the reader to start to read */
notify++;
if (HDwrite(fd_writer_to_reader, &notify, sizeof(int)) < 0) {
@@ -506,7 +505,7 @@ main(int argc, char **argv)
/* At communication interval, waits for the writer to finish creation before starting verification
*/
- if (step % s.csteps == 0) {
+ if (s.use_named_pipes && (step % s.csteps == 0)) {
/* The writer should have bumped up the value of notify.
* Do the same with verify and confirm it */
verify++;
@@ -532,7 +531,8 @@ main(int argc, char **argv)
}
/* Wait for a few ticks for the update to happen */
- decisleep(config.tick_len * s.update_interval);
+ if (s.use_named_pipes)
+ decisleep(config.tick_len * s.update_interval);
/* Start to verify group */
if (!verify_group(&s, step)) {
@@ -540,13 +540,14 @@ main(int argc, char **argv)
printf("verify_group failed\n");
/* At communication interval, tell the writer about the failure and exit */
- if (step % s.csteps == 0) {
+ if (s.use_named_pipes && (step % s.csteps == 0)) {
notify = -1;
HDwrite(fd_reader_to_writer, &notify, sizeof(int));
- goto error;
}
+
+ goto error;
} else {
- if (step % s.csteps == 0) {
+ if (s.use_named_pipes && (step % s.csteps == 0)) {
/* Send back the same nofity value for acknowledgement to tell the writer
* move to the next step */
if (HDwrite(fd_reader_to_writer, &notify, sizeof(int)) < 0) {
@@ -578,20 +579,20 @@ main(int argc, char **argv)
}
/* Both the writer and reader close the named pipes */
- if (HDclose(fd_writer_to_reader) < 0) {
+ if (s.use_named_pipes && HDclose(fd_writer_to_reader) < 0) {
H5_FAILED(); AT();
printf("HDclose failed\n");
goto error;
}
- if (HDclose(fd_reader_to_writer) < 0) {
+ if (s.use_named_pipes && HDclose(fd_reader_to_writer) < 0) {
H5_FAILED(); AT();
printf("HDclose failed\n");
goto error;
}
/* Reader finishes last and deletes the named pipes */
- if(!writer) {
+ if(s.use_named_pipes && !writer) {
if(HDremove(fifo_writer_to_reader) != 0) {
H5_FAILED(); AT();
printf("HDremove failed\n");
@@ -614,13 +615,13 @@ error:
H5Fclose(s.file);
} H5E_END_TRY;
- if (fd_writer_to_reader >= 0)
+ if (s.use_named_pipes && fd_writer_to_reader >= 0)
HDclose(fd_writer_to_reader);
- if (fd_reader_to_writer >= 0)
+ if (s.use_named_pipes && fd_reader_to_writer >= 0)
HDclose(fd_reader_to_writer);
- if(!writer) {
+ if(s.use_named_pipes && !writer) {
HDremove(fifo_writer_to_reader);
HDremove(fifo_reader_to_writer);
}
diff --git a/test/vfd_swmr_zoo_writer.c b/test/vfd_swmr_zoo_writer.c
index 75f3338..00dcd9e 100644
--- a/test/vfd_swmr_zoo_writer.c
+++ b/test/vfd_swmr_zoo_writer.c
@@ -11,7 +11,6 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <err.h>
-#include <libgen.h>
#define H5C_FRIEND /* suppress error about including H5Cpkg */
#define H5F_FRIEND /* suppress error about including H5Fpkg */
@@ -29,31 +28,30 @@
#include "genall5.h"
#include "vfd_swmr_common.h"
-#ifndef _arraycount
-#define _arraycount(_a) (sizeof(_a) / sizeof(_a[0]))
-#endif
+#define MAX_READ_LEN_IN_SECONDS 2
+#define TICK_LEN 4
typedef struct _shared_ticks {
uint64_t reader_tick;
} shared_ticks_t;
-typedef struct _tick_stats {
- uint64_t writer_tried_increase;
- uint64_t writer_aborted_increase;
- uint64_t writer_read_shared_file;
- uint64_t reader_tick_was_zero; // writer read reader tick equal to 0
- uint64_t reader_tick_lead_writer; // writer read reader tick greater than
- // proposed writer tick
- uint64_t writer_lead_reader_by[1]; // proposed writer tick lead reader
- // tick by `lead` ticks
- // `writer_lead_reader_by[lead]`
- // times, for `0 <= lead <= max_lag - 1`
-} tick_stats_t;
-
+int fd_writer_to_reader = -1, fd_reader_to_writer = -1;
+const char *fifo_writer_to_reader = "./fifo_writer_to_reader";
+const char *fifo_reader_to_writer = "./fifo_reader_to_writer";
+bool use_vfd_swmr = true;
+bool use_named_pipe = true;
+bool print_estack = false;
static H5F_vfd_swmr_config_t swmr_config;
-static tick_stats_t * tick_stats = NULL;
-static const hid_t badhid = H5I_INVALID_HID;
static bool writer;
+struct timespec ival = {MAX_READ_LEN_IN_SECONDS, 0}; /* Expected maximal time for reader's validation */
+
+zoo_config_t config = {
+ .proc_num = 0
+ , .skip_compact = false
+ , .skip_varlen = true
+ , .max_pause_msecs = 0
+ , .msgival = {.tv_sec = 0, .tv_nsec = 0}
+};
static void
#ifndef H5C_COLLECT_CACHE_STATS
@@ -74,335 +72,578 @@ print_cache_hits(H5C_t H5_ATTR_UNUSED *cache)
#endif
void
-zoo_create_hook(hid_t fid)
+zoo_create_hook(hid_t H5_ATTR_UNUSED fid)
{
dbgf(3, "%s: enter\n", __func__);
if (writer)
- H5Fvfd_swmr_end_tick(fid);
+ decisleep(1);
}
+/* Print out the menu for the command-line options */
static void
usage(const char *progname)
{
- fprintf(stderr, "usage: %s [-C] [-S] [-W] [-a] [-e] [-m] [-q] [-v]\n", progname);
+ fprintf(stderr, "usage: %s [-C] [-S] [-a] [-e] [-p] [-q] [-v]\n", progname);
fprintf(stderr, "\n -C: skip compact dataset tests\n");
- fprintf(stderr, " -S: do not use VFD SWMR\n");
- fprintf(stderr, " -W: do not wait for SIGINT or SIGUSR1\n");
- fprintf(stderr, " -a: run all tests, including variable-length data\n");
- fprintf(stderr, " -e: print error stacks\n");
- fprintf(stderr, " -m ms: maximum `ms` milliseconds pause between\n");
- fprintf(stderr, " each create/delete step\n");
- fprintf(stderr, " -q: be quiet: few/no progress messages\n");
- fprintf(stderr, " -v: be verbose: most progress messages\n");
+ fprintf(stderr, " -S: do not use VFD SWMR\n");
+ fprintf(stderr, " -a: run all tests, including variable-length data\n");
+ fprintf(stderr, " -e: print error stacks\n");
+ fprintf(stderr, " -l tick_num: expected maximal number of ticks from \n");
+ fprintf(stderr, " the writer's finishing zoo creation or deletion to the reader's finishing validation\n");
+ fprintf(stderr, " -N: do not use named pipes\n");
+ fprintf(stderr, " -q: be quiet: few/no progress messages\n");
+ fprintf(stderr, " -v: be verbose: most progress messages\n");
exit(EXIT_FAILURE);
}
-bool
-vfd_swmr_writer_may_increase_tick_to(uint64_t new_tick, bool wait_for_reader)
+/* Private function to help parsing command-line options */
+static int
+parse_command_line_options(int argc, char **argv)
{
- static int fd = -1;
- shared_ticks_t shared;
- ssize_t nread;
- h5_retry_t retry;
- bool do_try;
+ int ch;
+ unsigned long tmpl;
+ char *end;
+
+ while ((ch = getopt(argc, argv, "CSael:Nqv")) != -1) {
+ switch(ch) {
+ case 'C':
+ config.skip_compact = true;
+ break;
+ case 'S':
+ use_vfd_swmr = false;
+ break;
+ case 'a':
+ config.skip_varlen = false;
+ break;
+ case 'e':
+ print_estack = true;
+ break;
+ case 'l':
+ /* Expected maximal number of ticks from the writer's finishing zoo creation or deletion
+ * to the reader's finishing validation of zoo creation or deletion */
+ errno = 0;
+ tmpl = HDstrtoul(optarg, &end, 0);
+
+ if (end == optarg || *end != '\0') {
+ printf("couldn't parse `-l` argument `%s`", optarg);
+ goto error;
+ } else if (errno != 0) {
+ printf("couldn't parse `-l` argument `%s`", optarg);
+ goto error;
+ } else if (tmpl > UINT_MAX) {
+ printf("`-l` argument `%lu` too large", tmpl);
+ goto error;
+ }
+
+ {
+ /* Translate the tick number to time represented by the timespec struct */
+ float time = (float)(((unsigned)tmpl * TICK_LEN) / 10.0);
+ unsigned sec = (unsigned)time;
+ unsigned nsec = (unsigned)((time - sec) * 10 * 1000 * 1000);
+
+ ival.tv_sec = sec;
+ ival.tv_nsec = nsec;
+ }
+ break;
+ case 'N':
+ /* Disable named pipes, mainly for running the writer and reader seperately */
+ use_named_pipe = false;
+ break;
+ case 'q':
+ verbosity = 1;
+ break;
+ case 'v':
+ verbosity = 3;
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+ argv += optind;
+ argc -= optind;
- dbgf(3, "%s: enter\n", __func__);
+ if (argc > 0) {
+ H5_FAILED(); AT();
+ printf("unexpected command-line arguments");
+ goto error;
+ }
+
+ return 0;
+
+error:
+ return -1;
+}
- if (fd == -1) {
- fd = open("./shared_tick_num", O_RDONLY);
- if (fd == -1) {
- warn("%s: open", __func__); // TBD ratelimit/silence this warning
- return true;
+/* Writer creates two named pipes(FIFO) to coordinate two-way communication
+ * between the writer and the reader. Both the writer and reader open the named pipes */
+static int
+create_open_named_pipes(void)
+{
+ /* Writer creates two named pipes(FIFO) to coordinate two-way communication */
+ if (writer) {
+ if (HDmkfifo(fifo_writer_to_reader, 0600) < 0) {
+ H5_FAILED(); AT();
+ printf("HDmkfifo failed");
+ goto error;
}
- assert(tick_stats == NULL);
- tick_stats = calloc(1, sizeof(*tick_stats) +
- (swmr_config.max_lag - 1) * sizeof(tick_stats->writer_lead_reader_by[0]));
- if (tick_stats == NULL)
- err(EXIT_FAILURE, "%s: calloc", __func__);
+
+ if (HDmkfifo(fifo_reader_to_writer, 0600) < 0) {
+ H5_FAILED(); AT();
+ printf("HDmkfifo failed");
+ goto error;
+ }
+ }
+
+ /* Both the writer and reader open the pipes */
+ if ((fd_writer_to_reader = HDopen(fifo_writer_to_reader, O_RDWR)) < 0) {
+ H5_FAILED(); AT();
+ printf("fifo_writer_to_reader open failed");
+ goto error;
}
- tick_stats->writer_tried_increase++;
+ if ((fd_reader_to_writer = HDopen(fifo_reader_to_writer, O_RDWR)) < 0) {
+ H5_FAILED(); AT();
+ printf("fifo_reader_to_writer open failed");
+ goto error;
+ }
- for (do_try = h5_retry_init(&retry, 14, 10 * 1000 * 1000, 100 * 1000 * 1000); do_try;
- do_try = wait_for_reader && h5_retry_next(&retry)) {
+ return 0;
- tick_stats->writer_read_shared_file++;
+error:
+ return -1;
+}
+
+/* Notify the reader of finishing zoo creation by sending the timestamp
+ * and wait for the reader to finish validation before proceeding */
+static int
+notify_and_wait_for_reader(hid_t fid, int verify)
+{
+ int notify;
+ unsigned int i;
+ struct timespec last = {0, 0};
+
+ /* Get the time when finishing zoo creation */
+ if (HDclock_gettime(CLOCK_MONOTONIC, &last) < 0) {
+ H5_FAILED(); AT();
+ printf("HDclock_gettime failed");
+ goto error;
+ }
- if ((nread = pread(fd, &shared, sizeof(shared), 0)) == -1)
- err(EXIT_FAILURE, "%s: pread", __func__);
+ /* Notify the reader of finishing zoo creation by sending the timestamp */
+ if (HDwrite(fd_writer_to_reader, &last, sizeof(last)) < 0) {
+ H5_FAILED(); AT();
+ printf("HDwrite failed");
+ goto error;
+ }
- if (nread != sizeof(shared))
- errx(EXIT_FAILURE, "%s: pread", __func__);
+ /* During the wait, writer makes repeated HDF5 API calls so as to trigger
+ * EOT at approximately the correct time */
+ for(i = 0; i < swmr_config.max_lag + 1; i++) {
+ decisleep(swmr_config.tick_len);
- // TBD convert endianness
+ H5E_BEGIN_TRY {
+ H5Aexists(fid, "nonexistent");
+ } H5E_END_TRY;
+ }
- if (shared.reader_tick == 0) {
- tick_stats->reader_tick_was_zero++;
- return true;
- }
+ /* Wait until the reader finishes validating zoo creation */
+ if (HDread(fd_reader_to_writer, &notify, sizeof(int)) < 0) {
+ H5_FAILED(); AT();
+ printf("HDread failed");
+ goto error;
+ }
- if (new_tick < shared.reader_tick) {
- tick_stats->reader_tick_lead_writer++;
- return true;
- }
- if (new_tick <= shared.reader_tick + swmr_config.max_lag - 1) {
- uint64_t lead = new_tick - shared.reader_tick;
- assert(lead <= swmr_config.max_lag - 1);
- tick_stats->writer_lead_reader_by[lead]++;
- return true;
- }
+ if (notify != verify) {
+ H5_FAILED(); AT();
+ printf("expected %d but read %d", verify, notify);
+ goto error;
}
- if (wait_for_reader && !do_try)
- errx(EXIT_FAILURE, "%s: timed out waiting for reader", __func__);
- tick_stats->writer_aborted_increase++;
+ return 0;
- return false;
+error:
+ return -1;
}
-void
-vfd_swmr_reader_did_increase_tick_to(uint64_t new_tick)
+/* Notify the reader of finishing zoo deletion by sending the timestamp */
+static int
+notify_reader(void)
{
- static int fd = -1;
- shared_ticks_t shared;
- ssize_t nwritten;
+ struct timespec last = {0, 0};
- dbgf(3, "%s: enter\n", __func__);
+ /* Get the time when finishing zoo deletion */
+ if (HDclock_gettime(CLOCK_MONOTONIC, &last) < 0) {
+ H5_FAILED(); AT();
+ printf("HDclock_gettime failed");
+ goto error;
+ }
+
+ /* Notify the reader about finishing zoo deletion by sending the timestamp */
+ if (HDwrite(fd_writer_to_reader, &last, sizeof(last)) < 0) {
+ H5_FAILED(); AT();
+ printf("HDwrite failed");
+ goto error;
+ }
+
+ return 0;
+
+error:
+ return -1;
+}
+
+/* Wait for the writer's notice before starting to zoo validation */
+static int
+reader_verify(int verify)
+{
+ int notify;
+
+ if (HDread(fd_writer_to_reader, &notify, sizeof(int)) < 0) {
+ H5_FAILED(); AT();
+ printf("HDread failed");
+ goto error;
+ }
+
+ if (notify != verify) {
+ H5_FAILED(); AT();
+ printf("expected %d but read %d", verify, notify);
+ goto error;
+ }
- if (fd == -1) {
- // TBD create a temporary file, here, and move it to its final path
- // after writing it.
- fd = open("./shared_tick_num", O_RDWR | O_CREAT, 0600);
- if (fd == -1)
- err(EXIT_FAILURE, "%s: open", __func__);
+ return 0;
+
+error:
+ return -1;
+}
+
+/* Receive the notice of the writer finishing zoo creation (timestamp)
+ * Make sure the zoo validation doesn't take longer than the expected time.
+ * This time period is from the writer finishing zoo creation to the reader finishing
+ * the validation of zoo creation */
+static int
+reader_check_time_and_notify_writer(int notify)
+{
+ struct timespec last = {0, 0};
+
+ /* Receive the notice of the writer finishing zoo creation (timestamp) */
+ if (HDread(fd_writer_to_reader, &last, sizeof(last)) < 0) {
+ H5_FAILED(); AT();
+ printf("HDread failed");
+ goto error;
+ }
+
+ /* Make sure the zoo validation doesn't take longer than the expected time.
+ * This time period is from the writer finishing zoo creation to the reader finishing
+ * the validation of zoo creation */
+ if (below_speed_limit(&last, &ival)) {
+ AT();
+ warnx("validate_zoo took too long to finish");
}
- shared.reader_tick = new_tick;
+ /* Notify the writer that zoo validation is finished */
+ if (HDwrite(fd_reader_to_writer, &notify, sizeof(int)) < 0) {
+ H5_FAILED(); AT();
+ printf("HDwrite failed");
+ goto error;
+ }
- // TBD convert endianness
+ return 0;
- if ((nwritten = pwrite(fd, &shared, sizeof(shared), 0)) == -1)
- errx(EXIT_FAILURE, "%s: pwrite", __func__);
+error:
+ return -1;
+}
- if (nwritten != sizeof(shared))
- errx(EXIT_FAILURE, "%s: pwrite", __func__);
+/* Receive the finish notice (timestamp) from the writer.
+ * Make sure validation of zoo deletion doesn't take longer than the expected time.
+ * This time period is from the writer finishing zoo deletion to the reader finishing
+ * the validation of zoo deletion */
+static int
+reader_check_time_after_verify_deletion(void)
+{
+ struct timespec last = {0, 0};
- if (new_tick == 0) {
- if (unlink("./shared_tick_num") == -1)
- warn("%s: unlink", __func__);
- if (close(fd) == -1)
- err(EXIT_FAILURE, "%s: close", __func__);
- fd = -1;
+ if (HDread(fd_writer_to_reader, &last, sizeof(last)) < 0) {
+ H5_FAILED(); AT();
+ printf("HDread failed");
+ goto error;
}
+
+ if (below_speed_limit(&last, &ival)) {
+ AT();
+ warnx("validate_deleted_zoo took too long to finish");
+ }
+
+ return 0;
+
+error:
+ return -1;
+}
+
+/* Close and remove the named pipes */
+static int
+close_named_pipes(void)
+{
+ /* Close the named pipes */
+ if (HDclose(fd_writer_to_reader) < 0) {
+ H5_FAILED(); AT();
+ printf("HDclose failed\n");
+ goto error;
+ }
+
+ if (HDclose(fd_reader_to_writer) < 0) {
+ H5_FAILED(); AT();
+ printf("HDclose failed\n");
+ goto error;
+ }
+
+ /* Reader finishes last and deletes the named pipes */
+ if(!writer) {
+ if(HDremove(fifo_writer_to_reader) != 0) {
+ H5_FAILED(); AT();
+ printf("HDremove failed\n");
+ goto error;
+ }
+
+ if(HDremove(fifo_reader_to_writer) != 0) {
+ H5_FAILED(); AT();
+ printf("HDremove failed\n");
+ goto error;
+ }
+ }
+
+ return 0;
+
+error:
+ return -1;
}
int
main(int argc, char **argv)
{
- hid_t fapl, fcpl, fid;
- H5F_t * f;
- H5C_t * cache;
- sigset_t oldsigs;
- herr_t ret;
- zoo_config_t config = {.proc_num = 0,
- .skip_compact = false,
- .skip_varlen = true,
- .max_pause_msecs = 0,
- .msgival = {.tv_sec = 5, .tv_nsec = 0}};
- struct timespec lastmsgtime = {.tv_sec = 0, .tv_nsec = 0};
- bool wait_for_signal;
- int ch;
- unsigned seed;
- unsigned long tmpl;
- char * end;
- const char * seedvar = "H5_ZOO_STEP_SEED";
- bool use_vfd_swmr = true;
- bool print_estack = false;
- const char * progname = basename(argv[0]);
- const char * personality = strstr(progname, "vfd_swmr_zoo_");
- estack_state_t es;
- char step = 'b';
+ hid_t fapl = H5I_INVALID_HID, fcpl = H5I_INVALID_HID, fid = H5I_INVALID_HID;
+ H5F_t *f;
+ H5C_t *cache;
+ struct timespec lastmsgtime = {.tv_sec = 0, .tv_nsec = 0};
+ char *progname = NULL;
+ char *personality;
+ estack_state_t es;
H5F_vfd_swmr_config_t vfd_swmr_config;
+ int notify = 0, verify = 0;
+
+ if (H5_basename(argv[0], &progname) < 0) {
+ H5_FAILED(); AT();
+ printf("H5_basename failed\n");
+ goto error;
+ }
+
+ personality = HDstrstr(progname, "vfd_swmr_zoo_");
if (personality != NULL && strcmp(personality, "vfd_swmr_zoo_writer") == 0)
- writer = wait_for_signal = true;
+ writer = true;
else if (personality != NULL && strcmp(personality, "vfd_swmr_zoo_reader") == 0)
writer = false;
else {
- errx(EXIT_FAILURE, "unknown personality, expected vfd_swmr_zoo_{reader,writer}");
+ H5_FAILED(); AT();
+ printf("unknown personality, expected vfd_swmr_zoo_{reader,writer}");
+ goto error;
}
- if (writer)
- config.max_pause_msecs = 50;
-
- while ((ch = getopt(argc, argv, "CSWaem:qv")) != -1) {
- switch (ch) {
- case 'C':
- config.skip_compact = true;
- break;
- case 'S':
- use_vfd_swmr = false;
- break;
- case 'W':
- wait_for_signal = false;
- break;
- case 'a':
- config.skip_varlen = false;
- break;
- case 'e':
- print_estack = true;
- break;
- case 'm':
- errno = 0;
- tmpl = strtoul(optarg, &end, 0);
- if (end == optarg || *end != '\0')
- errx(EXIT_FAILURE, "couldn't parse `-m` argument `%s`", optarg);
- else if (errno != 0)
- err(EXIT_FAILURE, "couldn't parse `-m` argument `%s`", optarg);
- else if (tmpl > UINT_MAX)
- errx(EXIT_FAILURE, "`-m` argument `%lu` too large", tmpl);
- config.max_pause_msecs = (unsigned)tmpl;
- break;
- case 'q':
- verbosity = 1;
- break;
- case 'v':
- verbosity = 3;
- break;
- default:
- usage(argv[0]);
- break;
- }
- }
- argv += optind;
- argc -= optind;
-
- if (argc > 0)
- errx(EXIT_FAILURE, "unexpected command-line arguments");
+ parse_command_line_options(argc, argv);
/* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */
- init_vfd_swmr_config(&vfd_swmr_config, 4, 7, writer, FALSE, 128, "./zoo-shadow");
+ init_vfd_swmr_config(&vfd_swmr_config, TICK_LEN, 7, writer, FALSE, 128, "./zoo-shadow");
/* ? turn off use latest format argument via 1st argument? since later on it reset to early format */
/* use_latest_format, use_vfd_swmr, only_meta_page, config */
- fapl = vfd_swmr_create_fapl(true, use_vfd_swmr, true, &vfd_swmr_config);
-
- if (use_vfd_swmr && H5Pget_vfd_swmr_config(fapl, &swmr_config) < 0)
- errx(EXIT_FAILURE, "H5Pget_vfd_swmr_config");
+ if ((fapl = vfd_swmr_create_fapl(true, use_vfd_swmr, true, &vfd_swmr_config)) < 0) {
+ H5_FAILED(); AT();
+ printf("vfd_swmr_create_fapl");
+ goto error;
+ }
- if (fapl < 0)
- errx(EXIT_FAILURE, "vfd_swmr_create_fapl");
+ if (use_vfd_swmr && H5Pget_vfd_swmr_config(fapl, &swmr_config) < 0) {
+ H5_FAILED(); AT();
+ printf("H5Pget_vfd_swmr_config failed");
+ goto error;
+ }
if (H5Pset_libver_bounds(fapl, H5F_LIBVER_EARLIEST, H5F_LIBVER_LATEST) < 0) {
- errx(EXIT_FAILURE, "%s.%d: H5Pset_libver_bounds", __func__, __LINE__);
+ H5_FAILED(); AT();
+ printf("H5Pset_libver_bounds failed");
+ goto error;
}
- if ((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
- errx(EXIT_FAILURE, "H5Pcreate");
+ if ((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) {
+ H5_FAILED(); AT();
+ printf("H5Pcreate failed");
+ goto error;
+ }
- ret = H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, false, 1);
- if (ret < 0)
- errx(EXIT_FAILURE, "H5Pset_file_space_strategy");
+ if (H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, false, 1) < 0) {
+ H5_FAILED(); AT();
+ printf("H5Pset_file_space_strategy failed");
+ goto error;
+ }
if (writer)
fid = H5Fcreate("vfd_swmr_zoo.h5", H5F_ACC_TRUNC, fcpl, fapl);
else
fid = H5Fopen("vfd_swmr_zoo.h5", H5F_ACC_RDONLY, fapl);
- if (fid == badhid)
- errx(EXIT_FAILURE, writer ? "H5Fcreate" : "H5Fopen");
+ if (fid < 0) {
+ H5_FAILED(); AT();
+ printf(writer ? "H5Fcreate failed" : "H5Fopen failed");
+ goto error;
+ }
- if ((f = H5VL_object_verify(fid, H5I_FILE)) == NULL)
- errx(EXIT_FAILURE, "H5VL_object_verify");
+ if ((f = H5VL_object_verify(fid, H5I_FILE)) == NULL) {
+ H5_FAILED(); AT();
+ printf("H5VL_object_verify failed");
+ goto error;
+ }
cache = f->shared->cache;
- if (wait_for_signal)
- block_signals(&oldsigs);
+ /* Writer creates two named pipes(FIFO) to coordinate two-way communication
+ * between the writer and the reader. Both the writer and reader open the named pipes */
+ if (use_named_pipe && create_open_named_pipes() < 0) {
+ H5_FAILED(); AT();
+ printf("create_open_named_pipes failed");
+ goto error;
+ }
print_cache_hits(cache);
es = print_estack ? estack_get_state() : disable_estack();
if (writer) {
-
dbgf(2, "Writing zoo...\n");
- /* get seed from environment or else from time(3) */
- switch (fetch_env_ulong(seedvar, UINT_MAX, &tmpl)) {
- case -1:
- errx(EXIT_FAILURE, "%s: fetch_env_ulong", __func__);
- case 0:
- seed = (unsigned int)time(NULL);
- break;
- default:
- seed = (unsigned int)tmpl;
- break;
+ /* Writer tells reader to start */
+ notify = 1;
+ if (use_named_pipe && HDwrite(fd_writer_to_reader, &notify, sizeof(int)) < 0) {
+ H5_FAILED(); AT();
+ printf("HDwrite failed");
+ goto error;
}
- dbgf(1, "To reproduce, set seed (%s) to %u.\n", seedvar, seed);
-
- HDsrandom(seed);
-
- if (!create_zoo(fid, ".", &lastmsgtime, config))
- errx(EXIT_FAILURE, "create_zoo didn't pass self-check");
-
- /* Avoid deadlock: flush the file before waiting for the reader's
- * message.
- */
- if (H5Fflush(fid, H5F_SCOPE_GLOBAL) < 0)
- errx(EXIT_FAILURE, "%s: H5Fflush failed", __func__);
+ /* Start to create the zoo */
+ if (!create_zoo(fid, ".", &lastmsgtime, config)) {
+ H5_FAILED(); AT();
+ printf("create_zoo failed");
+ goto error;
+ }
- if (read(STDIN_FILENO, &step, sizeof(step)) == -1)
- err(EXIT_FAILURE, "read");
+ /* Notify the reader of finishing zoo creation by sending the timestamp
+ * and wait for the reader to finish validation before proceeding */
+ verify = 2;
+ if (use_named_pipe && notify_and_wait_for_reader(fid, verify) < 0) {
+ H5_FAILED(); AT();
+ printf("notify_and_wait_for_reader failed");
+ goto error;
+ }
- if (step != 'b')
- errx(EXIT_FAILURE, "expected 'b' read '%c'", step);
+ /* Start to delete the zoo */
+ if (!delete_zoo(fid, ".", &lastmsgtime, config)) {
+ H5_FAILED(); AT();
+ printf("delete_zoo failed");
+ goto error;
+ }
- if (!delete_zoo(fid, ".", &lastmsgtime, config))
- errx(EXIT_FAILURE, "delete_zoo failed");
- }
- else {
+ /* Notify the reader of finishing zoo deletion by sending the timestamp */
+ if (use_named_pipe && notify_reader() < 0) {
+ H5_FAILED(); AT();
+ printf("notify_reader failed");
+ goto error;
+ }
+ } else {
dbgf(2, "Reading zoo...\n");
+ /* Wait for the writer's notice before starting to zoo validation */
+ verify = 1;
+ if (use_named_pipe && reader_verify(verify) < 0) {
+ H5_FAILED(); AT();
+ printf("reader_verify failed");
+ goto error;
+ }
+
+ /* Validate the zoo creation */
while (!validate_zoo(fid, ".", &lastmsgtime, config))
;
- if (write(STDOUT_FILENO, &step, sizeof(step)) == -1)
- err(EXIT_FAILURE, "write");
+
+ /* Receive the notice of the writer finishing zoo creation (timestamp)
+ * Make sure the zoo validation doesn't take longer than the expected time.
+ * This time period is from the writer finishing zoo creation to the reader finishing
+ * the validation of zoo creation */
+ notify = 2;
+ if (use_named_pipe && reader_check_time_and_notify_writer(notify) < 0) {
+ H5_FAILED(); AT();
+ printf("reader_check_time_and_notify_writer failed");
+ goto error;
+ }
+
+ /* Start to validate the zoo deletion */
while (!validate_deleted_zoo(fid, ".", &lastmsgtime, config))
;
+
+ /* Receive the finish notice (timestamp) from the writer.
+ * Make sure validation of zoo deletion doesn't take longer than the expected time.
+ * This time period is from the writer finishing zoo deletion to the reader finishing
+ * the validation of zoo deletion */
+ if (use_named_pipe && reader_check_time_after_verify_deletion() < 0) {
+ H5_FAILED(); AT();
+ printf("reader_check_time_and_notify_writer failed");
+ goto error;
+ }
}
restore_estack(es);
- if (use_vfd_swmr && wait_for_signal)
- await_signal(fid);
+ if (H5Pclose(fapl) < 0) {
+ H5_FAILED(); AT();
+ printf("H5Pclose failed");
+ goto error;
+ }
+
+ if (H5Pclose(fcpl) < 0) {
+ H5_FAILED(); AT();
+ printf("H5Pclose failed");
+ goto error;
+ }
- if (writer && tick_stats != NULL) {
- uint64_t lead;
+ if (H5Fclose(fid) < 0) {
+ H5_FAILED(); AT();
+ printf("H5Fclose failed");
+ goto error;
+ }
- dbgf(2, "writer tried tick increase %" PRIu64 "\n", tick_stats->writer_tried_increase);
- dbgf(2, "writer aborted tick increase %" PRIu64 "\n", tick_stats->writer_aborted_increase);
- dbgf(2, "writer read shared file %" PRIu64 "\n", tick_stats->writer_read_shared_file);
- dbgf(2, "writer read reader tick equal to 0 %" PRIu64 "\n", tick_stats->reader_tick_was_zero);
- dbgf(2, "writer read reader tick leading writer %" PRIu64 "\n", tick_stats->reader_tick_lead_writer);
+ if (progname)
+ HDfree(progname);
- for (lead = 0; lead < swmr_config.max_lag; lead++) {
- dbgf(2, "writer tick lead writer by %" PRIu64 " %" PRIu64 "\n", lead,
- tick_stats->writer_lead_reader_by[lead]);
- }
+ if (use_named_pipe && close_named_pipes() < 0) {
+ H5_FAILED(); AT();
+ printf("close_named_pipes failed");
+ goto error;
}
- if (H5Pclose(fapl) < 0)
- errx(EXIT_FAILURE, "H5Pclose(fapl)");
+ return EXIT_SUCCESS;
- if (H5Pclose(fcpl) < 0)
- errx(EXIT_FAILURE, "H5Pclose(fcpl)");
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(fapl);
+ H5Pclose(fcpl);
+ H5Fclose(fid);
+ } H5E_END_TRY;
- if (H5Fclose(fid) < 0)
- errx(EXIT_FAILURE, "H5Fclose");
+ if (use_named_pipe && fd_writer_to_reader >= 0)
+ HDclose(fd_writer_to_reader);
- if (wait_for_signal)
- restore_signals(&oldsigs);
+ if (use_named_pipe && fd_reader_to_writer >= 0)
+ HDclose(fd_reader_to_writer);
- return EXIT_SUCCESS;
+ if(use_named_pipe && !writer) {
+ HDremove(fifo_writer_to_reader);
+ HDremove(fifo_reader_to_writer);
+ }
+
+ return EXIT_FAILURE;
}