summaryrefslogtreecommitdiffstats
path: root/wsrep-lib/wsrep-API/v26/examples/node/options.c
diff options
context:
space:
mode:
Diffstat (limited to 'wsrep-lib/wsrep-API/v26/examples/node/options.c')
-rw-r--r--wsrep-lib/wsrep-API/v26/examples/node/options.c291
1 files changed, 291 insertions, 0 deletions
diff --git a/wsrep-lib/wsrep-API/v26/examples/node/options.c b/wsrep-lib/wsrep-API/v26/examples/node/options.c
new file mode 100644
index 00000000..0bd08ffb
--- /dev/null
+++ b/wsrep-lib/wsrep-API/v26/examples/node/options.c
@@ -0,0 +1,291 @@
+/* Copyright (c) 2019-2020, Codership Oy. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "options.h"
+
+#include <ctype.h> // isspace()
+#include <errno.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h> // strtol()
+#include <string.h> // strcmp()
+
+/*
+ * getopt_long() declarations begin
+ */
+
+#define OPTS_NA no_argument
+#define OPTS_RA required_argument
+#define OPTS_OA optional_argument
+
+typedef enum opt
+{
+ OPTS_NOOPT = 0,
+ OPTS_ADDRESS = 'a',
+ OPTS_BOOTSTRAP = 'b',
+ OPTS_DELAY = 'd',
+ OPTS_DATA_DIR = 'f',
+ OPTS_HELP = 'h',
+ OPTS_PERIOD = 'i',
+ OPTS_MASTERS = 'm',
+ OPTS_NAME = 'n',
+ OPTS_OPTIONS = 'o',
+ OPTS_BASE_PORT = 'p',
+ OPTS_RECORDS = 'r',
+ OPTS_SLAVES = 's',
+ OPTS_BASE_HOST = 't',
+ OPTS_PROVIDER = 'v',
+ OPTS_WS_SIZE = 'w',
+ OPTS_OPS = 'x'
+}
+ opt_t;
+
+static struct option s_opts[] =
+{
+ { "address", OPTS_RA, NULL, OPTS_ADDRESS },
+ { "bootstrap", OPTS_NA, NULL, OPTS_BOOTSTRAP },
+ { "delay", OPTS_RA, NULL, OPTS_DELAY },
+ { "storage", OPTS_RA, NULL, OPTS_DATA_DIR },
+ { "help", OPTS_NA, NULL, OPTS_HELP },
+ { "period", OPTS_RA, NULL, OPTS_PERIOD },
+ { "masters", OPTS_RA, NULL, OPTS_MASTERS },
+ { "name", OPTS_RA, NULL, OPTS_NAME },
+ { "options", OPTS_RA, NULL, OPTS_OPTIONS, },
+ { "base-port", OPTS_RA, NULL, OPTS_BASE_PORT },
+ { "records", OPTS_RA, NULL, OPTS_RECORDS },
+ { "slaves", OPTS_RA, NULL, OPTS_SLAVES },
+ { "base-host", OPTS_RA, NULL, OPTS_BASE_HOST },
+ { "provider", OPTS_RA, NULL, OPTS_PROVIDER },
+ { "size", OPTS_RA, NULL, OPTS_WS_SIZE },
+ { "ops", OPTS_RA, NULL, OPTS_OPS },
+ { NULL, 0, NULL, 0 }
+};
+
+static const char* opts_string = "a:d:f:hi:m:n:o:p:r:s:t:v:w:x:";
+
+/*
+ * getopt_long() declarations end
+ */
+
+static const struct node_options opts_defaults =
+{
+ .provider = "none",
+ .address = "",
+ .options = "",
+ .name = "unnamed",
+ .data_dir = ".",
+ .base_host = "localhost",
+ .masters = 0,
+ .slaves = 1,
+ .ws_size = 1024,
+ .records = 1024*1024,
+ .delay = 0,
+ .base_port = 4567,
+ .period = 10,
+ .operations= 1,
+ .bootstrap = true
+};
+
+static void
+opts_print_help(FILE* out, const char* prog_name)
+{
+ fprintf(
+ out,
+ "Usage: %s [OPTION...]\n"
+ "\n"
+ " -h, --help this thing.\n"
+ " -v, --provider=PATH a path to wsrep provider library file.\n"
+ " -a, --address=STRING list of node addresses in the group.\n"
+ " If not set the node assumes that it is the first\n"
+ " node in the group (default)\n"
+ " -o, --options=STRING a string of wsrep provider options.\n"
+ " -n, --name=STRING human-readable node name.\n"
+ " -f, --data-dir=PATH a directory to save working data in.\n"
+ " Should be private to the process.\n"
+ " -t, --base-host=ADDRESS address of this node at which other members can\n"
+ " connect to it\n"
+ " -p, --base-port=NUM base port which the node shall listen for\n"
+ " connections from other members. This port will be\n"
+ " used for replication, port+1 for IST and port+2\n"
+ " for SST. Default: 4567\n"
+ " -m, --masters=NUM number of concurrent master workers.\n"
+ " -s, --slaves=NUM number of concurrent slave workers.\n"
+ " (can't be less than 1)\n"
+ " -w, --size=NUM desirable size of the resulting writesets\n"
+ " (approximate lower boundary). Default: 1K\n"
+ " -r, --records=NUM number of records in the store. Default: 1M\n"
+ " -x, --ops=NUM number of operations per transaction. Default: 1\n"
+ " -d, --delay=NUM delay in milliseconds between \"commits\"\n"
+ " (per master thread).\n"
+ " -b, --bootstrap bootstrap the cluster with this node.\n"
+ " Default: 'Yes' if --address is not given, 'No'\n"
+ " otherwise.\n"
+ " -i, --period period in seconds between performance stats output\n"
+ "\n"
+ , prog_name);
+}
+
+static void
+opts_print_config(FILE* out, const struct node_options* opts)
+{
+ fprintf(
+ out,
+ "Continuing with the following configuration:\n"
+ "provider: %s\n"
+ "address: %s\n"
+ "options: %s\n"
+ "name: %s\n"
+ "data dir: %s\n"
+ "base addr: %s:%ld\n"
+ "masters: %ld\n"
+ "slaves: %ld\n"
+ "writeset size: %ld bytes\n"
+ "records: %ld\n"
+ "operations: %ld\n"
+ "commit delay: %ld ms\n"
+ "stats period: %ld s\n"
+ "bootstrap: %s\n"
+ ,
+ opts->provider, opts->address, opts->options, opts->name, opts->data_dir,
+ opts->base_host, opts->base_port,
+ opts->masters, opts->slaves, opts->ws_size, opts->records,
+ opts->operations,
+ opts->delay, opts->period, opts->bootstrap ? "Yes" : "No"
+ );
+}
+
+static int
+opts_check_conversion(int cond, const char* ptr, int idx)
+{
+ if (!cond || errno || (*ptr != '\0' && !isspace(*ptr)))
+ {
+ fprintf(stderr, "Bad value for %s option.\n", s_opts[idx].name);
+ return EINVAL;
+ }
+ return 0;
+}
+
+int
+node_options_read(int argc, char* argv[], struct node_options* opts)
+{
+ *opts = opts_defaults;
+
+ int opt = 0;
+ int opt_idx = 0;
+ char* endptr;
+ int ret = 0;
+
+ bool address_given = false;
+ bool bootstrap_given = false;
+
+ while ((opt = getopt_long(argc, argv, opts_string, s_opts, &opt_idx)) != -1)
+ {
+ switch (opt)
+ {
+ case OPTS_ADDRESS:
+ address_given = strcmp(opts->address, optarg);
+ opts->address = optarg;
+ break;
+ case OPTS_BOOTSTRAP:
+ bootstrap_given = true;
+ opts->bootstrap = true;
+ break;
+ case OPTS_DELAY:
+ opts->delay = strtol(optarg, &endptr, 10);
+ if ((ret = opts_check_conversion(opts->delay >= 0, endptr, opt_idx)))
+ goto err;
+ break;
+ case OPTS_DATA_DIR:
+ opts->data_dir = optarg;
+ break;
+ case OPTS_HELP:
+ ret = 1;
+ goto help;
+ case OPTS_PERIOD:
+ opts->period = strtol(optarg, &endptr, 10);
+ if ((ret = opts_check_conversion(opts->period > 0, endptr, opt_idx)))
+ goto err;
+ break;
+ case OPTS_MASTERS:
+ opts->masters = strtol(optarg, &endptr, 10);
+ if ((ret = opts_check_conversion(opts->masters >= 0, endptr,
+ opt_idx)))
+ goto err;
+ break;
+ case OPTS_NAME:
+ opts->name = optarg;
+ break;
+ case OPTS_OPTIONS:
+ opts->options = optarg;
+ break;
+ case OPTS_BASE_PORT:
+ opts->base_port = strtol(optarg, &endptr, 10);
+ if ((ret = opts_check_conversion(
+ opts->base_port > 0 && opts->base_port < 65536,
+ endptr, opt_idx)))
+ goto err;
+ break;
+ case OPTS_RECORDS:
+ opts->records = strtol(optarg, &endptr, 10);
+ if ((ret = opts_check_conversion(opts->records >= 0, endptr,
+ opt_idx)))
+ goto err;
+ break;
+ case OPTS_SLAVES:
+ opts->slaves = strtol(optarg, &endptr, 10);
+ if ((ret = opts_check_conversion(opts->slaves > 0, endptr, opt_idx)))
+ goto err;
+ break;
+ case OPTS_BASE_HOST:
+ opts->base_host = optarg;
+ break;
+ case OPTS_PROVIDER:
+ opts->provider = optarg;
+ break;
+ case OPTS_WS_SIZE:
+ opts->ws_size = strtol(optarg, &endptr, 10);
+ if ((ret = opts_check_conversion(opts->ws_size > 0, endptr,
+ opt_idx)))
+ goto err;
+ break;
+ case OPTS_OPS:
+ opts->operations = strtol(optarg, &endptr, 10);
+ if ((ret = opts_check_conversion(opts->operations >= 1, endptr,
+ opt_idx)))
+ goto err;
+ break;
+ default:
+ ret = EINVAL;
+ }
+ }
+
+help:
+ if (ret) {
+ opts_print_help(stderr, argv[0]);
+ }
+ else
+ {
+ if (!bootstrap_given)
+ {
+ opts->bootstrap = !address_given;
+ }
+ opts_print_config(stdout, opts);
+ opts->delay *= 1000; /* convert to microseconds for usleep() */
+ }
+
+err:
+ return ret;
+}