From da688311afebd2d6b188c50cbf78c5e05e757ba9 Mon Sep 17 00:00:00 2001 From: David Young Date: Thu, 17 Sep 2020 14:34:46 -0500 Subject: Document some of the functions in here. Update the comment at the top of the file. NFCI. --- test/vfd_swmr_common.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/test/vfd_swmr_common.c b/test/vfd_swmr_common.c index e4f4889..f09336e 100644 --- a/test/vfd_swmr_common.c +++ b/test/vfd_swmr_common.c @@ -11,13 +11,8 @@ * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/*------------------------------------------------------------------------- - * - * Created: swmr_common.c - * - * Purpose: Utility functions for the SWMR test code. - * - *------------------------------------------------------------------------- +/* + * Utility functions for the VFD SWMR tests. */ /***********/ @@ -46,6 +41,9 @@ evsnprintf(char *buf, size_t bufsz, const char *fmt, va_list ap) errx(EXIT_FAILURE, "%s: buffer too small", __func__); } +/* Like snprintf(3), but abort the program with an error message on + * `stderr` if the buffer is too small or some other error occurs. + */ void esnprintf(char *buf, size_t bufsz, const char *fmt, ...) { @@ -69,6 +67,9 @@ dbgf(int level, const char *fmt, ...) va_end(ap); } +/* Disable HDF5 error-stack printing and return the previous state + * of error-stack printing. + */ estack_state_t disable_estack(void) { @@ -79,6 +80,7 @@ disable_estack(void) return es; } +/* Return the current state of HDF5 error-stack printing. */ estack_state_t estack_get_state(void) { @@ -89,12 +91,16 @@ estack_get_state(void) return es; } +/* Restore HDF5 error-stack printing to a state returned previously by + * `disable_estack` or `estack_get_state`. + */ void restore_estack(estack_state_t es) { (void)H5Eset_auto(H5E_DEFAULT, es.efunc, es.edata); } +/* Store the signal mask at `oldset` and then block all signals. */ void block_signals(sigset_t *oldset) { @@ -109,6 +115,7 @@ block_signals(sigset_t *oldset) err(EXIT_FAILURE, "%s.%d: sigprocmask", __func__, __LINE__); } +/* Restore the signal mask in `oldset`. */ void restore_signals(sigset_t *oldset) { @@ -133,6 +140,11 @@ strsignal(int signum) } #endif +/* Wait for any signal to occur and then return. Wake periodically + * during the wait to perform API calls: in this way, the + * VFD SWMR tick number advances and recent changes do not languish + * in HDF5 library buffers where readers cannot see them. + */ void await_signal(hid_t fid) { @@ -178,6 +190,9 @@ await_signal(hid_t fid) } } +/* Perform common VFD SWMR configuration on the file-access property list: + * configure page buffering, set reasonable VFD SWMR defaults. + */ hid_t vfd_swmr_create_fapl(bool writer, bool only_meta_pages, bool use_vfd_swmr, const char *mdfile_fmtstr, ...) -- cgit v0.12 From 8e2053bb3d29ab8f90cd28d7e66641ac2472063e Mon Sep 17 00:00:00 2001 From: David Young Date: Thu, 17 Sep 2020 14:35:54 -0500 Subject: Move below_speed_limit() from vfd_swmr_bigset_writer.c to vfd_swmr_common.c, document it, and fix a bug. --- test/vfd_swmr_bigset_writer.c | 24 ------------------------ test/vfd_swmr_common.c | 37 +++++++++++++++++++++++++++++++++++++ test/vfd_swmr_common.h | 2 ++ 3 files changed, 39 insertions(+), 24 deletions(-) diff --git a/test/vfd_swmr_bigset_writer.c b/test/vfd_swmr_bigset_writer.c index 001edd7..98824b5 100644 --- a/test/vfd_swmr_bigset_writer.c +++ b/test/vfd_swmr_bigset_writer.c @@ -694,30 +694,6 @@ close_extensible_dset(state_t *s, unsigned int which) } } -static bool -below_speed_limit(struct timespec *last, const struct timespec *ival) -{ - struct timespec now; - bool result; - - assert(0 <= last->tv_nsec && last->tv_nsec < 1000000000L); - assert(0 <= ival->tv_nsec && ival->tv_nsec < 1000000000L); - - if (clock_gettime(CLOCK_MONOTONIC, &now) == -1) - err(EXIT_FAILURE, "%s: clock_gettime", __func__); - - if (now.tv_sec - last->tv_sec > ival->tv_sec) - result = true; - else if (now.tv_sec - last->tv_sec < ival->tv_sec) - return false; - else - result = (now.tv_nsec - last->tv_nsec > ival->tv_nsec); - - *last = now; - - return result; -} - static void open_extensible_dset(state_t *s, unsigned int which) { diff --git a/test/vfd_swmr_common.c b/test/vfd_swmr_common.c index f09336e..b986b31 100644 --- a/test/vfd_swmr_common.c +++ b/test/vfd_swmr_common.c @@ -28,6 +28,43 @@ static const hid_t badhid = H5I_INVALID_HID; int verbosity = 2; +/* Return true no more than once in any `ival` interval of time, + * as measured by the system's monotonically increasing timer, to + * help rate-limit activities. + * + * Read the system's current time and compare it with the time stored in + * `last`. If the difference between `last` and the current time is + * greater than the duration `ival`, then record the current time at + * `last` and return true. Otherwise, return false. + */ +bool +below_speed_limit(struct timespec *last, const struct timespec *ival) +{ + struct timespec now; + bool result; + + assert(0 <= last->tv_nsec && last->tv_nsec < 1000000000L); + assert(0 <= ival->tv_nsec && ival->tv_nsec < 1000000000L); + + if (clock_gettime(CLOCK_MONOTONIC, &now) == -1) + err(EXIT_FAILURE, "%s: clock_gettime", __func__); + + if (now.tv_sec - last->tv_sec > ival->tv_sec) + result = true; + else if (now.tv_sec - last->tv_sec < ival->tv_sec) + result = false; + else + result = (now.tv_nsec - last->tv_nsec >= ival->tv_nsec); + + if (result) + *last = now; + + return result; +} + +/* Like vsnprintf(3), but abort the program with an error message on + * `stderr` if the buffer is too small or some other error occurs. + */ void evsnprintf(char *buf, size_t bufsz, const char *fmt, va_list ap) { diff --git a/test/vfd_swmr_common.h b/test/vfd_swmr_common.h index 8e1f877..51e8c80 100644 --- a/test/vfd_swmr_common.h +++ b/test/vfd_swmr_common.h @@ -81,6 +81,8 @@ H5TEST_DLLVAR unsigned symbol_count[NLEVELS]; extern "C" { #endif +H5TEST_DLL bool below_speed_limit(struct timespec *, const struct timespec *); + H5TEST_DLL estack_state_t estack_get_state(void); H5TEST_DLL estack_state_t disable_estack(void); H5TEST_DLL void restore_estack(estack_state_t); -- cgit v0.12 From 07ad063b4b57ae54881ab523ccdbeabbebe34fc0 Mon Sep 17 00:00:00 2001 From: David Young Date: Thu, 17 Sep 2020 15:24:36 -0500 Subject: Limit the repeat rate for duplicate zoo warnings to once every five seconds. --- test/cache_common.c | 1 + test/cache_common.h | 1 + test/cache_image.c | 26 ++++++++++++++------------ test/genall5.c | 36 ++++++++++++++++++++++++------------ test/genall5.h | 12 ++++++++---- test/vfd_swmr_zoo_writer.c | 10 ++++++---- 6 files changed, 54 insertions(+), 32 deletions(-) diff --git a/test/cache_common.c b/test/cache_common.c index 651534d..1be6fd2 100644 --- a/test/cache_common.c +++ b/test/cache_common.c @@ -25,6 +25,7 @@ hbool_t pass = TRUE; /* set to false on error */ const char *failure_mssg = NULL; +const char *last_failure_mssg = ""; static test_entry_t *pico_entries = NULL, *orig_pico_entries = NULL; static test_entry_t *nano_entries = NULL, *orig_nano_entries = NULL; diff --git a/test/cache_common.h b/test/cache_common.h index 785dc21..0d6f153 100644 --- a/test/cache_common.h +++ b/test/cache_common.h @@ -541,6 +541,7 @@ struct expected_entry_status /* global variable externs: */ H5TEST_DLLVAR hbool_t pass; /* set to false on error */ H5TEST_DLLVAR const char *failure_mssg; +H5TEST_DLLVAR const char *last_failure_mssg; H5TEST_DLLVAR test_entry_t * entries[NUMBER_OF_ENTRY_TYPES]; H5TEST_DLLVAR const int32_t max_indices[NUMBER_OF_ENTRY_TYPES]; diff --git a/test/cache_image.c b/test/cache_image.c index d4002c7..5716f07 100644 --- a/test/cache_image.c +++ b/test/cache_image.c @@ -27,6 +27,8 @@ const char *FILENAMES[] = { NULL }; +static struct timespec lastmsgtime = {.tv_sec = 0, .tv_nsec = 0}; + /* local utility function declarations */ static void create_datasets(hid_t file_id, int min_dset, int max_dset); static void delete_datasets(hid_t file_id, int min_dset, int max_dset); @@ -4819,9 +4821,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, + pass = create_zoo(file_id, process_group_name, &lastmsgtime, (zoo_config_t){.proc_num = min_group, .skip_varlen = false, - .skip_compact = false}); + .skip_compact = false, .msgival = {0, 0}}); #if H5C_COLLECT_CACHE_STATS if ( pass ) { @@ -4893,9 +4895,9 @@ 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, + pass = validate_zoo(file_id, process_group_name, &lastmsgtime, (zoo_config_t){.proc_num = max_group, .skip_varlen = false, - .skip_compact = false}); + .skip_compact = false, .msgival = {0, 0}}); } #if H5C_COLLECT_CACHE_STATS @@ -4937,9 +4939,9 @@ 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, + pass = create_zoo(file_id, process_group_name, &lastmsgtime, (zoo_config_t){.proc_num = max_group, .skip_varlen = false, - .skip_compact = false}); + .skip_compact = false, .msgival = {0, 0}}); } if ( show_progress ) @@ -5001,9 +5003,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, + pass = validate_zoo(file_id, process_group_name, &lastmsgtime, (zoo_config_t){.proc_num = i++, .skip_varlen = false, - .skip_compact = false}); + .skip_compact = false, .msgival = {0, 0}}); } #if H5C_COLLECT_CACHE_STATS @@ -5056,9 +5058,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, + pass = validate_zoo(file_id, process_group_name, &lastmsgtime, (zoo_config_t){.proc_num = i++, .skip_varlen = false, - .skip_compact = false}); + .skip_compact = false, .msgival = {0, 0}}); } #if H5C_COLLECT_CACHE_STATS @@ -5122,9 +5124,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, + pass = validate_zoo(file_id, process_group_name, &lastmsgtime, (zoo_config_t){.proc_num = i++, .skip_varlen = false, - .skip_compact = false}); + .skip_compact = false, .msgival = {0, 0}}); } #if H5C_COLLECT_CACHE_STATS diff --git a/test/genall5.c b/test/genall5.c index 0a64f37..2874b59 100644 --- a/test/genall5.c +++ b/test/genall5.c @@ -22,6 +22,7 @@ #include #include "cache_common.h" +#include "vfd_swmr_common.h" /* for below_speed_limit() */ #include "genall5.h" #define DSET_DIMS (1024 * 1024) @@ -2720,8 +2721,8 @@ random_pause(unsigned int max_pause_msecs) */ static bool -tend_zoo(hid_t fid, const char *base_path, zoo_config_t config, - const phase_t *phase, size_t nphases) +tend_zoo(hid_t fid, const char *base_path, struct timespec *lastmsgtime, + zoo_config_t config, const phase_t *phase, size_t nphases) { char full_path[1024]; int i, nwritten; @@ -2753,8 +2754,15 @@ tend_zoo(hid_t fid, const char *base_path, zoo_config_t config, random_pause(config.max_pause_msecs); } out: - if (!ok) - warnx("%s: %s", __func__, failure_mssg); + 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); + } + } return ok; } @@ -2780,11 +2788,12 @@ out: */ bool -create_zoo(hid_t fid, const char *base_path, zoo_config_t config) +create_zoo(hid_t fid, const char *base_path, struct timespec *lastmsgtime, + zoo_config_t config) { const phase_t phase[] = {PHASE_CREATE, PHASE_VALIDATE}; - return tend_zoo(fid, base_path, config, phase, NELMTS(phase)); + return tend_zoo(fid, base_path, lastmsgtime, config, phase, NELMTS(phase)); } /*------------------------------------------------------------------------- @@ -2807,26 +2816,29 @@ create_zoo(hid_t fid, const char *base_path, zoo_config_t config) */ bool -validate_zoo(hid_t fid, const char *base_path, zoo_config_t config) +validate_zoo(hid_t fid, const char *base_path, struct timespec *lastmsgtime, + zoo_config_t config) { const phase_t phase[] = {PHASE_VALIDATE}; - return tend_zoo(fid, base_path, config, phase, NELMTS(phase)); + return tend_zoo(fid, base_path, lastmsgtime, config, phase, NELMTS(phase)); } bool -delete_zoo(hid_t fid, const char *base_path, zoo_config_t config) +delete_zoo(hid_t fid, const char *base_path, struct timespec *lastmsgtime, + zoo_config_t config) { const phase_t phase[] = {PHASE_DELETE}; - return tend_zoo(fid, base_path, config, phase, NELMTS(phase)); + return tend_zoo(fid, base_path, lastmsgtime, config, phase, NELMTS(phase)); } bool -validate_deleted_zoo(hid_t fid, const char *base_path, zoo_config_t config) +validate_deleted_zoo(hid_t fid, const char *base_path, + struct timespec *lastmsgtime, zoo_config_t config) { const phase_t phase[] = {PHASE_VALIDATE_DELETION}; - return tend_zoo(fid, base_path, config, phase, NELMTS(phase)); + return tend_zoo(fid, base_path, lastmsgtime, config, phase, NELMTS(phase)); } diff --git a/test/genall5.h b/test/genall5.h index a03ccce..43fe15d 100644 --- a/test/genall5.h +++ b/test/genall5.h @@ -21,12 +21,16 @@ typedef struct _zoo_config { bool skip_compact; bool skip_varlen; unsigned max_pause_msecs; + struct timespec msgival; /* minimum interval between warning-message + * repetitions + */ } 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 create_zoo(hid_t, const char *, struct timespec *, zoo_config_t); +bool validate_zoo(hid_t, const char *, struct timespec *, zoo_config_t); +bool delete_zoo(hid_t, const char *, struct timespec *, zoo_config_t); +bool validate_deleted_zoo(hid_t, const char *, struct timespec *, + 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 3eb228a..860c4f9 100644 --- a/test/vfd_swmr_zoo_writer.c +++ b/test/vfd_swmr_zoo_writer.c @@ -215,7 +215,9 @@ main(int argc, char **argv) , .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; char vector[8]; @@ -346,7 +348,7 @@ main(int argc, char **argv) ostate = initstate(seed, vector, _arraycount(vector)); - if (!create_zoo(fid, ".", config)) + 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 @@ -361,18 +363,18 @@ main(int argc, char **argv) if (step != 'b') errx(EXIT_FAILURE, "expected 'b' read '%c'", step); - if (!delete_zoo(fid, ".", config)) + if (!delete_zoo(fid, ".", &lastmsgtime, config)) errx(EXIT_FAILURE, "delete_zoo failed"); (void)setstate(ostate); } else { dbgf(2, "Reading zoo...\n"); - while (!validate_zoo(fid, ".", config)) + while (!validate_zoo(fid, ".", &lastmsgtime, config)) ; if (write(STDOUT_FILENO, &step, sizeof(step)) == -1) err(EXIT_FAILURE, "write"); - while (!validate_deleted_zoo(fid, ".", config)) + while (!validate_deleted_zoo(fid, ".", &lastmsgtime, config)) ; } restore_estack(es); -- cgit v0.12