summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/genall5.c15
-rw-r--r--test/testvfdswmr.sh.in12
-rw-r--r--test/vfd_swmr.c15
-rw-r--r--test/vfd_swmr_common.c15
-rw-r--r--test/vfd_swmr_common.h1
-rw-r--r--test/vfd_swmr_zoo_writer.c162
6 files changed, 165 insertions, 55 deletions
diff --git a/test/genall5.c b/test/genall5.c
index 2874b59..1d9c86b 100644
--- a/test/genall5.c
+++ b/test/genall5.c
@@ -416,7 +416,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;
}
@@ -2755,12 +2755,13 @@ tend_zoo(hid_t fid, const char *base_path, struct timespec *lastmsgtime,
}
out:
if (!ok) {
- if (strcmp(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;
- warnx("%s: %s", __func__, failure_mssg);
+ /* Only the zoo test for VFD SWMR does this step, making sure it doesn't take too long.
+ * other tests sets config.msgival to 0 */
+ if (strcmp(failure_mssg, last_failure_mssg) != 0 && ((config.msgival.tv_sec || config.msgival.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 a66ddf4..97c13cf 100644
--- a/test/testvfdswmr.sh.in
+++ b/test/testvfdswmr.sh.in
@@ -547,16 +547,14 @@ 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 -l 5 -m 1000 -q &
pid_writer=$!
- STDOUT_PATH="./fifo" catch_out_err_and_rc vfd_swmr_zoo_reader \
- ../vfd_swmr_zoo_reader -q -W &
+ catch_out_err_and_rc vfd_swmr_zoo_reader \
+ ../vfd_swmr_zoo_reader -l 10 -q -W &
pid_reader=$!
# Wait for the reader to finish before signalling the
@@ -564,7 +562,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
@@ -580,7 +577,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 d49629f..9d2c2c0 100644
--- a/test/vfd_swmr.c
+++ b/test/vfd_swmr.c
@@ -824,21 +824,6 @@ error:
return 1;
} /* test_writer_create_open_flush() */
-/* Sleep for `tenths` tenths of a second.
- *
- * This routine may quietly perform a too-short sleep if an error occurs
- * in nanosleep(2).
- */
-static void
-decisleep(uint32_t tenths)
-{
- struct timespec delay = {.tv_sec = tenths / 10,
- .tv_nsec = tenths * 100 * 1000 * 1000};
-
- while (nanosleep(&delay, &delay) == -1 && errno == EINTR)
- ; // do nothing
-}
-
/*-------------------------------------------------------------------------
* Function: test_writer_md()
diff --git a/test/vfd_swmr_common.c b/test/vfd_swmr_common.c
index 043b7ed..bc68617 100644
--- a/test/vfd_swmr_common.c
+++ b/test/vfd_swmr_common.c
@@ -63,6 +63,21 @@ below_speed_limit(struct timespec *last, const struct timespec *ival)
return result;
}
+/* Sleep for `tenths` tenths of a second.
+ *
+ * This routine may quietly perform a too-short sleep if an error occurs
+ * in nanosleep(2).
+ */
+void
+decisleep(uint32_t tenths)
+{
+ struct timespec delay = {.tv_sec = tenths / 10,
+ .tv_nsec = tenths * 100 * 1000 * 1000};
+
+ while (nanosleep(&delay, &delay) == -1 && errno == EINTR)
+ ; // do nothing
+}
+
/* 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 a4bf50e..90c0f36 100644
--- a/test/vfd_swmr_common.h
+++ b/test/vfd_swmr_common.h
@@ -62,6 +62,7 @@ extern "C" {
#endif
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_zoo_writer.c b/test/vfd_swmr_zoo_writer.c
index c98b2e1..a7ae40a 100644
--- a/test/vfd_swmr_zoo_writer.c
+++ b/test/vfd_swmr_zoo_writer.c
@@ -37,6 +37,8 @@
#define _arraycount(_a) (sizeof(_a)/sizeof(_a[0]))
#endif
+#define MAX_READ_TIME 10
+
typedef struct _shared_ticks {
uint64_t reader_tick;
} shared_ticks_t;
@@ -93,7 +95,8 @@ usage(const char *progname)
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, " -l secs: maximal seconds for reader to validate the zoo\n");
+ fprintf(stderr, " -m ms: maximal `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");
@@ -112,6 +115,9 @@ vfd_swmr_writer_may_increase_tick_to(uint64_t new_tick, bool wait_for_reader)
dbgf(3, "%s: enter\n", __func__);
if (fd == -1) {
+ if (access("./shared_tick_num", F_OK ) < 0)
+ return true;
+
fd = open("./shared_tick_num", O_RDONLY);
if (fd == -1) {
warn("%s: open", __func__); // TBD ratelimit/silence this warning
@@ -208,14 +214,13 @@ 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}
+ , .msgival = {.tv_sec = MAX_READ_TIME, .tv_nsec = 0}
};
struct timespec lastmsgtime = {.tv_sec = 0, .tv_nsec = 0};
bool wait_for_signal;
@@ -230,8 +235,14 @@ main(int argc, char **argv)
const char *progname = basename(argv[0]);
const char *personality = strstr(progname, "vfd_swmr_zoo_");
estack_state_t es;
- char step = 'b';
H5F_vfd_swmr_config_t vfd_swmr_config;
+ int fd_writer_to_reader, fd_reader_to_writer;
+ const char *fifo_writer_to_reader = "./fifo_writer_to_reader";
+ const char *fifo_reader_to_writer = "./fifo_reader_to_writer";
+ int notify = 0;
+ unsigned int i;
+ struct timespec last = {0, 0};
+ struct timespec ival = {MAX_READ_TIME, 0}; /* Expected maximal time for reader's validation */
if (personality != NULL && strcmp(personality, "vfd_swmr_zoo_writer") == 0)
writer = wait_for_signal = true;
@@ -246,7 +257,7 @@ main(int argc, char **argv)
if (writer)
config.max_pause_msecs = 50;
- while ((ch = getopt(argc, argv, "CSWaem:qv")) != -1) {
+ while ((ch = getopt(argc, argv, "CSWael:m:qv")) != -1) {
switch(ch) {
case 'C':
config.skip_compact = true;
@@ -263,6 +274,18 @@ main(int argc, char **argv)
case 'e':
print_estack = true;
break;
+ case 'l':
+ /* Expected maximal time for reader's validation of zoo creation or deletion */
+ errno = 0;
+ tmpl = strtoul(optarg, &end, 0);
+ if (end == optarg || *end != '\0')
+ errx(EXIT_FAILURE, "couldn't parse `-l` argument `%s`", optarg);
+ else if (errno != 0)
+ err(EXIT_FAILURE, "couldn't parse `-l` argument `%s`", optarg);
+ else if (tmpl > UINT_MAX)
+ errx(EXIT_FAILURE, "`-l` argument `%lu` too large", tmpl);
+ ival.tv_sec = (unsigned)tmpl;
+ break;
case 'm':
errno = 0;
tmpl = strtoul(optarg, &end, 0);
@@ -328,14 +351,26 @@ main(int argc, char **argv)
cache = f->shared->cache;
- if (wait_for_signal)
- block_signals(&oldsigs);
+ /* Writer creates two named pipes(FIFO) to coordinate two-way communication */
+ if (writer) {
+ if (HDmkfifo(fifo_writer_to_reader, 0666) < 0)
+ errx(EXIT_FAILURE, "HDmkfifo");
+
+ if (HDmkfifo(fifo_reader_to_writer, 0666) < 0)
+ errx(EXIT_FAILURE, "HDmkfifo");
+ }
+
+ /* Both the writer and reader open the pipes */
+ if ((fd_writer_to_reader = HDopen(fifo_writer_to_reader, O_RDWR)) < 0)
+ errx(EXIT_FAILURE, "fifo_writer_to_reader open failed");
+
+ if ((fd_reader_to_writer = HDopen(fifo_reader_to_writer, O_RDWR)) < 0)
+ errx(EXIT_FAILURE, "fifo_reader_to_writer open failed");
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) */
@@ -350,44 +385,108 @@ main(int argc, char **argv)
break;
}
- dbgf(1, "To reproduce, set seed (%s) to %u.\n", seedvar, seed);
+ dbgf(2, "To reproduce, set seed (%s) to %u.\n", seedvar, seed);
+
+ /* Writer tells reader to start */
+ notify = 1;
+ if (HDwrite(fd_writer_to_reader, &notify, sizeof(int)) < 0)
+ err(EXIT_FAILURE, "write failed");
ostate = initstate(seed, vector, _arraycount(vector));
+ if (clock_gettime(CLOCK_MONOTONIC, &lastmsgtime) < 0)
+ errx(EXIT_FAILURE, "%s: clock_gettime", __func__);
+
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__);
+ /* Notify the reader of finishing zoo creation */
+ notify = 2;
+ if (HDwrite(fd_writer_to_reader, &notify, sizeof(int)) < 0)
+ err(EXIT_FAILURE, "write failed");
- if (read(STDIN_FILENO, &step, sizeof(step)) == -1)
- err(EXIT_FAILURE, "read");
+ /* 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);
+
+ H5Aexists(fid, "nonexistent");
+ }
- if (step != 'b')
- errx(EXIT_FAILURE, "expected 'b' read '%c'", step);
+ /* Wait until the reader finishes validating zoo creation */
+ if (HDread(fd_reader_to_writer, &notify, sizeof(int)) < 0)
+ err(EXIT_FAILURE, "read failed");
+ if (notify != 3)
+ errx(EXIT_FAILURE, "expected 2 but read %d", notify);
+
+ if (clock_gettime(CLOCK_MONOTONIC, &lastmsgtime) == -1)
+ errx(EXIT_FAILURE, "%s: clock_gettime", __func__);
if (!delete_zoo(fid, ".", &lastmsgtime, config))
errx(EXIT_FAILURE, "delete_zoo failed");
(void)setstate(ostate);
+
+ /* Notify the reader about finishing zoo deletion */
+ notify = 4;
+ if (HDwrite(fd_writer_to_reader, &notify, sizeof(int)) == -1)
+ err(EXIT_FAILURE, "write failed");
+
} else {
dbgf(2, "Reading zoo...\n");
+ /* Start to validate zoo creation after receiving the writer's notice */
+ if (HDread(fd_writer_to_reader, &notify, sizeof(int)) < 0)
+ err(EXIT_FAILURE, "read failed");
+ if (notify != 1)
+ errx(EXIT_FAILURE, "unexpected message %d", notify);
+
+ /* Get the current time */
+ if (clock_gettime(CLOCK_MONOTONIC, &lastmsgtime) < 0)
+ errx(EXIT_FAILURE, "%s: clock_gettime", __func__);
+
+ last.tv_sec = lastmsgtime.tv_sec;
+ last.tv_nsec = lastmsgtime.tv_nsec;
+
while (!validate_zoo(fid, ".", &lastmsgtime, config))
;
- if (write(STDOUT_FILENO, &step, sizeof(step)) == -1)
- err(EXIT_FAILURE, "write");
+ /* Make sure zoo validation doesn't take longer than the expected time */
+ if (below_speed_limit(&last, &ival))
+ warnx("validate_zoo took too long to finish");
+
+ /* Receive the notice of the writer finishing zoo creation */
+ if (HDread(fd_writer_to_reader, &notify, sizeof(int)) < 0)
+ err(EXIT_FAILURE, "read failed");
+ if (notify != 2)
+ errx(EXIT_FAILURE, "unexpected message %d", notify);
+
+ /* Notify the writer that zoo validation is finished */
+ notify = 3;
+ if (HDwrite(fd_reader_to_writer, &notify, sizeof(int)) < 0)
+ err(EXIT_FAILURE, "write failed");
+
+ /* Get the current time before validating zoo deletion */
+ if (clock_gettime(CLOCK_MONOTONIC, &lastmsgtime) < 0)
+ errx(EXIT_FAILURE, "%s: clock_gettime", __func__);
+
+ last.tv_sec = lastmsgtime.tv_sec;
+ last.tv_nsec = lastmsgtime.tv_nsec;
+
while (!validate_deleted_zoo(fid, ".", &lastmsgtime, config))
;
+
+ /* Make sure validation of zoo deletion doesn't take longer than the expected time */
+ if (below_speed_limit(&last, &ival))
+ warnx("validate_deleted_zoo took too long to finish");
+
+ /* Receive the finish notice from the writer */
+ if (HDread(fd_writer_to_reader, &notify, sizeof(int)) < 0)
+ err(EXIT_FAILURE, "read failed");
+ if (notify != 4)
+ errx(EXIT_FAILURE, "unexpected message %d", notify);
}
restore_estack(es);
- if (use_vfd_swmr && wait_for_signal)
- await_signal(fid);
-
if (writer && tick_stats != NULL) {
uint64_t lead;
@@ -417,8 +516,21 @@ main(int argc, char **argv)
if (H5Fclose(fid) < 0)
errx(EXIT_FAILURE, "H5Fclose");
- if (wait_for_signal)
- restore_signals(&oldsigs);
+ /* Close the named pipes */
+ if (HDclose(fd_writer_to_reader) < 0)
+ errx(EXIT_FAILURE, "HDclose");
+
+ if (HDclose(fd_reader_to_writer) < 0)
+ errx(EXIT_FAILURE, "HDclose");
+
+ /* Reader finishes last and deletes the named pipes */
+ if(!writer) {
+ if(HDremove(fifo_writer_to_reader) != 0)
+ errx(EXIT_FAILURE, "fifo_writer_to_reader deletion failed");
+
+ if(HDremove(fifo_reader_to_writer) != 0)
+ errx(EXIT_FAILURE, "fifo_reader_to_writer deletion failed");
+ }
return EXIT_SUCCESS;
}