summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Bostic <keith@wiredtiger.com>2013-11-20 08:57:55 -0500
committerKeith Bostic <keith@wiredtiger.com>2013-11-20 08:57:55 -0500
commit3e5ad346eaf0a8eaf8d2461f7ccbcacfae7e68c5 (patch)
treebdf45c879933dff522964b74afb3a326689bfe4a
parentaac0acc84db32f53aa25a91a1b1e03874c577795 (diff)
downloadmongo-3e5ad346eaf0a8eaf8d2461f7ccbcacfae7e68c5.tar.gz
Split wtperf up by moving configuration functions into their own file.
-rw-r--r--bench/wtperf/Makefile.am4
-rw-r--r--bench/wtperf/config.c442
-rw-r--r--bench/wtperf/misc.c110
-rw-r--r--bench/wtperf/wtperf.c686
-rw-r--r--bench/wtperf/wtperf.h103
5 files changed, 705 insertions, 640 deletions
diff --git a/bench/wtperf/Makefile.am b/bench/wtperf/Makefile.am
index e4ff8f11059..6e22be13a91 100644
--- a/bench/wtperf/Makefile.am
+++ b/bench/wtperf/Makefile.am
@@ -4,6 +4,8 @@ LDADD = $(top_builddir)/libwiredtiger.la -lm
noinst_PROGRAMS = wtperf
wtperf_LDFLAGS = -static
+wtperf_SOURCES =\
+ config.c misc.c wtperf.c wtperf.h wtperf_opt.i
# The benchmark can be run with no arguments as simple smoke tests
TESTS = $(noinst_PROGRAMS)
@@ -11,4 +13,4 @@ TESTS = $(noinst_PROGRAMS)
TESTS_ENVIRONMENT = rm -rf WT_TEST ; mkdir WT_TEST ;
clean-local:
- rm -rf WT_TEST
+ rm -rf WT_TEST *.core
diff --git a/bench/wtperf/config.c b/bench/wtperf/config.c
new file mode 100644
index 00000000000..2bad1cf7b16
--- /dev/null
+++ b/bench/wtperf/config.c
@@ -0,0 +1,442 @@
+/*-
+ * Public Domain 2008-2013 WiredTiger, Inc.
+ *
+ * This is free and unencumbered software released into the public domain.
+ *
+ * Anyone is free to copy, modify, publish, use, compile, sell, or
+ * distribute this software, either in source code form or as a compiled
+ * binary, for any purpose, commercial or non-commercial, and by any
+ * means.
+ *
+ * In jurisdictions that recognize copyright laws, the author or authors
+ * of this software dedicate any and all copyright interest in the
+ * software to the public domain. We make this dedication for the benefit
+ * of the public at large and to the detriment of our heirs and
+ * successors. We intend this dedication to be an overt act of
+ * relinquishment in perpetuity of all present and future rights to this
+ * software under copyright law.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "wtperf.h"
+
+/* All options changeable on command line using -o or -O are listed here. */
+static CONFIG_OPT config_opts[] = {
+#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);
+
+/* Assign the src config to the dest.
+ * Any storage allocated in dest is freed as a result.
+ */
+int
+config_assign(CONFIG *dest, const CONFIG *src)
+{
+ size_t i, len;
+ char *newstr, **pstr;
+
+ config_free(dest);
+ memcpy(dest, src, sizeof(CONFIG));
+
+ 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) {
+ len = strlen(*pstr) + 1;
+ if ((newstr = malloc(len)) == NULL)
+ return (enomem(src));
+ strncpy(newstr, *pstr, len);
+ *pstr = newstr;
+ }
+ }
+ return (0);
+}
+
+/* Free any storage allocated in the config struct.
+ */
+void
+config_free(CONFIG *cfg)
+{
+ size_t i;
+ char **pstr;
+
+ 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 **)
+ ((unsigned char *)cfg + config_opts[i].offset);
+ if (*pstr != NULL) {
+ free(*pstr);
+ *pstr = NULL;
+ }
+ }
+
+ free(cfg->uri);
+}
+
+/*
+ * Check a single key=value returned by the config parser
+ * against our table of valid keys, along with the expected type.
+ * If everything is okay, set the value.
+ */
+static int
+config_opt(CONFIG *cfg, WT_CONFIG_ITEM *k, WT_CONFIG_ITEM *v)
+{
+ CONFIG_OPT *popt;
+ char *newstr, **strp;
+ size_t i, nopt;
+ uint64_t 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];
+ break;
+ }
+ if (popt == 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);
+ return (EINVAL);
+ }
+ valueloc = ((unsigned char *)cfg + popt->offset);
+ switch (popt->type) {
+ case BOOL_TYPE:
+ if (v->type != WT_CONFIG_ITEM_BOOL) {
+ fprintf(stderr, "wtperf: Error: "
+ "bad bool value for \'%.*s=%.*s\'\n",
+ (int)k->len, k->str, (int)v->len, v->str);
+ return (EINVAL);
+ }
+ *(int *)valueloc = (int)v->val;
+ break;
+ case INT_TYPE:
+ if (v->type != WT_CONFIG_ITEM_NUM) {
+ fprintf(stderr, "wtperf: Error: "
+ "bad int value for \'%.*s=%.*s\'\n",
+ (int)k->len, k->str, (int)v->len, v->str);
+ return (EINVAL);
+ }
+ if (v->val > INT_MAX) {
+ fprintf(stderr, "wtperf: Error: "
+ "int value out of range for \'%.*s=%.*s\'\n",
+ (int)k->len, k->str, (int)v->len, v->str);
+ return (EINVAL);
+ }
+ *(int *)valueloc = (int)v->val;
+ break;
+ case UINT32_TYPE:
+ if (v->type != WT_CONFIG_ITEM_NUM) {
+ fprintf(stderr, "wtperf: Error: "
+ "bad uint32 value for \'%.*s=%.*s\'\n",
+ (int)k->len, k->str, (int)v->len, v->str);
+ return (EINVAL);
+ }
+ if (v->val < 0 || v->val > UINT_MAX) {
+ fprintf(stderr, "wtperf: Error: "
+ "uint32 value out of range for \'%.*s=%.*s\'\n",
+ (int)k->len, k->str, (int)v->len, v->str);
+ return (EINVAL);
+ }
+ *(uint32_t *)valueloc = (uint32_t)v->val;
+ break;
+ case CONFIG_STRING_TYPE:
+ if (v->type != WT_CONFIG_ITEM_STRING) {
+ fprintf(stderr, "wtperf: Error: "
+ "bad string value for \'%.*s=%.*s\'\n",
+ (int)k->len, k->str, (int)v->len, v->str);
+ return (EINVAL);
+ }
+ strp = (char **)valueloc;
+ newlen = v->len + 1;
+ if (*strp == NULL) {
+ if ((newstr = calloc(newlen, sizeof(char))) == NULL)
+ return (enomem(cfg));
+ strncpy(newstr, v->str, v->len);
+ } else {
+ newlen += (strlen(*strp) + 1);
+ if ((newstr = calloc(newlen, sizeof(char))) == NULL)
+ return (enomem(cfg));
+ snprintf(newstr, newlen,
+ "%s,%*s", *strp, (int)v->len, v->str);
+ /* Free the old value now we've copied it. */
+ free(*strp);
+ }
+ *strp = newstr;
+ break;
+ case STRING_TYPE:
+ if (v->type != WT_CONFIG_ITEM_STRING) {
+ fprintf(stderr, "wtperf: Error: "
+ "bad string value for \'%.*s=%.*s\'\n",
+ (int)k->len, k->str, (int)v->len, v->str);
+ return (EINVAL);
+ }
+ strp = (char **)valueloc;
+ free(*strp);
+ if ((newstr = malloc(v->len + 1)) == NULL)
+ return (enomem(cfg));
+ strncpy(newstr, v->str, v->len);
+ newstr[v->len] = '\0';
+ *strp = newstr;
+ break;
+ }
+ return (0);
+}
+
+/* Parse a configuration file.
+ * We recognize comments '#' and continuation via lines ending in '\'.
+ */
+int
+config_opt_file(CONFIG *cfg, WT_SESSION *parse_session, const char *filename)
+{
+ FILE *fp;
+ size_t linelen, optionpos;
+ int contline, linenum, ret;
+ char line[256], option[1024];
+ char *comment, *ltrim, *rtrim;
+
+ if ((fp = fopen(filename, "r")) == NULL) {
+ fprintf(stderr, "wtperf: %s: %s\n", filename, strerror(errno));
+ return (errno);
+ }
+
+ ret = 0;
+ optionpos = 0;
+ linenum = 0;
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ linenum++;
+ /* trim the line */
+ for (ltrim = line; *ltrim && isspace(*ltrim); ltrim++)
+ ;
+ rtrim = &ltrim[strlen(ltrim)];
+ if (rtrim > ltrim && rtrim[-1] == '\n')
+ rtrim--;
+
+ contline = (rtrim > ltrim && rtrim[-1] == '\\');
+ if (contline)
+ rtrim--;
+
+ comment = strchr(ltrim, '#');
+ if (comment != NULL && comment < rtrim)
+ rtrim = comment;
+ while (rtrim > ltrim && isspace(rtrim[-1]))
+ rtrim--;
+
+ linelen = (size_t)(rtrim - ltrim);
+ if (linelen == 0)
+ continue;
+
+ if (linelen + optionpos + 1 > sizeof(option)) {
+ fprintf(stderr, "wtperf: %s: %d: line overflow\n",
+ filename, linenum);
+ ret = EINVAL;
+ break;
+ }
+ *rtrim = '\0';
+ strncpy(&option[optionpos], ltrim, linelen);
+ option[optionpos + linelen] = '\0';
+ if (contline)
+ optionpos += linelen;
+ else {
+ if ((ret = config_opt_line(cfg,
+ parse_session, option)) != 0) {
+ fprintf(stderr, "wtperf: %s: %d: parse error\n",
+ filename, linenum);
+ break;
+ }
+ optionpos = 0;
+ }
+ }
+ if (ret == 0 && optionpos > 0) {
+ fprintf(stderr, "wtperf: %s: %d: last line continues\n",
+ filename, linenum);
+ ret = EINVAL;
+ }
+
+ (void)fclose(fp);
+ return (ret);
+}
+
+/* Parse a single line of config options.
+ * Continued lines have already been joined.
+ */
+int
+config_opt_line(CONFIG *cfg, WT_SESSION *parse_session, const char *optstr)
+{
+ WT_CONFIG_ITEM k, v;
+ WT_CONFIG_SCAN *scan;
+ WT_CONNECTION *conn;
+ WT_EXTENSION_API *wt_api;
+ int ret, t_ret;
+
+ conn = parse_session->connection;
+ wt_api = conn->get_extension_api(conn);
+
+ if ((ret = wt_api->config_scan_begin(wt_api, parse_session, optstr,
+ strlen(optstr), &scan)) != 0) {
+ lprintf(cfg, ret, 0, "Error in config_scan_begin");
+ return (ret);
+ }
+
+ while (ret == 0) {
+ if ((ret =
+ wt_api->config_scan_next(wt_api, scan, &k, &v)) != 0) {
+ /* Any parse error has already been reported. */
+ if (ret == WT_NOTFOUND)
+ ret = 0;
+ break;
+ }
+ ret = config_opt(cfg, &k, &v);
+ }
+ if ((t_ret = wt_api->config_scan_end(wt_api, scan)) != 0) {
+ lprintf(cfg, ret, 0, "Error in config_scan_end");
+ if (ret == 0)
+ ret = t_ret;
+ }
+
+ return (ret);
+}
+
+/* Set a single string config option */
+int
+config_opt_str(CONFIG *cfg, WT_SESSION *parse_session,
+ const char *name, const char *value)
+{
+ int ret;
+ char *optstr;
+
+ /* name="value" */
+ if ((optstr = malloc(strlen(name) + strlen(value) + 4)) == NULL)
+ return (enomem(cfg));
+ sprintf(optstr, "%s=\"%s\"", name, value);
+ ret = config_opt_line(cfg, parse_session, optstr);
+ free(optstr);
+ return (ret);
+}
+
+static void
+pretty_print(const char *p, const char *indent)
+{
+ const char *t;
+
+ for (;; p = t + 1) {
+ if (strlen(p) <= 70)
+ break;
+ for (t = p + 70; t > p && *t != ' '; --t)
+ ;
+ if (t == p) /* No spaces? */
+ break;
+ printf("%s%.*s\n",
+ indent == NULL ? "" : indent, (int)(t - p), p);
+ }
+ if (*p != '\0')
+ printf("%s%s\n", indent == NULL ? "" : indent, p);
+}
+
+static void
+config_opt_usage(void)
+{
+ size_t i, nopt;
+ const char *defaultval, *typestr;
+
+ pretty_print(
+ "The following are options settable using -o or -O, showing the "
+ "type and default value.\n", NULL);
+ pretty_print(
+ "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++) {
+ typestr = "?";
+ defaultval = config_opts[i].defaultval;
+ switch (config_opts[i].type) {
+ case BOOL_TYPE:
+ typestr = "boolean";
+ if (strcmp(defaultval, "0") == 0)
+ defaultval = "false";
+ else
+ defaultval = "true";
+ break;
+ case CONFIG_STRING_TYPE:
+ case STRING_TYPE:
+ typestr = "string";
+ break;
+ case INT_TYPE:
+ typestr = "int";
+ break;
+ case UINT32_TYPE:
+ typestr = "unsigned int";
+ break;
+ }
+ printf("%s (%s, default %s)\n",
+ config_opts[i].name, typestr, defaultval);
+ pretty_print(config_opts[i].description, "\t");
+ }
+}
+
+void
+print_config(CONFIG *cfg)
+{
+ printf("Workload configuration:\n");
+ printf("\thome: %s\n", cfg->home);
+ printf("\ttable_name: %s\n", cfg->table_name);
+ printf("\tConnection configuration: %s\n", cfg->conn_config);
+ printf("\tTable configuration: %s\n", cfg->table_config);
+ printf("\t%s\n", cfg->create ? "Creating" : "Using existing");
+ printf("\tWorkload period: %" PRIu32 "\n", cfg->run_time);
+ printf(
+ "\tCheckpoint interval: %" PRIu32 "\n", cfg->checkpoint_interval);
+ printf("\tReporting interval: %" PRIu32 "\n", cfg->report_interval);
+ printf("\tStatistics interval: %" PRIu32 "\n", cfg->stat_interval);
+ if (cfg->create) {
+ printf("\tInsert count: %" PRIu32 "\n", cfg->icount);
+ printf("\tNumber populate threads: %" PRIu32 "\n",
+ cfg->populate_threads);
+ }
+ printf("\tNumber read threads: %" PRIu32 "\n", cfg->read_threads);
+ printf("\tNumber insert threads: %" PRIu32 "\n", cfg->insert_threads);
+ if (cfg->insert_rmw)
+ printf("\tInsert operations are RMW.\n");
+ printf("\tNumber update threads: %" PRIu32 "\n", cfg->update_threads);
+ printf("\tkey size: %" PRIu32 " data size: %" PRIu32 "\n",
+ cfg->key_sz, cfg->data_sz);
+ printf("\tVerbosity: %" PRIu32 "\n", cfg->verbose);
+}
+
+void
+usage(void)
+{
+ printf("wtperf [-LMSv] [-C config] "
+ "[-h home] [-O file] [-o option] [-T config]\n");
+ printf("\t-L Use a large default configuration\n");
+ printf("\t-M Use a medium default configuration\n");
+ printf("\t-S Use a small default configuration\n");
+ printf("\t-C <string> additional connection configuration\n");
+ printf("\t (added to option conn_config)\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/misc.c b/bench/wtperf/misc.c
new file mode 100644
index 00000000000..2a4b4e31489
--- /dev/null
+++ b/bench/wtperf/misc.c
@@ -0,0 +1,110 @@
+/*-
+ * Public Domain 2008-2013 WiredTiger, Inc.
+ *
+ * This is free and unencumbered software released into the public domain.
+ *
+ * Anyone is free to copy, modify, publish, use, compile, sell, or
+ * distribute this software, either in source code form or as a compiled
+ * binary, for any purpose, commercial or non-commercial, and by any
+ * means.
+ *
+ * In jurisdictions that recognize copyright laws, the author or authors
+ * of this software dedicate any and all copyright interest in the
+ * software to the public domain. We make this dedication for the benefit
+ * of the public at large and to the detriment of our heirs and
+ * successors. We intend this dedication to be an overt act of
+ * relinquishment in perpetuity of all present and future rights to this
+ * software under copyright law.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "wtperf.h"
+
+int
+enomem(const CONFIG *cfg)
+{
+ const char *msg;
+
+ msg = "Unable to allocate memory";
+ if (cfg->logf == NULL)
+ fprintf(stderr, "%s\n", msg);
+ else
+ lprintf(cfg, ENOMEM, 0, "%s", msg);
+ return (ENOMEM);
+}
+
+/* Setup the logging output mechanism. */
+int
+setup_log_file(CONFIG *cfg)
+{
+ char *fname;
+ int ret;
+
+ ret = 0;
+
+ if (cfg->verbose < 1 && cfg->stat_interval == 0)
+ return (0);
+
+ if ((fname = calloc(strlen(cfg->home) +
+ strlen(cfg->table_name) + strlen(".stat") + 2, 1)) == NULL)
+ return (enomem(cfg));
+
+ sprintf(fname, "%s/%s.stat", cfg->home, cfg->table_name);
+ if ((cfg->logf = fopen(fname, "w")) == NULL) {
+ fprintf(stderr, "Statistics failed to open log file.\n");
+ ret = EINVAL;
+ } else {
+ /* Use line buffering for the log file. */
+ (void)setvbuf(cfg->logf, NULL, _IOLBF, 0);
+ }
+ free(fname);
+ return (ret);
+}
+
+/*
+ * Log printf - output a log message.
+ */
+void
+lprintf(const CONFIG *cfg, int err, uint32_t level, const char *fmt, ...)
+{
+ va_list ap;
+
+ if (err == 0 && level <= cfg->verbose) {
+ va_start(ap, fmt);
+ vfprintf(cfg->logf, fmt, ap);
+ va_end(ap);
+ fprintf(cfg->logf, "\n");
+
+ if (level < cfg->verbose) {
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+ printf("\n");
+ }
+ }
+ if (err == 0)
+ return;
+
+ /* We are dealing with an error. */
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, " Error: %s\n", wiredtiger_strerror(err));
+ if (cfg->logf != NULL) {
+ va_start(ap, fmt);
+ vfprintf(cfg->logf, fmt, ap);
+ va_end(ap);
+ fprintf(cfg->logf, " Error: %s\n", wiredtiger_strerror(err));
+ }
+
+ /* Never attempt to continue if we got a panic from WiredTiger. */
+ if (err == WT_PANIC)
+ exit(1);
+}
diff --git a/bench/wtperf/wtperf.c b/bench/wtperf/wtperf.c
index c767590ac11..fb602d1635a 100644
--- a/bench/wtperf/wtperf.c
+++ b/bench/wtperf/wtperf.c
@@ -24,118 +24,18 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <assert.h>
-#include <ctype.h>
-#include <dirent.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <math.h>
-#include <pthread.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <wiredtiger.h>
-#include <wiredtiger_ext.h>
-#include <gcc.h> /* WiredTiger internal */
-
-typedef struct { /* Per-thread structure */
- void *cfg; /* Enclosing handle */
-
- pthread_t handle; /* Handle */
- uint64_t read_ops; /* Read ops */
- uint64_t update_ops; /* Update ops */
-} CONFIG_THREAD;
-
-typedef struct {
- const char *home; /* WiredTiger home */
- char *uri; /* Object URI */
-
- WT_CONNECTION *conn; /* Database connection */
-
- FILE *logf; /* Logging handle */
-
- CONFIG_THREAD *rthreads, *ithreads, *popthreads, *uthreads;
-
- enum { WT_PERF_INIT, WT_PERF_POPULATE, WT_PERF_WORKER } phase;
-
- struct timeval phase_start_time;
-
- /* Fields changeable on command line are listed in wtperf_opt.i */
-#define OPT_DECLARE_STRUCT
-#include "wtperf_opt.i"
-#undef OPT_DECLARE_STRUCT
-
-} CONFIG;
-
-typedef enum {
- BOOL_TYPE, CONFIG_STRING_TYPE, INT_TYPE, STRING_TYPE, UINT32_TYPE
-} CONFIG_OPT_TYPE;
-
-typedef struct {
- const char *name;
- const char *description;
- const char *defaultval;
- CONFIG_OPT_TYPE type;
- size_t offset;
-} CONFIG_OPT;
-
-/* All options changeable on command line using -o or -O are listed here. */
-CONFIG_OPT config_opts[] = {
-
-#define OPT_DEFINE_DESC
-#include "wtperf_opt.i"
-#undef OPT_DEFINE_DESC
-
-};
-
-/* Worker thread types. */
-typedef enum {
- WORKER_READ, WORKER_INSERT, WORKER_INSERT_RMW, WORKER_UPDATE } worker_type;
-#define IS_INSERT_WORKER(w) \
- ((w) == WORKER_INSERT || (w) == WORKER_INSERT_RMW)
-
-/* Forward function definitions. */
-void *checkpoint_worker(void *);
-int config_assign(CONFIG *, const CONFIG *);
-void config_free(CONFIG *);
-int config_opt(CONFIG *, WT_CONFIG_ITEM *, WT_CONFIG_ITEM *);
-int config_opt_file(CONFIG *, WT_SESSION *, const char *);
-int config_opt_int(CONFIG *, WT_SESSION *, const char *, const char *);
-int config_opt_line(CONFIG *, WT_SESSION *, const char *);
-int config_opt_str(CONFIG *, WT_SESSION *, const char *, const char *);
-void config_opt_usage(void);
-int execute_populate(CONFIG *);
-int execute_workload(CONFIG *);
-int find_table_count(CONFIG *);
-void *insert_thread(void *);
-void lprintf(const CONFIG *cfg, int err, uint32_t level, const char *fmt, ...)
- WT_GCC_ATTRIBUTE((format (printf, 4, 5)));
-void *populate_thread(void *);
-void print_config(CONFIG *);
-void *read_thread(void *);
-int setup_log_file(CONFIG *);
-int start_threads(CONFIG *, u_int, CONFIG_THREAD **, void *(*func)(void *));
-void *stat_worker(void *);
-int stop_threads(CONFIG *, u_int, CONFIG_THREAD **);
-void *update_thread(void *);
-void usage(void);
-void worker(CONFIG_THREAD *, worker_type);
-uint64_t wtperf_rand(CONFIG *);
-uint64_t wtperf_value_range(CONFIG *);
+#include "wtperf.h"
#define DEFAULT_LSM_CONFIG \
"key_format=S,value_format=S,type=lsm,exclusive=true," \
"leaf_page_max=4kb,internal_page_max=64kb,allocation_size=4kb,"
+#define IS_INSERT_WORKER(w) \
+ ((w) == WORKER_INSERT || (w) == WORKER_INSERT_RMW)
+
/* Default values. */
-CONFIG default_cfg = {
+static const CONFIG default_cfg = {
"WT_TEST", /* home */
NULL, /* uri */
NULL, /* conn */
@@ -147,10 +47,9 @@ CONFIG default_cfg = {
#define OPT_DEFINE_DEFAULT
#include "wtperf_opt.i"
#undef OPT_DEFINE_DEFAULT
-
};
-const char *small_config_str =
+static const char * const small_config_str =
"conn_config=\"cache_size=500MB\","
"table_config=\"lsm_chunk_size=5MB\","
"icount=500000,"
@@ -161,7 +60,7 @@ const char *small_config_str =
"populate_threads=1,"
"read_threads=8,";
-const char *med_config_str =
+static const char * const med_config_str =
"conn_config=\"cache_size=1GB\","
"table_config=\"lsm_chunk_size=20MB\","
"icount=50000000,"
@@ -172,7 +71,7 @@ const char *med_config_str =
"populate_threads=1,"
"read_threads=16,";
-const char *large_config_str =
+static const char * const large_config_str =
"conn_config=\"cache_size=2GB\","
"table_config=\"lsm_chunk_size=50MB\","
"icount=500000000,"
@@ -184,17 +83,17 @@ const char *large_config_str =
"read_threads=16,";
-const char *debug_cconfig = "verbose=[lsm]";
-const char *debug_tconfig = "";
+static const char * const debug_cconfig = "verbose=[lsm]";
+static const char * const debug_tconfig = "";
-uint64_t g_nins_ops; /* insert count and key assignment */
-uint64_t g_npop_ops; /* population count and key assignment */
-uint64_t g_nread_ops; /* read operations */
-uint64_t g_nupdate_ops; /* update operations */
-uint32_t g_threads_quit; /* threads that exited early */
+static uint64_t g_nins_ops; /* insert count and key assignment */
+static uint64_t g_npop_ops; /* population count and key assignment */
+static uint64_t g_nread_ops; /* read operations */
+static uint64_t g_nupdate_ops; /* update operations */
+static uint32_t g_threads_quit; /* threads that exited early */
-int g_running; /* threads are running */
-int g_util_running; /* utility threads are running */
+static int g_running; /* threads are running */
+static int g_util_running; /* utility threads are running */
/*
* Atomic update where needed.
@@ -205,6 +104,22 @@ int g_util_running; /* utility threads are running */
#define ATOMIC_ADD(v, val) __sync_add_and_fetch(&(v), val)
#endif
+static void *checkpoint_worker(void *);
+static int execute_populate(CONFIG *);
+static int execute_workload(CONFIG *);
+static int find_table_count(CONFIG *);
+static void *insert_thread(void *);
+static void *populate_thread(void *);
+static void *read_thread(void *);
+static int start_threads(
+ CONFIG *, u_int, CONFIG_THREAD **, void *(*func)(void *));
+static void *stat_worker(void *);
+static int stop_threads(CONFIG *, u_int, CONFIG_THREAD **);
+static void *update_thread(void *);
+static void worker(CONFIG_THREAD *, worker_type);
+static uint64_t wtperf_rand(CONFIG *);
+static uint64_t wtperf_value_range(CONFIG *);
+
/* Retrieve an ID for the next populate operation. */
static inline uint64_t
get_next_populate(void)
@@ -249,20 +164,7 @@ sum_update_ops(CONFIG_THREAD *threads, u_int num)
return (total);
}
-static int
-enomem(const CONFIG *cfg)
-{
- const char *msg;
-
- msg = "Unable to allocate memory";
- if (cfg->logf == NULL)
- fprintf(stderr, "%s\n", msg);
- else
- lprintf(cfg, ENOMEM, 0, "%s", msg);
- return (ENOMEM);
-}
-
-void
+static void
worker(CONFIG_THREAD *thread, worker_type wtype)
{
CONFIG *cfg;
@@ -398,14 +300,14 @@ err: if (ret != 0)
free(key_buf);
}
-void *
+static void *
read_thread(void *arg)
{
worker((CONFIG_THREAD *)arg, WORKER_READ);
return (NULL);
}
-void *
+static void *
insert_thread(void *arg)
{
CONFIG *cfg;
@@ -416,14 +318,14 @@ insert_thread(void *arg)
return (NULL);
}
-void *
+static void *
update_thread(void *arg)
{
worker((CONFIG_THREAD *)arg, WORKER_UPDATE);
return (NULL);
}
-void *
+static void *
populate_thread(void *arg)
{
CONFIG *cfg;
@@ -525,7 +427,7 @@ err: if (ret != 0)
return (NULL);
}
-void *
+static void *
stat_worker(void *arg)
{
CONFIG *cfg;
@@ -645,7 +547,7 @@ err: if (session != NULL)
return (arg);
}
-void *
+static void *
checkpoint_worker(void *arg)
{
CONFIG *cfg;
@@ -691,7 +593,7 @@ err: if (session != NULL)
return (arg);
}
-int
+static int
execute_populate(CONFIG *cfg)
{
WT_CONNECTION *conn;
@@ -789,7 +691,7 @@ execute_populate(CONFIG *cfg)
return (0);
}
-int
+static int
execute_workload(CONFIG *cfg)
{
uint64_t last_inserts, last_reads, last_updates;
@@ -891,7 +793,7 @@ err: g_running = 0;
* Ensure that icount matches the number of records in the
* existing table.
*/
-int
+static int
find_table_count(CONFIG *cfg)
{
WT_CONNECTION *conn;
@@ -1204,384 +1106,7 @@ err: g_util_running = 0;
return (ret);
}
-/*
- * Following are utility functions.
- */
-
-/* Assign the src config to the dest.
- * Any storage allocated in dest is freed as a result.
- */
-int
-config_assign(CONFIG *dest, const CONFIG *src)
-{
- size_t i, len;
- char *newstr, **pstr;
-
- config_free(dest);
- memcpy(dest, src, sizeof(CONFIG));
-
- 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) {
- len = strlen(*pstr) + 1;
- if ((newstr = malloc(len)) == NULL)
- return (enomem(src));
- strncpy(newstr, *pstr, len);
- *pstr = newstr;
- }
- }
- return (0);
-}
-
-/* Free any storage allocated in the config struct.
- */
-void
-config_free(CONFIG *cfg)
-{
- size_t i;
- char **pstr;
-
- 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 **)
- ((unsigned char *)cfg + config_opts[i].offset);
- if (*pstr != NULL) {
- free(*pstr);
- *pstr = NULL;
- }
- }
-
- free(cfg->uri);
-}
-
-/*
- * Check a single key=value returned by the config parser
- * against our table of valid keys, along with the expected type.
- * If everything is okay, set the value.
- */
-int
-config_opt(CONFIG *cfg, WT_CONFIG_ITEM *k, WT_CONFIG_ITEM *v)
-{
- CONFIG_OPT *popt;
- char *newstr, **strp;
- size_t i, nopt;
- uint64_t 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];
- break;
- }
- if (popt == 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);
- return (EINVAL);
- }
- valueloc = ((unsigned char *)cfg + popt->offset);
- switch (popt->type) {
- case BOOL_TYPE:
- if (v->type != WT_CONFIG_ITEM_BOOL) {
- fprintf(stderr, "wtperf: Error: "
- "bad bool value for \'%.*s=%.*s\'\n",
- (int)k->len, k->str, (int)v->len, v->str);
- return (EINVAL);
- }
- *(int *)valueloc = (int)v->val;
- break;
- case INT_TYPE:
- if (v->type != WT_CONFIG_ITEM_NUM) {
- fprintf(stderr, "wtperf: Error: "
- "bad int value for \'%.*s=%.*s\'\n",
- (int)k->len, k->str, (int)v->len, v->str);
- return (EINVAL);
- }
- if (v->val > INT_MAX) {
- fprintf(stderr, "wtperf: Error: "
- "int value out of range for \'%.*s=%.*s\'\n",
- (int)k->len, k->str, (int)v->len, v->str);
- return (EINVAL);
- }
- *(int *)valueloc = (int)v->val;
- break;
- case UINT32_TYPE:
- if (v->type != WT_CONFIG_ITEM_NUM) {
- fprintf(stderr, "wtperf: Error: "
- "bad uint32 value for \'%.*s=%.*s\'\n",
- (int)k->len, k->str, (int)v->len, v->str);
- return (EINVAL);
- }
- if (v->val < 0 || v->val > UINT_MAX) {
- fprintf(stderr, "wtperf: Error: "
- "uint32 value out of range for \'%.*s=%.*s\'\n",
- (int)k->len, k->str, (int)v->len, v->str);
- return (EINVAL);
- }
- *(uint32_t *)valueloc = (uint32_t)v->val;
- break;
- case CONFIG_STRING_TYPE:
- if (v->type != WT_CONFIG_ITEM_STRING) {
- fprintf(stderr, "wtperf: Error: "
- "bad string value for \'%.*s=%.*s\'\n",
- (int)k->len, k->str, (int)v->len, v->str);
- return (EINVAL);
- }
- strp = (char **)valueloc;
- newlen = v->len + 1;
- if (*strp == NULL) {
- if ((newstr = calloc(newlen, sizeof(char))) == NULL)
- return (enomem(cfg));
- strncpy(newstr, v->str, v->len);
- } else {
- newlen += (strlen(*strp) + 1);
- if ((newstr = calloc(newlen, sizeof(char))) == NULL)
- return (enomem(cfg));
- snprintf(newstr, newlen,
- "%s,%*s", *strp, (int)v->len, v->str);
- /* Free the old value now we've copied it. */
- free(*strp);
- }
- *strp = newstr;
- break;
- case STRING_TYPE:
- if (v->type != WT_CONFIG_ITEM_STRING) {
- fprintf(stderr, "wtperf: Error: "
- "bad string value for \'%.*s=%.*s\'\n",
- (int)k->len, k->str, (int)v->len, v->str);
- return (EINVAL);
- }
- strp = (char **)valueloc;
- free(*strp);
- if ((newstr = malloc(v->len + 1)) == NULL)
- return (enomem(cfg));
- strncpy(newstr, v->str, v->len);
- newstr[v->len] = '\0';
- *strp = newstr;
- break;
- }
- return (0);
-}
-
-/* Parse a configuration file.
- * We recognize comments '#' and continuation via lines ending in '\'.
- */
-int
-config_opt_file(CONFIG *cfg, WT_SESSION *parse_session, const char *filename)
-{
- FILE *fp;
- size_t linelen, optionpos;
- int contline, linenum, ret;
- char line[256], option[1024];
- char *comment, *ltrim, *rtrim;
-
- if ((fp = fopen(filename, "r")) == NULL) {
- fprintf(stderr, "wtperf: %s: %s\n", filename, strerror(errno));
- return (errno);
- }
-
- ret = 0;
- optionpos = 0;
- linenum = 0;
- while (fgets(line, sizeof(line), fp) != NULL) {
- linenum++;
- /* trim the line */
- for (ltrim = line; *ltrim && isspace(*ltrim); ltrim++)
- ;
- rtrim = &ltrim[strlen(ltrim)];
- if (rtrim > ltrim && rtrim[-1] == '\n')
- rtrim--;
-
- contline = (rtrim > ltrim && rtrim[-1] == '\\');
- if (contline)
- rtrim--;
-
- comment = strchr(ltrim, '#');
- if (comment != NULL && comment < rtrim)
- rtrim = comment;
- while (rtrim > ltrim && isspace(rtrim[-1]))
- rtrim--;
-
- linelen = (size_t)(rtrim - ltrim);
- if (linelen == 0)
- continue;
-
- if (linelen + optionpos + 1 > sizeof(option)) {
- fprintf(stderr, "wtperf: %s: %d: line overflow\n",
- filename, linenum);
- ret = EINVAL;
- break;
- }
- *rtrim = '\0';
- strncpy(&option[optionpos], ltrim, linelen);
- option[optionpos + linelen] = '\0';
- if (contline)
- optionpos += linelen;
- else {
- if ((ret = config_opt_line(cfg,
- parse_session, option)) != 0) {
- fprintf(stderr, "wtperf: %s: %d: parse error\n",
- filename, linenum);
- break;
- }
- optionpos = 0;
- }
- }
- if (ret == 0 && optionpos > 0) {
- fprintf(stderr, "wtperf: %s: %d: last line continues\n",
- filename, linenum);
- ret = EINVAL;
- }
-
- (void)fclose(fp);
- return (ret);
-}
-
-/* Parse a single line of config options.
- * Continued lines have already been joined.
- */
-int
-config_opt_line(CONFIG *cfg, WT_SESSION *parse_session, const char *optstr)
-{
- WT_CONFIG_ITEM k, v;
- WT_CONFIG_SCAN *scan;
- WT_CONNECTION *conn;
- WT_EXTENSION_API *wt_api;
- int ret, t_ret;
-
- conn = parse_session->connection;
- wt_api = conn->get_extension_api(conn);
-
- if ((ret = wt_api->config_scan_begin(wt_api, parse_session, optstr,
- strlen(optstr), &scan)) != 0) {
- lprintf(cfg, ret, 0, "Error in config_scan_begin");
- return (ret);
- }
-
- while (ret == 0) {
- if ((ret =
- wt_api->config_scan_next(wt_api, scan, &k, &v)) != 0) {
- /* Any parse error has already been reported. */
- if (ret == WT_NOTFOUND)
- ret = 0;
- break;
- }
- ret = config_opt(cfg, &k, &v);
- }
- if ((t_ret = wt_api->config_scan_end(wt_api, scan)) != 0) {
- lprintf(cfg, ret, 0, "Error in config_scan_end");
- if (ret == 0)
- ret = t_ret;
- }
-
- return (ret);
-}
-
-/* Set a single string config option */
-int
-config_opt_str(CONFIG *cfg, WT_SESSION *parse_session,
- const char *name, const char *value)
-{
- int ret;
- char *optstr;
-
- /* name="value" */
- if ((optstr = malloc(strlen(name) + strlen(value) + 4)) == NULL)
- return (enomem(cfg));
- sprintf(optstr, "%s=\"%s\"", name, value);
- ret = config_opt_line(cfg, parse_session, optstr);
- free(optstr);
- return (ret);
-}
-
-/* Set a single int config option */
-int
-config_opt_int(CONFIG *cfg, WT_SESSION *parse_session,
- const char *name, const char *value)
-{
- int ret;
- char *optstr;
-
- /* name=value */
- if ((optstr = malloc(strlen(name) + strlen(value) + 2)) == NULL)
- return (enomem(cfg));
- sprintf(optstr, "%s=%s", name, value);
- ret = config_opt_line(cfg, parse_session, optstr);
- free(optstr);
- return (ret);
-}
-
-static void
-pretty_print(const char *p, const char *indent)
-{
- const char *t;
-
- for (;; p = t + 1) {
- if (strlen(p) <= 70)
- break;
- for (t = p + 70; t > p && *t != ' '; --t)
- ;
- if (t == p) /* No spaces? */
- break;
- printf("%s%.*s\n",
- indent == NULL ? "" : indent, (int)(t - p), p);
- }
- if (*p != '\0')
- printf("%s%s\n", indent == NULL ? "" : indent, p);
-}
-
-void
-config_opt_usage(void)
-{
- size_t i, nopt;
- const char *defaultval, *typestr;
-
- pretty_print(
- "The following are options settable using -o or -O, showing the "
- "type and default value.\n", NULL);
- pretty_print(
- "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++) {
- typestr = "?";
- defaultval = config_opts[i].defaultval;
- switch (config_opts[i].type) {
- case BOOL_TYPE:
- typestr = "boolean";
- if (strcmp(defaultval, "0") == 0)
- defaultval = "false";
- else
- defaultval = "true";
- break;
- case CONFIG_STRING_TYPE:
- case STRING_TYPE:
- typestr = "string";
- break;
- case INT_TYPE:
- typestr = "int";
- break;
- case UINT32_TYPE:
- typestr = "unsigned int";
- break;
- }
- printf("%s (%s, default %s)\n",
- config_opts[i].name, typestr, defaultval);
- pretty_print(config_opts[i].description, "\t");
- }
-}
-
-int
+static int
start_threads(
CONFIG *cfg, u_int num, CONFIG_THREAD **threadsp, void *(*func)(void *))
{
@@ -1604,7 +1129,7 @@ start_threads(
return (0);
}
-int
+static int
stop_threads(CONFIG *cfg, u_int num, CONFIG_THREAD **threadsp)
{
CONFIG_THREAD *threads;
@@ -1626,76 +1151,7 @@ stop_threads(CONFIG *cfg, u_int num, CONFIG_THREAD **threadsp)
return (0);
}
-/*
- * Log printf - output a log message.
- */
-void
-lprintf(const CONFIG *cfg, int err, uint32_t level, const char *fmt, ...)
-{
- va_list ap;
-
- if (err == 0 && level <= cfg->verbose) {
- va_start(ap, fmt);
- vfprintf(cfg->logf, fmt, ap);
- va_end(ap);
- fprintf(cfg->logf, "\n");
-
- if (level < cfg->verbose) {
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
- printf("\n");
- }
- }
- if (err == 0)
- return;
-
- /* We are dealing with an error. */
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
- fprintf(stderr, " Error: %s\n", wiredtiger_strerror(err));
- if (cfg->logf != NULL) {
- va_start(ap, fmt);
- vfprintf(cfg->logf, fmt, ap);
- va_end(ap);
- fprintf(cfg->logf, " Error: %s\n", wiredtiger_strerror(err));
- }
-
- /* Never attempt to continue if we got a panic from WiredTiger. */
- if (err == WT_PANIC)
- exit(1);
-}
-
-/* Setup the logging output mechanism. */
-int
-setup_log_file(CONFIG *cfg)
-{
- char *fname;
- int ret;
-
- ret = 0;
-
- if (cfg->verbose < 1 && cfg->stat_interval == 0)
- return (0);
-
- if ((fname = calloc(strlen(cfg->home) +
- strlen(cfg->table_name) + strlen(".stat") + 2, 1)) == NULL)
- return (enomem(cfg));
-
- sprintf(fname, "%s/%s.stat", cfg->home, cfg->table_name);
- if ((cfg->logf = fopen(fname, "w")) == NULL) {
- fprintf(stderr, "Statistics failed to open log file.\n");
- ret = EINVAL;
- } else {
- /* Use line buffering for the log file. */
- (void)setvbuf(cfg->logf, NULL, _IOLBF, 0);
- }
- free(fname);
- return (ret);
-}
-
-uint64_t
+static uint64_t
wtperf_value_range(CONFIG *cfg)
{
if (cfg->random_range == 0)
@@ -1706,7 +1162,7 @@ wtperf_value_range(CONFIG *cfg)
extern uint32_t __wt_random(void);
-uint64_t
+static uint64_t
wtperf_rand(CONFIG *cfg)
{
double S1, S2, U;
@@ -1737,51 +1193,3 @@ wtperf_rand(CONFIG *cfg)
rval = (rval % wtperf_value_range(cfg)) + 1;
return (rval);
}
-
-void
-print_config(CONFIG *cfg)
-{
- printf("Workload configuration:\n");
- printf("\thome: %s\n", cfg->home);
- printf("\ttable_name: %s\n", cfg->table_name);
- printf("\tConnection configuration: %s\n", cfg->conn_config);
- printf("\tTable configuration: %s\n", cfg->table_config);
- printf("\t%s\n", cfg->create ? "Creating" : "Using existing");
- printf("\tWorkload period: %" PRIu32 "\n", cfg->run_time);
- printf(
- "\tCheckpoint interval: %" PRIu32 "\n", cfg->checkpoint_interval);
- printf("\tReporting interval: %" PRIu32 "\n", cfg->report_interval);
- printf("\tStatistics interval: %" PRIu32 "\n", cfg->stat_interval);
- if (cfg->create) {
- printf("\tInsert count: %" PRIu32 "\n", cfg->icount);
- printf("\tNumber populate threads: %" PRIu32 "\n",
- cfg->populate_threads);
- }
- printf("\tNumber read threads: %" PRIu32 "\n", cfg->read_threads);
- printf("\tNumber insert threads: %" PRIu32 "\n", cfg->insert_threads);
- if (cfg->insert_rmw)
- printf("\tInsert operations are RMW.\n");
- printf("\tNumber update threads: %" PRIu32 "\n", cfg->update_threads);
- printf("\tkey size: %" PRIu32 " data size: %" PRIu32 "\n",
- cfg->key_sz, cfg->data_sz);
- printf("\tVerbosity: %" PRIu32 "\n", cfg->verbose);
-}
-
-void
-usage(void)
-{
- printf("wtperf [-LMSv] [-C config] "
- "[-h home] [-O file] [-o option] [-T config]\n");
- printf("\t-L Use a large default configuration\n");
- printf("\t-M Use a medium default configuration\n");
- printf("\t-S Use a small default configuration\n");
- printf("\t-C <string> additional connection configuration\n");
- printf("\t (added to option conn_config)\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/wtperf.h b/bench/wtperf/wtperf.h
new file mode 100644
index 00000000000..4086b46bb7d
--- /dev/null
+++ b/bench/wtperf/wtperf.h
@@ -0,0 +1,103 @@
+/*-
+ * Public Domain 2008-2013 WiredTiger, Inc.
+ *
+ * This is free and unencumbered software released into the public domain.
+ *
+ * Anyone is free to copy, modify, publish, use, compile, sell, or
+ * distribute this software, either in source code form or as a compiled
+ * binary, for any purpose, commercial or non-commercial, and by any
+ * means.
+ *
+ * In jurisdictions that recognize copyright laws, the author or authors
+ * of this software dedicate any and all copyright interest in the
+ * software to the public domain. We make this dedication for the benefit
+ * of the public at large and to the detriment of our heirs and
+ * successors. We intend this dedication to be an overt act of
+ * relinquishment in perpetuity of all present and future rights to this
+ * software under copyright law.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <math.h>
+#include <pthread.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <wiredtiger.h>
+#include <wiredtiger_ext.h>
+#include <gcc.h> /* WiredTiger internal */
+
+typedef struct { /* Per-thread structure */
+ void *cfg; /* Enclosing handle */
+
+ pthread_t handle; /* Handle */
+ uint64_t read_ops; /* Read ops */
+ uint64_t update_ops; /* Update ops */
+} CONFIG_THREAD;
+
+typedef struct {
+ const char *home; /* WiredTiger home */
+ char *uri; /* Object URI */
+
+ WT_CONNECTION *conn; /* Database connection */
+
+ FILE *logf; /* Logging handle */
+
+ CONFIG_THREAD *rthreads, *ithreads, *popthreads, *uthreads;
+
+ enum { WT_PERF_INIT, WT_PERF_POPULATE, WT_PERF_WORKER } phase;
+
+ struct timeval phase_start_time;
+
+ /* Fields changeable on command line are listed in wtperf_opt.i */
+#define OPT_DECLARE_STRUCT
+#include "wtperf_opt.i"
+#undef OPT_DECLARE_STRUCT
+
+} CONFIG;
+
+typedef enum {
+ BOOL_TYPE, CONFIG_STRING_TYPE, INT_TYPE, STRING_TYPE, UINT32_TYPE
+} CONFIG_OPT_TYPE;
+
+typedef struct {
+ const char *name;
+ const char *description;
+ const char *defaultval;
+ CONFIG_OPT_TYPE type;
+ size_t offset;
+} CONFIG_OPT;
+
+/* Worker thread types. */
+typedef enum {
+ WORKER_READ, WORKER_INSERT, WORKER_INSERT_RMW, WORKER_UPDATE } worker_type;
+
+int config_assign(CONFIG *, const CONFIG *);
+void config_free(CONFIG *);
+int config_opt_file(CONFIG *, WT_SESSION *, const char *);
+int config_opt_line(CONFIG *, WT_SESSION *, const char *);
+int config_opt_str(CONFIG *, WT_SESSION *, const char *, const char *);
+int enomem(const CONFIG *);
+void lprintf(const CONFIG *, int err, uint32_t, const char *, ...)
+ WT_GCC_ATTRIBUTE((format (printf, 4, 5)));
+void print_config(CONFIG *);
+int setup_log_file(CONFIG *);
+void usage(void);