summaryrefslogtreecommitdiffstats
path: root/test/vfd_swmr_group_writer.c
diff options
context:
space:
mode:
authorSongyu Lu <songyulu@hdfgroup.org>2021-03-10 17:07:21 (GMT)
committerSongyu Lu <songyulu@hdfgroup.org>2021-03-10 17:07:21 (GMT)
commit11486e26a23a9fe45199515e02c8062270cd8894 (patch)
treede19433278e3ec24d49fa00d2d1333508fa78c63 /test/vfd_swmr_group_writer.c
parent84b31b5a558bdc816e91c414f98155bf72ae1502 (diff)
downloadhdf5-11486e26a23a9fe45199515e02c8062270cd8894.zip
hdf5-11486e26a23a9fe45199515e02c8062270cd8894.tar.gz
hdf5-11486e26a23a9fe45199515e02c8062270cd8894.tar.bz2
Changing the signal handling to named pipe for better portablity.
Diffstat (limited to 'test/vfd_swmr_group_writer.c')
-rw-r--r--test/vfd_swmr_group_writer.c159
1 files changed, 120 insertions, 39 deletions
diff --git a/test/vfd_swmr_group_writer.c b/test/vfd_swmr_group_writer.c
index 2f355c2..112bcb4 100644
--- a/test/vfd_swmr_group_writer.c
+++ b/test/vfd_swmr_group_writer.c
@@ -12,13 +12,13 @@
*/
#include <err.h>
+#include <unistd.h> /* getopt(3) */
#define H5F_FRIEND /*suppress error about including H5Fpkg */
#include "hdf5.h"
#include "H5Fpkg.h"
-// #include "H5Iprivate.h"
#include "H5HGprivate.h"
#include "H5VLprivate.h"
@@ -29,8 +29,8 @@ typedef struct {
hid_t file, filetype, one_by_one_sid;
char filename[PATH_MAX];
char progname[PATH_MAX];
- struct timespec update_interval;
unsigned int asteps;
+ unsigned int csteps;
unsigned int nsteps;
bool wait_for_signal;
bool use_vfd_swmr;
@@ -42,12 +42,10 @@ typedef struct {
, .filename = "" \
, .filetype = H5T_NATIVE_UINT32 \
, .asteps = 10 \
+ , .csteps = 10 \
, .nsteps = 100 \
, .wait_for_signal = true \
- , .use_vfd_swmr = true \
- , .update_interval = (struct timespec){ \
- .tv_sec = 0 \
- , .tv_nsec = 1000000000UL / 30 /* 1/30 second */}}
+ , .use_vfd_swmr = true}
static void state_init(state_t *, int, char **);
@@ -56,7 +54,7 @@ static const hid_t badhid = H5I_INVALID_HID;
static void
usage(const char *progname)
{
- fprintf(stderr, "usage: %s [-S] [-W] [-a steps] [-b]\n"
+ fprintf(stderr, "usage: %s [-S] [-W] [-a steps] [-b] [-c]\n"
" [-n iterations] [-u milliseconds]\n"
"\n"
"-S: do not use VFD SWMR\n"
@@ -64,6 +62,7 @@ usage(const char *progname)
" exiting\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 iterations: how many times to expand each dataset\n"
"-u ms: milliseconds interval between updates\n"
" to %s.h5\n"
@@ -80,13 +79,12 @@ state_init(state_t *s, int argc, char **argv)
const hsize_t dims = 1;
char tfile[PATH_MAX];
char *end;
- unsigned long millis;
*s = ALL_HID_INITIALIZER;
esnprintf(tfile, sizeof(tfile), "%s", argv[0]);
esnprintf(s->progname, sizeof(s->progname), "%s", HDbasename(tfile));
- while ((ch = getopt(argc, argv, "SWa:bn:qu:")) != -1) {
+ while ((ch = getopt(argc, argv, "SWa:bc:n:qu:")) != -1) {
switch (ch) {
case 'S':
s->use_vfd_swmr = false;
@@ -95,6 +93,7 @@ state_init(state_t *s, int argc, char **argv)
s->wait_for_signal = false;
break;
case 'a':
+ case 'c':
case 'n':
errno = 0;
tmp = strtoul(optarg, &end, 0);
@@ -109,7 +108,9 @@ state_init(state_t *s, int argc, char **argv)
if (ch == 'a')
s->asteps = (unsigned)tmp;
- else
+ else if (ch == 'c')
+ s->csteps = (unsigned)tmp;
+ else if (ch == 'n')
s->nsteps = (unsigned)tmp;
break;
case 'b':
@@ -118,21 +119,6 @@ state_init(state_t *s, int argc, char **argv)
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);
- dbgf(1, "%lu milliseconds between updates\n", millis);
- break;
case '?':
default:
usage(s->progname);
@@ -146,6 +132,12 @@ state_init(state_t *s, int argc, char **argv)
if ((s->one_by_one_sid = H5Screate_simple(1, &dims, &dims)) < 0)
errx(EXIT_FAILURE, "H5Screate_simple failed");
+ if( s->csteps < 1 || s->csteps > s->nsteps)
+ errx(EXIT_FAILURE, "communication interval is out of bounds");
+
+ if( s->asteps < 1 || s->asteps > s->nsteps)
+ errx(EXIT_FAILURE, "attribute interval is out of bounds");
+
if (argc > 0)
errx(EXIT_FAILURE, "unexpected command-line arguments");
@@ -259,17 +251,30 @@ verify_group(state_t *s, unsigned int which)
return result;
}
+/* 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)
{
hid_t fapl, fcpl;
- sigset_t oldsigs;
herr_t ret;
unsigned step;
bool writer;
state_t s;
const char *personality;
H5F_vfd_swmr_config_t config;
+ const char *fifo_writer_to_reader = "./fifo_group_writer_to_reader";
+ const char *fifo_reader_to_writer = "./fifo_group_reader_to_writer";
+ int fd_writer_to_reader, fd_reader_to_writer;
+ int notify = 0, verify = 0;
+ unsigned int i;
state_init(&s, argc, argv);
@@ -310,27 +315,87 @@ main(int argc, char **argv)
if (s.file == badhid)
errx(EXIT_FAILURE, writer ? "H5Fcreate" : "H5Fopen");
- block_signals(&oldsigs);
+ /* Writer creates two named pipes(FIFO) to coordinate two-way communication */
+ if (writer) {
+ if (HDmkfifo(fifo_writer_to_reader, 0600) < 0)
+ errx(EXIT_FAILURE, "HDmkfifo");
+
+ if (HDmkfifo(fifo_reader_to_writer, 0600) < 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");
if (writer) {
+ /* Writer tells reader to start */
+ if (HDwrite(fd_writer_to_reader, &notify, sizeof(int)) < 0)
+ err(EXIT_FAILURE, "write failed");
+
for (step = 0; step < s.nsteps; step++) {
- dbgf(2, "step %d\n", step);
+ dbgf(2, "writer: step %d\n", step);
+
write_group(&s, step);
- nanosleep(&s.update_interval, NULL);
+
+ /* At communication interval, notifies the reader and waits for its response */
+ if (step % s.csteps == 0) {
+ /* Bump up the value and notify the reader */
+ notify++;
+ if (HDwrite(fd_writer_to_reader, &notify, sizeof(int)) < 0)
+ err(EXIT_FAILURE, "write failed");
+
+ /* During the wait, writer makes repeated HDF5 API calls
+ * to trigger EOT at approximately the correct time */
+ for(i = 0; i < config.max_lag + 1; i++) {
+ decisleep(config.tick_len);
+ H5Aexists(s.file, "nonexistent");
+ }
+
+ /* Receive the same value from the reader and verify it */
+ verify++;
+ if (HDread(fd_reader_to_writer, &notify, sizeof(int)) < 0)
+ err(EXIT_FAILURE, "read failed");
+
+ if (notify != verify)
+ errx(EXIT_FAILURE, "received message %d, expecting %d", notify, verify);
+ }
}
} else {
- for (step = 0; step < s.nsteps;) {
- dbgf(2, "step %d\n", step);
- if (verify_group(&s, step))
- step++;
- nanosleep(&s.update_interval, NULL);
- }
- }
+ /* Start to verify group creation after receiving the writer's notice */
+ if (HDread(fd_writer_to_reader, &notify, sizeof(int)) < 0)
+ err(EXIT_FAILURE, "read failed");
- if (s.use_vfd_swmr && s.wait_for_signal)
- await_signal(s.file);
+ /* Both notify and verify are 0 now */
+ if (notify != verify)
+ errx(EXIT_FAILURE, "received message %d, expecting %d", notify, verify);
+
+ for (step = 0; step < s.nsteps; step++) {
+ dbgf(2, "reader: step %d\n", step);
- restore_signals(&oldsigs);
+ while (!verify_group(&s, step))
+ ;
+
+ /* At communication interval, waits for the writer's notice and responds back */
+ if (step % s.csteps == 0) {
+ verify++;
+
+ /* Receive the notify that the writer bumped up the value */
+ if (HDread(fd_writer_to_reader, &notify, sizeof(int)) < 0)
+ err(EXIT_FAILURE, "read failed");
+
+ if (notify != verify)
+ errx(EXIT_FAILURE, "received message %d, expecting %d", notify, verify);
+
+ /* Send back the same nofity value for acknowledgement */
+ if (HDwrite(fd_reader_to_writer, &notify, sizeof(int)) < 0)
+ err(EXIT_FAILURE, "write failed");
+ }
+ }
+ }
if (H5Pclose(fapl) < 0)
errx(EXIT_FAILURE, "H5Pclose(fapl)");
@@ -341,5 +406,21 @@ main(int argc, char **argv)
if (H5Fclose(s.file) < 0)
errx(EXIT_FAILURE, "H5Fclose");
+ /* 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;
}