summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorvchoi <vchoi@jelly.ad.hdfgroup.org>2021-03-02 00:10:07 (GMT)
committervchoi <vchoi@jelly.ad.hdfgroup.org>2021-03-02 00:10:07 (GMT)
commitd9f44665cd19620118cd5f6a4fdfac5050200e70 (patch)
treedf63cc53b0f0aae8ffa8ad58fe31f21aff71c79b /test
parentf792bdbbc5b3669ac08a77a87e072c98d53fff60 (diff)
downloadhdf5-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.am16
-rw-r--r--test/vfd_swmr_common.c19
-rw-r--r--test/vfd_swmr_common.h9
-rw-r--r--test/vfd_swmr_credel.c483
-rw-r--r--test/vfd_swmr_gaussians.c753
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, &current_interval);
- if (timespeccmp(&current_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(&center[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;
-}