diff options
author | vchoi <vchoi@jelly.ad.hdfgroup.org> | 2021-03-02 00:10:07 (GMT) |
---|---|---|
committer | vchoi <vchoi@jelly.ad.hdfgroup.org> | 2021-03-02 00:10:07 (GMT) |
commit | d9f44665cd19620118cd5f6a4fdfac5050200e70 (patch) | |
tree | df63cc53b0f0aae8ffa8ad58fe31f21aff71c79b /test | |
parent | f792bdbbc5b3669ac08a77a87e072c98d53fff60 (diff) | |
download | hdf5-d9f44665cd19620118cd5f6a4fdfac5050200e70.zip hdf5-d9f44665cd19620118cd5f6a4fdfac5050200e70.tar.gz hdf5-d9f44665cd19620118cd5f6a4fdfac5050200e70.tar.bz2 |
Revert "Add the two VFD SWMR demo programs to the test directory so that they can be built as needed."
This reverts commit f6e7edcedf0339bd18ca0a995f9877a778180f5f.
Diffstat (limited to 'test')
-rw-r--r-- | test/Makefile.am | 16 | ||||
-rw-r--r-- | test/vfd_swmr_common.c | 19 | ||||
-rw-r--r-- | test/vfd_swmr_common.h | 9 | ||||
-rw-r--r-- | test/vfd_swmr_credel.c | 483 | ||||
-rw-r--r-- | test/vfd_swmr_gaussians.c | 753 |
5 files changed, 1 insertions, 1279 deletions
diff --git a/test/Makefile.am b/test/Makefile.am index 0aec03c..2b1d7d5 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -120,24 +120,10 @@ endif # --enable-build-all at configure time. # The gen_old_* files can only be compiled with older versions of the library # so do not appear in this list. -# Add the two VFD SWMR demo programs and build it as needed. BUILD_ALL_PROGS=gen_bad_ohdr gen_bogus gen_cross gen_deflate gen_filters gen_new_array \ gen_new_fill gen_new_group gen_new_mtime gen_new_super gen_noencoder \ gen_nullspace gen_udlinks space_overflow gen_filespace gen_specmetaread \ - gen_sizes_lheap gen_file_image gen_plist gen_bad_offset gen_bounds \ - vfd_swmr_gaussians vfd_swmr_credel - -# VFD SWMR demo: vfd_swmr_gaussians needs the curses library -vfd_swmr_gaussians_LDFLAGS=$(AM_LDFLAGS) @CURSES_LIBS@ -vfd_swmr_gaussians=$(AM_CFLAGS) @CURSES_LIBS@ - -# Writer for VFD SWMR demo -w_vfd_swmr_gaussians: vfd_swmr_gaussians - @test -e w_vfd_swmr_gaussians || ln -s vfd_swmr_gaussians w_vfd_swmr_gaussians - -# Reader for VFD SWMR demo -r_vfd_swmr_gaussians: vfd_swmr_gaussians - @test -e r_vfd_swmr_gaussians || ln -s vfd_swmr_gaussians r_vfd_swmr_gaussians + gen_sizes_lheap gen_file_image gen_plist gen_bad_offset gen_bounds if BUILD_ALL_CONDITIONAL noinst_PROGRAMS=$(BUILD_ALL_PROGS) diff --git a/test/vfd_swmr_common.c b/test/vfd_swmr_common.c index 9352a37..3f03ce7 100644 --- a/test/vfd_swmr_common.c +++ b/test/vfd_swmr_common.c @@ -418,22 +418,3 @@ fetch_env_ulong(const char *varname, unsigned long limit, unsigned long *valp) *valp = ul; return 1; } - -/* - * For demo credel.c: need to write up description - */ -size_t -strlcpy(char *dst, const char *src, size_t size) -{ - char *d; - const char *s; - - for (d = dst, s = src; (s - src) < (int)size; d++, s++) { - *d = *s; - if (*s == '\0') - return (size_t) (s - src); - } - - dst[size - 1] = '\0'; - return size; -} diff --git a/test/vfd_swmr_common.h b/test/vfd_swmr_common.h index bbcb28a..f64ee87 100644 --- a/test/vfd_swmr_common.h +++ b/test/vfd_swmr_common.h @@ -19,7 +19,6 @@ /***********/ #include <stdarg.h> -#include <unistd.h> /* For demo */ #include "h5test.h" /**********/ @@ -36,11 +35,6 @@ /* The message sent by writer that the file open is done--releasing the file lock */ #define VFD_SWMR_WRITER_MESSAGE "VFD_SWMR_WRITER_MESSAGE" -/* For demo */ -#ifndef __arraycount -#define __arraycount(__a) (sizeof(__a) / sizeof((__a)[0])) -#endif - /************/ /* Typedefs */ /************/ @@ -94,9 +88,6 @@ H5TEST_DLL void esnprintf(char *, size_t, const char *, ...) H5TEST_DLL int fetch_env_ulong(const char *, unsigned long, unsigned long *); -/* For demo */ -H5TEST_DLL size_t strlcpy(char *, const char *, size_t); - #ifdef __cplusplus } #endif diff --git a/test/vfd_swmr_credel.c b/test/vfd_swmr_credel.c deleted file mode 100644 index fe6f0d5..0000000 --- a/test/vfd_swmr_credel.c +++ /dev/null @@ -1,483 +0,0 @@ -/* - * Copyright by The HDF Group. - * Copyright by the Board of Trustees of the University of Illinois. - * 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://support.hdfgroup.org/ftp/HDF5/releases. - * If you do not have access to either file, you may request a copy from - * help@hdfgroup.org. - */ - -#include <assert.h> -#include <err.h> -#include <errno.h> -#include <libgen.h> /* basename(3) */ -#include <signal.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> /* struct timespec, nanosleep */ -#include <unistd.h> /* getopt, PATH_MAX, ... */ - -#include "hdf5.h" -#include "vfd_swmr_common.h" - -#define DATAROWS 1 -#define DATACOLS 10 -static const hsize_t dims[2] = {DATAROWS, DATACOLS}; -static const hsize_t chunk_dims[2] = {1, 1}; -static volatile sig_atomic_t unbroken = 1; - -typedef struct { - uint64_t created, deleted; -} stats_pair_t; - -typedef struct { - stats_pair_t datasets, groups; - uint64_t iterations; -} stats_t; - -typedef struct { - hid_t dataset[4], dataspace, dapl, dcpl, file, group[2]; - char output_file[PATH_MAX]; - char progname[PATH_MAX]; - struct timespec update_interval; - int verbose; - bool oneshot; - bool print_stats; - bool use_vfd_swmr; - uint64_t iterations_limit; - stats_t stats; -} state_t; - -#define ALL_HID_INITIALIZER (state_t){ \ - .dataspace = H5I_INVALID_HID \ - , .file = H5I_INVALID_HID \ - , .verbose = 0 \ - , .oneshot = false \ - , .use_vfd_swmr = true \ - , .print_stats = false \ - , .iterations_limit = UINT64_MAX \ - , .output_file = "" \ - , .update_interval = (struct timespec){ \ - .tv_sec = 0 \ - , .tv_nsec = 1000000000UL / 10 /* 1/10 second */} \ - , .stats = {{0, 0}, {0, 0}}} - -static void state_init(state_t *, int, char **); - -static void -write_dataset(state_t *s, const int64_t didx) -{ - const int ndatasets = __arraycount(s->dataset); - hid_t ds; - int32_t data[DATAROWS][DATACOLS]; - herr_t status; - unsigned int i, j; - - for (i = 0; i < (int)__arraycount(data); i++) { - for (j = 0; j < (int)__arraycount(data[i]); j++) { - int64_t k = (didx + j + i ) % (int64_t)__arraycount(data[i]); - - data[i][j] = (0 <= k && k < 3) ? 1 : 0; - if (s->verbose > 1) - fprintf(stderr, " %" PRId32, data[i][j]); - } - if (s->verbose > 1) - fprintf(stderr, "\n"); - } - - ds = s->dataset[didx % ndatasets]; - status = H5Dwrite(ds, H5T_NATIVE_INT32, H5S_ALL, H5S_ALL, - H5P_DEFAULT, data); - - if (status < 0) - errx(EXIT_FAILURE, "H5Dwrite failed"); - - if (H5Dflush(ds) < 0) - errx(EXIT_FAILURE, "H5Dflush failed"); -} - -static void -usage(const char *progname) -{ - fprintf(stderr, "usage: %s [-u milliseconds]\n" - "\n" - "-o: oneshot mode, perform one iteration, wait for a signal, " - "then quit.\n" - "-s: print statistics at end\n" - "-S: disable VFD SWMR mode\n" - "-u ms: milliseconds interval between updates to %s.h5\n" - "-v: verbose mode, mention creation/deletion; -vv: print data\n" - "\n", - progname, progname); - exit(EXIT_FAILURE); -} - -static void -print_stats(stats_t *s) -{ - printf("%10" PRIu64 " groups created\n", s->groups.created); - printf("%10" PRIu64 " groups deleted\n", s->groups.deleted); - printf("%10" PRIu64 " datasets created\n", s->datasets.created); - printf("%10" PRIu64 " datasets deleted\n", s->datasets.deleted); - printf("%10" PRIu64 " iterations\n", s->iterations); -} - -static void -state_init(state_t *s, int argc, char **argv) -{ - int ch, i, rc; - char tfile[PATH_MAX]; - char *end; - unsigned long millis; - uintmax_t niters; - - *s = ALL_HID_INITIALIZER; - strlcpy(tfile, argv[0], sizeof(tfile)); - strlcpy(s->progname, basename(tfile), sizeof(s->progname)); - while ((ch = getopt(argc, argv, "n:ou:sSv")) != -1) { - switch (ch) { - case 'n': - niters = strtoumax(optarg, &end, 0); - if (niters == UINTMAX_MAX && errno == ERANGE) { - err(EXIT_FAILURE, "option -%c argument \"%s\"", - ch, optarg); - } else if (*end != '\0') { - errx(EXIT_FAILURE, - "garbage after -%c argument \"%s\"", ch, - optarg); - } - s->iterations_limit = niters; - break; - case 'o': - s->oneshot = true; - break; - case 's': - s->print_stats = true; - break; - case 'S': - s->use_vfd_swmr = false; - break; - case 'u': - errno = 0; - millis = strtoul(optarg, &end, 0); - if (millis == ULONG_MAX && errno == ERANGE) { - err(EXIT_FAILURE, "option -%c argument \"%s\"", - ch, optarg); - } else if (*end != '\0') { - errx(EXIT_FAILURE, - "garbage after -%c argument \"%s\"", ch, - optarg); - } - s->update_interval.tv_sec = (time_t)(millis / 1000UL); - s->update_interval.tv_nsec = (long)((millis * 1000000UL) % 1000000000UL); - warnx("%lu milliseconds between updates", millis); - break; - case 'v': - s->verbose++; - break; - case '?': - default: - usage(s->progname); - } - } - argc -= optind; - argv += optind; - - for (i = 0; i < (int)__arraycount(s->dataset); i++) - s->dataset[i] = H5I_INVALID_HID; - - for (i = 0; i < (int)__arraycount(s->group); i++) - s->group[i] = H5I_INVALID_HID; - - rc = snprintf(s->output_file, sizeof(s->output_file), "%s.h5", s->progname); - if (rc == -1 || rc >= (int)sizeof(s->output_file)) - errx(EXIT_FAILURE, "output filename was truncated"); -} - -static void -delete_group(state_t *s, const int64_t gidx) -{ - hid_t g; - const int ngroups = __arraycount(s->group); - char gname[32]; - - assert(0 <= gidx); - - snprintf(gname, sizeof(gname), "/group-%" PRId64, gidx); - g = s->group[gidx % ngroups]; - - if (H5Ldelete(s->file, gname, H5P_DEFAULT) < 0) { - errx(EXIT_FAILURE, "%s: H5Ldelete(, \"%s\", ) failed", - __func__, gname); - } - - if (H5Gclose(g) < 0) - errx(EXIT_FAILURE, "H5Gclose failed"); - - if (s->verbose > 0) - fprintf(stderr, "Deleted group %s\n", gname); - - s->group[gidx % ngroups] = H5I_INVALID_HID; - s->stats.groups.deleted++; -} - -static void -create_group(state_t *s, const int64_t gidx) -{ - const int ngroups = __arraycount(s->group); - hid_t g; - char gname[32]; - - assert(0 <= gidx); - assert(s->group[gidx % ngroups] == H5I_INVALID_HID); - - snprintf(gname, sizeof(gname), "/group-%" PRId64, gidx); - g = H5Gcreate(s->file, gname, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - - if (g < 0) - errx(EXIT_FAILURE, "H5Gcreate failed"); - - if (s->verbose > 0) - fprintf(stderr, "Created group %s\n", gname); - s->group[gidx % ngroups] = g; - s->stats.groups.created++; -} - -static void -delete_dataset(state_t *s, const int64_t didx) -{ - const int ndatasets = __arraycount(s->dataset); - const hid_t ds = s->dataset[didx % ndatasets]; - char dname[32]; - const int64_t gidx = didx / 2; - - assert(0 <= gidx && 0 <= didx); - - snprintf(dname, sizeof(dname), "/group-%" PRId64 "/dataset-%" PRId64, - gidx, didx); - if (H5Ldelete(s->file, dname, H5P_DEFAULT) < 0) { - errx(EXIT_FAILURE, "%s: H5Ldelete(, \"%s\", ) failed", - __func__, dname); - } - - if (s->verbose > 0) - fprintf(stderr, "Deleted dataset %s\n", dname); -#if 1 - if (H5Dclose(ds) < 0) - errx(EXIT_FAILURE, "H5Dclose failed"); -#endif - s->dataset[didx % ndatasets] = H5I_INVALID_HID; - s->stats.datasets.deleted++; -} - -static void -create_dataset(state_t *s, const int64_t didx) -{ - const int ndatasets = __arraycount(s->dataset); - char dname[32]; - const int64_t gidx = didx / 2; - hid_t ds; - - assert(0 <= gidx && 0 <= didx); - assert(s->dataset[didx % ndatasets] == H5I_INVALID_HID); - - s->dataspace = H5Screate_simple(__arraycount(dims), dims, NULL); - - if (s->dataspace < 0) - errx(EXIT_FAILURE, "H5Screate_simple failed"); - - snprintf(dname, sizeof(dname), "/group-%" PRId64 "/dataset-%" PRId64, - gidx, didx); - ds = H5Dcreate2(s->file, dname, - H5T_STD_I32BE, s->dataspace, - H5P_DEFAULT, s->dcpl, s->dapl); - - if (H5Sclose(s->dataspace) < 0) - errx(EXIT_FAILURE, "H5Sclose failed"); - - s->dataspace = H5I_INVALID_HID; - - if (ds < 0) - errx(EXIT_FAILURE, "H5Dcreate(, \"%s\", ) failed", dname); - - if (s->verbose > 0) - fprintf(stderr, "Created dataset %s\n", dname); - s->dataset[didx % ndatasets] = ds; - s->stats.datasets.created++; -} - -static void -create_and_write_dataset(state_t *s, const int64_t didx) -{ -#if 0 - const int64_t gidx = didx / 2; - const int ngroups = __arraycount(s->group); - const hid_t g = s->group[gidx % ngroups]; - - if (H5Odisable_mdc_flushes(g) < 0) - err(EXIT_FAILURE, "H5Odisable_mdc_flushes failed"); -#endif - - create_dataset(s, didx); - write_dataset(s, didx); - -#if 0 - if (H5Oenable_mdc_flushes(g) < 0) - err(EXIT_FAILURE, "H5Oenable_mdc_flushes failed"); -#endif -} - -static void -handle_signal(int H5_ATTR_UNUSED signo) -{ - char msg[] = "Handling signal\n"; - write(STDERR_FILENO, msg, sizeof(msg) - 1); - unbroken = 0; -} - -static void -disestablish_handler(const struct sigaction *osa) -{ - if (sigaction(SIGINT, osa, NULL) == -1) - err(EXIT_FAILURE, "%s: sigaction", __func__); -} - -static void -establish_handler(struct sigaction *osa) -{ - struct sigaction sa; - - memset(&sa, '\0', sizeof(sa)); - sa.sa_handler = handle_signal; - sigemptyset(&sa.sa_mask); - if (sigaction(SIGINT, &sa, osa) == -1) - err(EXIT_FAILURE, "%s: sigaction", __func__); -} - -int -main(int argc, char **argv) -{ - hid_t fapl, fcpl; - struct sigaction osa; - state_t storage; - state_t *s = &storage; - int64_t i; - H5F_vfd_swmr_config_t config; - - memset(&config, '\0', sizeof(config)); - - state_init(s, argc, argv); - - /* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */ - init_vfd_swmr_config(&config, 4, 5, true, FALSE, 128, "./my_md_file"); - - /* use_latest_format, use_vfd_swmr, only_meta_page, config */ - fapl = vfd_swmr_create_fapl(false, s->use_vfd_swmr, true, &config); - if (fapl < 0) { - errx(EXIT_FAILURE, "%s.%d vfd_swmr_create_fapl failed", - __func__, __LINE__); - } - - fcpl = H5Pcreate(H5P_FILE_CREATE); - if (fcpl < 0) { - errx(EXIT_FAILURE, "%s.%d H5Pcreate failed", - __func__, __LINE__); - } - - /* Set file space strategy to paged aggregation in fcpl. - * Page buffering *requires* this strategy. - * - * I set the free-space threshold to 1GB so that deleted - * datasets are not recycled. - */ - if (H5Pset_file_space_strategy(fcpl, - H5F_FSPACE_STRATEGY_PAGE, false, 1024 * 1024 * 1024) < 0) - errx(EXIT_FAILURE, "H5Pset_file_space_strategy failed"); - - s->file = H5Fcreate(s->output_file, H5F_ACC_TRUNC, fcpl, fapl); - - H5Pclose(fapl); - - if (s->file < 0) - errx(EXIT_FAILURE, "H5Fcreate failed"); - - if ((s->dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0) { - errx(EXIT_FAILURE, "%s.%d: H5Pcreate failed", - __func__, __LINE__); - } - if ((s->dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0) { - errx(EXIT_FAILURE, "%s.%d: H5Pcreate failed", - __func__, __LINE__); - } - if (H5Pset_chunk(s->dcpl, 2, chunk_dims) < 0) - errx(EXIT_FAILURE, "H5Pset_chunk failed"); - if (H5Pset_chunk_cache(s->dapl, H5D_CHUNK_CACHE_NSLOTS_DEFAULT, 0, - H5D_CHUNK_CACHE_W0_DEFAULT) < 0) - errx(EXIT_FAILURE, "H5Pset_chunk_cache failed"); - - establish_handler(&osa); - - for (i = 0; i < 4; i++) { - s->stats.iterations++; - if (i % 2 == 0) - create_group(s, i / 2); - create_and_write_dataset(s, i); - } - - for (i = 5; unbroken; i += 2) { - delete_dataset(s, i - 5); - delete_dataset(s, i - 4); - delete_group(s, (i - 4) / 2); - create_group(s, i / 2); - create_and_write_dataset(s, i - 1); - create_and_write_dataset(s, i); - if (s->oneshot || ++s->stats.iterations >= s->iterations_limit) - break; - nanosleep(&s->update_interval, NULL); - } - - if (s->oneshot) { - sigset_t mask; - sigemptyset(&mask); - H5Fvfd_swmr_end_tick(s->file); - (void)sigsuspend(&mask); - } -#if 0 - fprintf(stderr, "Interrupted. Cleaning up.\n"); - - int j; - for (--i, j = 0; j < 4; j++, --i) { - if (i % 2 == 1) { - delete_dataset(s, i - 1); - delete_dataset(s, i); - delete_group(s, i / 2); - } - } - - for (j = 0; j < 4; j++) { - assert(s->dataset[j] == H5I_INVALID_HID); - assert(s->group[j / 2] == H5I_INVALID_HID); - } -#endif - - if (s->print_stats) - print_stats(&s->stats); - - if (H5Fclose(s->file) < 0) - errx(EXIT_FAILURE, "H5Fclose failed"); - - if (H5Pclose(s->dapl) < 0) - errx(EXIT_FAILURE, "H5Pclose failed"); - - if (H5Pclose(s->dcpl) < 0) - errx(EXIT_FAILURE, "H5Pclose failed"); - - disestablish_handler(&osa); - - return EXIT_SUCCESS; -} diff --git a/test/vfd_swmr_gaussians.c b/test/vfd_swmr_gaussians.c deleted file mode 100644 index 17231a9..0000000 --- a/test/vfd_swmr_gaussians.c +++ /dev/null @@ -1,753 +0,0 @@ -#include <assert.h> -#include <curses.h> -#include <err.h> -#include <errno.h> -#include <libgen.h> /* basename(3) */ -#include <math.h> /* expf(3) */ -#include <locale.h> /* setlocale(3) */ -#include <signal.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> /* struct timespec, nanosleep(2), time(3), - * clock_gettime(2) - */ -#include <unistd.h> /* getopt, PATH_MAX, ... */ - -#include <sys/param.h> /* for MIN(a, b) */ - -#include "hdf5.h" -#include "vfd_swmr_common.h" -#include "H5time_private.h" - -#define SWMR_TICK_LEN 4 /* in 100 ms */ - -typedef enum { - STANDALONE = 0 - , READ = 1 - , WRITE = 2 -} personality_t; - -typedef enum { - TOP = 0 - , BOTTOM - , LEFT - , RIGHT - , NSIDES -} side_t; - -typedef struct { - bool side[NSIDES]; -} inside_t; - -typedef struct { - float x, y; -} vec_t; - -#define RANK 3 -#define ROWS 20 -#define COLS 40 -static const hsize_t original_dims[RANK] = {0, ROWS, COLS}; -static const hsize_t max_dims[RANK] = {H5S_UNLIMITED, ROWS, COLS}; -static const hsize_t frame_dims[RANK] = {1, ROWS, COLS}; -static const hsize_t *chunk_dims = frame_dims; -static volatile sig_atomic_t unbroken = 1; - -typedef struct { - /* main-loop statistics */ - uint64_t max_elapsed_ns, min_elapsed_ns, total_elapsed_ns; - uint64_t total_loops; - hid_t dataset, memspace, dcpl, file, group; - char output_file[PATH_MAX]; - char progname[PATH_MAX]; - struct timespec update_interval; - bool fuzz; - bool constantrate; - unsigned int partstep; -} state_t; - -#define ALL_HID_INITIALIZER (state_t){ \ - .total_elapsed_ns = 0 \ - , .total_loops = 0 \ - , .min_elapsed_ns = UINT64_MAX \ - , .max_elapsed_ns = 0 \ - , .memspace = H5I_INVALID_HID \ - , .file = H5I_INVALID_HID \ - , .constantrate = false \ - , .partstep = 0 \ - , .output_file = "" \ - , .update_interval = (struct timespec){ \ - .tv_sec = 0 \ - , .tv_nsec = 1000000000UL / 30 /* 1/30 second */}} - -static void state_init(state_t *, int, char **); - -static void -usage(const char *progname) -{ - fprintf(stderr, "usage: %s [-u milliseconds]\n" - "\n" - "-c: increase the frame number continously (reader mode)\n" - "-f: add \"fuzz\" (linear noise) to the data (writer mode)\n" - "-u ms: milliseconds interval between updates to %s.h5\n" - "\n", - progname, progname); - exit(EXIT_FAILURE); -} - -static void -state_init(state_t *s, int argc, char **argv) -{ - int ch; - char tfile[PATH_MAX]; - char *end; - unsigned long millis; - int nprinted; - - *s = ALL_HID_INITIALIZER; - strlcpy(tfile, argv[0], sizeof(tfile)); - strlcpy(s->progname, basename(tfile), sizeof(s->progname)); - - while ((ch = getopt(argc, argv, "cfu:")) != -1) { - switch (ch) { - case 'c': - s->constantrate = true; - break; - case 'f': - s->fuzz = true; - 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); - - warnx("%lu milliseconds between updates", millis); - break; - case '?': - default: - usage(s->progname); - } - } - argc -= optind; - argv += optind; - - s->dataset = H5I_INVALID_HID; - s->group = H5I_INVALID_HID; - - s->memspace = H5Screate_simple(RANK, frame_dims, NULL); - - if (s->memspace < 0) { - errx(EXIT_FAILURE, "%s.%d: H5Screate_simple failed", - __func__, __LINE__); - } - - nprinted = snprintf(s->output_file, sizeof(s->output_file), - "%s.h5", s->progname); - if (nprinted < 0 || nprinted >= (int)sizeof(s->output_file)) { - errx(EXIT_FAILURE, "%s.%d: output filename truncated.", - __func__, __LINE__); - } -} - -static void -matrix_read(state_t *s, int *framenop, float mat[ROWS][COLS]) -{ - hid_t ds, filespace; - herr_t status; - hsize_t dims[RANK]; - int lead; - hssize_t temp; - - const uint64_t update_ms = timespec2ns(&s->update_interval) / 1000000; - const uint32_t tick_ms = SWMR_TICK_LEN * 100; - const uint64_t updates_per_tick = (tick_ms + update_ms - 1) / update_ms; - const uint64_t tmp = 2 * updates_per_tick; - const hssize_t hang_back = (hssize_t)tmp; - const int frameno = *framenop; - hsize_t offset[RANK] = {(hsize_t)frameno, 0, 0}; - - ds = s->dataset; - - if (H5Drefresh(ds) < 0) - errx(EXIT_FAILURE, "H5Drefresh failed"); - - filespace = H5Dget_space(ds); - - if (H5Sget_simple_extent_dims(filespace, dims, NULL) < 0) - errx(EXIT_FAILURE, "H5Sget_simple_extent_dims failed"); - - if (dims[1] != original_dims[1] || dims[2] != original_dims[2]) { - errx(EXIT_FAILURE, "Unexpected dimensions N x %ju x %ju", - (uintmax_t)dims[1], (uintmax_t)dims[2]); - } - - - temp = frameno + hang_back - (hssize_t)dims[0]; - lead = (int)temp; - - if (s->constantrate) { - *framenop = frameno + 1; - } else if (lead > hang_back * 2) { - if (++s->partstep % 3 == 0) - *framenop = frameno + 1; - } else if (lead > 0) { - if (++s->partstep % 2 == 0) - *framenop = frameno + 1; - } else if (lead == 0) { - *framenop = frameno + 1; - } else if (lead < -hang_back * 2) { - /* We're way behind, so jump close to the front. */ - temp = (hssize_t)dims[0] - hang_back; - *framenop = (int)temp; - } else /* lead < 0 */ { - *framenop = frameno + 1; - if (++s->partstep % 2 == 0) - *framenop = frameno + 2; - } - -#if 0 - if (!s->constantrate && (lead < -2 || 2 < lead)) { - int gain = 31250 / 4; - const struct timespec prior_integral = s->update_integral; - struct timespec current_interval; - if (lead > 0) - gain *= 2; - struct timespec adjustment = (struct timespec){.tv_sec = 0, - .tv_nsec = gain * MAX(MIN(4, lead), -4)}; - /* XXX clamp it XXX */ - timespecadd(&s->update_integral, - &adjustment, &s->update_integral); - timespecadd(&s->update_integral, - &s->update_interval, ¤t_interval); - if (timespeccmp(¤t_interval, &s->min_interval, <=)) - s->update_integral = prior_integral; - } -#endif - - if (frameno >= (int)dims[0]) { - int i, j; - for (i = 0; i < ROWS; i++) { - for (j = 0; j < COLS; j++) - mat[i][j] = ((i + j) % 2 == 0) ? 0. : 1.; - } - return; - } - - if (H5Sselect_hyperslab(filespace, H5S_SELECT_SET, offset, NULL, - frame_dims, NULL) < 0) - errx(EXIT_FAILURE, "H5Sselect_hyperslab failed"); - - status = H5Dread(ds, H5T_NATIVE_FLOAT, s->memspace, filespace, - H5P_DEFAULT, mat); - - if (status < 0) - errx(EXIT_FAILURE, "H5Dread failed"); - - if (H5Sclose(filespace) < 0) - errx(EXIT_FAILURE, "H5Sclose failed"); -} - -static void -matrix_write(state_t *s, int frameno, float mat[ROWS][COLS]) -{ - hid_t ds, filespace; - herr_t status; - hsize_t size[RANK] = {(hsize_t)frameno + 1, ROWS, COLS}; - hsize_t offset[RANK] = {(hsize_t)frameno, 0, 0}; - - ds = s->dataset; - - if (H5Dset_extent(ds, size) < 0) - errx(EXIT_FAILURE, "H5Dset_extent failed"); - - filespace = H5Dget_space(ds); - - if (H5Sselect_hyperslab(filespace, H5S_SELECT_SET, offset, NULL, - frame_dims, NULL) < 0) - errx(EXIT_FAILURE, "H5Sselect_hyperslab failed"); - - status = H5Dwrite(ds, H5T_NATIVE_FLOAT, s->memspace, filespace, - H5P_DEFAULT, mat); - - if (status < 0) - errx(EXIT_FAILURE, "H5Dwrite failed"); - - if (H5Sclose(filespace) < 0) - errx(EXIT_FAILURE, "H5Sclose failed"); - - if (H5Dflush(ds) < 0) - errx(EXIT_FAILURE, "H5Dflush failed"); -} - -static void -open_group(state_t *s) -{ - hid_t g; - const char *gname = "/group-0"; - - assert(s->group == H5I_INVALID_HID); - - g = H5Gopen(s->file, gname, H5P_DEFAULT); - - if (g < 0) - errx(EXIT_FAILURE, "H5Gcreate failed"); - - fprintf(stderr, "Opened group %s\n", gname); - s->group = g; -} - -static void -create_group(state_t *s) -{ - hid_t g; - const char *gname = "/group-0"; - - assert(s->group == H5I_INVALID_HID); - - g = H5Gcreate(s->file, gname, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - - if (g < 0) - errx(EXIT_FAILURE, "H5Gcreate failed"); - - s->group = g; -} - -static void -open_dataset(state_t *s) -{ - const char *dname = "/group-0/dataset-0"; - hid_t ds; - hid_t filespace; - hid_t ty; - hsize_t dims[RANK], maxdims[RANK]; - - assert(s->dataset == H5I_INVALID_HID); - - ds = H5Dopen(s->file, dname, H5P_DEFAULT); - - if (ds < 0) - errx(EXIT_FAILURE, "H5Dopen(, \"%s\", ) failed", dname); - - if ((ty = H5Dget_type(ds)) < 0) - errx(EXIT_FAILURE, "H5Dget_type failed"); - - if (H5Tequal(ty, H5T_IEEE_F32BE) <= 0) - errx(EXIT_FAILURE, "Unexpected data type"); - - if ((filespace = H5Dget_space(ds)) < 0) - errx(EXIT_FAILURE, "H5Dget_space failed"); - - if (H5Sget_simple_extent_ndims(filespace) != RANK) - errx(EXIT_FAILURE, "Unexpected rank"); - - if (H5Sget_simple_extent_dims(filespace, dims, maxdims) < 0) - errx(EXIT_FAILURE, "H5Sget_simple_extent_dims failed"); - - if (dims[1] != original_dims[1] || dims[2] != original_dims[2]) { - errx(EXIT_FAILURE, "Unexpected dimensions ? x %ju x %ju", - (uintmax_t)dims[1], (uintmax_t)dims[2]); - } - - if (maxdims[1] != original_dims[1] || maxdims[2] != original_dims[2]) { - errx(EXIT_FAILURE, - "Unexpected maximum dimensions ? x %ju x %ju", - (uintmax_t)dims[1], (uintmax_t)dims[2]); - } - - fprintf(stderr, "Opened dataset %s\n", dname); - s->dataset = ds; -} - -static void -create_dataset(state_t *s) -{ - const char *dname = "/group-0/dataset-0"; - hid_t ds; - hid_t filespace; - - assert(s->dataset == H5I_INVALID_HID); - - filespace = H5Screate_simple(__arraycount(original_dims), original_dims, - max_dims); - - if (filespace < 0) { - errx(EXIT_FAILURE, "%s.%d: H5Screate_simple failed", - __func__, __LINE__); - } - - if ((s->dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0) { - errx(EXIT_FAILURE, "%s.%d: H5Pcreate failed", - __func__, __LINE__); - } - - if (H5Pset_chunk(s->dcpl, RANK, chunk_dims) < 0) - errx(EXIT_FAILURE, "H5Pset_chunk failed"); - - ds = H5Dcreate2(s->file, dname, H5T_IEEE_F32BE, filespace, - H5P_DEFAULT, s->dcpl, H5P_DEFAULT); - - if (H5Sclose(filespace) < 0) - errx(EXIT_FAILURE, "H5Sclose failed"); - - filespace = H5I_INVALID_HID; - - if (ds < 0) - errx(EXIT_FAILURE, "H5Dcreate(, \"%s\", ) failed", dname); - - s->dataset = ds; -} - -static void -handle_signal(int H5_ATTR_UNUSED signo) -{ - unbroken = 0; -} - -static void -disestablish_handler(const struct sigaction *osa) -{ - if (sigaction(SIGINT, osa, NULL) == -1) - err(EXIT_FAILURE, "%s: sigaction", __func__); -} - -static void -establish_handler(struct sigaction *osa) -{ - struct sigaction sa; - - memset(&sa, '\0', sizeof(sa)); - sa.sa_handler = handle_signal; - sigemptyset(&sa.sa_mask); - if (sigaction(SIGINT, &sa, osa) == -1) - err(EXIT_FAILURE, "%s: sigaction", __func__); -} - -static void -step(vec_t *center, vec_t *direction, float steplen, bool *recursed) -{ - static const float top = 0., bottom = (float)COLS, - left = 0., right = (float)ROWS; - struct { - bool top, bottom, left, right; - } bounce = {false, false, false, false}; - float xback, yback; - vec_t before = *center; - vec_t after = (vec_t){.x = before.x + direction->x * steplen, - .y = before.y + direction->y * steplen}; - - if (before.x < right && after.x >= right) { - xback = (right - before.x) / (after.x - before.x); - bounce.right = true; - } else if (before.x > left && after.x <= left) { - xback = (before.x - left) / (before.x - after.x); - bounce.left = true; - } else - xback = 0.; - - if (before.y < bottom && after.y >= bottom) { - yback = (bottom - before.y) / (after.y - before.y); - bounce.bottom = true; - } else if (before.y > top && after.y <= top) { - yback = (before.y - top) / (before.y - after.y); - bounce.top = true; - } else - yback = 0.; - - /* I shorten the step length until a corner crossing becomes - * a side crossing. - */ - if ((bounce.top && bounce.right) || - (bounce.right && bounce.bottom) || - (bounce.bottom && bounce.left) || - (bounce.left && bounce.top)) { - - float newsteplen = steplen * 2 / 3; - if (recursed != NULL) - *recursed = true; - step(center, direction, newsteplen, NULL); - step(center, direction, steplen - newsteplen, NULL); - } - if (bounce.right || bounce.left) { - after.x = before.x + direction->x * (2 * xback - 1) * steplen; - direction->x = -direction->x; - } - if (bounce.top || bounce.bottom) { - after.y = before.y + direction->y * (2 * yback - 1) * steplen; - direction->y = -direction->y; - } - *center = after; -} - -static float -gaussian(float x, float y, float r) -{ - return expf(-(x * x + y * y) / (r * r)); -} - -static int -stepno(float v) -{ - if ((double)v < 1. / 8.) - return 0; - if ((double)v < 3. / 8.) - return 1; - if ((double)v < 7 / 8.) - return 2; - - return 3; -} - -static void -draw_border(WINDOW *w) -{ - wborder(w, 0, 0, 0, 0, 0, 0, 0, 0); -} - -static void -matrix_draw(WINDOW *w, float mat[ROWS][COLS]) -{ - int ch, i, j; - static char steps[] = " .oO"; - - wclear(w); - draw_border(w); - for (i = 0; i < ROWS; i++) { - wmove(w, 1 + i, 1); - for (j = 0; j < COLS; j++) { - ch = steps[stepno(mat[i][j])]; - waddch(w, (const chtype)ch); - } - } - - wnoutrefresh(w); -} - -static void -matrix_compute(vec_t *center, size_t ncenters, float mat[ROWS][COLS]) -{ - int i, j, k; - float radius = 4; - - for (i = 0; i < ROWS; i++) { - for (j = 0; j < COLS; j++) { - mat[i][j] = 0.; - for (k = 0; k < (int)ncenters; k++) { - mat[i][j] += gaussian((float)i - center[k].x, - (float)j - center[k].y, radius); - } - } - } -} - -static void -move_centers(vec_t *center, vec_t *direction, size_t ncenters) -{ - const float steplen = (float).01; - int k; - bool recursed[2] = {false, false}; - - for (k = 0; k < (int)ncenters; k++) { - recursed[k] = false; - step(¢er[k], &direction[k], steplen, &recursed[k]); - } -} - -static void -matrix_open(state_t *s, bool rw) -{ - const char *func; - hid_t fapl, fcpl; - H5F_vfd_swmr_config_t config; - - memset(&config, '\0', sizeof(config)); - - /* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */ - init_vfd_swmr_config(&config, SWMR_TICK_LEN, 5, rw, FALSE, 128, "./my_md_file"); - - /* use_latest_format, use_vfd_swmr, only_meta_page, config */ - fapl = vfd_swmr_create_fapl(false, true, true, &config); - if (fapl < 0) { - errx(EXIT_FAILURE, "%s.%d vfd_swmr_create_fapl failed", - __func__, __LINE__); - } - - fcpl = H5Pcreate(H5P_FILE_CREATE); - if (fcpl < 0) { - errx(EXIT_FAILURE, "%s.%d H5Pcreate failed", - __func__, __LINE__); - } - - /* Set file space strategy to paged aggregation in fcpl. - * Page buffering *requires* this strategy. - * - * I set the free-space threshold to 1GB so that deleted - * datasets are not recycled. - */ - if (H5Pset_file_space_strategy(fcpl, - H5F_FSPACE_STRATEGY_PAGE, false, 1024 * 1024 * 1024) < 0) - errx(EXIT_FAILURE, "H5Pset_file_space_strategy failed"); - - if (rw) { - s->file = H5Fcreate("vfd_swmr_gaussians.h5", H5F_ACC_TRUNC, fcpl, fapl); - func = "H5Fcreate"; - } else { - s->file = H5Fopen("vfd_swmr_gaussians.h5", H5F_ACC_RDONLY, fapl); - func = "H5Fopen"; - } - - H5Pclose(fapl); - - if (s->file < 0) - errx(EXIT_FAILURE, "%s failed", func); -} - -static void -fuzz(float mat[ROWS][COLS]) -{ - int i, j; - - for (i = 0; i < ROWS; i++) { - for (j = 0; j < COLS; j++) { - long int temp = random() / RAND_MAX * (long int)(9. / 64.); - mat[i][j] += (float)temp; - } - } -} - -int -main(int argc, char **argv) -{ - char buf[32]; - float mat[ROWS][COLS]; - int frameno; - vec_t center[2] = {{.x = .5, .y = .5}, - {.x = ROWS - .5, .y = COLS - .5}}; - vec_t direction[2] = {{.x = 3, .y = 7}, {.x = 43, .y = 41}}; - struct sigaction osa; - WINDOW *topw = NULL, *w = NULL; - personality_t personality; - state_t s; - uint64_t temp; - - srandom((unsigned int)time(NULL)); - - setlocale(LC_ALL, ""); - - state_init(&s, argc, argv); - - switch (s.progname[0]) { - case 'r': - personality = READ; - break; - case 'w': - personality = WRITE; - break; - default: - personality = STANDALONE; - break; - } - establish_handler(&osa); - - switch (personality) { - case WRITE: - matrix_open(&s, true); - create_group(&s); - create_dataset(&s); - break; - case READ: - matrix_open(&s, false); - open_group(&s); - open_dataset(&s); - break; - default: - break; - } - - if ((topw = initscr()) == NULL) - errx(EXIT_FAILURE, "initscr failed"); - else if ((w = subwin(topw, ROWS + 2, COLS + 2, 0, 0)) == NULL) - errx(EXIT_FAILURE, "subwin failed"); - - for (frameno = 0; unbroken; ) { - struct timespec elapsed, start, stop; - uint64_t elapsed_ns; - clock_gettime(CLOCK_MONOTONIC, &start); - - switch (personality) { - case READ: - matrix_read(&s, &frameno, mat); - break; - case WRITE: - case STANDALONE: - matrix_compute(center, __arraycount(center), mat); - if (s.fuzz) - fuzz(mat); - break; - } - switch (personality) { - case READ: - case STANDALONE: - matrix_draw(w, mat); -#if 0 - wmove(topw, ROWS + 3, 0); - waddstr(topw, "\"Don't cross the streams.\""); -#endif - break; - case WRITE: - matrix_write(&s, frameno, mat); - break; - } - - snprintf(buf, sizeof(buf), "Frame %d.", frameno); - wmove(topw, ROWS + 2, 0); - waddstr(topw, buf); - snprintf(buf, sizeof(buf), "Rate %lld/s.", - 1000000000ULL / timespec2ns(&s.update_interval)); - wmove(topw, ROWS + 2, COLS + 2 - (int)strlen(buf)); - waddstr(topw, buf); - wnoutrefresh(topw); - doupdate(); - - nanosleep(&s.update_interval, NULL); - - switch (personality) { - case STANDALONE: - case WRITE: - move_centers(center, direction, __arraycount(center)); - frameno++; - break; - case READ: - break; - } - clock_gettime(CLOCK_MONOTONIC, &stop); - - timespecsub(&stop, &start, &elapsed); - elapsed_ns = timespec2ns(&elapsed); - - if (elapsed_ns < s.min_elapsed_ns) - s.min_elapsed_ns = elapsed_ns; - if (elapsed_ns > s.max_elapsed_ns) - s.max_elapsed_ns = elapsed_ns; - s.total_elapsed_ns += elapsed_ns; - s.total_loops++; - } - endwin(); - fprintf(stderr, "Iteration stats:\n"); - fprintf(stderr, "min. elapsed %" PRIu64 " ms\n", - s.min_elapsed_ns / 1000000); - fprintf(stderr, "max. elapsed %" PRIu64 " ms\n", - s.max_elapsed_ns / 1000000); - temp = s.total_elapsed_ns / s.total_loops / 1000000; - fprintf(stderr, "avg. elapsed %.3f ms\n", (double)temp); - disestablish_handler(&osa); - return EXIT_SUCCESS; -} |