summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorkyang2014 <kyang2014@users.noreply.github.com>2021-10-01 20:43:41 (GMT)
committerGitHub <noreply@github.com>2021-10-01 20:43:41 (GMT)
commit5592111747b1e6ea1e934a3c13d3395312215c31 (patch)
treeb3975d174f840759cf4f4dab5162f4b9e41fa8a2 /test
parent1c3e79c1234831f3d01920921406bdb2fea0b56f (diff)
parent34478970510246c45ffa76d2b868aff90727eda1 (diff)
downloadhdf5-5592111747b1e6ea1e934a3c13d3395312215c31.zip
hdf5-5592111747b1e6ea1e934a3c13d3395312215c31.tar.gz
hdf5-5592111747b1e6ea1e934a3c13d3395312215c31.tar.bz2
Merge pull request #1006 from kyang2014/feature/vfd_swmr
Feature/vfd swmr
Diffstat (limited to 'test')
-rw-r--r--test/Makefile.am3
-rw-r--r--test/vfd_swmr_dsetops_writer.c2
-rw-r--r--test/vfd_swmr_gfail_writer.c798
-rw-r--r--test/vfd_swmr_group_writer.c39
4 files changed, 833 insertions, 9 deletions
diff --git a/test/Makefile.am b/test/Makefile.am
index 3ae26bd..6df1653 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -55,6 +55,7 @@ SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) links_env$(EXEEXT) \
vfd_swmr_vlstr_reader$(EXEEXT) vfd_swmr_vlstr_writer$(EXEEXT) \
vfd_swmr_zoo_reader$(EXEEXT) vfd_swmr_zoo_writer$(EXEEXT) \
vfd_swmr_gperf_reader$(EXEEXT) vfd_swmr_gperf_writer$(EXEEXT) \
+ vfd_swmr_gfail_reader$(EXEEXT) vfd_swmr_gfail_writer$(EXEEXT) \
vds_env$(EXEEXT) \
vds_swmr_gen$(EXEEXT) vds_swmr_reader$(EXEEXT) vds_swmr_writer$(EXEEXT)
if HAVE_SHARED_CONDITIONAL
@@ -113,6 +114,7 @@ check_PROGRAMS=$(TEST_PROG) error_test err_compat tcheck_version \
vfd_swmr_zoo_reader vfd_swmr_zoo_writer \
vfd_swmr_attrdset_reader vfd_swmr_attrdset_writer \
vfd_swmr_gperf_reader vfd_swmr_gperf_writer \
+ vfd_swmr_gfail_reader vfd_swmr_gfail_writer \
vfd_swmr_check_compat \
vfd_swmr_dsetchks_reader vfd_swmr_dsetchks_writer \
swmr_check_compat_vfd vds_env vds_swmr_gen vds_swmr_reader vds_swmr_writer \
@@ -181,6 +183,7 @@ vfd_swmr_zoo_reader_SOURCES=vfd_swmr_zoo_writer.c genall5.c
vfd_swmr_bigset_reader_SOURCES=vfd_swmr_bigset_writer.c
vfd_swmr_group_reader_SOURCES=vfd_swmr_group_writer.c
vfd_swmr_gperf_reader_SOURCES=vfd_swmr_gperf_writer.c
+vfd_swmr_gfail_reader_SOURCES=vfd_swmr_gfail_writer.c
vfd_swmr_dsetops_reader_SOURCES=vfd_swmr_dsetops_writer.c
vfd_swmr_attrdset_writer_SOURCES=vfd_swmr_attrdset_writer.c
diff --git a/test/vfd_swmr_dsetops_writer.c b/test/vfd_swmr_dsetops_writer.c
index f98843d..3704c44 100644
--- a/test/vfd_swmr_dsetops_writer.c
+++ b/test/vfd_swmr_dsetops_writer.c
@@ -149,7 +149,7 @@ static bool verify_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_
static bool verify_dsets_action(unsigned action, const state_t *s, const dsets_state_t *ds, unsigned which,
bool fileclosed);
static bool verify_dset(hid_t did, hid_t tid, hid_t mem_sid, hid_t file_sid, hsize_t *start, hsize_t *stride,
- size_t *count, hsize_t *block, unsigned int *vbuf, bool fileclosed,
+ hsize_t *count, hsize_t *block, unsigned int *vbuf, bool fileclosed,
bool flush_raw_data);
static bool verify_dset_compact(const state_t *s, const dsets_state_t *ds, bool fileclosed,
bool flush_raw_data);
diff --git a/test/vfd_swmr_gfail_writer.c b/test/vfd_swmr_gfail_writer.c
new file mode 100644
index 0000000..430ed89
--- /dev/null
+++ b/test/vfd_swmr_gfail_writer.c
@@ -0,0 +1,798 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://www.hdfgroup.org/licenses. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: To demostrate the four issues uncovered during the test plan
+ * 1.4 part 1.
+ *
+ * Setup:
+ * Writer:
+ * 1) Create an HDF5 file
+ * 2) Create many groups
+ * 3) Use the named pipe to send the reader a message to start verifying
+ * 4) Call H5Fvfd_swmr_end_tick immeidately after sending out the message to the reader
+ * 5) Sleep for two ticks before receiving a message from the reader that informs the reader
+ * started verifying
+ * 6) If the option to delete the group is off(by default), just sleep for a relatively long time,
+ * then close the HDF5 file.
+ * Else delete the last 1000 groups that are just created if the total number of
+ * created groups is greater than 1000.
+ * Call H5Fvfd_swmr_end_tick sleep for a relatively long time,
+ * then close HDF5 file.
+ * Reader:
+ * 1) Open the HDF5 file
+ * 2) Wait for the writer's message that informs the writer finished creating groups.
+ * 3) After receiving the message from the writer, send a message back to the writer,
+ * then call H5Literate to iterate through all the groups. The callback function just checks if
+ * the group name's prefix is valid.
+ * An #if 0 #endif block can help the user easily tune to check the iterated group names.
+ * 4) HDclock_gettime is used to check the total time of H5Literate call.
+ * 5) Close the HDF5 file.
+ *
+ * The number of groups, the tick length, the max lag, the page buffer size, the page size and the
+ * sleep duration on the writer side before closing the file are configurable.
+ * Users can also choose an option to delete 1000 groups after creating a larger number of groups.
+ * We only test to creat the groups with the latest file format. The option to create a
+ * group via the earliest file format is still there.
+ *
+ * Issues and expected design fail
+ *
+ * The parameter numbers that can reproduce the issues are tested at jelly.
+ * To duplicate the issues at other machines, the number of groups to be created should be different.
+ *
+ * Issue 1: HDassert(oent->length == nent->length) error.
+ * Need to UNCOMMENT out the HDassert(oent->length == nent->length) at ../src/H5Fvfd_swmr.c.
+ * May also modify the group number a bit to see the assertion error.
+ *
+ * GROUP_n=340000
+ * ./vfd_swmr_gfail_writer -q -n $GROUP_n &
+ * ./vfd_swmr_gfail_reader -n $GROUP_n &
+ *
+ * Issue 2: H5C__load_entry(): incorrect metadata checksum after all read attempts addr
+ * Sometimes the expected
+ * "Reader's API time exceeds max_lag of ticks, may increase the value of max_lag." may appear
+ * You may need to modify the group number a bit to see the unexpected error message.
+ *
+ * GROUP_n=420000
+ * ./vfd_swmr_gfail_writer -q -n $GROUP_n &
+ * ./vfd_swmr_gfail_reader -n $GROUP_n &
+ *
+ * Issue 3: Assertion `length == cache_ptr->page_size || page ......' failed
+ * This failure occurs when page size and page buffer size change from 4K to 8K.
+ * This issue seems to be always repeatable with the following number of groups.
+ *
+ * GROUP_n=320000
+ * ./vfd_swmr_gfail_writer -q -B 8192 -s 8192 -n $GROUP_n &
+ * ./vfd_swmr_gfail_reader -B 8192 -s 8192 -n $GROUP_n &
+
+ * Issue 4: not enough space to copy index
+ * To duplicate this failure, the number of groups should be much larger, 2 millions.
+ * The max_lag and tick_len should also be set to big numbers.
+ * This issue seems to be always repeatable with the following number of groups.
+ *
+ * GROUP_n=2000000
+ * ./vfd_swmr_gfail_writer -q -m 40 -t 10 -n $GROUP_n &
+ * ./vfd_swmr_gfail_reader -m 40 -t 10 -n $GROUP_n &
+
+ * Expected design fail
+ *
+ * Writer creates a large number of groups, then deletes the last 1000 groups,
+ * With the following settings, the expected
+ * "Reader's API time exceeds max_lag of ticks, may increase the value of max_lag."
+ * should appear. If not, increases the GROUP_n.
+ *
+ * GROUP_n=320000
+ * ./vfd_swmr_gfail_writer -q -d -n $GROUP_n &
+ * ./vfd_swmr_gfail_reader -n $GROUP_n &
+ *
+ * When increasing the max_lag, we may see the program run normally since
+ * the reader can finish iterating all the groups within the max_lag of ticks.
+ * The following program should end normally. If not, increase the max_lag.
+ * ./vfd_swmr_gfail_writer -m 9 -q -d -n $GROUP_n &
+ * ./vfd_swmr_gfail_reader -m 9 -n $GROUP_n &
+
+ */
+
+#define H5F_FRIEND /*suppress error about including H5Fpkg */
+
+#include "hdf5.h"
+
+#include "H5Fpkg.h"
+#include "H5HGprivate.h"
+#include "H5VLprivate.h"
+
+#include "testhdf5.h"
+#include "vfd_swmr_common.h"
+
+#ifndef H5_HAVE_WIN32_API
+
+#define TIME_PASSED(X, Y) \
+ ((double)((Y.tv_sec - X.tv_sec) * 1000000000 + (Y.tv_nsec - X.tv_nsec))) / 1000000000.0
+
+typedef struct {
+ hid_t file, filetype, one_by_one_sid;
+ char filename[PATH_MAX];
+ char progname[PATH_MAX];
+ unsigned int nsteps;
+ bool use_vfd_swmr;
+ bool old_style_grp;
+ bool use_named_pipes;
+ uint32_t w_sleep_len;
+ uint32_t max_lag;
+ uint32_t tick_len;
+ unsigned int ps;
+ unsigned int pbs;
+ bool del_grp;
+ int np_fd_w_to_r;
+ int np_fd_r_to_w;
+ int np_notify;
+ int np_verify;
+} state_t;
+
+#define ALL_HID_INITIALIZER \
+ (state_t) \
+ { \
+ .file = H5I_INVALID_HID, .one_by_one_sid = H5I_INVALID_HID, .filename = "", \
+ .filetype = H5T_NATIVE_UINT32, .nsteps = 10000, .use_vfd_swmr = true, .old_style_grp = false, \
+ .use_named_pipes = true, .w_sleep_len = 112, .tick_len = 4, .max_lag = 7, .ps = 4096, .pbs = 4096, \
+ .del_grp = false, .np_fd_w_to_r = -1, .np_fd_r_to_w = -1, .np_notify = 0, .np_verify = 0 \
+ }
+
+/*
+ * Operator function to be called by H5Literate.
+ */
+herr_t op_func(hid_t loc_id, const char *name, const H5L_info_t *info, void *operator_data);
+
+static void
+usage(const char *progname)
+{
+ HDfprintf(stderr,
+ "usage: %s [-S] [-G] [-n number_of_groups] \n"
+ " [-N] [-d] [-q] [-T w_sleep_len] [-t tick_len] [-m max_lag][-B pbs] [-s ps]\n"
+ "\n"
+ "-S: do not use VFD SWMR\n"
+ "-G: old-style type of group\n"
+ "-n ngroups: the number of groups\n"
+ "-N: do not use named pipes, \n"
+ " mainly for running the writer and reader seperately\n"
+ "-t tick_len: length of a tick in tenths of a second.\n"
+ "-m max_lag: maximum expected lag(in ticks) between writer and readers\n"
+ "-B pbs: page buffer size in bytes:\n"
+ " The default value is 4K(4096).\n"
+ "-s ps: page size used by page aggregation, page buffer and \n"
+ " the metadata file. The default value is 4K(4096).\n"
+ "-T w_sleep_len: Before closing the file, the sleep length in tenths of a second \n"
+ " on the writer side. The default is 112 tenths of a second \n"
+ " That is 4*max_lag*tick_len if tick_len is 4 and max_lag is 7. \n"
+ "-d del_grp: true: delete 1000 groups after creating >1000 groups. \n"
+ "-q: silence printouts, few messages\n"
+ "\n",
+ progname);
+ HDexit(EXIT_FAILURE);
+}
+
+static bool
+state_init(state_t *s, int argc, char **argv)
+{
+ unsigned long tmp;
+ int ch;
+ const hsize_t dims = 1;
+ char * tfile = NULL;
+ char * end;
+
+ *s = ALL_HID_INITIALIZER;
+
+ if (H5_basename(argv[0], &tfile) < 0) {
+ HDprintf("H5_basename failed\n");
+ TEST_ERROR;
+ }
+
+ esnprintf(s->progname, sizeof(s->progname), "%s", tfile);
+
+ if (tfile) {
+ HDfree(tfile);
+ tfile = NULL;
+ }
+
+ while ((ch = getopt(argc, argv, "SGNn:T:t:m:B:s:dq")) != -1) {
+ switch (ch) {
+ case 'S':
+ s->use_vfd_swmr = false;
+ break;
+ case 'G':
+ s->old_style_grp = true;
+ break;
+ case 'N':
+ s->use_named_pipes = false;
+ break;
+ case 'd':
+ s->del_grp = true;
+ break;
+ case 'n':
+ case 'T':
+ case 't':
+ case 'm':
+ case 'B':
+ case 's':
+
+ errno = 0;
+ tmp = HDstrtoul(optarg, &end, 0);
+ if (end == optarg || *end != '\0') {
+ HDprintf("couldn't parse `-%c` argument `%s`\n", ch, optarg);
+ TEST_ERROR;
+ }
+ else if (errno != 0) {
+ HDprintf("couldn't parse `-%c` argument `%s`\n", ch, optarg);
+ TEST_ERROR;
+ }
+ else if (tmp > UINT_MAX) {
+ HDprintf("`-%c` argument `%lu` too large\n", ch, tmp);
+ TEST_ERROR;
+ }
+
+ if (ch == 'n')
+ s->nsteps = (unsigned)tmp;
+ else if (ch == 'T')
+ s->w_sleep_len = (unsigned)tmp;
+ else if (ch == 't')
+ s->tick_len = (unsigned)tmp;
+ else if (ch == 'm')
+ s->max_lag = (unsigned)tmp;
+ else if (ch == 'B')
+ s->pbs = (unsigned)tmp;
+ else if (ch == 's')
+ s->ps = (unsigned)tmp;
+ break;
+ case 'q':
+ verbosity = 0;
+ break;
+ case '?':
+ default:
+ usage(s->progname);
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0) {
+ HDprintf("unexpected command-line arguments\n");
+ TEST_ERROR;
+ }
+
+ /* space for attributes */
+ if ((s->one_by_one_sid = H5Screate_simple(1, &dims, &dims)) < 0) {
+ HDprintf("H5Screate_simple failed\n");
+ TEST_ERROR;
+ }
+
+ esnprintf(s->filename, sizeof(s->filename), "vfd_swmr_group.h5");
+
+ return true;
+
+error:
+ if (tfile)
+ HDfree(tfile);
+ return false;
+}
+
+/* Named Pipe Subroutine: np_wr_send_receive
+ * Description:
+ * The writer sends a message to the reader,
+ * then waits for max_lag ticks,
+ * then checks the returned message from the reader.
+ * Return:
+ * True if succeed
+ * False if an error occurs in any step above.
+ * An error is mostly caused by an unexpected
+ * notification number from the message sent
+ * by the reader.
+ */
+static bool
+np_wr_send_receive(state_t *s)
+{
+
+ /* Bump up the value of notify to notice the reader to start to read */
+ s->np_notify++;
+ if (HDwrite(s->np_fd_w_to_r, &(s->np_notify), sizeof(int)) < 0) {
+ HDprintf("HDwrite failed\n");
+ TEST_ERROR;
+ }
+
+ /* Call the end tick */
+ if (H5Fvfd_swmr_end_tick(s->file) < 0)
+ TEST_ERROR;
+
+ /* Sleep for two ticks to wait for the reader's message */
+ decisleep(2 * s->tick_len);
+
+ /* Receive the same value from the reader and verify it before
+ * going to the next step */
+ (s->np_verify)++;
+ if (HDread(s->np_fd_r_to_w, &(s->np_notify), sizeof(int)) < 0) {
+ HDprintf("HDread failed\n");
+ TEST_ERROR;
+ }
+
+ if (s->np_notify == -1) {
+ HDprintf("reader failed to verify group or attribute operation.\n");
+ TEST_ERROR;
+ }
+
+ if (s->np_notify != s->np_verify) {
+ HDprintf("received message %d, expecting %d\n", s->np_notify, s->np_verify);
+ TEST_ERROR;
+ }
+
+ return true;
+
+error:
+ return false;
+}
+
+/* Named Pipe Subroutine: np_rd_receive
+ * Description:
+ * The reader receives a message from the writer,
+ * then checks if the notification number from
+ * the writer is expected.
+ * Return:
+ * True if succeed
+ * False if an error occurs in any step above.
+ * An error is mostly caused by an unexpected
+ * notification number from the message sent
+ * by the writer.
+ */
+static bool
+np_rd_receive(state_t *s)
+{
+
+ /* The writer should have bumped up the value of notify.
+ * Do the same with verify and confirm it */
+ s->np_verify++;
+
+ /* Receive the notify that the writer bumped up the value */
+ if (HDread(s->np_fd_w_to_r, &(s->np_notify), sizeof(int)) < 0) {
+ HDprintf("HDread failed\n");
+ TEST_ERROR;
+ }
+
+ if (s->np_notify == -1) {
+ HDprintf("writer failed to create group or carry out an attribute operation.\n");
+ TEST_ERROR;
+ }
+
+ if (s->np_notify != s->np_verify) {
+ HDprintf("received message %d, expecting %d\n", s->np_notify, s->np_verify);
+ TEST_ERROR;
+ }
+
+ return true;
+
+error:
+ return false;
+}
+
+/* Named Pipe Subroutine: np_rd_send
+ * Description:
+ * The reader sends an acknowledgement to the writer
+ * Return:
+ * True if succeed
+ * False if an error occurs in sending the message.
+ */
+static bool
+np_rd_send(state_t *s)
+{
+
+ if (HDwrite(s->np_fd_r_to_w, &(s->np_notify), sizeof(int)) < 0) {
+ H5_FAILED();
+ AT();
+ HDprintf("HDwrite failed\n");
+ return false;
+ }
+ else
+ return true;
+}
+
+/* Named Pipe Subroutine: np_send_error
+ * Description:
+ * An error (notification number is 1) message is sent
+ * either from the reader or the writer.
+ * A boolean input parameter is used to choose
+ * either reader or writer.
+ * Return:
+ * None
+ */
+static void
+np_send_error(state_t *s, bool writer)
+{
+ s->np_notify = -1;
+ if (writer)
+ HDwrite(s->np_fd_w_to_r, &(s->np_notify), sizeof(int));
+ else
+ HDwrite(s->np_fd_r_to_w, &(s->np_notify), sizeof(int));
+}
+
+/*-------------------------------------------------------------------------
+ * Function: create_group
+ *
+ * Purpose: Create a group and then close it.
+ *
+ * Parameters: state_t *s
+ * The struct that stores information of HDF5 file, named pipe
+ * and some VFD SWMR configuration parameters
+ *
+ * unsigned int which
+ * The number of iterations for group creation
+ *
+ *
+ * Return: Success: true
+ * Failure: false
+ *
+ * Note: This is called by the main() function.
+ *-------------------------------------------------------------------------
+ */
+
+static bool
+create_group(state_t *s, unsigned int which)
+{
+ char name[sizeof("/group-9999999999")];
+ hid_t g = H5I_INVALID_HID;
+
+ esnprintf(name, sizeof(name), "/group-%u", which);
+
+ if ((g = H5Gcreate2(s->file, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) {
+ HDprintf("H5Gcreate2 failed\n");
+ TEST_ERROR;
+ }
+
+ if (H5Gclose(g) < 0) {
+ HDprintf("H5Gclose failed\n");
+ TEST_ERROR;
+ }
+
+ return true;
+
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Gclose(g);
+ }
+ H5E_END_TRY;
+
+ return false;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: delete_group
+ *
+ * Purpose: Delete a group
+ *
+ * Parameters: state_t *s
+ * The struct that stores information of HDF5 file, named pipe
+ * and some VFD SWMR configuration parameters
+ *
+ * unsigned int which
+ * The number of iterations for group creation
+ *
+ *
+ * Return: Success: true
+ * Failure: false
+ *
+ * Note: This is called by the main() function.
+ *-------------------------------------------------------------------------
+ */
+
+static bool
+delete_group(state_t *s, unsigned int which)
+{
+ char name[sizeof("/group-9999999999")];
+
+ esnprintf(name, sizeof(name), "/group-%u", which);
+
+ if (H5Ldelete(s->file, name, H5P_DEFAULT) < 0) {
+ HDprintf("H5Ldelete failed\n");
+ TEST_ERROR;
+ }
+
+ return true;
+
+error:
+
+ return false;
+}
+
+int
+main(int argc, char **argv)
+{
+ hid_t fapl = H5I_INVALID_HID, fcpl = H5I_INVALID_HID;
+ unsigned step;
+ bool writer = false;
+ 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 = -1, fd_reader_to_writer = -1;
+ int notify = 0, verify = 0;
+ bool wg_ret = false;
+
+ struct timespec start_time, end_time;
+ double temp_time;
+
+ if (!state_init(&s, argc, argv)) {
+ HDprintf("state_init failed\n");
+ TEST_ERROR;
+ }
+
+ personality = HDstrstr(s.progname, "vfd_swmr_gfail_");
+
+ if (personality != NULL && HDstrcmp(personality, "vfd_swmr_gfail_writer") == 0)
+ writer = true;
+ else if (personality != NULL && HDstrcmp(personality, "vfd_swmr_gfail_reader") == 0)
+ writer = false;
+ else {
+ HDprintf("unknown personality, expected vfd_swmr_gfail_{reader,writer}\n");
+ TEST_ERROR;
+ }
+
+ /* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */
+ init_vfd_swmr_config(&config, s.tick_len, s.max_lag, writer, TRUE, 128, "./group-shadow");
+
+ /* If old-style option is chosen, use the earliest file format(H5F_LIBVER_EARLIEST)
+ * as the second parameter of H5Pset_libver_bound() that is called by
+ * vfd_swmr_create_fapl. Otherwise, the latest file format(H5F_LIBVER_LATEST)
+ * should be used as the second parameter of H5Pset_libver_bound().
+ * Also pass the use_vfd_swmr, only_meta_page, page_buf_size, config to vfd_swmr_create_fapl().*/
+ if ((fapl = vfd_swmr_create_fapl(!s.old_style_grp, s.use_vfd_swmr, true, s.pbs, &config)) < 0) {
+ HDprintf("vfd_swmr_create_fapl failed\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, s.ps)) < 0) {
+ HDprintf("vfd_swmr_create_fcpl() failed");
+ TEST_ERROR;
+ }
+
+ if (writer)
+ s.file = H5Fcreate(s.filename, H5F_ACC_TRUNC, fcpl, fapl);
+ else
+ s.file = H5Fopen(s.filename, H5F_ACC_RDONLY, fapl);
+
+ if (s.file < 0) {
+ HDprintf("H5Fcreate/open failed\n");
+ TEST_ERROR;
+ }
+
+ /* Use two named pipes(FIFO) to coordinate the writer and reader for
+ * two-way communication.
+ * One is for the writer to write to the reader.
+ * The other one is for the reader to signal the writer. */
+ if (s.use_named_pipes && writer) {
+ /* Writer creates two named pipes(FIFO) */
+ if (HDmkfifo(fifo_writer_to_reader, 0600) < 0) {
+ HDprintf("HDmkfifo failed\n");
+ TEST_ERROR;
+ }
+
+ if (HDmkfifo(fifo_reader_to_writer, 0600) < 0) {
+ HDprintf("HDmkfifo failed\n");
+ TEST_ERROR;
+ }
+ }
+
+ /* Both the writer and reader open the pipes */
+ if (s.use_named_pipes && (fd_writer_to_reader = HDopen(fifo_writer_to_reader, O_RDWR)) < 0) {
+ HDprintf("HDopen failed\n");
+ TEST_ERROR;
+ }
+
+ if (s.use_named_pipes && (fd_reader_to_writer = HDopen(fifo_reader_to_writer, O_RDWR)) < 0) {
+ HDprintf("HDopen failed\n");
+ TEST_ERROR;
+ }
+
+ /* Pass the named pipe information to the struct of state_t s, for attribute tests.*/
+ if (s.use_named_pipes) {
+ s.np_fd_w_to_r = fd_writer_to_reader;
+ s.np_fd_r_to_w = fd_reader_to_writer;
+ s.np_notify = notify;
+ s.np_verify = verify;
+ }
+
+ if (writer) {
+
+ for (step = 0; step < s.nsteps; step++) {
+ dbgf(2, "writer: step %d\n", step);
+
+ wg_ret = create_group(&s, step);
+ if (wg_ret == false) {
+ if (s.use_named_pipes)
+ np_send_error(&s, true);
+ HDprintf("create groups failed\n");
+ TEST_ERROR;
+ }
+ }
+ if (s.use_named_pipes && np_wr_send_receive(&s) == false) {
+ HDprintf("writer: write group - verification failed.\n");
+ TEST_ERROR;
+ }
+
+ /* Delete 1000 groups if the del_grp option is true. */
+ if (s.del_grp && s.nsteps > 1000) {
+ printf("Deleting groups. \n");
+ for (step = s.nsteps - 1; step >= (s.nsteps - 1000); step--) {
+ dbgf(2, "writer: deleting step %d\n", step);
+
+ wg_ret = delete_group(&s, step);
+ if (wg_ret == false) {
+ HDprintf("delete group_operations failed\n");
+ TEST_ERROR;
+ }
+ }
+ /* end tick,may be not necessary. */
+ if (H5Fvfd_swmr_end_tick(s.file) < 0)
+ TEST_ERROR;
+ }
+
+ /* May be necessary for the writer to wait a longer time before
+ closing the file.
+ The default value is 112 tenths of a second(4*s.tick_len*s.max_lag)
+ if tick_len is 4 and max_lag is 7.
+ */
+ decisleep(s.w_sleep_len);
+ }
+ else { /*Reader */
+ if (s.use_named_pipes) {
+ if (false == np_rd_receive(&s)) {
+ TEST_ERROR;
+ }
+
+ dbgf(2, "reader receives the message.\n");
+ if (np_rd_send(&s) == false) {
+ TEST_ERROR;
+ }
+ dbgf(2, "reader sends the message.\n ");
+ }
+
+ if (HDclock_gettime(CLOCK_MONOTONIC, &start_time) == -1) {
+ fprintf(stderr, "HDclock_gettime failed");
+ TEST_ERROR;
+ }
+
+ printf("Reader: call back function: check group names.\n");
+ if (H5Literate(s.file, H5_INDEX_NAME, H5_ITER_NATIVE, NULL, op_func, NULL) < 0) {
+ printf("H5Literate failed \n");
+ TEST_ERROR;
+ }
+ if (HDclock_gettime(CLOCK_MONOTONIC, &end_time) == -1) {
+ fprintf(stderr, "HDclock_gettime failed");
+ TEST_ERROR;
+ }
+ temp_time = TIME_PASSED(start_time, end_time);
+ fprintf(stdout, "H5Literate: temp time = %lf\n", temp_time);
+ }
+
+ if (H5Pclose(fapl) < 0) {
+ HDprintf("H5Pclose failed\n");
+ TEST_ERROR;
+ }
+
+ if (H5Pclose(fcpl) < 0) {
+ HDprintf("H5Pclose failed\n");
+ TEST_ERROR;
+ }
+
+ if (H5Sclose(s.one_by_one_sid) < 0) {
+ HDprintf("H5Sclose failed\n");
+ TEST_ERROR;
+ }
+
+ if (H5Fclose(s.file) < 0) {
+ HDprintf("H5Fclose failed\n");
+ TEST_ERROR;
+ }
+
+ /* Both the writer and reader close the named pipes */
+ if (s.use_named_pipes && HDclose(fd_writer_to_reader) < 0) {
+ HDprintf("HDclose failed\n");
+ TEST_ERROR;
+ }
+
+ if (s.use_named_pipes && HDclose(fd_reader_to_writer) < 0) {
+ HDprintf("HDclose failed\n");
+ TEST_ERROR;
+ }
+
+ /* Reader finishes last and deletes the named pipes */
+ if (s.use_named_pipes && !writer) {
+ if (HDremove(fifo_writer_to_reader) != 0) {
+ HDprintf("HDremove failed\n");
+ TEST_ERROR;
+ }
+
+ if (HDremove(fifo_reader_to_writer) != 0) {
+ HDprintf("HDremove failed\n");
+ TEST_ERROR;
+ }
+ }
+
+ return EXIT_SUCCESS;
+
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Pclose(fapl);
+ H5Pclose(fcpl);
+ H5Sclose(s.one_by_one_sid);
+ H5Fclose(s.file);
+ }
+ H5E_END_TRY;
+
+ if (s.use_named_pipes && fd_writer_to_reader >= 0)
+ HDclose(fd_writer_to_reader);
+
+ if (s.use_named_pipes && fd_reader_to_writer >= 0)
+ HDclose(fd_reader_to_writer);
+
+ if (s.use_named_pipes && !writer) {
+ HDremove(fifo_writer_to_reader);
+ HDremove(fifo_reader_to_writer);
+ }
+
+ return EXIT_FAILURE;
+}
+/************************************************************
+
+ Operator function. Prints the name and type of the object
+ being examined.
+
+ ************************************************************/
+herr_t
+op_func(hid_t loc_id, const char *name, const H5L_info_t *info, void *operator_data)
+{
+
+ /* avoid compiler warnings */
+ (void)loc_id;
+ (void)info;
+ (void)operator_data;
+
+#if 0 /* Kent for debugging purpose. */
+ char * subname;
+ int grp_num;
+#endif
+
+ if (strncmp(name, "group", (size_t)5) != 0) {
+ printf("Iteration failed: group name is %s\n", name);
+ return -1;
+ }
+ else {
+#if 0 /* Kent for debugging purpose. */
+ subname = name + 6;
+ grp_num = atoi((const char *)subname);
+ if (grp_num > 1450000 && grp_num % 5000 == 0)
+ dbgf(2, "Group name is %s\n", name);
+#endif
+ return 0;
+ }
+}
+
+#else /* H5_HAVE_WIN32_API */
+
+int
+main(void)
+{
+ HDfprintf(stderr, "Non-POSIX platform. Skipping.\n");
+ return EXIT_SUCCESS;
+} /* end main() */
+
+#endif /* H5_HAVE_WIN32_API */
diff --git a/test/vfd_swmr_group_writer.c b/test/vfd_swmr_group_writer.c
index c240ee5..5881300 100644
--- a/test/vfd_swmr_group_writer.c
+++ b/test/vfd_swmr_group_writer.c
@@ -43,6 +43,8 @@ typedef struct {
bool attr_test;
uint32_t max_lag;
uint32_t tick_len;
+ uint32_t ps;
+ uint32_t pbs;
int np_fd_w_to_r;
int np_fd_r_to_w;
int np_notify;
@@ -56,8 +58,8 @@ typedef struct {
.filetype = H5T_NATIVE_UINT32, .asteps = 10, .csteps = 10, .nsteps = 100, \
.update_interval = READER_WAIT_TICKS, .use_vfd_swmr = true, .old_style_grp = false, \
.use_named_pipes = true, .grp_op_pattern = ' ', .grp_op_test = false, .at_pattern = ' ', \
- .attr_test = false, .tick_len = 4, .max_lag = 7, .np_fd_w_to_r = -1, .np_fd_r_to_w = -1, \
- .np_notify = 0, .np_verify = 0 \
+ .attr_test = false, .tick_len = 4, .max_lag = 7, .ps = 4096, .pbs = 4096, .np_fd_w_to_r = -1, \
+ .np_fd_r_to_w = -1, .np_notify = 0, .np_verify = 0 \
}
static void
@@ -66,6 +68,7 @@ usage(const char *progname)
HDfprintf(stderr,
"usage: %s [-S] [-G] [-a steps] [-b] [-c] [-n iterations]\n"
" [-N] [-q] [-u numb_ticks] [-A at_pattern] [-O grp_op_pattern]\n"
+ " [-t tick_len] [-m max_lag][-B pbs] [-s ps] \n"
"\n"
"-S: do not use VFD SWMR\n"
"-G: old-style type of group\n"
@@ -76,6 +79,12 @@ usage(const char *progname)
"-N: do not use named pipes, \n"
" mainly for running the writer and reader seperately\n"
"-u numb_ticks: `numb_ticks` for the reader to wait before verification\n"
+ "-t tick_len: length of a tick in tenths of a second.\n"
+ "-m max_lag: maximum expected lag(in ticks) between writer and readers\n"
+ "-B pbs: page buffer size in bytes:\n"
+ " The default value is 4K(4096).\n"
+ "-s ps: page size used by page aggregation, page buffer and \n"
+ " the metadata file. The default value is 4K(4096).\n"
"-A at_pattern: `at_pattern' for different attribute tests\n"
" The value of `at_pattern` is one of the following:\n"
" `compact` - Attributes added in compact storage\n"
@@ -158,7 +167,7 @@ state_init(state_t *s, int argc, char **argv)
tfile = NULL;
}
- while ((ch = getopt(argc, argv, "SGa:bc:n:Nqu:A:O:")) != -1) {
+ while ((ch = getopt(argc, argv, "SGa:bc:n:Nqu:t:m:B:s:A:O:")) != -1) {
switch (ch) {
case 'S':
s->use_vfd_swmr = false;
@@ -170,6 +179,10 @@ state_init(state_t *s, int argc, char **argv)
case 'c':
case 'n':
case 'u':
+ case 't':
+ case 'm':
+ case 'B':
+ case 's':
errno = 0;
tmp = HDstrtoul(optarg, &end, 0);
if (end == optarg || *end != '\0') {
@@ -193,6 +206,14 @@ state_init(state_t *s, int argc, char **argv)
s->nsteps = (unsigned)tmp;
else if (ch == 'u')
s->update_interval = (unsigned)tmp;
+ else if (ch == 't')
+ s->tick_len = (unsigned)tmp;
+ else if (ch == 'm')
+ s->max_lag = (unsigned)tmp;
+ else if (ch == 'B')
+ s->pbs = (unsigned)tmp;
+ else if (ch == 's')
+ s->ps = (unsigned)tmp;
break;
case 'b':
s->filetype = H5T_STD_U32BE;
@@ -284,6 +305,10 @@ state_init(state_t *s, int argc, char **argv)
TEST_ERROR;
}
+ if (s->pbs < s->ps) {
+ HDprintf("Page buffer size cannot be smaller than the page size.s\n");
+ TEST_ERROR;
+ }
if (argc > 0) {
HDprintf("unexpected command-line arguments\n");
TEST_ERROR;
@@ -4987,20 +5012,20 @@ main(int argc, char **argv)
}
/* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */
- init_vfd_swmr_config(&config, 4, 7, writer, TRUE, 128, "./group-shadow");
+ init_vfd_swmr_config(&config, s.tick_len, s.max_lag, writer, TRUE, 128, "./group-shadow");
/* If old-style option is chosen, use the earliest file format(H5F_LIBVER_EARLIEST)
* as the second parameter of H5Pset_libver_bound() that is called by
* vfd_swmr_create_fapl. Otherwise, the latest file format(H5F_LIBVER_LATEST)
* should be used as the second parameter of H5Pset_libver_bound().
* Also pass the use_vfd_swmr, only_meta_page, page_buf_size, config to vfd_swmr_create_fapl().*/
- if ((fapl = vfd_swmr_create_fapl(!s.old_style_grp, s.use_vfd_swmr, true, 4096, &config)) < 0) {
+ if ((fapl = vfd_swmr_create_fapl(!s.old_style_grp, s.use_vfd_swmr, true, s.pbs, &config)) < 0) {
HDprintf("vfd_swmr_create_fapl failed\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) {
+ if ((fcpl = vfd_swmr_create_fcpl(H5F_FSPACE_STRATEGY_PAGE, s.ps)) < 0) {
HDprintf("vfd_swmr_create_fcpl() failed");
TEST_ERROR;
}
@@ -5049,8 +5074,6 @@ main(int argc, char **argv)
s.np_fd_r_to_w = fd_reader_to_writer;
s.np_notify = notify;
s.np_verify = verify;
- s.tick_len = config.tick_len;
- s.max_lag = config.max_lag;
}
/* For attribute test, force the named pipe to communicate in every step.