summaryrefslogtreecommitdiff
path: root/bench
diff options
context:
space:
mode:
authorKeith Bostic <keith.bostic@mongodb.com>2016-08-31 01:57:46 -0400
committerAlex Gorrod <alexander.gorrod@mongodb.com>2016-08-31 15:57:46 +1000
commit43e0c3dd822fec07f03091c7d6bcd318911d6c99 (patch)
tree030febf54e980f6a67217aee3d3b1493bfd770a6 /bench
parent3dedd2205bdfdcae537172ab9c5a2228b983e808 (diff)
downloadmongo-43e0c3dd822fec07f03091c7d6bcd318911d6c99.tar.gz
WT-2842 split wtperf's configuration into per-database and per-run parts (#2971)
Diffstat (limited to 'bench')
-rw-r--r--bench/wtperf/config.c429
-rw-r--r--bench/wtperf/config_opt.h14
-rw-r--r--bench/wtperf/doxy.c2
-rw-r--r--bench/wtperf/idle_table_cycle.c42
-rw-r--r--bench/wtperf/misc.c15
-rw-r--r--bench/wtperf/track.c17
-rw-r--r--bench/wtperf/wtperf.c745
-rw-r--r--bench/wtperf/wtperf.h58
-rw-r--r--bench/wtperf/wtperf_opt.i8
-rw-r--r--bench/wtperf/wtperf_truncate.c20
10 files changed, 714 insertions, 636 deletions
diff --git a/bench/wtperf/config.c b/bench/wtperf/config.c
index a2960902ec1..f7718632ae6 100644
--- a/bench/wtperf/config.c
+++ b/bench/wtperf/config.c
@@ -28,15 +28,19 @@
#include "wtperf.h"
-/* All options changeable on command line using -o or -O are listed here. */
-static CONFIG_OPT config_opts[] = {
+static CONFIG_OPT config_opts_desc[] = { /* Option descriptions */
#define OPT_DEFINE_DESC
#include "wtperf_opt.i"
#undef OPT_DEFINE_DESC
};
-static int config_opt(CONFIG *, WT_CONFIG_ITEM *, WT_CONFIG_ITEM *);
-static void config_opt_usage(void);
+static CONFIG_OPTS config_opts_default = { /* Option defaults */
+#define OPT_DEFINE_DEFAULT
+#include "wtperf_opt.i"
+#undef OPT_DEFINE_DEFAULT
+
+ { NULL, NULL } /* config_head */
+};
/*
* STRING_MATCH --
@@ -47,6 +51,68 @@ static void config_opt_usage(void);
(strncmp(str, bytes, len) == 0 && (str)[(len)] == '\0')
/*
+ * config_opt_init --
+ * Initialize the global configuration options.
+ */
+void
+config_opt_init(CONFIG_OPTS **retp)
+{
+ CONFIG_OPT *desc;
+ CONFIG_OPTS *opts;
+ size_t i;
+ char **strp;
+ void *valueloc;
+
+ opts = dmalloc(sizeof(CONFIG_OPTS));
+ *opts = config_opts_default;
+
+ TAILQ_INIT(&opts->config_head);
+
+ /*
+ * Option strings come-and-go as we configure them, so allocate copies
+ * of the default strings now so that we can always free the string as
+ * we allocate new versions.
+ */
+ for (i = 0, desc = config_opts_desc;
+ i < WT_ELEMENTS(config_opts_desc); i++, ++desc)
+ if (desc->type == CONFIG_STRING_TYPE) {
+ valueloc = ((uint8_t *)opts + desc->offset);
+ strp = (char **)valueloc;
+ *strp = dstrdup(*strp);
+ }
+
+ *retp = opts;
+}
+
+/*
+ * config_opt_cleanup --
+ * Clean up the global configuration options.
+ */
+void
+config_opt_cleanup(CONFIG_OPTS *opts)
+{
+ CONFIG_OPT *desc;
+ CONFIG_QUEUE_ENTRY *config_line;
+ size_t i;
+ char **strp;
+ void *valueloc;
+
+ for (i = 0, desc = config_opts_desc;
+ i < WT_ELEMENTS(config_opts_desc); i++, ++desc)
+ if (desc->type == CONFIG_STRING_TYPE) {
+ valueloc = ((uint8_t *)opts + desc->offset);
+ strp = (char **)valueloc;
+ free(*strp);
+ }
+
+ while ((config_line = TAILQ_FIRST(&opts->config_head)) != NULL) {
+ TAILQ_REMOVE(&opts->config_head, config_line, q);
+ free(config_line->string);
+ free(config_line);
+ }
+}
+
+/*
* config_unescape --
* Modify a string in place, replacing any backslash escape sequences.
* The modified string is always shorter.
@@ -94,161 +160,6 @@ config_unescape(char *orig)
}
/*
- * config_copy --
- * CONFIG structure initialization, based on a source configuration.
- */
-int
-config_copy(CONFIG *dest, const CONFIG *src)
-{
- CONFIG_QUEUE_ENTRY *conf_line, *tmp_line;
- size_t i;
- char *newstr, **pstr;
-
- memcpy(dest, src, sizeof(CONFIG));
-
- if (src->home != NULL)
- dest->home = dstrdup(src->home);
- if (src->monitor_dir != NULL)
- dest->monitor_dir = dstrdup(src->monitor_dir);
- if (src->partial_config != NULL)
- dest->partial_config = dstrdup(src->partial_config);
- if (src->reopen_config != NULL)
- dest->reopen_config = dstrdup(src->reopen_config);
- if (src->base_uri != NULL)
- dest->base_uri = dstrdup(src->base_uri);
-
- if (src->uris != NULL) {
- dest->uris = dcalloc(src->table_count, sizeof(char *));
- for (i = 0; i < src->table_count; i++)
- dest->uris[i] = dstrdup(src->uris[i]);
- }
-
- if (src->async_config != NULL)
- dest->async_config = dstrdup(src->async_config);
-
- dest->ckptthreads = NULL;
- dest->popthreads = NULL;
- dest->workers = NULL;
-
- if (src->workload != NULL) {
- dest->workload = dcalloc(WORKLOAD_MAX, sizeof(WORKLOAD));
- memcpy(dest->workload,
- src->workload, WORKLOAD_MAX * sizeof(WORKLOAD));
- }
-
- for (i = 0; i < sizeof(config_opts) / sizeof(config_opts[0]); i++)
- if (config_opts[i].type == STRING_TYPE ||
- config_opts[i].type == CONFIG_STRING_TYPE) {
- pstr = (char **)
- ((u_char *)dest + config_opts[i].offset);
- if (*pstr != NULL) {
- newstr = dstrdup(*pstr);
- *pstr = newstr;
- }
- }
-
- TAILQ_INIT(&dest->stone_head);
- TAILQ_INIT(&dest->config_head);
-
- /* Clone the config string information into the new cfg object */
- TAILQ_FOREACH(conf_line, &src->config_head, c) {
- tmp_line = dcalloc(sizeof(CONFIG_QUEUE_ENTRY), 1);
- tmp_line->string = dstrdup(conf_line->string);
- TAILQ_INSERT_TAIL(&dest->config_head, tmp_line, c);
- }
- return (0);
-}
-
-/*
- * config_free --
- * Free any storage allocated in the config struct.
- */
-void
-config_free(CONFIG *cfg)
-{
- CONFIG_QUEUE_ENTRY *config_line;
- size_t i;
- char **pstr;
-
- free(cfg->home);
- free(cfg->monitor_dir);
- free(cfg->partial_config);
- free(cfg->reopen_config);
- free(cfg->base_uri);
-
- if (cfg->uris != NULL) {
- for (i = 0; i < cfg->table_count; i++)
- free(cfg->uris[i]);
- free(cfg->uris);
- }
-
- free(cfg->async_config);
-
- free(cfg->ckptthreads);
- free(cfg->popthreads);
-
- free(cfg->workers);
- free(cfg->workload);
-
- cleanup_truncate_config(cfg);
-
- while (!TAILQ_EMPTY(&cfg->config_head)) {
- config_line = TAILQ_FIRST(&cfg->config_head);
- TAILQ_REMOVE(&cfg->config_head, config_line, c);
- free(config_line->string);
- free(config_line);
- }
-
- for (i = 0; i < sizeof(config_opts) / sizeof(config_opts[0]); i++)
- if (config_opts[i].type == STRING_TYPE ||
- config_opts[i].type == CONFIG_STRING_TYPE) {
- pstr = (char **)
- ((u_char *)cfg + config_opts[i].offset);
- free(*pstr);
- *pstr = NULL;
- }
-}
-
-/*
- * config_compress --
- * Parse the compression configuration.
- */
-int
-config_compress(CONFIG *cfg)
-{
- int ret;
- const char *s;
-
- ret = 0;
- s = cfg->compression;
- if (strcmp(s, "none") == 0) {
- cfg->compress_ext = NULL;
- cfg->compress_table = NULL;
- } else if (strcmp(s, "lz4") == 0) {
-#ifndef HAVE_BUILTIN_EXTENSION_LZ4
- cfg->compress_ext = LZ4_EXT;
-#endif
- cfg->compress_table = LZ4_BLK;
- } else if (strcmp(s, "snappy") == 0) {
-#ifndef HAVE_BUILTIN_EXTENSION_SNAPPY
- cfg->compress_ext = SNAPPY_EXT;
-#endif
- cfg->compress_table = SNAPPY_BLK;
- } else if (strcmp(s, "zlib") == 0) {
-#ifndef HAVE_BUILTIN_EXTENSION_ZLIB
- cfg->compress_ext = ZLIB_EXT;
-#endif
- cfg->compress_table = ZLIB_BLK;
- } else {
- fprintf(stderr,
- "invalid compression configuration: %s\n", s);
- ret = EINVAL;
- }
- return (ret);
-
-}
-
-/*
* config_threads --
* Parse the thread configuration.
*/
@@ -428,30 +339,32 @@ err: if (group != NULL)
static int
config_opt(CONFIG *cfg, WT_CONFIG_ITEM *k, WT_CONFIG_ITEM *v)
{
- CONFIG_OPT *popt;
+ CONFIG_OPTS *opts;
+ CONFIG_OPT *desc;
char *begin, *newstr, **strp;
int ret;
- size_t i, newlen, nopt;
+ size_t i, newlen;
void *valueloc;
- popt = NULL;
- nopt = sizeof(config_opts)/sizeof(config_opts[0]);
- for (i = 0; i < nopt; i++)
- if (strlen(config_opts[i].name) == k->len &&
- strncmp(config_opts[i].name, k->str, k->len) == 0) {
- popt = &config_opts[i];
+ opts = cfg->opts;
+
+ desc = NULL;
+ for (i = 0; i < WT_ELEMENTS(config_opts_desc); i++)
+ if (strlen(config_opts_desc[i].name) == k->len &&
+ strncmp(config_opts_desc[i].name, k->str, k->len) == 0) {
+ desc = &config_opts_desc[i];
break;
}
- if (popt == NULL) {
+ if (desc == NULL) {
fprintf(stderr, "wtperf: Error: "
"unknown option \'%.*s\'\n", (int)k->len, k->str);
fprintf(stderr, "Options:\n");
- for (i = 0; i < nopt; i++)
- fprintf(stderr, "\t%s\n", config_opts[i].name);
+ for (i = 0; i < WT_ELEMENTS(config_opts_desc); i++)
+ fprintf(stderr, "\t%s\n", config_opts_desc[i].name);
return (EINVAL);
}
- valueloc = ((u_char *)cfg + popt->offset);
- switch (popt->type) {
+ valueloc = ((uint8_t *)opts + desc->offset);
+ switch (desc->type) {
case BOOL_TYPE:
if (v->type != WT_CONFIG_ITEM_BOOL) {
fprintf(stderr, "wtperf: Error: "
@@ -657,7 +570,7 @@ config_opt_file(CONFIG *cfg, const char *filename)
if (contline)
optionpos += linelen;
else {
- if ((ret = config_opt_line(cfg, option)) != 0) {
+ if ((ret = config_opt_str(cfg, option)) != 0) {
fprintf(stderr, "wtperf: %s: %d: parse error\n",
filename, linenum);
break;
@@ -682,19 +595,22 @@ config_opt_file(CONFIG *cfg, const char *filename)
}
/*
- * config_opt_line --
+ * config_opt_str --
* Parse a single line of config options. Continued lines have already
* been joined.
*/
int
-config_opt_line(CONFIG *cfg, const char *optstr)
+config_opt_str(CONFIG *cfg, const char *optstr)
{
+ CONFIG_OPTS *opts;
CONFIG_QUEUE_ENTRY *config_line;
WT_CONFIG_ITEM k, v;
WT_CONFIG_PARSER *scan;
size_t len;
int ret, t_ret;
+ opts = cfg->opts;
+
len = strlen(optstr);
if ((ret = wiredtiger_config_parser_open(
NULL, optstr, len, &scan)) != 0) {
@@ -710,7 +626,7 @@ config_opt_line(CONFIG *cfg, const char *optstr)
*/
config_line = dcalloc(sizeof(CONFIG_QUEUE_ENTRY), 1);
config_line->string = dstrdup(optstr);
- TAILQ_INSERT_TAIL(&cfg->config_head, config_line, c);
+ TAILQ_INSERT_TAIL(&opts->config_head, config_line, q);
while (ret == 0) {
if ((ret = scan->next(scan, &k, &v)) != 0) {
@@ -731,11 +647,11 @@ config_opt_line(CONFIG *cfg, const char *optstr)
}
/*
- * config_opt_str --
- * Set a single string config option.
+ * config_opt_name_value --
+ * Set a name/value configuration pair.
*/
int
-config_opt_str(CONFIG *cfg, const char *name, const char *value)
+config_opt_name_value(CONFIG *cfg, const char *name, const char *value)
{
int ret;
char *optstr;
@@ -743,7 +659,7 @@ config_opt_str(CONFIG *cfg, const char *name, const char *value)
/* name="value" */
optstr = dmalloc(strlen(name) + strlen(value) + 4);
sprintf(optstr, "%s=\"%s\"", name, value);
- ret = config_opt_line(cfg, optstr);
+ ret = config_opt_str(cfg, optstr);
free(optstr);
return (ret);
}
@@ -755,56 +671,59 @@ config_opt_str(CONFIG *cfg, const char *name, const char *value)
int
config_sanity(CONFIG *cfg)
{
+ CONFIG_OPTS *opts;
WORKLOAD *workp;
u_int i;
+ opts = cfg->opts;
+
/* Various intervals should be less than the run-time. */
- if (cfg->run_time > 0 &&
- ((cfg->checkpoint_threads != 0 &&
- cfg->checkpoint_interval > cfg->run_time) ||
- cfg->report_interval > cfg->run_time ||
- cfg->sample_interval > cfg->run_time)) {
+ if (opts->run_time > 0 &&
+ ((opts->checkpoint_threads != 0 &&
+ opts->checkpoint_interval > opts->run_time) ||
+ opts->report_interval > opts->run_time ||
+ opts->sample_interval > opts->run_time)) {
fprintf(stderr, "interval value longer than the run-time\n");
return (EINVAL);
}
/* The maximum is here to keep file name construction simple. */
- if (cfg->table_count < 1 || cfg->table_count > 99999) {
+ if (opts->table_count < 1 || opts->table_count > 99999) {
fprintf(stderr,
"invalid table count, less than 1 or greater than 99999\n");
return (EINVAL);
}
- if (cfg->database_count < 1 || cfg->database_count > 99) {
+ if (opts->database_count < 1 || opts->database_count > 99) {
fprintf(stderr,
"invalid database count, less than 1 or greater than 99\n");
return (EINVAL);
}
- if (cfg->pareto > 100) {
+ if (opts->pareto > 100) {
fprintf(stderr,
"Invalid pareto distribution - should be a percentage\n");
return (EINVAL);
}
- if (cfg->value_sz_max < cfg->value_sz) {
+ if (opts->value_sz_max < opts->value_sz) {
if (F_ISSET(cfg, CFG_GROW)) {
fprintf(stderr, "value_sz_max %" PRIu32
" must be greater than or equal to value_sz %"
- PRIu32 "\n", cfg->value_sz_max, cfg->value_sz);
+ PRIu32 "\n", opts->value_sz_max, opts->value_sz);
return (EINVAL);
} else
- cfg->value_sz_max = cfg->value_sz;
+ opts->value_sz_max = opts->value_sz;
}
- if (cfg->value_sz_min > cfg->value_sz) {
+ if (opts->value_sz_min > opts->value_sz) {
if (F_ISSET(cfg, CFG_SHRINK)) {
fprintf(stderr, "value_sz_min %" PRIu32
" must be less than or equal to value_sz %"
- PRIu32 "\n", cfg->value_sz_min, cfg->value_sz);
+ PRIu32 "\n", opts->value_sz_min, opts->value_sz);
return (EINVAL);
} else
- cfg->value_sz_min = cfg->value_sz;
+ opts->value_sz_min = opts->value_sz;
}
- if (cfg->readonly && cfg->workload != NULL)
+ if (opts->readonly && cfg->workload != NULL)
for (i = 0, workp = cfg->workload;
i < cfg->workload_cnt; ++i, ++workp)
if (workp->insert != 0 || workp->update != 0 ||
@@ -822,21 +741,21 @@ config_sanity(CONFIG *cfg)
* Consolidate repeated configuration settings so that it only appears
* once in the configuration output file.
*/
-void
-config_consolidate(CONFIG *cfg)
+static void
+config_consolidate(CONFIG_OPTS *opts)
{
CONFIG_QUEUE_ENTRY *conf_line, *test_line, *tmp;
char *string_key;
/*
- * This loop iterates over the config queue and for entry checks if an
- * entry later in the queue has the same key. If a match is found then
- * the current queue entry is removed and we continue.
+ * This loop iterates over the config queue and for each entry checks if
+ * a later queue entry has the same key. If there's a match, the current
+ * queue entry is removed and we continue.
*/
- conf_line = TAILQ_FIRST(&cfg->config_head);
+ conf_line = TAILQ_FIRST(&opts->config_head);
while (conf_line != NULL) {
string_key = strchr(conf_line->string, '=');
- tmp = test_line = TAILQ_NEXT(conf_line, c);
+ tmp = test_line = TAILQ_NEXT(conf_line, q);
while (test_line != NULL) {
/*
* The + 1 here forces the '=' sign to be matched
@@ -847,85 +766,71 @@ config_consolidate(CONFIG *cfg)
if (strncmp(conf_line->string, test_line->string,
(size_t)((string_key - conf_line->string) + 1))
== 0) {
- TAILQ_REMOVE(&cfg->config_head, conf_line, c);
+ TAILQ_REMOVE(&opts->config_head, conf_line, q);
free(conf_line->string);
free(conf_line);
break;
}
- test_line = TAILQ_NEXT(test_line, c);
+ test_line = TAILQ_NEXT(test_line, q);
}
conf_line = tmp;
}
}
/*
- * config_to_file --
+ * config_opt_log --
* Write the final config used in this execution to a file.
*/
void
-config_to_file(CONFIG *cfg)
+config_opt_log(CONFIG_OPTS *opts, const char *path)
{
CONFIG_QUEUE_ENTRY *config_line;
FILE *fp;
- size_t req_len;
- char *path;
- fp = NULL;
+ testutil_checkfmt(((fp = fopen(path, "w")) == NULL), "%s", path);
- /* Backup the config */
- req_len = strlen(cfg->home) + strlen("/CONFIG.wtperf") + 1;
- path = dcalloc(req_len, 1);
- snprintf(path, req_len, "%s/CONFIG.wtperf", cfg->home);
- if ((fp = fopen(path, "w")) == NULL) {
- lprintf(cfg, errno, 0, "%s", path);
- goto err;
- }
+ config_consolidate(opts);
- /* Print the config dump */
- fprintf(fp,"# Warning. This config includes "
+ fprintf(fp,"# Warning: This config includes "
"unwritten, implicit configuration defaults.\n"
"# Changes to those values may cause differences in behavior.\n");
- config_consolidate(cfg);
- config_line = TAILQ_FIRST(&cfg->config_head);
- while (config_line != NULL) {
+ TAILQ_FOREACH(config_line, &opts->config_head, q)
fprintf(fp, "%s\n", config_line->string);
- config_line = TAILQ_NEXT(config_line, c);
- }
-
-err: free(path);
- if (fp != NULL)
- (void)fclose(fp);
+ testutil_check(fclose(fp));
}
/*
- * config_print --
+ * config_opt_print --
* Print out the configuration in verbose mode.
*/
void
-config_print(CONFIG *cfg)
+config_opt_print(CONFIG *cfg)
{
+ CONFIG_OPTS *opts;
WORKLOAD *workp;
u_int i;
+ opts = cfg->opts;
+
printf("Workload configuration:\n");
printf("\t" "Home: %s\n", cfg->home);
- printf("\t" "Table name: %s\n", cfg->table_name);
- printf("\t" "Connection configuration: %s\n", cfg->conn_config);
- if (cfg->sess_config != NULL)
- printf("\t" "Session configuration: %s\n", cfg->sess_config);
+ printf("\t" "Table name: %s\n", opts->table_name);
+ printf("\t" "Connection configuration: %s\n", opts->conn_config);
+ if (opts->sess_config != NULL)
+ printf("\t" "Session configuration: %s\n", opts->sess_config);
printf("\t%s table: %s\n",
- cfg->create ? "Creating new" : "Using existing",
- cfg->table_config);
+ opts->create ? "Creating new" : "Using existing",
+ opts->table_config);
printf("\t" "Key size: %" PRIu32 ", value size: %" PRIu32 "\n",
- cfg->key_sz, cfg->value_sz);
- if (cfg->create)
+ opts->key_sz, opts->value_sz);
+ if (opts->create)
printf("\t" "Populate threads: %" PRIu32 ", inserting %" PRIu32
" rows\n",
- cfg->populate_threads, cfg->icount);
+ opts->populate_threads, opts->icount);
printf("\t" "Workload seconds, operations: %" PRIu32 ", %" PRIu32 "\n",
- cfg->run_time, cfg->run_ops);
+ opts->run_time, opts->run_ops);
if (cfg->workload != NULL) {
printf("\t" "Workload configuration(s):\n");
for (i = 0, workp = cfg->workload;
@@ -939,11 +844,11 @@ config_print(CONFIG *cfg)
}
printf("\t" "Checkpoint threads, interval: %" PRIu32 ", %" PRIu32 "\n",
- cfg->checkpoint_threads, cfg->checkpoint_interval);
- printf("\t" "Reporting interval: %" PRIu32 "\n", cfg->report_interval);
- printf("\t" "Sampling interval: %" PRIu32 "\n", cfg->sample_interval);
+ opts->checkpoint_threads, opts->checkpoint_interval);
+ printf("\t" "Reporting interval: %" PRIu32 "\n", opts->report_interval);
+ printf("\t" "Sampling interval: %" PRIu32 "\n", opts->sample_interval);
- printf("\t" "Verbosity: %" PRIu32 "\n", cfg->verbose);
+ printf("\t" "Verbosity: %" PRIu32 "\n", opts->verbose);
}
/*
@@ -973,10 +878,10 @@ pretty_print(const char *p, const char *indent)
* config_opt_usage --
* Configuration usage error message.
*/
-static void
+void
config_opt_usage(void)
{
- size_t i, nopt;
+ size_t i;
const char *defaultval, *typestr;
pretty_print(
@@ -986,11 +891,10 @@ config_opt_usage(void)
"String values must be enclosed in \" quotes, boolean values must "
"be either true or false.\n", NULL);
- nopt = sizeof(config_opts)/sizeof(config_opts[0]);
- for (i = 0; i < nopt; i++) {
- defaultval = config_opts[i].defaultval;
+ for (i = 0; i < WT_ELEMENTS(config_opts_desc); i++) {
+ defaultval = config_opts_desc[i].defaultval;
typestr = "string";
- switch (config_opts[i].type) {
+ switch (config_opts_desc[i].type) {
case BOOL_TYPE:
typestr = "boolean";
if (strcmp(defaultval, "0") == 0)
@@ -1009,28 +913,7 @@ config_opt_usage(void)
break;
}
printf("%s (%s, default=%s)\n",
- config_opts[i].name, typestr, defaultval);
- pretty_print(config_opts[i].description, "\t");
+ config_opts_desc[i].name, typestr, defaultval);
+ pretty_print(config_opts_desc[i].description, "\t");
}
}
-
-/*
- * usage --
- * wtperf usage print, no error.
- */
-void
-usage(void)
-{
- printf("wtperf [-C config] "
- "[-H mount] [-h home] [-O file] [-o option] [-T config]\n");
- printf("\t-C <string> additional connection configuration\n");
- printf("\t (added to option conn_config)\n");
- printf("\t-H <mount> configure Helium volume mount point\n");
- printf("\t-h <string> Wired Tiger home must exist, default WT_TEST\n");
- printf("\t-O <file> file contains options as listed below\n");
- printf("\t-o option=val[,option=val,...] set options listed below\n");
- printf("\t-T <string> additional table configuration\n");
- printf("\t (added to option table_config)\n");
- printf("\n");
- config_opt_usage();
-}
diff --git a/bench/wtperf/config_opt.h b/bench/wtperf/config_opt.h
index b7eff8e143f..3f1ab642227 100644
--- a/bench/wtperf/config_opt.h
+++ b/bench/wtperf/config_opt.h
@@ -37,3 +37,17 @@ typedef struct {
CONFIG_OPT_TYPE type;
size_t offset;
} CONFIG_OPT;
+
+typedef struct __config_queue_entry {
+ char *string;
+ TAILQ_ENTRY(__config_queue_entry) q;
+} CONFIG_QUEUE_ENTRY;
+
+typedef struct { /* Option structure */
+#define OPT_DECLARE_STRUCT
+#include "wtperf_opt.i"
+#undef OPT_DECLARE_STRUCT
+
+ /* Queue head to save a copy of the config to be output */
+ TAILQ_HEAD(__config_qh, __config_queue_entry) config_head;
+} CONFIG_OPTS;
diff --git a/bench/wtperf/doxy.c b/bench/wtperf/doxy.c
index 26d73168ef2..4a9426da123 100644
--- a/bench/wtperf/doxy.c
+++ b/bench/wtperf/doxy.c
@@ -26,9 +26,11 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <sys/types.h>
#include <string.h>
#include <stdio.h>
+#include "queue.h"
#include "config_opt.h"
static const CONFIG_OPT config_opts[] = {
diff --git a/bench/wtperf/idle_table_cycle.c b/bench/wtperf/idle_table_cycle.c
index 3c079bb560f..ad6b075be77 100644
--- a/bench/wtperf/idle_table_cycle.c
+++ b/bench/wtperf/idle_table_cycle.c
@@ -32,25 +32,28 @@ static int
check_timing(CONFIG *cfg,
const char *name, struct timespec start, struct timespec *stop)
{
+ CONFIG_OPTS *opts;
uint64_t last_interval;
int ret;
+ opts = cfg->opts;
+
if ((ret = __wt_epoch(NULL, stop)) != 0) {
lprintf(cfg, ret, 0,
"Get time failed in cycle_idle_tables.");
- cfg->error = ret;
+ cfg->error = true;
return (ret);
}
last_interval = (uint64_t)(WT_TIMEDIFF_SEC(*stop, start));
- if (last_interval > cfg->idle_table_cycle) {
+ if (last_interval > opts->idle_table_cycle) {
lprintf(cfg, ret, 0,
"Cycling idle table failed because %s took %" PRIu64
" seconds which is longer than configured acceptable"
" maximum of %" PRIu32 ".",
- name, last_interval, cfg->idle_table_cycle);
- cfg->error = ETIMEDOUT;
+ name, last_interval, opts->idle_table_cycle);
+ cfg->error = true;
return (ETIMEDOUT);
}
return (0);
@@ -65,16 +68,18 @@ cycle_idle_tables(void *arg)
{
struct timespec start, stop;
CONFIG *cfg;
- WT_SESSION *session;
+ CONFIG_OPTS *opts;
WT_CURSOR *cursor;
+ WT_SESSION *session;
int cycle_count, ret;
char uri[512];
cfg = (CONFIG *)arg;
+ opts = cfg->opts;
cycle_count = 0;
if ((ret = cfg->conn->open_session(
- cfg->conn, NULL, cfg->sess_config, &session)) != 0) {
+ cfg->conn, NULL, opts->sess_config, &session)) != 0) {
lprintf(cfg, ret, 0,
"Error opening a session on %s", cfg->home);
return (NULL);
@@ -89,18 +94,18 @@ cycle_idle_tables(void *arg)
if ((ret = __wt_epoch(NULL, &start)) != 0) {
lprintf(cfg, ret, 0,
"Get time failed in cycle_idle_tables.");
- cfg->error = ret;
+ cfg->error = true;
return (NULL);
}
/* Create a table. */
if ((ret = session->create(
- session, uri, cfg->table_config)) != 0) {
+ session, uri, opts->table_config)) != 0) {
if (ret == EBUSY)
continue;
lprintf(cfg, ret, 0,
"Table create failed in cycle_idle_tables.");
- cfg->error = ret;
+ cfg->error = true;
return (NULL);
}
if (check_timing(cfg, "create", start, &stop) != 0)
@@ -112,13 +117,13 @@ cycle_idle_tables(void *arg)
session, uri, NULL, NULL, &cursor)) != 0) {
lprintf(cfg, ret, 0,
"Cursor open failed in cycle_idle_tables.");
- cfg->error = ret;
+ cfg->error = true;
return (NULL);
}
if ((ret = cursor->close(cursor)) != 0) {
lprintf(cfg, ret, 0,
"Cursor close failed in cycle_idle_tables.");
- cfg->error = ret;
+ cfg->error = true;
return (NULL);
}
if (check_timing(cfg, "cursor", start, &stop) != 0)
@@ -136,7 +141,7 @@ cycle_idle_tables(void *arg)
if (ret != 0 && ret != EBUSY) {
lprintf(cfg, ret, 0,
"Table drop failed in cycle_idle_tables.");
- cfg->error = ret;
+ cfg->error = true;
return (NULL);
}
if (check_timing(cfg, "drop", start, &stop) != 0)
@@ -156,17 +161,19 @@ cycle_idle_tables(void *arg)
int
start_idle_table_cycle(CONFIG *cfg, pthread_t *idle_table_cycle_thread)
{
+ CONFIG_OPTS *opts;
pthread_t thread_id;
int ret;
- if (cfg->idle_table_cycle == 0)
+ opts = cfg->opts;
+
+ if (opts->idle_table_cycle == 0)
return (0);
cfg->idle_cycle_run = true;
if ((ret = pthread_create(
&thread_id, NULL, cycle_idle_tables, cfg)) != 0) {
- lprintf(
- cfg, ret, 0, "Error creating idle table cycle thread.");
+ lprintf(cfg, ret, 0, "Error creating idle table cycle thread.");
cfg->idle_cycle_run = false;
return (ret);
}
@@ -178,9 +185,12 @@ start_idle_table_cycle(CONFIG *cfg, pthread_t *idle_table_cycle_thread)
int
stop_idle_table_cycle(CONFIG *cfg, pthread_t idle_table_cycle_thread)
{
+ CONFIG_OPTS *opts;
int ret;
- if (cfg->idle_table_cycle == 0 || !cfg->idle_cycle_run)
+ opts = cfg->opts;
+
+ if (opts->idle_table_cycle == 0 || !cfg->idle_cycle_run)
return (0);
cfg->idle_cycle_run = false;
diff --git a/bench/wtperf/misc.c b/bench/wtperf/misc.c
index 2821216f240..14a6610f5bc 100644
--- a/bench/wtperf/misc.c
+++ b/bench/wtperf/misc.c
@@ -32,18 +32,20 @@
int
setup_log_file(CONFIG *cfg)
{
+ CONFIG_OPTS *opts;
int ret;
char *fname;
+ opts = cfg->opts;
ret = 0;
- if (cfg->verbose < 1)
+ if (opts->verbose < 1)
return (0);
fname = dcalloc(strlen(cfg->monitor_dir) +
- strlen(cfg->table_name) + strlen(".stat") + 2, 1);
+ strlen(opts->table_name) + strlen(".stat") + 2, 1);
- sprintf(fname, "%s/%s.stat", cfg->monitor_dir, cfg->table_name);
+ sprintf(fname, "%s/%s.stat", cfg->monitor_dir, opts->table_name);
cfg->logf = fopen(fname, "w");
if (cfg->logf == NULL) {
ret = errno;
@@ -64,15 +66,18 @@ setup_log_file(CONFIG *cfg)
void
lprintf(const CONFIG *cfg, int err, uint32_t level, const char *fmt, ...)
{
+ CONFIG_OPTS *opts;
va_list ap;
- if (err == 0 && level <= cfg->verbose) {
+ opts = cfg->opts;
+
+ if (err == 0 && level <= opts->verbose) {
va_start(ap, fmt);
vfprintf(cfg->logf, fmt, ap);
va_end(ap);
fprintf(cfg->logf, "\n");
- if (level < cfg->verbose) {
+ if (level < opts->verbose) {
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
diff --git a/bench/wtperf/track.c b/bench/wtperf/track.c
index b3f4847d9d0..0464d22fb79 100644
--- a/bench/wtperf/track.c
+++ b/bench/wtperf/track.c
@@ -34,14 +34,16 @@
uint64_t
sum_pop_ops(CONFIG *cfg)
{
+ CONFIG_OPTS *opts;
CONFIG_THREAD *thread;
uint64_t total;
u_int i;
+ opts = cfg->opts;
total = 0;
for (i = 0, thread = cfg->popthreads;
- thread != NULL && i < cfg->populate_threads; ++i, ++thread)
+ thread != NULL && i < opts->populate_threads; ++i, ++thread)
total += thread->insert.ops;
return (total);
}
@@ -52,14 +54,16 @@ sum_pop_ops(CONFIG *cfg)
uint64_t
sum_ckpt_ops(CONFIG *cfg)
{
+ CONFIG_OPTS *opts;
CONFIG_THREAD *thread;
uint64_t total;
u_int i;
+ opts = cfg->opts;
total = 0;
for (i = 0, thread = cfg->ckptthreads;
- thread != NULL && i < cfg->checkpoint_threads; ++i, ++thread)
+ thread != NULL && i < opts->checkpoint_threads; ++i, ++thread)
total += thread->ckpt.ops;
return (total);
}
@@ -70,17 +74,20 @@ sum_ckpt_ops(CONFIG *cfg)
static uint64_t
sum_ops(CONFIG *cfg, size_t field_offset)
{
+ CONFIG_OPTS *opts;
CONFIG_THREAD *thread;
uint64_t total;
int64_t i, th_cnt;
+ opts = cfg->opts;
total = 0;
+
if (cfg->popthreads == NULL) {
thread = cfg->workers;
th_cnt = cfg->workers_cnt;
} else {
thread = cfg->popthreads;
- th_cnt = cfg->populate_threads;
+ th_cnt = opts->populate_threads;
}
for (i = 0; thread != NULL && i < th_cnt; ++i, ++thread)
total += ((TRACK *)((uint8_t *)thread + field_offset))->ops;
@@ -117,12 +124,14 @@ static void
latency_op(CONFIG *cfg,
size_t field_offset, uint32_t *avgp, uint32_t *minp, uint32_t *maxp)
{
+ CONFIG_OPTS *opts;
CONFIG_THREAD *thread;
TRACK *track;
uint64_t ops, latency, tmp;
int64_t i, th_cnt;
uint32_t max, min;
+ opts = cfg->opts;
ops = latency = 0;
max = 0;
min = UINT32_MAX;
@@ -132,7 +141,7 @@ latency_op(CONFIG *cfg,
th_cnt = cfg->workers_cnt;
} else {
thread = cfg->popthreads;
- th_cnt = cfg->populate_threads;
+ th_cnt = opts->populate_threads;
}
for (i = 0; thread != NULL && i < th_cnt; ++i, ++thread) {
track = (TRACK *)((uint8_t *)thread + field_offset);
diff --git a/bench/wtperf/wtperf.c b/bench/wtperf/wtperf.c
index c689fca80f7..a628f847476 100644
--- a/bench/wtperf/wtperf.c
+++ b/bench/wtperf/wtperf.c
@@ -31,44 +31,6 @@
/* Default values. */
#define DEFAULT_HOME "WT_TEST"
#define DEFAULT_MONITOR_DIR "WT_TEST"
-static const CONFIG default_cfg = {
- NULL, /* home */
- NULL, /* monitor dir */
- NULL, /* partial logging */
- NULL, /* reopen config */
- NULL, /* base_uri */
- NULL, /* uris */
- NULL, /* conn */
- NULL, /* logf */
- NULL, /* async */
- NULL, NULL, /* compressor ext, blk */
- NULL, NULL, /* populate, checkpoint threads */
-
- NULL, /* worker threads */
- 0, /* worker thread count */
- NULL, /* workloads */
- 0, /* workload count */
- 0, /* use_asyncops */
- 0, /* checkpoint operations */
- 0, /* insert operations */
- 0, /* read operations */
- 0, /* truncate operations */
- 0, /* update operations */
- 0, /* insert key */
- 0, /* checkpoint in progress */
- 0, /* thread error */
- 0, /* notify threads to stop */
- 0, /* in warmup phase */
- false, /* Signal for idle cycle thread */
- 0, /* total seconds running */
- 0, /* flags */
- {NULL, NULL}, /* the truncate queue */
- {NULL, NULL}, /* the config queue */
-
-#define OPT_DEFINE_DEFAULT
-#include "wtperf_opt.i"
-#undef OPT_DEFINE_DEFAULT
-};
static const char * const debug_cconfig = "";
static const char * const debug_tconfig = "";
@@ -110,9 +72,12 @@ get_next_incr(CONFIG *cfg)
static void
randomize_value(CONFIG_THREAD *thread, char *value_buf)
{
+ CONFIG_OPTS *opts;
uint8_t *vb;
uint32_t i, max_range, rand_val;
+ opts = thread->cfg->opts;
+
/*
* Limit how much of the buffer we validate for length, this means
* that only threads that do growing updates will ever make changes to
@@ -121,11 +86,11 @@ randomize_value(CONFIG_THREAD *thread, char *value_buf)
* in this performance sensitive function.
*/
if (thread->workload == NULL || thread->workload->update_delta == 0)
- max_range = thread->cfg->value_sz;
+ max_range = opts->value_sz;
else if (thread->workload->update_delta > 0)
- max_range = thread->cfg->value_sz_max;
+ max_range = opts->value_sz_max;
else
- max_range = thread->cfg->value_sz_min;
+ max_range = opts->value_sz_min;
/*
* Generate a single random value and re-use it. We generally only
@@ -157,15 +122,19 @@ randomize_value(CONFIG_THREAD *thread, char *value_buf)
static uint32_t
map_key_to_table(CONFIG *cfg, uint64_t k)
{
- if (cfg->range_partition) {
+ CONFIG_OPTS *opts;
+
+ opts = cfg->opts;
+
+ if (opts->range_partition) {
/* Take care to return a result in [0..table_count-1]. */
- if (k > cfg->icount + cfg->random_range)
+ if (k > opts->icount + opts->random_range)
return (0);
return ((uint32_t)((k - 1) /
- ((cfg->icount + cfg->random_range + cfg->table_count - 1) /
- cfg->table_count)));
+ ((opts->icount + opts->random_range +
+ opts->table_count - 1) / opts->table_count)));
} else
- return ((uint32_t)(k % cfg->table_count));
+ return ((uint32_t)(k % opts->table_count));
}
/*
@@ -177,23 +146,25 @@ static inline void
update_value_delta(CONFIG_THREAD *thread)
{
CONFIG *cfg;
+ CONFIG_OPTS *opts;
char * value;
int64_t delta, len, new_len;
cfg = thread->cfg;
+ opts = cfg->opts;
value = thread->value_buf;
delta = thread->workload->update_delta;
len = (int64_t)strlen(value);
if (delta == INT64_MAX)
delta = __wt_random(&thread->rnd) %
- (cfg->value_sz_max - cfg->value_sz);
+ (opts->value_sz_max - opts->value_sz);
/* Ensure we aren't changing across boundaries */
- if (delta > 0 && len + delta > cfg->value_sz_max)
- delta = cfg->value_sz_max - len;
- else if (delta < 0 && len + delta < cfg->value_sz_min)
- delta = cfg->value_sz_min - len;
+ if (delta > 0 && len + delta > opts->value_sz_max)
+ delta = opts->value_sz_max - len;
+ else if (delta < 0 && len + delta < opts->value_sz_min)
+ delta = opts->value_sz_min - len;
/* Bail if there isn't anything to do */
if (delta == 0)
@@ -204,7 +175,7 @@ update_value_delta(CONFIG_THREAD *thread)
else {
/* Extend the value by the configured amount. */
for (new_len = len;
- new_len < cfg->value_sz_max && new_len - len < delta;
+ new_len < opts->value_sz_max && new_len - len < delta;
new_len++)
value[new_len] = 'a';
}
@@ -279,7 +250,7 @@ err:
/* Panic if error */
lprintf(cfg, ret, 0, "Error in op %" PRIu64,
op->get_id(op));
- cfg->error = cfg->stop = 1;
+ cfg->error = cfg->stop = true;
return (1);
}
@@ -352,6 +323,7 @@ static void *
worker_async(void *arg)
{
CONFIG *cfg;
+ CONFIG_OPTS *opts;
CONFIG_THREAD *thread;
WT_ASYNC_OP *asyncop;
WT_CONNECTION *conn;
@@ -362,6 +334,7 @@ worker_async(void *arg)
thread = (CONFIG_THREAD *)arg;
cfg = thread->cfg;
+ opts = cfg->opts;
conn = cfg->conn;
key_buf = thread->key_buf;
@@ -378,10 +351,10 @@ worker_async(void *arg)
switch (*op) {
case WORKER_INSERT:
case WORKER_INSERT_RMW:
- if (cfg->random_range)
+ if (opts->random_range)
next_val = wtperf_rand(thread);
else
- next_val = cfg->icount + get_next_incr(cfg);
+ next_val = opts->icount + get_next_incr(cfg);
break;
case WORKER_READ:
case WORKER_UPDATE:
@@ -422,14 +395,14 @@ worker_async(void *arg)
break;
goto op_err;
case WORKER_INSERT:
- if (cfg->random_value)
+ if (opts->random_value)
randomize_value(thread, value_buf);
asyncop->set_value(asyncop, value_buf);
if ((ret = asyncop->insert(asyncop)) == 0)
break;
goto op_err;
case WORKER_UPDATE:
- if (cfg->random_value)
+ if (opts->random_value)
randomize_value(thread, value_buf);
asyncop->set_value(asyncop, value_buf);
if ((ret = asyncop->update(asyncop)) == 0)
@@ -452,7 +425,7 @@ op_err: lprintf(cfg, ret, 0,
/* Notify our caller we failed and shut the system down. */
if (0) {
-err: cfg->error = cfg->stop = 1;
+err: cfg->error = cfg->stop = true;
}
return (NULL);
}
@@ -465,15 +438,17 @@ err: cfg->error = cfg->stop = 1;
static int
do_range_reads(CONFIG *cfg, WT_CURSOR *cursor)
{
+ CONFIG_OPTS *opts;
size_t range;
uint64_t next_val, prev_val;
char *range_key_buf;
char buf[512];
int ret;
+ opts = cfg->opts;
ret = 0;
- if (cfg->read_range == 0)
+ if (opts->read_range == 0)
return (0);
memset(&buf[0], 0, 512 * sizeof(char));
@@ -483,7 +458,7 @@ do_range_reads(CONFIG *cfg, WT_CURSOR *cursor)
testutil_check(cursor->get_key(cursor, &range_key_buf));
extract_key(range_key_buf, &next_val);
- for (range = 0; range < cfg->read_range; ++range) {
+ for (range = 0; range < opts->read_range; ++range) {
prev_val = next_val;
ret = cursor->next(cursor);
/* We are done if we reach the end. */
@@ -509,6 +484,7 @@ worker(void *arg)
{
struct timespec start, stop;
CONFIG *cfg;
+ CONFIG_OPTS *opts;
CONFIG_THREAD *thread;
TRACK *trk;
WT_CONNECTION *conn;
@@ -524,6 +500,7 @@ worker(void *arg)
thread = (CONFIG_THREAD *)arg;
cfg = thread->cfg;
+ opts = cfg->opts;
conn = cfg->conn;
cursors = NULL;
ops = 0;
@@ -532,12 +509,12 @@ worker(void *arg)
trk = NULL;
if ((ret = conn->open_session(
- conn, NULL, cfg->sess_config, &session)) != 0) {
+ conn, NULL, opts->sess_config, &session)) != 0) {
lprintf(cfg, ret, 0, "worker: WT_CONNECTION.open_session");
goto err;
}
- cursors = dcalloc(cfg->table_count, sizeof(WT_CURSOR *));
- for (i = 0; i < cfg->table_count_idle; i++) {
+ cursors = dcalloc(opts->table_count, sizeof(WT_CURSOR *));
+ for (i = 0; i < opts->table_count_idle; i++) {
snprintf(buf, 512, "%s_idle%05d", cfg->uris[0], (int)i);
if ((ret = session->open_cursor(
session, buf, NULL, NULL, &tmp_cursor)) != 0) {
@@ -551,7 +528,7 @@ worker(void *arg)
goto err;
}
}
- for (i = 0; i < cfg->table_count; i++) {
+ for (i = 0; i < opts->table_count; i++) {
if ((ret = session->open_cursor(session,
cfg->uris[i], NULL, NULL, &cursors[i])) != 0) {
lprintf(cfg, ret, 0,
@@ -590,10 +567,10 @@ worker(void *arg)
case WORKER_INSERT:
case WORKER_INSERT_RMW:
trk = &thread->insert;
- if (cfg->random_range)
+ if (opts->random_range)
next_val = wtperf_rand(thread);
else
- next_val = cfg->icount + get_next_incr(cfg);
+ next_val = opts->icount + get_next_incr(cfg);
break;
case WORKER_READ:
trk = &thread->read;
@@ -631,8 +608,8 @@ worker(void *arg)
* is 0, to avoid first time latency spikes.
*/
measure_latency =
- cfg->sample_interval != 0 && trk != NULL &&
- trk->ops != 0 && (trk->ops % cfg->sample_rate == 0);
+ opts->sample_interval != 0 && trk != NULL &&
+ trk->ops != 0 && (trk->ops % opts->sample_rate == 0);
if (measure_latency && (ret = __wt_epoch(NULL, &start)) != 0) {
lprintf(cfg, ret, 0, "Get time call failed");
goto err;
@@ -677,7 +654,7 @@ worker(void *arg)
/* FALLTHROUGH */
case WORKER_INSERT:
- if (cfg->random_value)
+ if (opts->random_value)
randomize_value(thread, value_buf);
cursor->set_value(cursor, value_buf);
if ((ret = cursor->insert(cursor)) == 0)
@@ -708,14 +685,14 @@ worker(void *arg)
* safe, and be sure to NUL-terminate.
*/
strncpy(value_buf,
- value, cfg->value_sz_max - 1);
+ value, opts->value_sz_max - 1);
if (thread->workload->update_delta != 0)
update_value_delta(thread);
if (value_buf[0] == 'a')
value_buf[0] = 'b';
else
value_buf[0] = 'a';
- if (cfg->random_value)
+ if (opts->random_value)
randomize_value(thread, value_buf);
cursor->set_value(cursor, value_buf);
if ((ret = cursor->update(cursor)) == 0)
@@ -769,7 +746,7 @@ op_err: if (ret == WT_ROLLBACK && ops_per_txn != 0) {
}
/* Release the cursor, if we have multiple tables. */
- if (cfg->table_count > 1 && ret == 0 &&
+ if (opts->table_count > 1 && ret == 0 &&
*op != WORKER_INSERT && *op != WORKER_INSERT_RMW) {
if ((ret = cursor->reset(cursor)) != 0) {
lprintf(cfg, ret, 0, "Cursor reset failed");
@@ -828,7 +805,7 @@ op_err: if (ret == WT_ROLLBACK && ops_per_txn != 0) {
/* Notify our caller we failed and shut the system down. */
if (0) {
-err: cfg->error = cfg->stop = 1;
+err: cfg->error = cfg->stop = true;
}
free(cursors);
@@ -883,8 +860,11 @@ run_mix_schedule_op(WORKLOAD *workp, int op, int64_t op_cnt)
static int
run_mix_schedule(CONFIG *cfg, WORKLOAD *workp)
{
+ CONFIG_OPTS *opts;
int64_t pct;
+ opts = cfg->opts;
+
/* Confirm reads, inserts, truncates and updates cannot all be zero. */
if (workp->insert == 0 && workp->read == 0 &&
workp->truncate == 0 && workp->update == 0) {
@@ -915,7 +895,7 @@ run_mix_schedule(CONFIG *cfg, WORKLOAD *workp)
*/
if (workp->insert != 0 && workp->read == 0 && workp->update == 0) {
memset(workp->ops,
- cfg->insert_rmw ? WORKER_INSERT_RMW : WORKER_INSERT,
+ opts->insert_rmw ? WORKER_INSERT_RMW : WORKER_INSERT,
sizeof(workp->ops));
return (0);
}
@@ -947,7 +927,7 @@ run_mix_schedule(CONFIG *cfg, WORKLOAD *workp)
(workp->insert + workp->read + workp->update);
if (pct != 0)
run_mix_schedule_op(workp,
- cfg->insert_rmw ? WORKER_INSERT_RMW : WORKER_INSERT, pct);
+ opts->insert_rmw ? WORKER_INSERT_RMW : WORKER_INSERT, pct);
pct = (workp->update * 100) /
(workp->insert + workp->read + workp->update);
if (pct != 0)
@@ -960,6 +940,7 @@ populate_thread(void *arg)
{
struct timespec start, stop;
CONFIG *cfg;
+ CONFIG_OPTS *opts;
CONFIG_THREAD *thread;
TRACK *trk;
WT_CONNECTION *conn;
@@ -974,6 +955,7 @@ populate_thread(void *arg)
thread = (CONFIG_THREAD *)arg;
cfg = thread->cfg;
+ opts = cfg->opts;
conn = cfg->conn;
session = NULL;
cursors = NULL;
@@ -984,17 +966,17 @@ populate_thread(void *arg)
value_buf = thread->value_buf;
if ((ret = conn->open_session(
- conn, NULL, cfg->sess_config, &session)) != 0) {
+ conn, NULL, opts->sess_config, &session)) != 0) {
lprintf(cfg, ret, 0, "populate: WT_CONNECTION.open_session");
goto err;
}
/* Do bulk loads if populate is single-threaded. */
cursor_config =
- (cfg->populate_threads == 1 && !cfg->index) ? "bulk" : NULL;
+ (opts->populate_threads == 1 && !opts->index) ? "bulk" : NULL;
/* Create the cursors. */
- cursors = dcalloc(cfg->table_count, sizeof(WT_CURSOR *));
- for (i = 0; i < cfg->table_count; i++) {
+ cursors = dcalloc(opts->table_count, sizeof(WT_CURSOR *));
+ for (i = 0; i < opts->table_count; i++) {
if ((ret = session->open_cursor(
session, cfg->uris[i], NULL,
cursor_config, &cursors[i])) != 0) {
@@ -1008,12 +990,12 @@ populate_thread(void *arg)
/* Populate the databases. */
for (intxn = 0, opcount = 0;;) {
op = get_next_incr(cfg);
- if (op > cfg->icount)
+ if (op > opts->icount)
break;
- if (cfg->populate_ops_per_txn != 0 && !intxn) {
+ if (opts->populate_ops_per_txn != 0 && !intxn) {
if ((ret = session->begin_transaction(
- session, cfg->transaction_config)) != 0) {
+ session, opts->transaction_config)) != 0) {
lprintf(cfg, ret, 0,
"Failed starting transaction.");
goto err;
@@ -1026,14 +1008,14 @@ populate_thread(void *arg)
cursor = cursors[map_key_to_table(cfg, op)];
generate_key(cfg, key_buf, op);
measure_latency =
- cfg->sample_interval != 0 &&
- trk->ops != 0 && (trk->ops % cfg->sample_rate == 0);
+ opts->sample_interval != 0 &&
+ trk->ops != 0 && (trk->ops % opts->sample_rate == 0);
if (measure_latency && (ret = __wt_epoch(NULL, &start)) != 0) {
lprintf(cfg, ret, 0, "Get time call failed");
goto err;
}
cursor->set_key(cursor, key_buf);
- if (cfg->random_value)
+ if (opts->random_value)
randomize_value(thread, value_buf);
cursor->set_value(cursor, value_buf);
if ((ret = cursor->insert(cursor)) == WT_ROLLBACK) {
@@ -1067,12 +1049,12 @@ populate_thread(void *arg)
}
++thread->insert.ops; /* Same as trk->ops */
- if (cfg->checkpoint_stress_rate != 0 &&
- (op % cfg->checkpoint_stress_rate) == 0)
+ if (opts->checkpoint_stress_rate != 0 &&
+ (op % opts->checkpoint_stress_rate) == 0)
stress_checkpoint_due = 1;
- if (cfg->populate_ops_per_txn != 0) {
- if (++opcount < cfg->populate_ops_per_txn)
+ if (opts->populate_ops_per_txn != 0) {
+ if (++opcount < opts->populate_ops_per_txn)
continue;
opcount = 0;
@@ -1103,7 +1085,7 @@ populate_thread(void *arg)
/* Notify our caller we failed and shut the system down. */
if (0) {
-err: cfg->error = cfg->stop = 1;
+err: cfg->error = cfg->stop = true;
}
free(cursors);
@@ -1115,6 +1097,7 @@ populate_async(void *arg)
{
struct timespec start, stop;
CONFIG *cfg;
+ CONFIG_OPTS *opts;
CONFIG_THREAD *thread;
TRACK *trk;
WT_ASYNC_OP *asyncop;
@@ -1126,6 +1109,7 @@ populate_async(void *arg)
thread = (CONFIG_THREAD *)arg;
cfg = thread->cfg;
+ opts = cfg->opts;
conn = cfg->conn;
session = NULL;
ret = 0;
@@ -1135,7 +1119,7 @@ populate_async(void *arg)
value_buf = thread->value_buf;
if ((ret = conn->open_session(
- conn, NULL, cfg->sess_config, &session)) != 0) {
+ conn, NULL, opts->sess_config, &session)) != 0) {
lprintf(cfg, ret, 0, "populate: WT_CONNECTION.open_session");
goto err;
}
@@ -1146,8 +1130,8 @@ populate_async(void *arg)
* the time to process by workers.
*/
measure_latency =
- cfg->sample_interval != 0 &&
- trk->ops != 0 && (trk->ops % cfg->sample_rate == 0);
+ opts->sample_interval != 0 &&
+ trk->ops != 0 && (trk->ops % opts->sample_rate == 0);
if (measure_latency && (ret = __wt_epoch(NULL, &start)) != 0) {
lprintf(cfg, ret, 0, "Get time call failed");
goto err;
@@ -1155,7 +1139,7 @@ populate_async(void *arg)
/* Populate the databases. */
for (;;) {
op = get_next_incr(cfg);
- if (op > cfg->icount)
+ if (op > opts->icount)
break;
/*
* Allocate an async op for whichever table.
@@ -1170,7 +1154,7 @@ populate_async(void *arg)
asyncop->app_private = thread;
generate_key(cfg, key_buf, op);
asyncop->set_key(asyncop, key_buf);
- if (cfg->random_value)
+ if (opts->random_value)
randomize_value(thread, value_buf);
asyncop->set_value(asyncop, value_buf);
if ((ret = asyncop->insert(asyncop)) != 0) {
@@ -1204,7 +1188,7 @@ populate_async(void *arg)
/* Notify our caller we failed and shut the system down. */
if (0) {
-err: cfg->error = cfg->stop = 1;
+err: cfg->error = cfg->stop = true;
}
return (NULL);
}
@@ -1215,6 +1199,7 @@ monitor(void *arg)
struct timespec t;
struct tm *tm, _tm;
CONFIG *cfg;
+ CONFIG_OPTS *opts;
FILE *fp;
size_t len;
uint64_t min_thr, reads, inserts, updates;
@@ -1230,12 +1215,14 @@ monitor(void *arg)
char buf[64], *path;
cfg = (CONFIG *)arg;
- assert(cfg->sample_interval != 0);
+ opts = cfg->opts;
+ assert(opts->sample_interval != 0);
+
fp = NULL;
path = NULL;
- min_thr = (uint64_t)cfg->min_throughput;
- latency_max = (uint32_t)ms_to_us(cfg->max_latency);
+ min_thr = (uint64_t)opts->min_throughput;
+ latency_max = (uint32_t)ms_to_us(opts->max_latency);
/* Open the logging file. */
len = strlen(cfg->monitor_dir) + 100;
@@ -1266,7 +1253,7 @@ monitor(void *arg)
"\n");
last_reads = last_inserts = last_updates = 0;
while (!cfg->stop) {
- for (i = 0; i < cfg->sample_interval; i++) {
+ for (i = 0; i < opts->sample_interval; i++) {
sleep(1);
if (cfg->stop)
break;
@@ -1291,8 +1278,8 @@ monitor(void *arg)
latency_insert(cfg, &insert_avg, &insert_min, &insert_max);
latency_update(cfg, &update_avg, &update_min, &update_max);
- cur_reads = (reads - last_reads) / cfg->sample_interval;
- cur_updates = (updates - last_updates) / cfg->sample_interval;
+ cur_reads = (reads - last_reads) / opts->sample_interval;
+ cur_updates = (updates - last_updates) / opts->sample_interval;
/*
* For now the only item we need to worry about changing is
* inserts when we transition from the populate phase to
@@ -1302,7 +1289,7 @@ monitor(void *arg)
cur_inserts = 0;
else
cur_inserts =
- (inserts - last_inserts) / cfg->sample_interval;
+ (inserts - last_inserts) / opts->sample_interval;
(void)fprintf(fp,
"%s,%" PRIu32
@@ -1322,7 +1309,7 @@ monitor(void *arg)
if (latency_max != 0 &&
(read_max > latency_max || insert_max > latency_max ||
update_max > latency_max)) {
- if (cfg->max_latency_fatal) {
+ if (opts->max_latency_fatal) {
level = 1;
msg_err = WT_PANIC;
str = "ERROR";
@@ -1341,7 +1328,7 @@ monitor(void *arg)
((cur_reads != 0 && cur_reads < min_thr) ||
(cur_inserts != 0 && cur_inserts < min_thr) ||
(cur_updates != 0 && cur_updates < min_thr))) {
- if (cfg->min_throughput_fatal) {
+ if (opts->min_throughput_fatal) {
level = 1;
msg_err = WT_PANIC;
str = "ERROR";
@@ -1363,7 +1350,7 @@ monitor(void *arg)
/* Notify our caller we failed and shut the system down. */
if (0) {
-err: cfg->error = cfg->stop = 1;
+err: cfg->error = cfg->stop = true;
}
if (fp != NULL)
@@ -1377,6 +1364,7 @@ static void *
checkpoint_worker(void *arg)
{
CONFIG *cfg;
+ CONFIG_OPTS *opts;
CONFIG_THREAD *thread;
WT_CONNECTION *conn;
WT_SESSION *session;
@@ -1386,11 +1374,12 @@ checkpoint_worker(void *arg)
thread = (CONFIG_THREAD *)arg;
cfg = thread->cfg;
+ opts = cfg->opts;
conn = cfg->conn;
session = NULL;
if ((ret = conn->open_session(
- conn, NULL, cfg->sess_config, &session)) != 0) {
+ conn, NULL, opts->sess_config, &session)) != 0) {
lprintf(cfg, ret, 0,
"open_session failed in checkpoint thread.");
goto err;
@@ -1398,7 +1387,7 @@ checkpoint_worker(void *arg)
while (!cfg->stop) {
/* Break the sleep up, so we notice interrupts faster. */
- for (i = 0; i < cfg->checkpoint_interval; i++) {
+ for (i = 0; i < opts->checkpoint_interval; i++) {
sleep(1);
if (cfg->stop)
break;
@@ -1411,12 +1400,12 @@ checkpoint_worker(void *arg)
lprintf(cfg, ret, 0, "Get time failed in checkpoint.");
goto err;
}
- cfg->ckpt = 1;
+ cfg->ckpt = true;
if ((ret = session->checkpoint(session, NULL)) != 0) {
lprintf(cfg, ret, 0, "Checkpoint failed.");
goto err;
}
- cfg->ckpt = 0;
+ cfg->ckpt = false;
++thread->ckpt.ops;
if ((ret = __wt_epoch(NULL, &e)) != 0) {
@@ -1434,7 +1423,7 @@ checkpoint_worker(void *arg)
/* Notify our caller we failed and shut the system down. */
if (0) {
-err: cfg->error = cfg->stop = 1;
+err: cfg->error = cfg->stop = true;
}
return (NULL);
@@ -1444,6 +1433,7 @@ static int
execute_populate(CONFIG *cfg)
{
struct timespec start, stop;
+ CONFIG_OPTS *opts;
CONFIG_THREAD *popth;
WT_ASYNC_OP *asyncop;
pthread_t idle_table_cycle_thread;
@@ -1454,10 +1444,12 @@ execute_populate(CONFIG *cfg)
int elapsed, ret;
void *(*pfunc)(void *);
+ opts = cfg->opts;
+
lprintf(cfg, 0, 1,
"Starting %" PRIu32
" populate thread(s) for %" PRIu32 " items",
- cfg->populate_threads, cfg->icount);
+ opts->populate_threads, opts->icount);
/* Start cycling idle tables if configured. */
if ((ret = start_idle_table_cycle(cfg, &idle_table_cycle_thread)) != 0)
@@ -1465,15 +1457,16 @@ execute_populate(CONFIG *cfg)
cfg->insert_key = 0;
- cfg->popthreads = dcalloc(cfg->populate_threads, sizeof(CONFIG_THREAD));
- if (cfg->use_asyncops > 0) {
+ cfg->popthreads =
+ dcalloc(opts->populate_threads, sizeof(CONFIG_THREAD));
+ if (cfg->use_asyncops) {
lprintf(cfg, 0, 1, "Starting %" PRIu32 " async thread(s)",
- cfg->async_threads);
+ opts->async_threads);
pfunc = populate_async;
} else
pfunc = populate_thread;
if ((ret = start_threads(cfg, NULL,
- cfg->popthreads, cfg->populate_threads, pfunc)) != 0)
+ cfg->popthreads, opts->populate_threads, pfunc)) != 0)
return (ret);
if ((ret = __wt_epoch(NULL, &start)) != 0) {
@@ -1481,26 +1474,26 @@ execute_populate(CONFIG *cfg)
return (ret);
}
for (elapsed = 0, interval = 0, last_ops = 0;
- cfg->insert_key < cfg->icount && cfg->error == 0;) {
+ cfg->insert_key < opts->icount && !cfg->error;) {
/*
* Sleep for 100th of a second, report_interval is in second
* granularity, each 100th increment of elapsed is a single
* increment of interval.
*/
(void)usleep(10000);
- if (cfg->report_interval == 0 || ++elapsed < 100)
+ if (opts->report_interval == 0 || ++elapsed < 100)
continue;
elapsed = 0;
- if (++interval < cfg->report_interval)
+ if (++interval < opts->report_interval)
continue;
interval = 0;
- cfg->totalsec += cfg->report_interval;
+ cfg->totalsec += opts->report_interval;
cfg->insert_ops = sum_pop_ops(cfg);
lprintf(cfg, 0, 1,
"%" PRIu64 " populate inserts (%" PRIu64 " of %"
PRIu32 ") in %" PRIu32 " secs (%" PRIu32 " total secs)",
cfg->insert_ops - last_ops, cfg->insert_ops,
- cfg->icount, cfg->report_interval, cfg->totalsec);
+ opts->icount, opts->report_interval, cfg->totalsec);
last_ops = cfg->insert_ops;
}
if ((ret = __wt_epoch(NULL, &stop)) != 0) {
@@ -1516,19 +1509,19 @@ execute_populate(CONFIG *cfg)
*/
popth = cfg->popthreads;
cfg->popthreads = NULL;
- ret = stop_threads(cfg, cfg->populate_threads, popth);
+ ret = stop_threads(cfg, opts->populate_threads, popth);
free(popth);
if (ret != 0)
return (ret);
/* Report if any worker threads didn't finish. */
- if (cfg->error != 0) {
+ if (cfg->error) {
lprintf(cfg, WT_ERROR, 0,
"Populate thread(s) exited without finishing.");
return (WT_ERROR);
}
- lprintf(cfg, 0, 1, "Finished load of %" PRIu32 " items", cfg->icount);
+ lprintf(cfg, 0, 1, "Finished load of %" PRIu32 " items", opts->icount);
msecs = WT_TIMEDIFF_MS(stop, start);
/*
@@ -1540,7 +1533,7 @@ execute_populate(CONFIG *cfg)
print_ops_sec = 0;
} else {
print_secs = (double)msecs / (double)MSEC_PER_SEC;
- print_ops_sec = (uint64_t)(cfg->icount / print_secs);
+ print_ops_sec = (uint64_t)(opts->icount / print_secs);
}
lprintf(cfg, 0, 1,
"Load time: %.2f\n" "load ops/sec: %" PRIu64,
@@ -1551,15 +1544,15 @@ execute_populate(CONFIG *cfg)
* set an unlimited timeout because if we close the connection
* then any in-progress compact/merge is aborted.
*/
- if (cfg->compact) {
- assert(cfg->async_threads > 0);
+ if (opts->compact) {
+ assert(opts->async_threads > 0);
lprintf(cfg, 0, 1, "Compact after populate");
if ((ret = __wt_epoch(NULL, &start)) != 0) {
lprintf(cfg, ret, 0, "Get time failed in populate.");
return (ret);
}
- tables = cfg->table_count;
- for (i = 0; i < cfg->table_count; i++) {
+ tables = opts->table_count;
+ for (i = 0; i < opts->table_count; i++) {
/*
* If no ops are available, retry. Any other error,
* return.
@@ -1600,9 +1593,12 @@ execute_populate(CONFIG *cfg)
static int
close_reopen(CONFIG *cfg)
{
+ CONFIG_OPTS *opts;
int ret;
- if (!cfg->readonly && !cfg->reopen_connection)
+ opts = cfg->opts;
+
+ if (!opts->readonly && !opts->reopen_connection)
return (0);
/*
* Reopen the connection. We do this so that the workload phase always
@@ -1628,7 +1624,7 @@ close_reopen(CONFIG *cfg)
* threads looking for work that will never arrive don't affect
* performance.
*/
- if (cfg->compact && cfg->use_asyncops == 0) {
+ if (opts->compact && !cfg->use_asyncops) {
if ((ret = cfg->conn->reconfigure(
cfg->conn, "async=(enabled=false)")) != 0) {
lprintf(cfg, ret, 0, "Reconfigure async off failed");
@@ -1641,6 +1637,7 @@ close_reopen(CONFIG *cfg)
static int
execute_workload(CONFIG *cfg)
{
+ CONFIG_OPTS *opts;
CONFIG_THREAD *threads;
WORKLOAD *workp;
WT_CONNECTION *conn;
@@ -1653,6 +1650,8 @@ execute_workload(CONFIG *cfg)
int ret, t_ret;
void *(*pfunc)(void *);
+ opts = cfg->opts;
+
cfg->insert_key = 0;
cfg->insert_ops = cfg->read_ops = cfg->truncate_ops = 0;
cfg->update_ops = 0;
@@ -1667,26 +1666,26 @@ execute_workload(CONFIG *cfg)
if ((ret = start_idle_table_cycle(cfg, &idle_table_cycle_thread)) != 0)
return (ret);
- if (cfg->warmup != 0)
- cfg->in_warmup = 1;
+ if (opts->warmup != 0)
+ cfg->in_warmup = true;
/* Allocate memory for the worker threads. */
cfg->workers = dcalloc((size_t)cfg->workers_cnt, sizeof(CONFIG_THREAD));
- if (cfg->use_asyncops > 0) {
+ if (cfg->use_asyncops) {
lprintf(cfg, 0, 1, "Starting %" PRIu32 " async thread(s)",
- cfg->async_threads);
+ opts->async_threads);
pfunc = worker_async;
} else
pfunc = worker;
- if (cfg->session_count_idle != 0) {
- sessions = dcalloc((size_t)cfg->session_count_idle,
+ if (opts->session_count_idle != 0) {
+ sessions = dcalloc((size_t)opts->session_count_idle,
sizeof(WT_SESSION *));
conn = cfg->conn;
- for (i = 0; i < cfg->session_count_idle; ++i)
- if ((ret = conn->open_session(
- conn, NULL, cfg->sess_config, &sessions[i])) != 0) {
+ for (i = 0; i < opts->session_count_idle; ++i)
+ if ((ret = conn->open_session(conn,
+ NULL, opts->sess_config, &sessions[i])) != 0) {
lprintf(cfg, ret, 0,
"execute_workload: idle open_session");
goto err;
@@ -1714,15 +1713,15 @@ execute_workload(CONFIG *cfg)
threads += workp->threads;
}
- if (cfg->warmup != 0) {
+ if (opts->warmup != 0) {
lprintf(cfg, 0, 1,
- "Waiting for warmup duration of %" PRIu32, cfg->warmup);
- sleep(cfg->warmup);
- cfg->in_warmup = 0;
+ "Waiting for warmup duration of %" PRIu32, opts->warmup);
+ sleep(opts->warmup);
+ cfg->in_warmup = false;
}
- for (interval = cfg->report_interval, run_time = cfg->run_time,
- run_ops = cfg->run_ops; cfg->error == 0;) {
+ for (interval = opts->report_interval,
+ run_time = opts->run_time, run_ops = opts->run_ops; !cfg->error;) {
/*
* Sleep for one second at a time.
* If we are tracking run time, check to see if we're done, and
@@ -1751,8 +1750,8 @@ execute_workload(CONFIG *cfg)
/* If writing out throughput information, see if it's time. */
if (interval == 0 || --interval > 0)
continue;
- interval = cfg->report_interval;
- cfg->totalsec += cfg->report_interval;
+ interval = opts->report_interval;
+ cfg->totalsec += opts->report_interval;
lprintf(cfg, 0, 1,
"%" PRIu64 " reads, %" PRIu64 " inserts, %" PRIu64
@@ -1763,7 +1762,7 @@ execute_workload(CONFIG *cfg)
cfg->update_ops - last_updates,
cfg->truncate_ops - last_truncates,
cfg->ckpt_ops - last_ckpts,
- cfg->report_interval, cfg->totalsec);
+ opts->report_interval, cfg->totalsec);
last_reads = cfg->read_ops;
last_inserts = cfg->insert_ops;
last_updates = cfg->update_ops;
@@ -1772,7 +1771,7 @@ execute_workload(CONFIG *cfg)
}
/* Notify the worker threads they are done. */
-err: cfg->stop = 1;
+err: cfg->stop = true;
/* Stop cycling idle tables. */
if ((ret = stop_idle_table_cycle(cfg, idle_table_cycle_thread)) != 0)
@@ -1783,12 +1782,12 @@ err: cfg->stop = 1;
ret = t_ret;
/* Drop tables if configured to and this isn't an error path */
- if (ret == 0 && cfg->drop_tables && (ret = drop_all_tables(cfg)) != 0)
+ if (ret == 0 && opts->drop_tables && (ret = drop_all_tables(cfg)) != 0)
lprintf(cfg, ret, 0, "Drop tables failed.");
free(sessions);
/* Report if any worker threads didn't finish. */
- if (cfg->error != 0) {
+ if (cfg->error) {
lprintf(cfg, WT_ERROR, 0,
"Worker thread(s) exited without finishing.");
if (ret == 0)
@@ -1804,6 +1803,7 @@ err: cfg->stop = 1;
static int
find_table_count(CONFIG *cfg)
{
+ CONFIG_OPTS *opts;
WT_CONNECTION *conn;
WT_CURSOR *cursor;
WT_SESSION *session;
@@ -1811,16 +1811,17 @@ find_table_count(CONFIG *cfg)
int ret, t_ret;
char *key;
+ opts = cfg->opts;
conn = cfg->conn;
max_icount = 0;
if ((ret = conn->open_session(
- conn, NULL, cfg->sess_config, &session)) != 0) {
+ conn, NULL, opts->sess_config, &session)) != 0) {
lprintf(cfg, ret, 0,
"find_table_count: open_session failed");
goto out;
}
- for (i = 0; i < cfg->table_count; i++) {
+ for (i = 0; i < opts->table_count; i++) {
if ((ret = session->open_cursor(session, cfg->uris[i],
NULL, NULL, &cursor)) != 0) {
lprintf(cfg, ret, 0,
@@ -1853,61 +1854,65 @@ err: if ((t_ret = session->close(session, NULL)) != 0) {
lprintf(cfg, ret, 0,
"find_table_count: session close failed");
}
- cfg->icount = max_icount;
+ opts->icount = max_icount;
out: return (ret);
}
/*
- * Populate the uri array if more than one table is being used.
+ * Populate the uri array.
*/
static void
create_uris(CONFIG *cfg)
{
- size_t base_uri_len;
+ CONFIG_OPTS *opts;
+ size_t len;
uint32_t i;
- char *uri;
- base_uri_len = strlen(cfg->base_uri);
- cfg->uris = dcalloc(cfg->table_count, sizeof(char *));
- for (i = 0; i < cfg->table_count; i++) {
- uri = cfg->uris[i] = dcalloc(base_uri_len + 6, 1);
- /*
- * If there is only one table, just use base name.
- */
- if (cfg->table_count == 1)
- memcpy(uri, cfg->base_uri, base_uri_len);
+ opts = cfg->opts;
+
+ cfg->uris = dcalloc(opts->table_count, sizeof(char *));
+ len = strlen("table:") + strlen(opts->table_name) + 20;
+ for (i = 0; i < opts->table_count; i++) {
+ /* If there is only one table, just use the base name. */
+ cfg->uris[i] = dmalloc(len);
+ if (opts->table_count == 1)
+ sprintf(cfg->uris[i], "table:%s", opts->table_name);
else
- sprintf(uri, "%s%05d", cfg->base_uri, i);
+ sprintf(
+ cfg->uris[i], "table:%s%05d", opts->table_name, i);
}
}
static int
create_tables(CONFIG *cfg)
{
+ CONFIG_OPTS *opts;
WT_SESSION *session;
size_t i;
int ret;
char buf[512];
+ opts = cfg->opts;
+
if ((ret = cfg->conn->open_session(
- cfg->conn, NULL, cfg->sess_config, &session)) != 0) {
+ cfg->conn, NULL, opts->sess_config, &session)) != 0) {
lprintf(cfg, ret, 0,
"Error opening a session on %s", cfg->home);
return (ret);
}
- for (i = 0; i < cfg->table_count_idle; i++) {
+ for (i = 0; i < opts->table_count_idle; i++) {
snprintf(buf, 512, "%s_idle%05d", cfg->uris[0], (int)i);
if ((ret = session->create(
- session, buf, cfg->table_config)) != 0) {
+ session, buf, opts->table_config)) != 0) {
lprintf(cfg, ret, 0,
"Error creating idle table %s", buf);
return (ret);
}
}
- for (i = 0; i < cfg->table_count; i++) {
- if (cfg->log_partial && i > 0) {
+ for (i = 0; i < opts->table_count; i++) {
+ if (opts->log_partial && i > 0) {
if (((ret = session->create(session,
cfg->uris[i], cfg->partial_config)) != 0)) {
lprintf(cfg, ret, 0,
@@ -1915,12 +1920,12 @@ create_tables(CONFIG *cfg)
return (ret);
}
} else if ((ret = session->create(
- session, cfg->uris[i], cfg->table_config)) != 0) {
+ session, cfg->uris[i], opts->table_config)) != 0) {
lprintf(cfg, ret, 0,
"Error creating table %s", cfg->uris[i]);
return (ret);
}
- if (cfg->index) {
+ if (opts->index) {
snprintf(buf, 512, "index:%s:val_idx",
cfg->uris[i] + strlen("table:"));
if ((ret = session->create(
@@ -1940,48 +1945,172 @@ create_tables(CONFIG *cfg)
return (0);
}
+/*
+ * config_copy --
+ * Create a new CONFIG structure as a duplicate of a previous one.
+ */
+static int
+config_copy(const CONFIG *src, CONFIG **retp)
+{
+ CONFIG *dest;
+ CONFIG_OPTS *opts;
+ size_t i;
+
+ opts = src->opts;
+
+ dest = dcalloc(1, sizeof(CONFIG));
+
+ if (src->home != NULL)
+ dest->home = dstrdup(src->home);
+ if (src->monitor_dir != NULL)
+ dest->monitor_dir = dstrdup(src->monitor_dir);
+ if (src->partial_config != NULL)
+ dest->partial_config = dstrdup(src->partial_config);
+ if (src->reopen_config != NULL)
+ dest->reopen_config = dstrdup(src->reopen_config);
+
+ if (src->uris != NULL) {
+ dest->uris = dcalloc(opts->table_count, sizeof(char *));
+ for (i = 0; i < opts->table_count; i++)
+ dest->uris[i] = dstrdup(src->uris[i]);
+ }
+
+ if (src->async_config != NULL)
+ dest->async_config = dstrdup(src->async_config);
+
+ dest->ckptthreads = NULL;
+ dest->popthreads = NULL;
+ dest->workers = NULL;
+
+ if (src->workload != NULL) {
+ dest->workload = dcalloc(WORKLOAD_MAX, sizeof(WORKLOAD));
+ memcpy(dest->workload,
+ src->workload, WORKLOAD_MAX * sizeof(WORKLOAD));
+ }
+
+ TAILQ_INIT(&dest->stone_head);
+
+ dest->opts = src->opts;
+
+ *retp = dest;
+ return (0);
+}
+
+/*
+ * config_free --
+ * Free any storage allocated in the CONFIG structure.
+ */
+static void
+config_free(CONFIG *cfg)
+{
+ CONFIG_OPTS *opts;
+ size_t i;
+
+ opts = cfg->opts;
+
+ free(cfg->home);
+ free(cfg->monitor_dir);
+ free(cfg->partial_config);
+ free(cfg->reopen_config);
+
+ if (cfg->uris != NULL) {
+ for (i = 0; i < opts->table_count; i++)
+ free(cfg->uris[i]);
+ free(cfg->uris);
+ }
+
+ free(cfg->async_config);
+
+ free(cfg->ckptthreads);
+ free(cfg->popthreads);
+
+ free(cfg->workers);
+ free(cfg->workload);
+
+ cleanup_truncate_config(cfg);
+}
+
+/*
+ * config_compress --
+ * Parse the compression configuration.
+ */
+static int
+config_compress(CONFIG *cfg)
+{
+ CONFIG_OPTS *opts;
+ int ret;
+ const char *s;
+
+ opts = cfg->opts;
+ ret = 0;
+
+ s = opts->compression;
+ if (strcmp(s, "none") == 0) {
+ cfg->compress_ext = NULL;
+ cfg->compress_table = NULL;
+ } else if (strcmp(s, "lz4") == 0) {
+#ifndef HAVE_BUILTIN_EXTENSION_LZ4
+ cfg->compress_ext = LZ4_EXT;
+#endif
+ cfg->compress_table = LZ4_BLK;
+ } else if (strcmp(s, "snappy") == 0) {
+#ifndef HAVE_BUILTIN_EXTENSION_SNAPPY
+ cfg->compress_ext = SNAPPY_EXT;
+#endif
+ cfg->compress_table = SNAPPY_BLK;
+ } else if (strcmp(s, "zlib") == 0) {
+#ifndef HAVE_BUILTIN_EXTENSION_ZLIB
+ cfg->compress_ext = ZLIB_EXT;
+#endif
+ cfg->compress_table = ZLIB_BLK;
+ } else {
+ fprintf(stderr,
+ "invalid compression configuration: %s\n", s);
+ ret = EINVAL;
+ }
+ return (ret);
+
+}
+
static int
start_all_runs(CONFIG *cfg)
{
CONFIG *next_cfg, **configs;
+ CONFIG_OPTS *opts;
pthread_t *threads;
- size_t home_len, i;
+ size_t i, len;
int ret, t_ret;
- char *new_home;
- ret = 0;
+ opts = cfg->opts;
configs = NULL;
+ ret = 0;
- if (cfg->database_count == 1)
+ if (opts->database_count == 1)
return (start_run(cfg));
/* Allocate an array to hold our config struct copies. */
- configs = dcalloc(cfg->database_count, sizeof(CONFIG *));
+ configs = dcalloc(opts->database_count, sizeof(CONFIG *));
/* Allocate an array to hold our thread IDs. */
- threads = dcalloc(cfg->database_count, sizeof(pthread_t));
+ threads = dcalloc(opts->database_count, sizeof(pthread_t));
- home_len = strlen(cfg->home);
- for (i = 0; i < cfg->database_count; i++) {
- next_cfg = dcalloc(1, sizeof(CONFIG));
- configs[i] = next_cfg;
- if ((ret = config_copy(next_cfg, cfg)) != 0)
+ len = strlen(cfg->home);
+ for (i = 0; i < opts->database_count; i++) {
+ if ((ret = config_copy(cfg, &next_cfg)) != 0)
goto err;
+ configs[i] = next_cfg;
/* Setup a unique home directory for each database. */
- new_home = dmalloc(home_len + 5);
- snprintf(new_home, home_len + 5, "%s/D%02d", cfg->home, (int)i);
- free(next_cfg->home);
- next_cfg->home = new_home;
+ next_cfg->home = dmalloc(len + 5);
+ snprintf(next_cfg->home,
+ len + 5, "%s/D%02d", cfg->home, (int)i);
/* If the monitor dir is default, update it too. */
- if (strcmp(cfg->monitor_dir, cfg->home) == 0) {
- free(next_cfg->monitor_dir);
- next_cfg->monitor_dir = dstrdup(new_home);
- }
+ if (strcmp(cfg->monitor_dir, cfg->home) == 0)
+ next_cfg->monitor_dir = dstrdup(next_cfg->home);
/* If creating the sub-database, recreate its home */
- if (cfg->create != 0)
+ if (opts->create != 0)
recreate_dir(next_cfg->home);
if ((ret = pthread_create(
@@ -1992,14 +2121,14 @@ start_all_runs(CONFIG *cfg)
}
/* Wait for threads to finish. */
- for (i = 0; i < cfg->database_count; i++)
+ for (i = 0; i < opts->database_count; i++)
if ((t_ret = pthread_join(threads[i], NULL)) != 0) {
lprintf(cfg, ret, 0, "Error joining thread");
if (ret == 0)
ret = t_ret;
}
-err: for (i = 0; i < cfg->database_count && configs[i] != NULL; i++) {
+err: for (i = 0; i < opts->database_count && configs[i] != NULL; i++) {
config_free(configs[i]);
free(configs[i]);
}
@@ -2025,11 +2154,13 @@ thread_run_wtperf(void *arg)
static int
start_run(CONFIG *cfg)
{
+ CONFIG_OPTS *opts;
pthread_t monitor_thread;
uint64_t total_ops;
uint32_t run_time;
int monitor_created, ret, t_ret;
+ opts = cfg->opts;
monitor_created = ret = 0;
/* [-Wconditional-uninitialized] */
memset(&monitor_thread, 0, sizeof(monitor_thread));
@@ -2038,7 +2169,7 @@ start_run(CONFIG *cfg)
goto err;
if ((ret = wiredtiger_open( /* Open the real connection. */
- cfg->home, NULL, cfg->conn_config, &cfg->conn)) != 0) {
+ cfg->home, NULL, opts->conn_config, &cfg->conn)) != 0) {
lprintf(cfg, ret, 0, "Error connecting to %s", cfg->home);
goto err;
}
@@ -2046,27 +2177,26 @@ start_run(CONFIG *cfg)
create_uris(cfg);
/* If creating, create the tables. */
- if (cfg->create != 0 && (ret = create_tables(cfg)) != 0)
+ if (opts->create != 0 && (ret = create_tables(cfg)) != 0)
goto err;
/* Start the monitor thread. */
- if (cfg->sample_interval != 0) {
+ if (opts->sample_interval != 0) {
if ((ret = pthread_create(
&monitor_thread, NULL, monitor, cfg)) != 0) {
- lprintf(
- cfg, ret, 0, "Error creating monitor thread.");
+ lprintf(cfg, ret, 0, "Error creating monitor thread.");
goto err;
}
monitor_created = 1;
}
/* If creating, populate the table. */
- if (cfg->create != 0 && execute_populate(cfg) != 0)
+ if (opts->create != 0 && execute_populate(cfg) != 0)
goto err;
/* Optional workload. */
if (cfg->workers_cnt != 0 &&
- (cfg->run_time != 0 || cfg->run_ops != 0)) {
+ (opts->run_time != 0 || opts->run_ops != 0)) {
/*
* If we have a workload, close and reopen the connection so
* that LSM can detect read-only workloads.
@@ -2075,18 +2205,18 @@ start_run(CONFIG *cfg)
goto err;
/* Didn't create, set insert count. */
- if (cfg->create == 0 && cfg->random_range == 0 &&
- find_table_count(cfg) != 0)
+ if (opts->create == 0 &&
+ opts->random_range == 0 && find_table_count(cfg) != 0)
goto err;
/* Start the checkpoint thread. */
- if (cfg->checkpoint_threads != 0) {
+ if (opts->checkpoint_threads != 0) {
lprintf(cfg, 0, 1,
"Starting %" PRIu32 " checkpoint thread(s)",
- cfg->checkpoint_threads);
+ opts->checkpoint_threads);
cfg->ckptthreads = dcalloc(
- cfg->checkpoint_threads, sizeof(CONFIG_THREAD));
+ opts->checkpoint_threads, sizeof(CONFIG_THREAD));
if (start_threads(cfg, NULL, cfg->ckptthreads,
- cfg->checkpoint_threads, checkpoint_worker) != 0)
+ opts->checkpoint_threads, checkpoint_worker) != 0)
goto err;
}
/* Execute the workload. */
@@ -2101,7 +2231,7 @@ start_run(CONFIG *cfg)
cfg->ckpt_ops = sum_ckpt_ops(cfg);
total_ops = cfg->read_ops + cfg->insert_ops + cfg->update_ops;
- run_time = cfg->run_time == 0 ? 1 : cfg->run_time;
+ run_time = opts->run_time == 0 ? 1 : opts->run_time;
lprintf(cfg, 0, 1,
"Executed %" PRIu64 " read operations (%" PRIu64
"%%) %" PRIu64 " ops/sec",
@@ -2135,7 +2265,7 @@ err: if (ret == 0)
}
/* Notify the worker threads they are done. */
- cfg->stop = 1;
+ cfg->stop = true;
if ((t_ret = stop_threads(cfg, 1, cfg->ckptthreads)) != 0)
if (ret == 0)
@@ -2157,12 +2287,13 @@ err: if (ret == 0)
}
if (ret == 0) {
- if (cfg->run_time == 0 && cfg->run_ops == 0)
+ if (opts->run_time == 0 && opts->run_ops == 0)
lprintf(cfg, 0, 1, "Run completed");
else
lprintf(cfg, 0, 1, "Run completed: %" PRIu32 " %s",
- cfg->run_time == 0 ? cfg->run_ops : cfg->run_time,
- cfg->run_time == 0 ? "operations" : "seconds");
+ opts->run_time == 0 ?
+ opts->run_ops : opts->run_time,
+ opts->run_time == 0 ? "operations" : "seconds");
}
if (cfg->logf != NULL) {
@@ -2178,32 +2309,55 @@ extern int __wt_optind, __wt_optreset;
extern char *__wt_optarg;
void (*custom_die)(void) = NULL;
+/*
+ * usage --
+ * wtperf usage print, no error.
+ */
+static void
+usage(void)
+{
+ printf("wtperf [-C config] "
+ "[-H mount] [-h home] [-O file] [-o option] [-T config]\n");
+ printf("\t-C <string> additional connection configuration\n");
+ printf("\t (added to option conn_config)\n");
+ printf("\t-H <mount> configure Helium volume mount point\n");
+ printf("\t-h <string> Wired Tiger home must exist, default WT_TEST\n");
+ printf("\t-O <file> file contains options as listed below\n");
+ printf("\t-o option=val[,option=val,...] set options listed below\n");
+ printf("\t-T <string> additional table configuration\n");
+ printf("\t (added to option table_config)\n");
+ printf("\n");
+ config_opt_usage();
+}
+
int
main(int argc, char *argv[])
{
CONFIG *cfg, _cfg;
+ CONFIG_OPTS *opts;
size_t req_len, sreq_len;
bool monitor_set;
int ch, ret;
- const char *opts = "C:h:m:O:o:T:";
+ const char *cmdflags = "C:h:m:O:o:T:";
const char *config_opts;
- char *cc_buf, *sess_cfg, *tc_buf, *user_cconfig, *user_tconfig;
-
- monitor_set = false;
- ret = 0;
- config_opts = NULL;
- cc_buf = sess_cfg = tc_buf = user_cconfig = user_tconfig = NULL;
+ char *cc_buf, *path, *sess_cfg, *tc_buf, *user_cconfig, *user_tconfig;
- /* Setup the default configuration values. */
+ /* The first CONFIG structure (from which all others are derived). */
cfg = &_cfg;
memset(cfg, 0, sizeof(*cfg));
- if (config_copy(cfg, &default_cfg))
- goto err;
cfg->home = dstrdup(DEFAULT_HOME);
cfg->monitor_dir = dstrdup(DEFAULT_MONITOR_DIR);
+ TAILQ_INIT(&cfg->stone_head);
+ config_opt_init(&cfg->opts);
+
+ opts = cfg->opts;
+ monitor_set = false;
+ ret = 0;
+ config_opts = NULL;
+ cc_buf = sess_cfg = tc_buf = user_cconfig = user_tconfig = NULL;
/* Do a basic validation of options, and home is needed before open. */
- while ((ch = __wt_getopt("wtperf", argc, argv, opts)) != EOF)
+ while ((ch = __wt_getopt("wtperf", argc, argv, cmdflags)) != EOF)
switch (ch) {
case 'C':
if (user_cconfig == NULL)
@@ -2259,16 +2413,16 @@ main(int argc, char *argv[])
/* Parse options that override values set via a configuration file. */
__wt_optreset = __wt_optind = 1;
- while ((ch = __wt_getopt("wtperf", argc, argv, opts)) != EOF)
+ while ((ch = __wt_getopt("wtperf", argc, argv, cmdflags)) != EOF)
switch (ch) {
case 'o':
/* Allow -o key=value */
- if (config_opt_line(cfg, __wt_optarg) != 0)
+ if (config_opt_str(cfg, __wt_optarg) != 0)
goto einval;
break;
}
- if (cfg->populate_threads == 0 && cfg->icount != 0) {
+ if (opts->populate_threads == 0 && opts->icount != 0) {
lprintf(cfg, 1, 0,
"Cannot have 0 populate threads when icount is set\n");
goto err;
@@ -2280,16 +2434,16 @@ main(int argc, char *argv[])
* If the user wants compaction, then we also enable async for
* the compact operation, but not for the workloads.
*/
- if (cfg->async_threads > 0) {
+ if (opts->async_threads > 0) {
if (F_ISSET(cfg, CFG_TRUNCATE)) {
lprintf(cfg, 1, 0, "Cannot run truncate and async\n");
goto err;
}
- cfg->use_asyncops = 1;
+ cfg->use_asyncops = true;
}
- if (cfg->compact && cfg->async_threads == 0)
- cfg->async_threads = 2;
- if (cfg->async_threads > 0) {
+ if (opts->compact && opts->async_threads == 0)
+ opts->async_threads = 2;
+ if (opts->async_threads > 0) {
/*
* The maximum number of async threads is two digits, so just
* use that to compute the space we need. Assume the default
@@ -2300,34 +2454,29 @@ main(int argc, char *argv[])
cfg->async_config = dmalloc(req_len);
snprintf(cfg->async_config, req_len,
",async=(enabled=true,threads=%" PRIu32 ")",
- cfg->async_threads);
+ opts->async_threads);
}
if ((ret = config_compress(cfg)) != 0)
goto err;
/* You can't have truncate on a random collection. */
- if (F_ISSET(cfg, CFG_TRUNCATE) && cfg->random_range) {
+ if (F_ISSET(cfg, CFG_TRUNCATE) && opts->random_range) {
lprintf(cfg, 1, 0, "Cannot run truncate and random_range\n");
goto err;
}
/* We can't run truncate with more than one table. */
- if (F_ISSET(cfg, CFG_TRUNCATE) && cfg->table_count > 1) {
+ if (F_ISSET(cfg, CFG_TRUNCATE) && opts->table_count > 1) {
lprintf(cfg, 1, 0, "Cannot truncate more than 1 table\n");
goto err;
}
- /* Build the URI from the table name. */
- req_len = strlen("table:") + strlen(cfg->table_name) + 2;
- cfg->base_uri = dmalloc(req_len);
- snprintf(cfg->base_uri, req_len, "table:%s", cfg->table_name);
-
/* Make stdout line buffered, so verbose output appears quickly. */
__wt_stream_set_line_buffer(stdout);
/* Concatenate non-default configuration strings. */
- if (cfg->verbose > 1 || user_cconfig != NULL ||
- cfg->session_count_idle > 0 || cfg->compress_ext != NULL ||
+ if (opts->verbose > 1 || user_cconfig != NULL ||
+ opts->session_count_idle > 0 || cfg->compress_ext != NULL ||
cfg->async_config != NULL) {
req_len = strlen(debug_cconfig) + 3;
if (user_cconfig != NULL)
@@ -2336,14 +2485,14 @@ main(int argc, char *argv[])
req_len += strlen(cfg->async_config);
if (cfg->compress_ext != NULL)
req_len += strlen(cfg->compress_ext);
- if (cfg->session_count_idle > 0) {
+ if (opts->session_count_idle > 0) {
sreq_len = strlen(",session_max=") + 6;
req_len += sreq_len;
sess_cfg = dmalloc(sreq_len);
snprintf(sess_cfg, sreq_len,
",session_max=%" PRIu32,
- cfg->session_count_idle + cfg->workers_cnt +
- cfg->populate_threads + 10);
+ opts->session_count_idle +
+ cfg->workers_cnt + opts->populate_threads + 10);
}
cc_buf = dmalloc(req_len);
/*
@@ -2352,81 +2501,82 @@ main(int argc, char *argv[])
snprintf(cc_buf, req_len, "%s%s%s%s%s%s%s",
cfg->async_config ? cfg->async_config : "",
cfg->compress_ext ? cfg->compress_ext : "",
- cfg->verbose > 1 && strlen(debug_cconfig) ? ",": "",
- cfg->verbose > 1 &&
+ opts->verbose > 1 && strlen(debug_cconfig) ? ",": "",
+ opts->verbose > 1 &&
strlen(debug_cconfig) ? debug_cconfig : "",
sess_cfg ? sess_cfg : "",
user_cconfig ? ",": "",
user_cconfig ? user_cconfig : "");
- if (strlen(cc_buf))
- if ((ret = config_opt_str(
- cfg, "conn_config", cc_buf)) != 0)
- goto err;
+ if (strlen(cc_buf) && (ret =
+ config_opt_name_value(cfg, "conn_config", cc_buf)) != 0)
+ goto err;
}
- if (cfg->verbose > 1 || cfg->index ||
+ if (opts->verbose > 1 || opts->index ||
user_tconfig != NULL || cfg->compress_table != NULL) {
req_len = strlen(debug_tconfig) + 3;
if (user_tconfig != NULL)
req_len += strlen(user_tconfig);
if (cfg->compress_table != NULL)
req_len += strlen(cfg->compress_table);
- if (cfg->index)
+ if (opts->index)
req_len += strlen(INDEX_COL_NAMES);
tc_buf = dmalloc(req_len);
/*
* This is getting hard to parse.
*/
snprintf(tc_buf, req_len, "%s%s%s%s%s%s",
- cfg->index ? INDEX_COL_NAMES : "",
+ opts->index ? INDEX_COL_NAMES : "",
cfg->compress_table ? cfg->compress_table : "",
- cfg->verbose > 1 && strlen(debug_tconfig) ? ",": "",
- cfg->verbose > 1 &&
+ opts->verbose > 1 && strlen(debug_tconfig) ? ",": "",
+ opts->verbose > 1 &&
strlen(debug_tconfig) ? debug_tconfig : "",
user_tconfig ? ",": "",
user_tconfig ? user_tconfig : "");
- if (strlen(tc_buf))
- if ((ret = config_opt_str(
- cfg, "table_config", tc_buf)) != 0)
- goto err;
+ if (strlen(tc_buf) && (ret =
+ config_opt_name_value(cfg, "table_config", tc_buf)) != 0)
+ goto err;
}
- if (cfg->log_partial && cfg->table_count > 1) {
- req_len = strlen(cfg->table_config) +
+ if (opts->log_partial && opts->table_count > 1) {
+ req_len = strlen(opts->table_config) +
strlen(LOG_PARTIAL_CONFIG) + 1;
cfg->partial_config = dmalloc(req_len);
snprintf(cfg->partial_config, req_len, "%s%s",
- cfg->table_config, LOG_PARTIAL_CONFIG);
+ opts->table_config, LOG_PARTIAL_CONFIG);
}
/*
* Set the config for reopen. If readonly add in that string.
* If not readonly then just copy the original conn_config.
*/
- if (cfg->readonly)
- req_len = strlen(cfg->conn_config) +
+ if (opts->readonly)
+ req_len = strlen(opts->conn_config) +
strlen(READONLY_CONFIG) + 1;
else
- req_len = strlen(cfg->conn_config) + 1;
+ req_len = strlen(opts->conn_config) + 1;
cfg->reopen_config = dmalloc(req_len);
- if (cfg->readonly)
+ if (opts->readonly)
snprintf(cfg->reopen_config, req_len, "%s%s",
- cfg->conn_config, READONLY_CONFIG);
+ opts->conn_config, READONLY_CONFIG);
else
- snprintf(cfg->reopen_config, req_len, "%s",
- cfg->conn_config);
+ snprintf(cfg->reopen_config, req_len, "%s", opts->conn_config);
/* Sanity-check the configuration. */
if ((ret = config_sanity(cfg)) != 0)
goto err;
/* If creating, remove and re-create the home directory. */
- if (cfg->create != 0)
+ if (opts->create != 0)
recreate_dir(cfg->home);
/* Write a copy of the config. */
- config_to_file(cfg);
+ req_len = strlen(cfg->home) + strlen("/CONFIG.wtperf") + 1;
+ path = dmalloc(req_len);
+ snprintf(path, req_len, "%s/CONFIG.wtperf", cfg->home);
+ config_opt_log(opts, path);
+ free(path);
/* Display the configuration. */
- if (cfg->verbose > 1)
- config_print(cfg);
+ if (opts->verbose > 1)
+ config_opt_print(cfg);
if ((ret = start_all_runs(cfg)) != 0)
goto err;
@@ -2436,6 +2586,8 @@ einval: ret = EINVAL;
}
err: config_free(cfg);
+ config_opt_cleanup(opts);
+
free(cc_buf);
free(sess_cfg);
free(tc_buf);
@@ -2449,10 +2601,13 @@ static int
start_threads(CONFIG *cfg,
WORKLOAD *workp, CONFIG_THREAD *base, u_int num, void *(*func)(void *))
{
+ CONFIG_OPTS *opts;
CONFIG_THREAD *thread;
u_int i;
int ret;
+ opts = cfg->opts;
+
/* Initialize the threads. */
for (i = 0, thread = base; i < num; ++i, ++thread) {
thread->cfg = cfg;
@@ -2473,14 +2628,14 @@ start_threads(CONFIG *cfg,
* don't, it's not enough memory to bother. These buffers hold
* strings: trailing NUL is included in the size.
*/
- thread->key_buf = dcalloc(cfg->key_sz, 1);
- thread->value_buf = dcalloc(cfg->value_sz_max, 1);
+ thread->key_buf = dcalloc(opts->key_sz, 1);
+ thread->value_buf = dcalloc(opts->value_sz_max, 1);
/*
* Initialize and then toss in a bit of random values if needed.
*/
- memset(thread->value_buf, 'a', cfg->value_sz - 1);
- if (cfg->random_value)
+ memset(thread->value_buf, 'a', opts->value_sz - 1);
+ if (opts->random_value)
randomize_value(thread, thread->value_buf);
/*
@@ -2552,22 +2707,24 @@ static int
drop_all_tables(CONFIG *cfg)
{
struct timespec start, stop;
+ CONFIG_OPTS *opts;
WT_SESSION *session;
size_t i;
uint64_t msecs;
int ret, t_ret;
+ opts = cfg->opts;
+
/* Drop any tables. */
if ((ret = cfg->conn->open_session(
- cfg->conn, NULL, cfg->sess_config, &session)) != 0) {
+ cfg->conn, NULL, opts->sess_config, &session)) != 0) {
lprintf(cfg, ret, 0,
"Error opening a session on %s", cfg->home);
return (ret);
}
testutil_check(__wt_epoch(NULL, &start));
- for (i = 0; i < cfg->table_count; i++) {
- if ((ret = session->drop(
- session, cfg->uris[i], NULL)) != 0) {
+ for (i = 0; i < opts->table_count; i++) {
+ if ((ret = session->drop(session, cfg->uris[i], NULL)) != 0) {
lprintf(cfg, ret, 0,
"Error dropping table %s", cfg->uris[i]);
goto err;
@@ -2577,7 +2734,7 @@ drop_all_tables(CONFIG *cfg)
msecs = WT_TIMEDIFF_MS(stop, start);
lprintf(cfg, 0, 1,
"Executed %" PRIu32 " drop operations average time %" PRIu64 "ms",
- cfg->table_count, msecs / cfg->table_count);
+ opts->table_count, msecs / opts->table_count);
err: if ((t_ret = session->close(session, NULL)) != 0 && ret == 0)
ret = t_ret;
@@ -2587,25 +2744,31 @@ err: if ((t_ret = session->close(session, NULL)) != 0 && ret == 0)
static uint64_t
wtperf_value_range(CONFIG *cfg)
{
- if (cfg->random_range)
- return (cfg->icount + cfg->random_range);
+ CONFIG_OPTS *opts;
+
+ opts = cfg->opts;
+
+ if (opts->random_range)
+ return (opts->icount + opts->random_range);
/*
* It is legal to configure a zero size populate phase, hide that
* from other code by pretending the range is 1 in that case.
*/
- if (cfg->icount + cfg->insert_key == 0)
+ if (opts->icount + cfg->insert_key == 0)
return (1);
- return (cfg->icount + cfg->insert_key - (u_int)(cfg->workers_cnt + 1));
+ return (opts->icount + cfg->insert_key - (u_int)(cfg->workers_cnt + 1));
}
static uint64_t
wtperf_rand(CONFIG_THREAD *thread)
{
CONFIG *cfg;
+ CONFIG_OPTS *opts;
double S1, S2, U;
uint64_t rval;
cfg = thread->cfg;
+ opts = cfg->opts;
/*
* Use WiredTiger's random number routine: it's lock-free and fairly
@@ -2614,11 +2777,11 @@ wtperf_rand(CONFIG_THREAD *thread)
rval = __wt_random(&thread->rnd);
/* Use Pareto distribution to give 80/20 hot/cold values. */
- if (cfg->pareto != 0) {
+ if (opts->pareto != 0) {
#define PARETO_SHAPE 1.5
S1 = (-1 / PARETO_SHAPE);
S2 = wtperf_value_range(cfg) *
- (cfg->pareto / 100.0) * (PARETO_SHAPE - 1);
+ (opts->pareto / 100.0) * (PARETO_SHAPE - 1);
U = 1 - (double)rval / (double)UINT32_MAX;
rval = (uint64_t)((pow(U, S1) - 1) * S2);
/*
diff --git a/bench/wtperf/wtperf.h b/bench/wtperf/wtperf.h
index 9d6ef2f56ea..b3e173eb37e 100644
--- a/bench/wtperf/wtperf.h
+++ b/bench/wtperf/wtperf.h
@@ -95,12 +95,6 @@ struct __truncate_queue_entry {
TAILQ_ENTRY(__truncate_queue_entry) q;
};
-struct __config_queue_entry {
- char *string;
- TAILQ_ENTRY(__config_queue_entry) c;
-};
-typedef struct __config_queue_entry CONFIG_QUEUE_ENTRY;
-
/* Steering for the throttle configuration */
typedef struct {
struct timespec last_increment; /* Time that we last added more ops */
@@ -120,14 +114,14 @@ struct __config { /* Configuration structure */
char *monitor_dir; /* Monitor output dir */
char *partial_config; /* Config string for partial logging */
char *reopen_config; /* Config string for conn reopen */
- char *base_uri; /* Object URI */
- char **uris; /* URIs if multiple tables */
+ char **uris; /* URIs */
WT_CONNECTION *conn; /* Database connection */
FILE *logf; /* Logging handle */
- char *async_config; /* Config string for async */
+ char *async_config; /* Config string for async */
+ bool use_asyncops; /* Use async operations */
const char *compress_ext; /* Compression extension for conn */
const char *compress_table; /* Compression arg to table create */
@@ -141,9 +135,7 @@ struct __config { /* Configuration structure */
WORKLOAD *workload; /* Workloads */
u_int workload_cnt;
- uint32_t use_asyncops; /* Use async operations */
/* State tracking variables. */
-
uint64_t ckpt_ops; /* checkpoint operations */
uint64_t insert_ops; /* insert operations */
uint64_t read_ops; /* read operations */
@@ -152,10 +144,10 @@ struct __config { /* Configuration structure */
uint64_t insert_key; /* insert key */
- volatile int ckpt; /* checkpoint in progress */
- volatile int error; /* thread error */
- volatile int stop; /* notify threads to stop */
- volatile int in_warmup; /* Running warmup phase */
+ volatile bool ckpt; /* checkpoint in progress */
+ volatile bool error; /* thread error */
+ volatile bool stop; /* notify threads to stop */
+ volatile bool in_warmup; /* running warmup phase */
volatile bool idle_cycle_run; /* Signal for idle cycle thread */
@@ -169,13 +161,7 @@ struct __config { /* Configuration structure */
/* Queue head for use with the Truncate Logic */
TAILQ_HEAD(__truncate_qh, __truncate_queue_entry) stone_head;
- /* Queue head to save a copy of the config to be output */
- TAILQ_HEAD(__config_qh, __config_queue_entry) config_head;
-
- /* Fields changeable on command line are listed in wtperf_opt.i */
-#define OPT_DECLARE_STRUCT
-#include "wtperf_opt.i"
-#undef OPT_DECLARE_STRUCT
+ CONFIG_OPTS *opts; /* Global configuration */
};
#define ELEMENTS(a) (sizeof(a) / sizeof(a[0]))
@@ -259,35 +245,33 @@ struct __config_thread { /* Per-thread structure */
};
void cleanup_truncate_config(CONFIG *);
-int config_compress(CONFIG *);
-void config_free(CONFIG *);
-int config_copy(CONFIG *, const CONFIG *);
int config_opt_file(CONFIG *, const char *);
-int config_opt_line(CONFIG *, const char *);
-int config_opt_str(CONFIG *, const char *, const char *);
-void config_to_file(CONFIG *);
-void config_consolidate(CONFIG *);
-void config_print(CONFIG *);
+void config_opt_cleanup(CONFIG_OPTS *);
+void config_opt_init(CONFIG_OPTS **);
+void config_opt_log(CONFIG_OPTS *, const char *);
+int config_opt_name_value(CONFIG *, const char *, const char *);
+void config_opt_print(CONFIG *);
+int config_opt_str(CONFIG *, const char *);
+void config_opt_usage(void);
int config_sanity(CONFIG *);
void latency_insert(CONFIG *, uint32_t *, uint32_t *, uint32_t *);
+void latency_print(CONFIG *);
void latency_read(CONFIG *, uint32_t *, uint32_t *, uint32_t *);
void latency_update(CONFIG *, uint32_t *, uint32_t *, uint32_t *);
-void latency_print(CONFIG *);
int run_truncate(
- CONFIG *, CONFIG_THREAD *, WT_CURSOR *, WT_SESSION *, int *);
+ CONFIG *, CONFIG_THREAD *, WT_CURSOR *, WT_SESSION *, int *);
int setup_log_file(CONFIG *);
void setup_throttle(CONFIG_THREAD*);
int setup_truncate(CONFIG *, CONFIG_THREAD *, WT_SESSION *);
int start_idle_table_cycle(CONFIG *, pthread_t *);
int stop_idle_table_cycle(CONFIG *, pthread_t);
+void worker_throttle(CONFIG_THREAD*);
uint64_t sum_ckpt_ops(CONFIG *);
uint64_t sum_insert_ops(CONFIG *);
uint64_t sum_pop_ops(CONFIG *);
uint64_t sum_read_ops(CONFIG *);
uint64_t sum_truncate_ops(CONFIG *);
uint64_t sum_update_ops(CONFIG *);
-void usage(void);
-void worker_throttle(CONFIG_THREAD*);
void lprintf(const CONFIG *, int err, uint32_t, const char *, ...)
#if defined(__GNUC__)
@@ -298,10 +282,14 @@ __attribute__((format (printf, 4, 5)))
static inline void
generate_key(CONFIG *cfg, char *key_buf, uint64_t keyno)
{
+ CONFIG_OPTS *opts;
+
+ opts = cfg->opts;
+
/*
* Don't change to snprintf, sprintf is faster in some tests.
*/
- sprintf(key_buf, "%0*" PRIu64, cfg->key_sz - 1, keyno);
+ sprintf(key_buf, "%0*" PRIu64, opts->key_sz - 1, keyno);
}
static inline void
diff --git a/bench/wtperf/wtperf_opt.i b/bench/wtperf/wtperf_opt.i
index f1f26bd0d01..9db71f5dd69 100644
--- a/bench/wtperf/wtperf_opt.i
+++ b/bench/wtperf/wtperf_opt.i
@@ -38,14 +38,14 @@
#ifdef OPT_DEFINE_DESC
#define DEF_OPT_AS_BOOL(name, initval, desc) \
- { #name, desc, #initval, BOOL_TYPE, offsetof(CONFIG, name) },
+ { #name, desc, #initval, BOOL_TYPE, offsetof(CONFIG_OPTS, name) },
#define DEF_OPT_AS_CONFIG_STRING(name, initval, desc) \
{ #name, desc, initval, CONFIG_STRING_TYPE, \
- offsetof(CONFIG, name) },
+ offsetof(CONFIG_OPTS, name) },
#define DEF_OPT_AS_STRING(name, initval, desc) \
- { #name, desc, initval, STRING_TYPE, offsetof(CONFIG, name) },
+ { #name, desc, initval, STRING_TYPE, offsetof(CONFIG_OPTS, name) },
#define DEF_OPT_AS_UINT32(name, initval, desc) \
- { #name, desc, #initval, UINT32_TYPE, offsetof(CONFIG, name) },
+ { #name, desc, #initval, UINT32_TYPE, offsetof(CONFIG_OPTS, name) },
#endif
#ifdef OPT_DEFINE_DEFAULT
diff --git a/bench/wtperf/wtperf_truncate.c b/bench/wtperf/wtperf_truncate.c
index e6ebc83c681..aac79b4b96d 100644
--- a/bench/wtperf/wtperf_truncate.c
+++ b/bench/wtperf/wtperf_truncate.c
@@ -35,8 +35,9 @@ decode_key(char *key_buf)
}
int
-setup_truncate(CONFIG *cfg, CONFIG_THREAD *thread, WT_SESSION *session) {
-
+setup_truncate(CONFIG *cfg, CONFIG_THREAD *thread, WT_SESSION *session)
+{
+ CONFIG_OPTS *opts;
TRUNCATE_CONFIG *trunc_cfg;
TRUNCATE_QUEUE_ENTRY *truncate_item;
WORKLOAD *workload;
@@ -45,6 +46,7 @@ setup_truncate(CONFIG *cfg, CONFIG_THREAD *thread, WT_SESSION *session) {
int ret;
uint64_t end_point, final_stone_gap, i, start_point;
+ opts = cfg->opts;
end_point = final_stone_gap = start_point = 0;
trunc_cfg = &thread->trunc_cfg;
workload = thread->workload;
@@ -104,7 +106,7 @@ setup_truncate(CONFIG *cfg, CONFIG_THREAD *thread, WT_SESSION *session) {
for (i = 1; i <= trunc_cfg->needed_stones; i++) {
truncate_item =
dcalloc(sizeof(TRUNCATE_QUEUE_ENTRY), 1);
- truncate_item->key = dcalloc(cfg->key_sz, 1);
+ truncate_item->key = dcalloc(opts->key_sz, 1);
generate_key(
cfg, truncate_item->key, trunc_cfg->stone_gap * i);
truncate_item->diff =
@@ -124,16 +126,18 @@ err: if ((ret = cursor->close(cursor)) != 0) {
int
run_truncate(CONFIG *cfg, CONFIG_THREAD *thread,
- WT_CURSOR *cursor, WT_SESSION *session, int *truncatedp) {
-
+ WT_CURSOR *cursor, WT_SESSION *session, int *truncatedp)
+{
+ CONFIG_OPTS *opts;
TRUNCATE_CONFIG *trunc_cfg;
TRUNCATE_QUEUE_ENTRY *truncate_item;
char *next_key;
int ret, t_ret;
uint64_t used_stone_gap;
- ret = 0;
+ opts = cfg->opts;
trunc_cfg = &thread->trunc_cfg;
+ ret = 0;
*truncatedp = 0;
/* Update the total inserts */
@@ -170,7 +174,7 @@ run_truncate(CONFIG *cfg, CONFIG_THREAD *thread,
while (trunc_cfg->num_stones < trunc_cfg->needed_stones) {
trunc_cfg->last_key += used_stone_gap;
truncate_item = dcalloc(sizeof(TRUNCATE_QUEUE_ENTRY), 1);
- truncate_item->key = dcalloc(cfg->key_sz, 1);
+ truncate_item->key = dcalloc(opts->key_sz, 1);
generate_key(cfg, truncate_item->key, trunc_cfg->last_key);
truncate_item->diff = used_stone_gap;
TAILQ_INSERT_TAIL(&cfg->stone_head, truncate_item, q);
@@ -190,7 +194,7 @@ run_truncate(CONFIG *cfg, CONFIG_THREAD *thread,
* Truncate the content via a single truncate call or a cursor walk
* depending on the configuration.
*/
- if (cfg->truncate_single_ops) {
+ if (opts->truncate_single_ops) {
while ((ret = cursor->next(cursor)) == 0) {
testutil_check(cursor->get_key(cursor, &next_key));
if (strcmp(next_key, truncate_item->key) == 0)