From 13e930d306fc38940b00fe020ededbc9a191c4d2 Mon Sep 17 00:00:00 2001 From: David Young Date: Tue, 21 Apr 2020 15:39:25 -0500 Subject: Add a `skip compact` configuration for skipping the "zoo" tests for compact datasets. Bundle the zoo-test configuration into a new type, zoo_config_t. Add a couple new "zoo" test phases, "delete" and "validate-deletion", to the existing "create" and "verify" phases. Give names and numbers to all phases with the new `enum`, `phase_t`, and refactor so that tend_zoo runs a selection of phases at each step. Stub the "delete" and "validate-deletion" phases for most test steps. Actually implement for compact dataset (ds_cpt_i) test. In tend_zoo(), delay for 50 milliseconds after running all steps. Really, this should delay after each step.... Implement vfd_swmr_writer_may_increase_tick_to() and vfd_swmr_reader_did_increase_tick_to() with a file that reader and writer share. The reader saves its current tick number in the shared file. The writer does not advance its tick number past the reader's. Collect some statistics in vfd_swmr_writer_may_increase_tick_to() and print them before the writer exits. Add option flags for skipping compact dataset tests (-C) and for printing error stacks (-e). Update the usage message, which was stale before the new options were added. Delete some dead code. Add #if 0'd-out code for the reader to wait for the writer before running "delete" and "validate-deletion" steps. --- test/cache_image.c | 30 +++-- test/genall5.c | 271 ++++++++++++++++++++++++++++++++++++--------- test/genall5.h | 22 ++-- test/vfd_swmr_zoo_writer.c | 251 +++++++++++++++++++++++++++++++++++------ 4 files changed, 472 insertions(+), 102 deletions(-) diff --git a/test/cache_image.c b/test/cache_image.c index f3db30b..d4002c7 100644 --- a/test/cache_image.c +++ b/test/cache_image.c @@ -4819,7 +4819,9 @@ cache_image_smoke_check_5(hbool_t single_file_vfd) /* 3) Construct a "zoo" in the above group, and validate it. */ if ( pass ) - pass = create_zoo(file_id, process_group_name, min_group, false); + pass = create_zoo(file_id, process_group_name, + (zoo_config_t){.proc_num = min_group, .skip_varlen = false, + .skip_compact = false}); #if H5C_COLLECT_CACHE_STATS if ( pass ) { @@ -4890,8 +4892,11 @@ cache_image_smoke_check_5(hbool_t single_file_vfd) /* 6) Validate the "zoo" created in the previous file open. */ - if ( pass ) - pass = validate_zoo(file_id, process_group_name, max_group, false); + if ( pass ) { + pass = validate_zoo(file_id, process_group_name, + (zoo_config_t){.proc_num = max_group, .skip_varlen = false, + .skip_compact = false}); + } #if H5C_COLLECT_CACHE_STATS if ( pass ) { @@ -4931,8 +4936,11 @@ cache_image_smoke_check_5(hbool_t single_file_vfd) /* 8) Construct a "zoo" in the above group, and validate it. */ - if ( pass ) - pass = create_zoo(file_id, process_group_name, max_group, false); + if ( pass ) { + pass = create_zoo(file_id, process_group_name, + (zoo_config_t){.proc_num = max_group, .skip_varlen = false, + .skip_compact = false}); + } if ( show_progress ) HDfprintf(stdout, "%s:L4 cp = %d, max_group = %d, pass = %d.\n", @@ -4993,7 +5001,9 @@ cache_image_smoke_check_5(hbool_t single_file_vfd) i = min_group; while(pass && i <= max_group) { HDsprintf(process_group_name, "/process_%d", i); - pass = validate_zoo(file_id, process_group_name, i++, false); + pass = validate_zoo(file_id, process_group_name, + (zoo_config_t){.proc_num = i++, .skip_varlen = false, + .skip_compact = false}); } #if H5C_COLLECT_CACHE_STATS @@ -5046,7 +5056,9 @@ cache_image_smoke_check_5(hbool_t single_file_vfd) while ( ( pass ) && ( i <= max_group ) ) { HDsprintf(process_group_name, "/process_%d", i); - pass = validate_zoo(file_id, process_group_name, i++, false); + pass = validate_zoo(file_id, process_group_name, + (zoo_config_t){.proc_num = i++, .skip_varlen = false, + .skip_compact = false}); } #if H5C_COLLECT_CACHE_STATS @@ -5110,7 +5122,9 @@ cache_image_smoke_check_5(hbool_t single_file_vfd) i = min_group; while ( ( pass ) && ( i <= max_group ) ) { HDsprintf(process_group_name, "/process_%d", i); - pass = validate_zoo(file_id, process_group_name, i++, false); + pass = validate_zoo(file_id, process_group_name, + (zoo_config_t){.proc_num = i++, .skip_varlen = false, + .skip_compact = false}); } #if H5C_COLLECT_CACHE_STATS diff --git a/test/genall5.c b/test/genall5.c index d9064d8..ec2849b 100644 --- a/test/genall5.c +++ b/test/genall5.c @@ -19,6 +19,8 @@ * of the same name. */ +#include + #include "cache_common.h" #include "genall5.h" @@ -27,6 +29,45 @@ #define DSET_CHUNK_DIMS 1024 #define DSET_COMPACT_DIMS 4096 +typedef enum phase {PHASE_CREATE, PHASE_VALIDATE, PHASE_DELETE, + PHASE_VALIDATE_DELETION} phase_t; + +static bool rm_ns_grp_0(hid_t, const char *); +static bool rm_ns_grp_c(hid_t, const char *, unsigned); +static bool rm_ns_grp_d(hid_t, const char *, unsigned); +static bool rm_os_grp_0(hid_t, const char *); +static bool rm_os_grp_n(hid_t, const char *, int, unsigned); +static bool rm_ds_ctg_i(hid_t, const char *, hbool_t); +static bool rm_ds_chk_i(hid_t, const char *, hbool_t); +static bool rm_ds_cpt_i(hid_t, const char *, hbool_t); +static bool rm_ds_ctg_v(hid_t, const char *, hbool_t); + +static bool missing_ns_grp_0(hid_t, const char *); +static bool missing_ns_grp_c(hid_t, const char *, unsigned); +static bool missing_ns_grp_d(hid_t, const char *, unsigned); +static bool missing_os_grp_0(hid_t, const char *); +static bool missing_os_grp_n(hid_t, const char *, int, unsigned); +static bool missing_ds_ctg_i(hid_t, const char *, hbool_t); +static bool missing_ds_chk_i(hid_t, const char *, hbool_t); +static bool missing_ds_cpt_i(hid_t, const char *, hbool_t); +static bool missing_ds_ctg_v(hid_t, const char *, hbool_t); + +#define FN_ITEM_DEFN(__name, ...) \ + typedef bool (*__name##fn_t)(__VA_ARGS__); \ + static const __name##fn_t __name##_fntbl[] = \ + {__name, vrfy_##__name, rm_##__name, missing_##__name} + +FN_ITEM_DEFN(ns_grp_0, hid_t, const char *); +FN_ITEM_DEFN(ns_grp_c, hid_t, const char *, unsigned); +FN_ITEM_DEFN(ns_grp_d, hid_t, const char *, unsigned); +FN_ITEM_DEFN(os_grp_0, hid_t, const char *); +FN_ITEM_DEFN(os_grp_n, hid_t, const char *, int, unsigned); +FN_ITEM_DEFN(ds_ctg_i, hid_t, const char *, bool); +FN_ITEM_DEFN(ds_chk_i, hid_t, const char *, bool); +FN_ITEM_DEFN(ds_cpt_i, hid_t, const char *, bool); +FN_ITEM_DEFN(ds_ctg_v, hid_t, const char *, bool); + +#undef FN_ITEM_DEFN /*------------------------------------------------------------------------- * Function: ns_grp_0 @@ -45,6 +86,18 @@ *------------------------------------------------------------------------- */ +static bool +missing_ns_grp_0(hid_t fid, const char *group_name) +{ + return true; +} + +static bool +rm_ns_grp_0(hid_t fid, const char *group_name) +{ + return true; +} + bool ns_grp_0(hid_t fid, const char *group_name) { @@ -198,6 +251,18 @@ vrfy_ns_grp_0(hid_t fid, const char *group_name) *------------------------------------------------------------------------- */ +static bool +missing_ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks) +{ + return true; +} + +static bool +rm_ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks) +{ + return true; +} + bool ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks) { @@ -530,6 +595,18 @@ vrfy_ns_grp_c(hid_t fid, const char *group_name, unsigned nlinks) *------------------------------------------------------------------------- */ +static bool +missing_ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks) +{ + return true; +} + +static bool +rm_ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks) +{ + return true; +} + bool ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks) { @@ -857,6 +934,18 @@ vrfy_ns_grp_d(hid_t fid, const char *group_name, unsigned nlinks) *------------------------------------------------------------------------- */ +static bool +missing_os_grp_0(hid_t fid, const char *group_name) +{ + return true; +} + +static bool +rm_os_grp_0(hid_t fid, const char *group_name) +{ + return true; +} + bool os_grp_0(hid_t fid, const char *group_name) { @@ -1019,6 +1108,19 @@ vrfy_os_grp_0(hid_t fid, const char *group_name) *------------------------------------------------------------------------- */ +static bool +missing_os_grp_n(hid_t fid, const char *group_name, int proc_num, + unsigned nlinks) +{ + return true; +} + +static bool +rm_os_grp_n(hid_t fid, const char *group_name, int proc_num, unsigned nlinks) +{ + return true; +} + bool os_grp_n(hid_t fid, const char *group_name, int proc_num, unsigned nlinks) { @@ -1292,6 +1394,18 @@ vrfy_os_grp_n(hid_t fid, const char *group_name, int proc_num, unsigned nlinks) * *------------------------------------------------------------------------- */ +static bool +missing_ds_ctg_i(hid_t fid, const char *dset_name, hbool_t write_data) +{ + return true; +} + +static bool +rm_ds_ctg_i(hid_t fid, const char *dset_name, hbool_t write_data) +{ + return true; +} + bool ds_ctg_i(hid_t fid, const char *dset_name, hbool_t write_data) { @@ -1541,6 +1655,18 @@ vrfy_ds_ctg_i(hid_t fid, const char *dset_name, hbool_t write_data) * *------------------------------------------------------------------------- */ +static bool +missing_ds_chk_i(hid_t fid, const char *dset_name, hbool_t write_data) +{ + return true; +} + +static bool +rm_ds_chk_i(hid_t fid, const char *dset_name, hbool_t write_data) +{ + return true; +} + bool ds_chk_i(hid_t fid, const char *dset_name, hbool_t write_data) { @@ -1818,6 +1944,28 @@ vrfy_ds_chk_i(hid_t fid, const char *dset_name, hbool_t write_data) * *------------------------------------------------------------------------- */ +static bool +missing_ds_cpt_i(hid_t fid, const char *dset_name, hbool_t H5_ATTR_UNUSED write_data) +{ + if (H5Lexists(fid, dset_name, H5P_DEFAULT) >= 0) { + failure_mssg = "rm_ds_cpt_i: H5Lexists unexpectedly succeeded."; + return false; + } + + return true; +} + +static bool +rm_ds_cpt_i(hid_t fid, const char *dset_name, hbool_t H5_ATTR_UNUSED write_data) +{ + if (H5Ldelete(fid, dset_name, H5P_DEFAULT) < 0) { + failure_mssg = "rm_ds_cpt_i: H5Ldelete failed."; + return false; + } + + return true; +} + bool ds_cpt_i(hid_t fid, const char *dset_name, hbool_t write_data) { @@ -2084,6 +2232,18 @@ vrfy_ds_cpt_i(hid_t fid, const char *dset_name, hbool_t write_data) * *------------------------------------------------------------------------- */ +static bool +missing_ds_ctg_v(hid_t fid, const char *dset_name, hbool_t write_data) +{ + return true; +} + +static bool +rm_ds_ctg_v(hid_t fid, const char *dset_name, hbool_t write_data) +{ + return true; +} + bool ds_ctg_v(hid_t fid, const char *dset_name, hbool_t write_data) { @@ -2409,97 +2569,83 @@ vrfy_ds_ctg_v(hid_t fid, const char *dset_name, hbool_t write_data) * * Return `true` if the selector was valid, `false` if it was not. */ + static bool -create_or_validate_selection(hid_t fid, const char *full_path, int proc_num, - int selector, bool skip_varlen, bool validate, bool *okp) +create_or_validate_selection(hid_t fid, const char *full_path, + int selector, zoo_config_t config, phase_t phase, bool *okp) { - const bool wr = !validate; bool ok; switch (selector) { case 0: /* Add & verify an empty "new style" group */ - ok = wr ? ns_grp_0(fid, full_path) : vrfy_ns_grp_0(fid, full_path); + ok = ns_grp_0_fntbl[phase](fid, full_path); break; case 1: /* Add & verify a compact "new style" group (3 link messages) */ - ok = wr ? ns_grp_c(fid, full_path, 3) - : vrfy_ns_grp_c(fid, full_path, 3); + ok = ns_grp_c_fntbl[phase](fid, full_path, 3); break; case 2: /* Add & verify a dense "new style" group (w/300 links, * in v2 B-tree & fractal heap) */ - ok = wr ? ns_grp_d(fid, full_path, 300) - : vrfy_ns_grp_d(fid, full_path, 300); + ok = ns_grp_d_fntbl[phase](fid, full_path, 300); break; case 3: /* Add & verify an empty "old style" group to file */ - ok = wr ? os_grp_0(fid, full_path) : vrfy_os_grp_0(fid, full_path); + ok = os_grp_0_fntbl[phase](fid, full_path); break; case 4: /* Add & verify an "old style" group (w/300 links, in * v1 B-tree & local heap) to file */ - ok = wr ? os_grp_n(fid, full_path, proc_num, 300) - : vrfy_os_grp_n(fid, full_path, proc_num, 300); + ok = os_grp_n_fntbl[phase](fid, full_path, config.proc_num, 300); break; case 5: /* Add & verify a contiguous dataset w/integer datatype (but no data) * to file */ - ok = wr ? ds_ctg_i(fid, full_path, FALSE) - : vrfy_ds_ctg_i(fid, full_path, FALSE); + ok = ds_ctg_i_fntbl[phase](fid, full_path, false); break; case 6: /* Add & verify a contiguous dataset w/integer datatype (with data) * to file */ - ok = wr ? ds_ctg_i(fid, full_path, TRUE) - : vrfy_ds_ctg_i(fid, full_path, TRUE); + ok = ds_ctg_i_fntbl[phase](fid, full_path, true); break; case 7: /* Add & verify a chunked dataset w/integer datatype (but no data) * to file */ - ok = wr ? ds_chk_i(fid, full_path, FALSE) - : vrfy_ds_chk_i(fid, full_path, FALSE); + ok = ds_chk_i_fntbl[phase](fid, full_path, false); break; case 8: /* Add & verify a chunked dataset w/integer datatype (and data) * to file */ - ok = wr ? ds_chk_i(fid, full_path, TRUE) - : vrfy_ds_chk_i(fid, full_path, TRUE); + ok = ds_chk_i_fntbl[phase](fid, full_path, true); break; case 9: /* Add & verify a compact dataset w/integer datatype (but no data) * to file */ - ok = wr ? ds_cpt_i(fid, full_path, FALSE) - : vrfy_ds_cpt_i(fid, full_path, FALSE); + ok = config.skip_compact || + ds_cpt_i_fntbl[phase](fid, full_path, false); break; case 10: /* Add & verify a compact dataset w/integer datatype (and data) * to file */ - ok = wr ? ds_cpt_i(fid, full_path, TRUE) - : vrfy_ds_cpt_i(fid, full_path, TRUE); + ok = config.skip_compact || ds_cpt_i_fntbl[phase](fid, full_path, true); break; case 11: - if (skip_varlen) - return false; /* Add & verify a contiguous dataset w/variable-length datatype * (but no data) to file */ - ok = wr ? ds_ctg_v(fid, full_path, FALSE) - : vrfy_ds_ctg_v(fid, full_path, FALSE); + ok = config.skip_varlen || ds_ctg_v_fntbl[phase](fid, full_path, false); break; case 12: - if (skip_varlen) - return false; /* Add & verify a contiguous dataset w/variable-length datatype * (and data) to file */ - ok = wr ? ds_ctg_v(fid, full_path, TRUE) - : vrfy_ds_ctg_v(fid, full_path, TRUE); + ok = config.skip_varlen || ds_ctg_v_fntbl[phase](fid, full_path, true); break; default: return false; @@ -2509,47 +2655,50 @@ create_or_validate_selection(hid_t fid, const char *full_path, int proc_num, } /* Create and validate objects or, if `only_validate` is true, only - * validate objects in file `fid` under group `base_path`. `proc_num` - * tells the processor number the test runs on. If `skip_varlen` is + * validate objects in file `fid` under group `base_path`. `config.proc_num` + * tells the processor number the test runs on. If `config.skip_varlen` is * true, do NOT perform tests that use variable-length data. * * Return true if all tests pass, false if any test fails. */ + static bool -tend_zoo(hid_t fid, const char *base_path, int proc_num, bool skip_varlen, - bool only_validate) +tend_zoo(hid_t fid, const char *base_path, zoo_config_t config, + const phase_t *phase, size_t nphases) { - const bool create = !only_validate; + struct timespec delay = {.tv_sec = 0, .tv_nsec = 50 * 1000 * 1000}; char full_path[1024]; int i, nwritten; + size_t j; char *leafp; bool ok = true; nwritten = snprintf(full_path, sizeof(full_path), "%s/*", base_path); if (nwritten < 0 || (size_t)nwritten >= sizeof(full_path)) { - failure_mssg = "create_zoo: snprintf failed"; + failure_mssg = "tend_zoo: snprintf failed"; return false; } if ((leafp = strrchr(full_path, '*')) == NULL) { - failure_mssg = "create_zoo: strrchr failed"; + failure_mssg = "tend_zoo: strrchr failed"; return false; } for (i = 0; ok; i++) { assert('A' + i <= 'Z'); *leafp = (char)('A' + i); - if (create && - !create_or_validate_selection(fid, full_path, proc_num, i, - skip_varlen, false, &ok)) - break; - zoo_create_hook(fid); - if (!create_or_validate_selection(fid, full_path, proc_num, i, - skip_varlen, true, &ok)) - break; + for (j = 0; j < nphases; j++) { + if (!create_or_validate_selection(fid, full_path, i, config, + phase[j], &ok)) + goto out; + if (phase[j] == PHASE_CREATE || phase[j] == PHASE_DELETE) + zoo_create_hook(fid); + } } + nanosleep(&delay, NULL); +out: if (!ok) - fprintf(stderr, "%s: %s\n", __func__, failure_mssg); + warnx("%s: %s", __func__, failure_mssg); return ok; } @@ -2575,9 +2724,11 @@ tend_zoo(hid_t fid, const char *base_path, int proc_num, bool skip_varlen, */ bool -create_zoo(hid_t fid, const char *base_path, int proc_num, bool skip_varlen) +create_zoo(hid_t fid, const char *base_path, zoo_config_t config) { - return tend_zoo(fid, base_path, proc_num, skip_varlen, false); + const phase_t phase[] = {PHASE_CREATE, PHASE_VALIDATE}; + + return tend_zoo(fid, base_path, config, phase, NELMTS(phase)); } /*------------------------------------------------------------------------- @@ -2600,8 +2751,26 @@ create_zoo(hid_t fid, const char *base_path, int proc_num, bool skip_varlen) */ bool -validate_zoo(hid_t fid, const char *base_path, int proc_num, bool skip_varlen) +validate_zoo(hid_t fid, const char *base_path, zoo_config_t config) +{ + const phase_t phase[] = {PHASE_VALIDATE}; + + return tend_zoo(fid, base_path, config, phase, NELMTS(phase)); +} + +bool +delete_zoo(hid_t fid, const char *base_path, zoo_config_t config) { - return tend_zoo(fid, base_path, proc_num, skip_varlen, true); + const phase_t phase[] = {PHASE_DELETE}; + + return tend_zoo(fid, base_path, config, phase, NELMTS(phase)); +} + +bool +validate_deleted_zoo(hid_t fid, const char *base_path, zoo_config_t config) +{ + const phase_t phase[] = {PHASE_VALIDATE_DELETION}; + + return tend_zoo(fid, base_path, config, phase, NELMTS(phase)); } diff --git a/test/genall5.h b/test/genall5.h index 3878da1..4e5fbba 100644 --- a/test/genall5.h +++ b/test/genall5.h @@ -11,17 +11,21 @@ * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* Programmer: John Mainzer - * 9/4/15 - * - * This file contains declarations of all functions defined - * in genall5.c +/* + * This file contains declarations of all functions defined in genall5.c */ -bool create_zoo(hid_t fid, const char *base_path, int proc_num, - bool skip_varlen); -bool validate_zoo(hid_t fid, const char *base_path, int proc_num, - bool skip_varlen); +typedef struct _zoo_config { + int proc_num; + bool continue_on_failure; + bool skip_compact; + bool skip_varlen; +} zoo_config_t; + +bool create_zoo(hid_t, const char *, zoo_config_t); +bool validate_zoo(hid_t, const char *, zoo_config_t); +bool delete_zoo(hid_t, const char *, zoo_config_t); +bool validate_deleted_zoo(hid_t, const char *, zoo_config_t); bool ns_grp_0(hid_t fid, const char *group_name); bool vrfy_ns_grp_0(hid_t fid, const char *group_name); diff --git a/test/vfd_swmr_zoo_writer.c b/test/vfd_swmr_zoo_writer.c index d4f9cbe..a3e0a08 100644 --- a/test/vfd_swmr_zoo_writer.c +++ b/test/vfd_swmr_zoo_writer.c @@ -16,11 +16,13 @@ #include /* nanosleep(2) */ #include /* getopt(3) */ -#define H5C_FRIEND /*suppress error about including H5Cpkg */ -#define H5F_FRIEND /*suppress error about including H5Fpkg */ +#define H5C_FRIEND /* suppress error about including H5Cpkg */ +#define H5F_FRIEND /* suppress error about including H5Fpkg */ #include "hdf5.h" +#include "H5private.h" +#include "H5retry_private.h" #include "H5Cpkg.h" #include "H5Fpkg.h" // #include "H5Iprivate.h" @@ -31,14 +33,25 @@ #include "genall5.h" #include "vfd_swmr_common.h" -enum _step { - CREATE = 0 -, LENGTHEN -, SHORTEN -, DELETE -, NSTEPS -} step_t; - +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; + +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 caught_out_of_bounds = false; static bool writer; @@ -66,10 +79,13 @@ zoo_create_hook(hid_t fid) static void usage(const char *progname) { - fprintf(stderr, "usage: %s [-W] [-V]\n", progname); - fprintf(stderr, "\n -W: do not wait for SIGINT or SIGUSR1\n"); - fprintf(stderr, "\n -S: do not use VFD SWMR\n"); + fprintf(stderr, "usage: %s [-C] [-S] [-W] [-a] [-e] [-n] [-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, " -n: number of test steps to perform\n"); fprintf(stderr, " -q: be quiet: few/no progress messages\n"); fprintf(stderr, " -v: be verbose: most progress messages\n"); @@ -86,6 +102,108 @@ H5HG_trap(const char *reason) return true; } +bool +vfd_swmr_writer_may_increase_tick_to(uint64_t new_tick, bool wait_for_reader) +{ + static int fd = -1; + shared_ticks_t shared; + ssize_t nread; + h5_retry_t retry; + bool do_try; + + fprintf(stderr, "%s: enter\n", __func__); + + if (fd == -1) { + fd = open("./shared_tick_num", O_RDONLY); + if (fd == -1) { + warn("%s: open", __func__); // TBD ratelimit/silence this warning + return true; + } + 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__); + } + + tick_stats->writer_tried_increase++; + + 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)) { + + tick_stats->writer_read_shared_file++; + + if ((nread = pread(fd, &shared, sizeof(shared), 0)) == -1) + err(EXIT_FAILURE, "%s: pread", __func__); + + if (nread != sizeof(shared)) + errx(EXIT_FAILURE, "%s: pread", __func__); + + // TBD convert endianness + + if (shared.reader_tick == 0) { + tick_stats->reader_tick_was_zero++; + return true; + } + + 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 (wait_for_reader && !do_try) + errx(EXIT_FAILURE, "%s: timed out waiting for reader", __func__); + + tick_stats->writer_aborted_increase++; + + return false; +} + +void +vfd_swmr_reader_did_increase_tick_to(uint64_t new_tick) +{ + static int fd = -1; + shared_ticks_t shared; + ssize_t nwritten; + + fprintf(stderr, "%s: enter\n", __func__); + + 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__); + } + + shared.reader_tick = new_tick; + + // TBD convert endianness + + if ((nwritten = pwrite(fd, &shared, sizeof(shared), 0)) == -1) + errx(EXIT_FAILURE, "%s: pwrite", __func__); + + if (nwritten != sizeof(shared)) + errx(EXIT_FAILURE, "%s: pwrite", __func__); + + 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; + } +} + int main(int argc, char **argv) { @@ -94,18 +212,26 @@ main(int argc, char **argv) H5C_t *cache; sigset_t oldsigs; herr_t ret; - bool skip_varlen = true, wait_for_signal; + zoo_config_t config = { + .proc_num = 0 + , .skip_compact = false + , .skip_varlen = true}; + bool wait_for_signal; int ch; bool use_vfd_swmr = true; + bool print_estack = false; #if 0 unsigned long tmp; char *end; - int i, ntimes = 100; + int i; const struct timespec delay = {.tv_sec = 0, .tv_nsec = 1000 * 1000 * 1000 / 10}; #endif const char *progname = basename(argv[0]); estack_state_t es; +#if 0 + char step[2] = "ab"; +#endif dbgf(1, "0th arg %s, personality `%s`\n", argv[0], progname); @@ -118,8 +244,11 @@ main(int argc, char **argv) "unknown personality, expected vfd_swmr_zoo_{reader,writer}"); } - while ((ch = getopt(argc, argv, "SWan:qv")) != -1) { + while ((ch = getopt(argc, argv, "CSWaen:qv")) != -1) { switch(ch) { + case 'C': + config.skip_compact = true; + break; case 'S': use_vfd_swmr = false; break; @@ -127,21 +256,11 @@ main(int argc, char **argv) wait_for_signal = false; break; case 'a': - skip_varlen = false; + config.skip_varlen = false; break; -#if 0 - case 'n': - errno = 0; - tmp = strtoul(optarg, &end, 0); - if (end == optarg || *end != '\0') - errx(EXIT_FAILURE, "couldn't parse `-n` argument `%s`", optarg); - else if (errno != 0) - err(EXIT_FAILURE, "couldn't parse `-n` argument `%s`", optarg); - else if (tmp > INT_MAX) - errx(EXIT_FAILURE, "`-n` argument `%lu` too large", tmp); - ntimes = (int)tmp; + case 'e': + print_estack = true; break; -#endif case 'q': verbosity = 1; break; @@ -161,9 +280,16 @@ main(int argc, char **argv) fapl = vfd_swmr_create_fapl(writer, true, use_vfd_swmr); + if (use_vfd_swmr && H5Pget_vfd_swmr_config(fapl, &swmr_config) < 0) + errx(EXIT_FAILURE, "H5Pget_vfd_swmr_config"); + if (fapl < 0) errx(EXIT_FAILURE, "vfd_swmr_create_fapl"); + if (H5Pset_libver_bounds(fapl, H5F_LIBVER_EARLIEST, H5F_LIBVER_LATEST) < 0){ + errx(EXIT_FAILURE, "%s.%d: H5Pset_libver_bounds", __func__, __LINE__); + } + if ((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) errx(EXIT_FAILURE, "H5Pcreate"); @@ -189,23 +315,77 @@ main(int argc, char **argv) print_cache_hits(cache); - es = disable_estack(); + es = print_estack ? estack_get_state() : disable_estack(); if (writer) { + +#if 0 + H5Fvfd_swmr_end_tick(fid); + + if (read(STDIN_FILENO, &step[0], sizeof(step[0])) == -1) + err(EXIT_FAILURE, "read"); + + if (step[0] != 'a') + errx(EXIT_FAILURE, "expected 'a' read '%c'", step[0]); +#endif + dbgf(1, "Writing zoo...\n"); - if (!create_zoo(fid, ".", 0, skip_varlen)) + + if (!create_zoo(fid, ".", config)) errx(EXIT_FAILURE, "create_zoo didn't pass self-check"); + +#if 1 + H5Fvfd_swmr_end_tick(fid); +#endif + +#if 0 + if (read(STDIN_FILENO, &step[1], sizeof(step[1])) == -1) + err(EXIT_FAILURE, "read"); + + if (step[1] != 'b') + errx(EXIT_FAILURE, "expected 'b' read '%c'", step[1]); + + if (!delete_zoo(fid, ".", config)) + errx(EXIT_FAILURE, "delete_zoo failed"); +#endif } else { dbgf(1, "Reading zoo...\n"); - while (!validate_zoo(fid, ".", 0, skip_varlen)) +#if 0 + if (write(STDOUT_FILENO, &step[0], sizeof(step[0])) == -1) + err(EXIT_FAILURE, "write"); +#endif + while (!validate_zoo(fid, ".", config)) + ; +#if 0 + if (write(STDOUT_FILENO, &step[1], sizeof(step[1])) == -1) + err(EXIT_FAILURE, "write"); + while (!validate_deleted_zoo(fid, ".", config)) ; +#endif } restore_estack(es); if (use_vfd_swmr && wait_for_signal) await_signal(fid); - if (wait_for_signal) - restore_signals(&oldsigs); + if (writer && tick_stats != NULL) { + uint64_t lead; + + dbgf(1, "writer tried tick increase %" PRIu64 "\n", + tick_stats->writer_tried_increase); + dbgf(1, "writer aborted tick increase %" PRIu64 "\n", + tick_stats->writer_aborted_increase); + dbgf(1, "writer read shared file %" PRIu64 "\n", + tick_stats->writer_read_shared_file); + dbgf(1, "writer read reader tick equal to 0 %" PRIu64 "\n", + tick_stats->reader_tick_was_zero); + dbgf(1, "writer read reader tick leading writer %" PRIu64 "\n", + tick_stats->reader_tick_lead_writer); + + for (lead = 0; lead < swmr_config.max_lag; lead++) { + dbgf(1, "writer tick lead writer by %" PRIu64 " %" PRIu64 "\n", + lead, tick_stats->writer_lead_reader_by[lead]); + } + } if (H5Pclose(fapl) < 0) errx(EXIT_FAILURE, "H5Pclose(fapl)"); @@ -216,5 +396,8 @@ main(int argc, char **argv) if (H5Fclose(fid) < 0) errx(EXIT_FAILURE, "H5Fclose"); + if (wait_for_signal) + restore_signals(&oldsigs); + return EXIT_SUCCESS; } -- cgit v0.12