summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Gorrod <alexander.gorrod@mongodb.com>2016-05-27 15:50:49 +1000
committerAlex Gorrod <alexander.gorrod@mongodb.com>2016-05-27 15:50:49 +1000
commit6f9a7a41f21476235b0bb99f0f16a2d7f738c2e0 (patch)
tree761773c90ee4d070dbcfd6ea9b7bfcb9d3b26fc3
parent636a7b25ef3eca6b98009330f4d35337d4f35717 (diff)
parent4d13c2b911e8ad6a8993704ecd3007af302232a6 (diff)
downloadmongo-6f9a7a41f21476235b0bb99f0f16a2d7f738c2e0.tar.gz
Merge branch 'develop' into mongodb-3.4
-rw-r--r--SConstruct10
-rw-r--r--bench/wtperf/config.c203
-rw-r--r--bench/wtperf/runners/evict-btree-stress.wtperf12
-rw-r--r--bench/wtperf/wtperf.c39
-rw-r--r--bench/wtperf/wtperf.h25
-rw-r--r--bench/wtperf/wtperf_opt.i2
-rw-r--r--build_posix/Make.subdirs2
-rw-r--r--dist/api_data.py10
-rwxr-xr-xdist/s_c_test_create105
-rwxr-xr-xdist/s_string4
-rw-r--r--dist/s_string.ok4
-rw-r--r--dist/stat_data.py3
-rw-r--r--examples/c/ex_access.c6
-rw-r--r--examples/c/ex_all.c2
-rw-r--r--examples/c/ex_async.c20
-rw-r--r--examples/c/ex_backup.c8
-rw-r--r--examples/c/ex_call_center.c6
-rw-r--r--examples/c/ex_config_parse.c26
-rw-r--r--examples/c/ex_cursor.c12
-rw-r--r--examples/c/ex_data_source.c4
-rw-r--r--examples/c/ex_encrypt.c6
-rw-r--r--examples/c/ex_event_handler.c8
-rw-r--r--examples/c/ex_extending.c13
-rw-r--r--examples/c/ex_extractor.c2
-rw-r--r--examples/c/ex_file_system.c308
-rw-r--r--examples/c/ex_hello.c20
-rw-r--r--examples/c/ex_log.c9
-rw-r--r--examples/c/ex_pack.c20
-rw-r--r--examples/c/ex_process.c20
-rw-r--r--examples/c/ex_schema.c6
-rw-r--r--examples/c/ex_scope.c11
-rw-r--r--examples/c/ex_stat.c9
-rw-r--r--examples/c/ex_sync.c7
-rw-r--r--examples/c/ex_thread.c4
-rw-r--r--src/block/block_map.c6
-rw-r--r--src/block/block_mgr.c2
-rw-r--r--src/block/block_read.c12
-rw-r--r--src/block/block_write.c9
-rw-r--r--src/checksum/power8/crc32.S7
-rw-r--r--src/config/config_collapse.c4
-rw-r--r--src/config/config_def.c5
-rw-r--r--src/conn/conn_api.c22
-rw-r--r--src/conn/conn_cache_pool.c1
-rw-r--r--src/cursor/cur_join.c43
-rw-r--r--src/docs/custom-file-systems.dox29
-rw-r--r--src/docs/spell.ok3
-rw-r--r--src/docs/wtperf.dox2
-rw-r--r--src/include/btree.i21
-rw-r--r--src/include/cache.i16
-rw-r--r--src/include/extern.h3
-rw-r--r--src/include/os.h7
-rw-r--r--src/include/os_fhandle.i29
-rw-r--r--src/include/os_fs.i17
-rw-r--r--src/include/os_fstream.i42
-rw-r--r--src/include/session.h2
-rw-r--r--src/include/stat.h3
-rw-r--r--src/include/wiredtiger.in307
-rw-r--r--src/meta/meta_turtle.c12
-rw-r--r--src/os_common/os_fhandle.c10
-rw-r--r--src/os_common/os_fs_inmemory.c22
-rw-r--r--src/os_common/os_fstream.c98
-rw-r--r--src/os_common/os_fstream_stdio.c6
-rw-r--r--src/os_posix/os_fallocate.c16
-rw-r--r--src/os_posix/os_fs.c72
-rw-r--r--src/os_posix/os_map.c2
-rw-r--r--src/os_win/os_fs.c30
-rw-r--r--src/reconcile/rec_write.c19
-rw-r--r--src/session/session_api.c33
-rw-r--r--src/support/stat.c12
-rw-r--r--src/utilities/util_load.c1
-rw-r--r--test/bloom/Makefile.am9
-rw-r--r--test/bloom/test_bloom.c2
-rw-r--r--test/checkpoint/Makefile.am9
-rw-r--r--test/checkpoint/test_checkpoint.h2
-rw-r--r--test/csuite/Makefile.am21
-rw-r--r--test/csuite/wt1965_col_efficiency/main.c186
-rw-r--r--test/csuite/wt2246_col_append/main.c158
-rw-r--r--test/csuite/wt2535_insert_race/main.c159
-rw-r--r--test/cursor_order/Makefile.am10
-rw-r--r--test/cursor_order/cursor_order.h2
-rw-r--r--test/fops/Makefile.am9
-rw-r--r--test/fops/thread.h2
-rw-r--r--test/format/Makefile.am17
-rw-r--r--test/format/format.h2
-rw-r--r--test/format/ops.c13
-rw-r--r--test/format/util.c12
-rw-r--r--test/huge/Makefile.am9
-rw-r--r--test/huge/huge.c2
-rw-r--r--test/manydbs/Makefile.am9
-rw-r--r--test/manydbs/manydbs.c2
-rw-r--r--test/packing/Makefile.am9
-rw-r--r--test/packing/intpack-test.c2
-rw-r--r--test/packing/intpack-test2.c2
-rw-r--r--test/packing/intpack-test3.c3
-rw-r--r--test/packing/packing-test.c2
-rw-r--r--test/readonly/Makefile.am9
-rw-r--r--test/readonly/readonly.c2
-rw-r--r--test/recovery/Makefile.am11
-rw-r--r--test/recovery/random-abort.c13
-rw-r--r--test/recovery/truncated-log.c16
-rw-r--r--test/salvage/Makefile.am9
-rw-r--r--test/salvage/salvage.c2
-rw-r--r--test/suite/test_dump.py23
-rw-r--r--test/suite/wttest.py8
-rw-r--r--test/thread/Makefile.am11
-rw-r--r--test/thread/thread.h2
-rw-r--r--test/utility/Makefile.am4
-rw-r--r--test/utility/misc.c (renamed from test/utility/test_util.i)82
-rw-r--r--test/utility/parse_opts.c132
-rw-r--r--test/utility/test_util.h128
-rw-r--r--test/utility/thread.c141
-rw-r--r--tools/wtstats/stat_data.py1
112 files changed, 2290 insertions, 828 deletions
diff --git a/SConstruct b/SConstruct
index 425a531fda2..c724d94da7c 100644
--- a/SConstruct
+++ b/SConstruct
@@ -393,10 +393,16 @@ env.Append(BUILDERS={'SmokeTest' : Builder(action = builder_smoke_test)})
#Build the tests and setup the "scons test" target
+testutil = env.Library('testutil',
+ [
+ 'test/utility/misc.c',
+ 'test/utility/parse_opts.c'
+ ])
+
#Don't test bloom on Windows, its broken
t = env.Program("t_bloom",
"test/bloom/test_bloom.c",
- LIBS=[wtlib] + wtlibs)
+ LIBS=[wtlib, testutil] + wtlibs)
#env.Alias("check", env.SmokeTest(t))
Default(t)
@@ -419,7 +425,7 @@ t = env.Program("t_fops",
["test/fops/file.c",
"test/fops/fops.c",
"test/fops/t.c"],
- LIBS=[wtlib, shim] + wtlibs)
+ LIBS=[wtlib, shim, testutil] + wtlibs)
env.Append(CPPPATH=["test/utility"])
env.Alias("check", env.SmokeTest(t))
Default(t)
diff --git a/bench/wtperf/config.c b/bench/wtperf/config.c
index e83d6fcceed..d8c2de6e587 100644
--- a/bench/wtperf/config.c
+++ b/bench/wtperf/config.c
@@ -47,6 +47,53 @@ static void config_opt_usage(void);
(strncmp(str, bytes, len) == 0 && (str)[(len)] == '\0')
/*
+ * config_unescape --
+ * Modify a string in place, replacing any backslash escape sequences.
+ * The modified string is always shorter.
+ */
+static int
+config_unescape(char *orig)
+{
+ char ch, *dst, *s;
+
+ for (dst = s = orig; *s != '\0';) {
+ if ((ch = *s++) == '\\') {
+ ch = *s++;
+ switch (ch) {
+ case 'b':
+ *dst++ = '\b';
+ break;
+ case 'f':
+ *dst++ = '\f';
+ break;
+ case 'n':
+ *dst++ = '\n';
+ break;
+ case 'r':
+ *dst++ = '\r';
+ break;
+ case 't':
+ *dst++ = '\t';
+ break;
+ case '\\':
+ case '/':
+ case '\"': /* Backslash needed for spell check. */
+ *dst++ = ch;
+ break;
+ default:
+ /* Note: Unicode (\u) not implemented. */
+ fprintf(stderr,
+ "invalid escape in string: %s\n", orig);
+ return (EINVAL);
+ }
+ } else
+ *dst++ = ch;
+ }
+ *dst = '\0';
+ return (0);
+}
+
+/*
* config_assign --
* Assign the src config to the dest, any storage allocated in dest is
* freed as a result.
@@ -363,7 +410,8 @@ static int
config_opt(CONFIG *cfg, WT_CONFIG_ITEM *k, WT_CONFIG_ITEM *v)
{
CONFIG_OPT *popt;
- char *newstr, **strp;
+ char *begin, *newstr, **strp;
+ int ret;
size_t i, newlen, nopt;
void *valueloc;
@@ -438,15 +486,20 @@ config_opt(CONFIG *cfg, WT_CONFIG_ITEM *k, WT_CONFIG_ITEM *v)
}
strp = (char **)valueloc;
newlen = v->len + 1;
- if (*strp == NULL) {
- newstr = dstrdup(v->str);
- } else {
- newlen += (strlen(*strp) + 1);
+ if (*strp == NULL)
+ begin = newstr = dstrdup(v->str);
+ else {
+ newlen += strlen(*strp) + 1;
newstr = dcalloc(newlen, sizeof(char));
snprintf(newstr, newlen,
"%s,%*s", *strp, (int)v->len, v->str);
/* Free the old value now we've copied it. */
free(*strp);
+ begin = &newstr[(newlen - 1) - v->len];
+ }
+ if ((ret = config_unescape(begin)) != 0) {
+ free(newstr);
+ return (ret);
}
*strp = newstr;
break;
@@ -487,84 +540,99 @@ config_opt(CONFIG *cfg, WT_CONFIG_ITEM *k, WT_CONFIG_ITEM *v)
int
config_opt_file(CONFIG *cfg, const char *filename)
{
- struct stat sb;
- ssize_t read_size;
- size_t buf_size, linelen, optionpos;
- int contline, fd, linenum, ret;
- char option[1024];
- char *comment, *file_buf, *line, *ltrim, *rtrim;
+ FILE *fp;
+ size_t linelen, optionpos;
+ int linenum, ret;
+ bool contline;
+ char line[4 * 1024], option[4 * 1024];
+ char *comment, *ltrim, *rtrim;
- file_buf = NULL;
+ ret = 0;
- if ((fd = open(filename, O_RDONLY)) == -1) {
+ if ((fp = fopen(filename, "r")) == NULL) {
fprintf(stderr, "wtperf: %s: %s\n", filename, strerror(errno));
return (errno);
}
- if ((ret = fstat(fd, &sb)) != 0) {
- fprintf(stderr, "wtperf: stat of %s: %s\n",
- filename, strerror(errno));
- ret = errno;
- goto err;
- }
- buf_size = (size_t)sb.st_size;
- file_buf = dcalloc(buf_size + 2, 1);
- read_size = read(fd, file_buf, buf_size);
- if (read_size == -1
-#ifndef _WIN32
- /* Windows automatically translates \r\n -> \n so counts will be off */
- || (size_t)read_size != buf_size
-#endif
- ) {
- fprintf(stderr,
- "wtperf: read unexpected amount from config file\n");
- ret = EINVAL;
- goto err;
- }
- /* Make sure the buffer is terminated correctly. */
- file_buf[read_size] = '\0';
- ret = 0;
optionpos = 0;
linenum = 0;
- /*
- * We should switch this from using strtok to generating a single
- * WiredTiger configuration string compatible string, and using
- * the WiredTiger configuration parser to parse it at once.
- */
-#define WTPERF_CONFIG_DELIMS "\n\\"
- for (line = strtok(file_buf, WTPERF_CONFIG_DELIMS);
- line != NULL;
- line = strtok(NULL, WTPERF_CONFIG_DELIMS)) {
+ while (fgets(line, sizeof(line), fp) != NULL) {
linenum++;
- /* trim the line */
+
+ /* Skip leading space. */
for (ltrim = line; *ltrim && isspace(*ltrim); ltrim++)
;
- rtrim = &ltrim[strlen(ltrim)];
- if (rtrim > ltrim && rtrim[-1] == '\n')
+
+ /*
+ * Find the end of the line; if there's no trailing newline, the
+ * the line is too long for the buffer or the file was corrupted
+ * (there's no terminating newline in the file).
+ */
+ for (rtrim = line; *rtrim && *rtrim != '\n'; rtrim++)
+ ;
+ if (*rtrim != '\n') {
+ fprintf(stderr,
+ "wtperf: %s: %d: configuration line too long\n",
+ filename, linenum);
+ ret = EINVAL;
+ break;
+ }
+
+ /* Skip trailing space. */
+ while (rtrim > ltrim && isspace(rtrim[-1]))
rtrim--;
- contline = (rtrim > ltrim && rtrim[-1] == '\\');
+ /*
+ * If the last non-space character in the line is an escape, the
+ * line will be continued. Checked early because the line might
+ * otherwise be empty.
+ */
+ contline = rtrim > ltrim && rtrim[-1] == '\\';
if (contline)
rtrim--;
- comment = strchr(ltrim, '#');
- if (comment != NULL && comment < rtrim)
+ /*
+ * Discard anything after the first hash character. Check after
+ * the escape character, the escape can appear after a comment.
+ */
+ if ((comment = strchr(ltrim, '#')) != NULL)
rtrim = comment;
+
+ /* Skip trailing space again. */
while (rtrim > ltrim && isspace(rtrim[-1]))
rtrim--;
- linelen = (size_t)(rtrim - ltrim);
- if (linelen == 0)
- continue;
+ /*
+ * Check for empty lines: note that the right-hand boundary can
+ * cross over the left-hand boundary, less-than or equal to is
+ * the correct test.
+ */
+ if (rtrim <= ltrim) {
+ /*
+ * If we're continuing from this line, or we haven't
+ * started building an option, ignore this line.
+ */
+ if (contline || optionpos == 0)
+ continue;
+
+ /*
+ * An empty line terminating an option we're building;
+ * clean things up so we can proceed.
+ */
+ linelen = 0;
+ } else
+ linelen = (size_t)(rtrim - ltrim);
+ ltrim[linelen] = '\0';
if (linelen + optionpos + 1 > sizeof(option)) {
- fprintf(stderr, "wtperf: %s: %d: line overflow\n",
+ fprintf(stderr,
+ "wtperf: %s: %d: option value overflow\n",
filename, linenum);
ret = EINVAL;
break;
}
- *rtrim = '\0';
- strncpy(&option[optionpos], ltrim, linelen);
+
+ memcpy(&option[optionpos], ltrim, linelen);
option[optionpos + linelen] = '\0';
if (contline)
optionpos += linelen;
@@ -577,16 +645,19 @@ config_opt_file(CONFIG *cfg, const char *filename)
optionpos = 0;
}
}
- if (ret == 0 && optionpos > 0) {
- fprintf(stderr, "wtperf: %s: %d: last line continues\n",
- filename, linenum);
- ret = EINVAL;
- goto err;
+ if (ret == 0) {
+ if (ferror(fp)) {
+ fprintf(stderr, "wtperf: %s: read error\n", filename);
+ ret = errno;
+ }
+ if (optionpos > 0) {
+ fprintf(stderr, "wtperf: %s: %d: last line continues\n",
+ filename, linenum);
+ ret = EINVAL;
+ }
}
-err: if (fd != -1)
- (void)close(fd);
- free(file_buf);
+ (void)fclose(fp);
return (ret);
}
@@ -754,7 +825,7 @@ config_consolidate(CONFIG *cfg)
* as being the same key.
*/
if (strncmp(conf_line->string, test_line->string,
- (size_t)(string_key - conf_line->string + 1))
+ (size_t)((string_key - conf_line->string) + 1))
== 0) {
TAILQ_REMOVE(&cfg->config_head, conf_line, c);
free(conf_line->string);
diff --git a/bench/wtperf/runners/evict-btree-stress.wtperf b/bench/wtperf/runners/evict-btree-stress.wtperf
new file mode 100644
index 00000000000..740fb88c050
--- /dev/null
+++ b/bench/wtperf/runners/evict-btree-stress.wtperf
@@ -0,0 +1,12 @@
+# wtperf options file: evict btree configuration
+conn_config="cache_size=50M,eviction=(threads_max=4)"
+table_config="type=file"
+icount=10000000
+report_interval=5
+run_time=120
+populate_threads=1
+threads=((count=16,reads=1))
+# Add throughput/latency monitoring
+max_latency=2000
+sample_interval=5
+session_count_idle=100
diff --git a/bench/wtperf/wtperf.c b/bench/wtperf/wtperf.c
index 9d57bdcf6b0..1a3d98d3e3e 100644
--- a/bench/wtperf/wtperf.c
+++ b/bench/wtperf/wtperf.c
@@ -1631,6 +1631,8 @@ execute_workload(CONFIG *cfg)
{
CONFIG_THREAD *threads;
WORKLOAD *workp;
+ WT_CONNECTION *conn;
+ WT_SESSION **sessions;
pthread_t idle_table_cycle_thread;
uint64_t last_ckpts, last_inserts, last_reads, last_truncates;
uint64_t last_updates;
@@ -1647,6 +1649,8 @@ execute_workload(CONFIG *cfg)
last_updates = 0;
ret = 0;
+ sessions = NULL;
+
/* Start cycling idle tables. */
if ((ret = start_idle_table_cycle(cfg, &idle_table_cycle_thread)) != 0)
return (ret);
@@ -1664,6 +1668,18 @@ execute_workload(CONFIG *cfg)
} else
pfunc = worker;
+ if (cfg->session_count_idle != 0) {
+ sessions = dcalloc((size_t)cfg->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) {
+ lprintf(cfg, ret, 0,
+ "execute_workload: idle open_session");
+ goto err;
+ }
+ }
/* Start each workload. */
for (threads = cfg->workers, i = 0,
workp = cfg->workload; i < cfg->workload_cnt; ++i, ++workp) {
@@ -1758,6 +1774,7 @@ err: cfg->stop = 1;
if (ret == 0 && cfg->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) {
lprintf(cfg, WT_ERROR, 0,
@@ -2170,15 +2187,15 @@ int
main(int argc, char *argv[])
{
CONFIG *cfg, _cfg;
- size_t req_len;
+ size_t req_len, sreq_len;
int ch, monitor_set, ret;
const char *opts = "C:H:h:m:O:o:T:";
const char *config_opts;
- char *cc_buf, *tc_buf, *user_cconfig, *user_tconfig;
+ char *cc_buf, *sess_cfg, *tc_buf, *user_cconfig, *user_tconfig;
monitor_set = ret = 0;
config_opts = NULL;
- cc_buf = tc_buf = user_cconfig = user_tconfig = NULL;
+ cc_buf = sess_cfg = tc_buf = user_cconfig = user_tconfig = NULL;
/* Setup the default configuration values. */
cfg = &_cfg;
@@ -2317,7 +2334,8 @@ main(int argc, char *argv[])
/* Concatenate non-default configuration strings. */
if (cfg->verbose > 1 || user_cconfig != NULL ||
- cfg->compress_ext != NULL || cfg->async_config != NULL) {
+ cfg->session_count_idle > 0 || cfg->compress_ext != NULL ||
+ cfg->async_config != NULL) {
req_len = strlen(cfg->conn_config) + strlen(debug_cconfig) + 3;
if (user_cconfig != NULL)
req_len += strlen(user_cconfig);
@@ -2325,16 +2343,26 @@ 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) {
+ sreq_len = strlen(",session_max=") + 6;
+ req_len += sreq_len;
+ sess_cfg = dcalloc(sreq_len, 1);
+ snprintf(sess_cfg, sreq_len,
+ ",session_max=%" PRIu32,
+ cfg->session_count_idle + cfg->workers_cnt +
+ cfg->populate_threads + 10);
+ }
cc_buf = dcalloc(req_len, 1);
/*
* This is getting hard to parse.
*/
- snprintf(cc_buf, req_len, "%s%s%s%s%s%s%s",
+ snprintf(cc_buf, req_len, "%s%s%s%s%s%s%s%s",
cfg->conn_config,
cfg->async_config ? cfg->async_config : "",
cfg->compress_ext ? cfg->compress_ext : "",
cfg->verbose > 1 ? ",": "",
cfg->verbose > 1 ? debug_cconfig : "",
+ sess_cfg ? sess_cfg : "",
user_cconfig ? ",": "",
user_cconfig ? user_cconfig : "");
if ((ret = config_opt_str(cfg, "conn_config", cc_buf)) != 0)
@@ -2410,6 +2438,7 @@ einval: ret = EINVAL;
err: config_free(cfg);
free(cc_buf);
+ free(sess_cfg);
free(tc_buf);
free(user_cconfig);
free(user_tconfig);
diff --git a/bench/wtperf/wtperf.h b/bench/wtperf/wtperf.h
index a2b497b3142..83fab4d6028 100644
--- a/bench/wtperf/wtperf.h
+++ b/bench/wtperf/wtperf.h
@@ -30,33 +30,8 @@
#define HAVE_WTPERF_H
#include <wt_internal.h>
-
-#ifndef _WIN32
-#include <sys/time.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-
#include <assert.h>
-#include <ctype.h>
-#ifndef _WIN32
-#include <dirent.h>
-#endif
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <limits.h>
#include <math.h>
-#ifndef _WIN32
-#include <pthread.h>
-#endif
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifndef _WIN32
-#include <unistd.h>
-#endif
#ifdef _WIN32
#include "windows_shim.h"
diff --git a/bench/wtperf/wtperf_opt.i b/bench/wtperf/wtperf_opt.i
index b5e274a17c2..2afd20f777f 100644
--- a/bench/wtperf/wtperf_opt.i
+++ b/bench/wtperf/wtperf_opt.i
@@ -163,6 +163,8 @@ DEF_OPT_AS_UINT32(sample_rate, 50,
"how often the latency of operations is measured. One for every operation,"
"two for every second operation, three for every third operation etc.")
DEF_OPT_AS_CONFIG_STRING(sess_config, "", "session configuration string")
+DEF_OPT_AS_UINT32(session_count_idle, 0,
+ "number of idle sessions to create. Default 0.")
DEF_OPT_AS_CONFIG_STRING(table_config,
"key_format=S,value_format=S,type=lsm,exclusive=true,"
"allocation_size=4kb,internal_page_max=64kb,leaf_page_max=4kb,"
diff --git a/build_posix/Make.subdirs b/build_posix/Make.subdirs
index 4e1f829c0c5..64749378ed1 100644
--- a/build_posix/Make.subdirs
+++ b/build_posix/Make.subdirs
@@ -25,8 +25,10 @@ examples/java JAVA
lang/python PYTHON
# Make the tests
+test/utility
test/bloom
test/checkpoint
+test/csuite
test/cursor_order
test/fops
test/format
diff --git a/dist/api_data.py b/dist/api_data.py
index 20c4433efc8..f7b4cd6e03b 100644
--- a/dist/api_data.py
+++ b/dist/api_data.py
@@ -787,15 +787,19 @@ methods = {
]),
'WT_SESSION.drop' : Method([
+ Config('checkpoint_wait', 'true', r'''
+ wait for the checkpoint lock, if \c checkpoint_wait=false, fail if
+ this lock is not available immediately''',
+ type='boolean', undoc=True),
Config('force', 'false', r'''
return success if the object does not exist''',
type='boolean'),
- Config('remove_files', 'true', r'''
- should the underlying files be removed?''',
- type='boolean'),
Config('lock_wait', 'true', r'''
wait for locks, if \c lock_wait=false, fail if any required locks are
not available immediately''',
+ type='boolean', undoc=True),
+ Config('remove_files', 'true', r'''
+ should the underlying files be removed?''',
type='boolean'),
]),
diff --git a/dist/s_c_test_create b/dist/s_c_test_create
new file mode 100755
index 00000000000..fd0fa809d99
--- /dev/null
+++ b/dist/s_c_test_create
@@ -0,0 +1,105 @@
+#! /bin/sh
+
+#
+# Usage: s_c_test_create test_name
+#
+# Create a new test case in the C test suite.
+# This will create the infrastructure for a new C test case. The given
+# test name is a new directory in the C suite directory and the Makefile
+# components and C program template are created.
+#
+# Any 'make check' variations of this test should be added to the smoke.sh
+# script in the main C suite directory.
+#
+tmp=__a
+trap 'rm -f $tmp; exit 0' 0 1 2 3 13 15
+
+if [ "x$1" = "x" ]; then
+ echo "Usage: $0 test_name"
+ exit 1
+fi
+CSUITE_DIRECTORY=../test/csuite
+MAKEFILE_NAME=$CSUITE_DIRECTORY/Makefile.am
+
+TEST_NAME=$1
+
+exists=`grep $TEST_NAME $MAKEFILE_NAME`
+
+if [ "x$exists" != "x" ]; then
+ echo "Test with requested name already exists. Try another name."
+ exit 1
+fi
+
+# Create a subdirectory and stub for the new test
+mkdir $CSUITE_DIRECTORY/$TEST_NAME
+
+(cat <<EOF
+/*-
+ * Public Domain 2014-2016 MongoDB, Inc.
+ * Public Domain 2008-2014 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 "test_util.h"
+
+/*
+ * JIRA ticket reference:
+ * Test case description:
+ * Failure mode:
+ */
+
+void (*custom_die)(void) = NULL;
+
+int
+main(int argc, char *argv[])
+{
+ TEST_OPTS *opts, _opts;
+
+ opts = &_opts;
+ memset(opts, 0, sizeof(*opts));
+ testutil_check(testutil_parse_opts(argc, argv, opts));
+ testutil_make_work_dir(opts->home);
+
+ /*
+ * Insert test implementation here.
+ */
+
+ testutil_cleanup(opts);
+
+ return (0);
+}
+EOF
+) > $CSUITE_DIRECTORY/$TEST_NAME/main.c
+
+
+# Now update the C test suite makefile to include the new test case
+
+NEW_MAKE_SECT="test_${TEST_NAME}_SOURCES = ${TEST_NAME}\/main.c\\nnoinst_PROGRAMS = test_${TEST_NAME}\\n\\n"
+
+cat $CSUITE_DIRECTORY/Makefile.am | awk \
+ "/^# Script add new line here/ && !modif { printf(\"$NEW_MAKE_SECT\"); modif=1 } {print}" > $tmp
+
+mv $tmp $CSUITE_DIRECTORY/Makefile.am
+
+exit 0
diff --git a/dist/s_string b/dist/s_string
index 3a4f9e190d3..32aa7528979 100755
--- a/dist/s_string
+++ b/dist/s_string
@@ -31,7 +31,9 @@ replace() {
# Check the spelling of an individual file.
check() {
# Strip out git hashes, which are seven character hex strings.
- sed 's/ [0-9a-f]\{7\} / /g' ../$2 | aspell --lang=en $1 list |
+ # Strip out double quote char literals ('"'), they confuse aspell.
+ sed -e 's/ [0-9a-f]\{7\} / /g' -e "s/'\"'//g" ../$2 |
+ aspell --lang=en $1 list |
sort -u |
comm -23 /dev/stdin s_string.ok > $t
test -s $t && {
diff --git a/dist/s_string.ok b/dist/s_string.ok
index 81d09a55225..2cceccc538e 100644
--- a/dist/s_string.ok
+++ b/dist/s_string.ok
@@ -146,6 +146,7 @@ IEC
IEEE
IKEY
IMPL
+IMPL's
INCR
INIT
INITIALIZER
@@ -880,6 +881,7 @@ os
osfhandle
ovfl
ownp
+pR
packv
pagesize
parens
@@ -925,6 +927,7 @@ pushms
putK
putV
pv
+pvA
pwrite
py
qdown
@@ -1079,6 +1082,7 @@ uncompresssed
undef
unencrypted
unesc
+unescape
unescaped
unicode
uninstantiated
diff --git a/dist/stat_data.py b/dist/stat_data.py
index 0486d94e278..48066c11700 100644
--- a/dist/stat_data.py
+++ b/dist/stat_data.py
@@ -187,6 +187,9 @@ connection_stats = [
CacheStat('cache_eviction_split_leaf', 'leaf pages split during eviction'),
CacheStat('cache_eviction_walk', 'pages walked for eviction'),
CacheStat('cache_eviction_worker_evicting', 'eviction worker thread evicting pages'),
+ CacheStat('cache_hazard_checks', 'hazard pointer check calls'),
+ CacheStat('cache_hazard_max', 'hazard pointer maximum array length', 'max_aggregate,no_scale'),
+ CacheStat('cache_hazard_walks', 'hazard pointer check entries walked'),
CacheStat('cache_inmem_split', 'in-memory page splits'),
CacheStat('cache_inmem_splittable', 'in-memory page passed criteria to be split'),
CacheStat('cache_lookaside_insert', 'lookaside table insert calls'),
diff --git a/examples/c/ex_access.c b/examples/c/ex_access.c
index cc42982617b..d7f3cc557ad 100644
--- a/examples/c/ex_access.c
+++ b/examples/c/ex_access.c
@@ -60,8 +60,8 @@ main(void)
if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0 ||
(ret = conn->open_session(conn, NULL, NULL, &session)) != 0) {
fprintf(stderr, "Error connecting to %s: %s\n",
- home, wiredtiger_strerror(ret));
- return (ret);
+ home == NULL ? "." : home, wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
}
/*! [access example connection] */
@@ -95,5 +95,5 @@ main(void)
ret = conn->close(conn, NULL);
/*! [access example close] */
- return (ret);
+ return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
diff --git a/examples/c/ex_all.c b/examples/c/ex_all.c
index ea97668c697..dd807922c10 100644
--- a/examples/c/ex_all.c
+++ b/examples/c/ex_all.c
@@ -1214,5 +1214,5 @@ main(void)
/*! [Get the WiredTiger library version #2] */
}
- return (ret);
+ return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
diff --git a/examples/c/ex_async.c b/examples/c/ex_async.c
index ecdbd2f4fea..f7531a5c3d8 100644
--- a/examples/c/ex_async.c
+++ b/examples/c/ex_async.c
@@ -31,7 +31,9 @@
#include <errno.h>
#include <inttypes.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+
#ifndef _WIN32
#include <unistd.h>
#else
@@ -48,7 +50,6 @@
#define ATOMIC_ADD(v, val) __sync_add_and_fetch(&(v), val)
#endif
-static const char * const home = NULL;
static int global_error = 0;
/*! [async example callback implementation] */
@@ -120,8 +121,19 @@ main(void)
WT_CONNECTION *conn;
WT_SESSION *session;
int i, ret;
+ const char *home;
char k[MAX_KEYS][16], v[MAX_KEYS][16];
+ /*
+ * Create a clean test directory for this run of the test program if the
+ * environment variable isn't already set (as is done by make check).
+ */
+ if (getenv("WIREDTIGER_HOME") == NULL) {
+ home = "WT_HOME";
+ ret = system("rm -rf WT_HOME && mkdir WT_HOME");
+ } else
+ home = NULL;
+
/*! [async example connection] */
ret = wiredtiger_open(home, NULL,
"create,cache_size=100MB,"
@@ -148,7 +160,7 @@ main(void)
if (ret == EBUSY)
sleep(1);
else
- return (ret);
+ return (EXIT_FAILURE);
}
/*! [async handle allocation] */
@@ -198,7 +210,7 @@ main(void)
if (ret == EBUSY)
sleep(1);
else
- return (ret);
+ return (EXIT_FAILURE);
}
/*! [async search] */
@@ -220,5 +232,5 @@ main(void)
printf("Searched for %" PRIu32 " keys\n", ex_asynckeys.num_keys);
- return (ret);
+ return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
diff --git a/examples/c/ex_backup.c b/examples/c/ex_backup.c
index 12eeaa4b7c3..0697cbb3458 100644
--- a/examples/c/ex_backup.c
+++ b/examples/c/ex_backup.c
@@ -273,12 +273,12 @@ main(void)
snprintf(cmd_buf, sizeof(cmd_buf), "rm -rf %s && mkdir %s", home, home);
if ((ret = system(cmd_buf)) != 0) {
fprintf(stderr, "%s: failed ret %d\n", cmd_buf, ret);
- return (ret);
+ return (EXIT_FAILURE);
}
if ((ret = wiredtiger_open(home, NULL, CONN_CONFIG, &wt_conn)) != 0) {
fprintf(stderr, "Error connecting to %s: %s\n",
home, wiredtiger_strerror(ret));
- return (ret);
+ return (EXIT_FAILURE);
}
ret = setup_directories();
@@ -320,7 +320,9 @@ main(void)
* comparison between the incremental and original.
*/
ret = wt_conn->close(wt_conn, NULL);
+
printf("Final comparison: dumping and comparing data\n");
ret = compare_backups(0);
- return (ret);
+
+ return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
diff --git a/examples/c/ex_call_center.c b/examples/c/ex_call_center.c
index d401507d165..cd53a1cdaf9 100644
--- a/examples/c/ex_call_center.c
+++ b/examples/c/ex_call_center.c
@@ -107,8 +107,8 @@ main(void)
if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0) {
fprintf(stderr, "Error connecting to %s: %s\n",
- home, wiredtiger_strerror(ret));
- return (1);
+ home == NULL ? "." : home, wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
}
/* Note: further error checking omitted for clarity. */
@@ -245,5 +245,5 @@ main(void)
ret = conn->close(conn, NULL);
- return (ret);
+ return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
diff --git a/examples/c/ex_config_parse.c b/examples/c/ex_config_parse.c
index be3c78bedd4..40508b38204 100644
--- a/examples/c/ex_config_parse.c
+++ b/examples/c/ex_config_parse.c
@@ -32,6 +32,7 @@
#include <inttypes.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <wiredtiger.h>
@@ -51,12 +52,12 @@ main(void)
NULL, config_string, strlen(config_string), &parser)) != 0) {
fprintf(stderr, "Error creating configuration parser: %s\n",
wiredtiger_strerror(ret));
- return (ret);
+ return (EXIT_FAILURE);
}
if ((ret = parser->close(parser)) != 0) {
fprintf(stderr, "Error closing configuration parser: %s\n",
wiredtiger_strerror(ret));
- return (ret);
+ return (EXIT_FAILURE);
}
/*! [Create a configuration parser] */
@@ -64,7 +65,7 @@ main(void)
NULL, config_string, strlen(config_string), &parser)) != 0) {
fprintf(stderr, "Error creating configuration parser: %s\n",
wiredtiger_strerror(ret));
- return (ret);
+ return (EXIT_FAILURE);
}
{
@@ -76,7 +77,7 @@ main(void)
if ((ret = parser->get(parser, "page_size", &v)) != 0) {
fprintf(stderr,
"page_size configuration: %s", wiredtiger_strerror(ret));
- return (ret);
+ return (EXIT_FAILURE);
}
my_page_size = v.val;
/*! [get] */
@@ -91,7 +92,7 @@ main(void)
NULL, config_string, strlen(config_string), &parser)) != 0) {
fprintf(stderr, "Error creating configuration parser: %s\n",
wiredtiger_strerror(ret));
- return (ret);
+ return (EXIT_FAILURE);
}
/*! [next] */
/*
@@ -112,7 +113,7 @@ main(void)
NULL, config_string, strlen(config_string), &parser)) != 0) {
fprintf(stderr, "Error creating configuration parser: %s\n",
wiredtiger_strerror(ret));
- return (ret);
+ return (EXIT_FAILURE);
}
/*! [nested get] */
@@ -125,7 +126,7 @@ main(void)
if ((ret = parser->get(parser, "log.file_max", &v)) != 0) {
fprintf(stderr,
"log.file_max configuration: %s", wiredtiger_strerror(ret));
- return (ret);
+ return (EXIT_FAILURE);
}
printf("log file max: %" PRId64 "\n", v.val);
/*! [nested get] */
@@ -135,7 +136,7 @@ main(void)
NULL, config_string, strlen(config_string), &parser)) != 0) {
fprintf(stderr, "Error creating configuration parser: %s\n",
wiredtiger_strerror(ret));
- return (ret);
+ return (EXIT_FAILURE);
}
/*! [nested traverse] */
{
@@ -150,11 +151,10 @@ main(void)
"Error creating nested configuration "
"parser: %s\n",
wiredtiger_strerror(ret));
- ret = parser->close(parser);
- return (ret);
+ break;
}
- while ((ret = sub_parser->next(
- sub_parser, &k, &v)) == 0)
+ while ((ret =
+ sub_parser->next(sub_parser, &k, &v)) == 0)
printf("\t%.*s\n", (int)k.len, k.str);
ret = sub_parser->close(sub_parser);
}
@@ -163,5 +163,5 @@ main(void)
ret = parser->close(parser);
}
- return (ret);
+ return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
diff --git a/examples/c/ex_cursor.c b/examples/c/ex_cursor.c
index 67c945ebc0b..b8ed6ab169d 100644
--- a/examples/c/ex_cursor.c
+++ b/examples/c/ex_cursor.c
@@ -181,12 +181,12 @@ main(void)
if ((ret = wiredtiger_open(
home, NULL, "create,statistics=(fast)", &conn)) != 0)
fprintf(stderr, "Error connecting to %s: %s\n",
- home, wiredtiger_strerror(ret));
+ home == NULL ? "." : home, wiredtiger_strerror(ret));
/* Open a session for the current thread's work. */
if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0)
fprintf(stderr, "Error opening a session on %s: %s\n",
- home, wiredtiger_strerror(ret));
+ home == NULL ? "." : home, wiredtiger_strerror(ret));
ret = session->create(session, "table:world",
"key_format=r,value_format=5sii,"
@@ -220,9 +220,11 @@ main(void)
ret = cursor->close(cursor);
/* Note: closing the connection implicitly closes open session(s). */
- if ((ret = conn->close(conn, NULL)) != 0)
+ if ((ret = conn->close(conn, NULL)) != 0) {
fprintf(stderr, "Error closing %s: %s\n",
- home, wiredtiger_strerror(ret));
+ home == NULL ? "." : home, wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
+ }
- return (ret);
+ return (EXIT_SUCCESS);
}
diff --git a/examples/c/ex_data_source.c b/examples/c/ex_data_source.c
index dd2b835e6ae..c550b337b78 100644
--- a/examples/c/ex_data_source.c
+++ b/examples/c/ex_data_source.c
@@ -667,7 +667,7 @@ main(void)
(void)wt_api->msg_printf(wt_api, NULL, "configuration complete");
/*! [WT_EXTENSION_API default_session] */
- (void)conn->close(conn, NULL);
+ ret = conn->close(conn, NULL);
- return (ret);
+ return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
diff --git a/examples/c/ex_encrypt.c b/examples/c/ex_encrypt.c
index c53a61c92ea..a919148aff0 100644
--- a/examples/c/ex_encrypt.c
+++ b/examples/c/ex_encrypt.c
@@ -51,7 +51,7 @@ __declspec(dllexport)
#endif
int add_my_encryptors(WT_CONNECTION *connection);
-static const char *home = NULL;
+static const char *home;
#define SYS_KEYID "system"
#define SYS_PW "system_password"
@@ -587,6 +587,8 @@ main(void)
printf("Verified key %s; value %s\n", key1, val1);
}
+
ret = conn->close(conn, NULL);
- return (ret);
+
+ return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
diff --git a/examples/c/ex_event_handler.c b/examples/c/ex_event_handler.c
index ea30a5990fb..f2cdd00d9d7 100644
--- a/examples/c/ex_event_handler.c
+++ b/examples/c/ex_event_handler.c
@@ -112,7 +112,7 @@ config_event_handler(void)
/* Make an invalid API call, to ensure the event handler works. */
printf("ex_event_handler: expect an error message to follow\n");
- (void)conn->open_session(conn, NULL, "isolation=invalid", &session);
+ ret = conn->open_session(conn, NULL, "isolation=invalid", &session);
ret = conn->close(conn, NULL);
@@ -122,6 +122,8 @@ config_event_handler(void)
int
main(void)
{
+ int ret;
+
/*
* Create a clean test directory for this run of the test program if the
* environment variable isn't already set (as is done by make check).
@@ -132,5 +134,7 @@ main(void)
} else
home = NULL;
- return (config_event_handler());
+ ret = config_event_handler();
+
+ return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
diff --git a/examples/c/ex_extending.c b/examples/c/ex_extending.c
index 4d265ae1d2b..f276cdd3e1e 100644
--- a/examples/c/ex_extending.c
+++ b/examples/c/ex_extending.c
@@ -108,7 +108,7 @@ main(void)
/* Open a connection to the database, creating it if necessary. */
if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0)
fprintf(stderr, "Error connecting to %s: %s\n",
- home, wiredtiger_strerror(ret));
+ home == NULL ? "." : home, wiredtiger_strerror(ret));
/*! [add collator nocase] */
ret = conn->add_collator(conn, "nocase", &nocasecoll, NULL);
@@ -119,15 +119,12 @@ main(void)
/* Open a session for the current thread's work. */
if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0)
fprintf(stderr, "Error opening a session on %s: %s\n",
- home, wiredtiger_strerror(ret));
+ home == NULL ? "." : home, wiredtiger_strerror(ret));
- /* XXX Do some work... */
+ /* Do some work... */
- /* Note: closing the connection implicitly closes open session(s). */
- if ((ret = conn->close(conn, NULL)) != 0)
+ ret = conn->close(conn, NULL);
/*! [add collator prefix10] */
- fprintf(stderr, "Error closing %s: %s\n",
- home, wiredtiger_strerror(ret));
- return (ret);
+ return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
diff --git a/examples/c/ex_extractor.c b/examples/c/ex_extractor.c
index 8623f4759fc..f9d7af4af0f 100644
--- a/examples/c/ex_extractor.c
+++ b/examples/c/ex_extractor.c
@@ -283,5 +283,5 @@ main(void)
ret = conn->close(conn, NULL);
- return (ret);
+ return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
diff --git a/examples/c/ex_file_system.c b/examples/c/ex_file_system.c
index 18ea9b7242e..6ba0b95c338 100644
--- a/examples/c/ex_file_system.c
+++ b/examples/c/ex_file_system.c
@@ -28,12 +28,18 @@
* ex_file_system.c
* demonstrates how to use the custom file system interface
*/
-#include <assert.h>
-#include <stdlib.h>
#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
#include <string.h>
+#if (defined(_WIN32) && _MSC_VER < 1900)
+/* snprintf is not supported on <= VS2013 */
+#define snprintf _snprintf
+#endif
#include <wiredtiger.h>
+#include <wiredtiger_ext.h>
+
#include "queue_example.h"
static const char *home;
@@ -55,6 +61,8 @@ typedef struct {
/* Queue of file handles */
TAILQ_HEAD(demo_file_handle_qh, demo_file_handle) fileq;
+ WT_EXTENSION_API *wtext; /* Extension functions */
+
} DEMO_FILE_SYSTEM;
typedef struct demo_file_handle {
@@ -69,8 +77,10 @@ typedef struct demo_file_handle {
uint32_t ref; /* Reference count */
char *buf; /* In-memory contents */
- size_t size;
+ size_t bufsize; /* In-memory buffer size */
+
size_t off; /* Read/write offset */
+ size_t size; /* Read/write data size */
} DEMO_FILE_HANDLE;
/*
@@ -126,39 +136,110 @@ static DEMO_FILE_HANDLE *demo_handle_search(WT_FILE_SYSTEM *, const char *);
#define DEMO_FILE_SIZE_INCREMENT 32768
/*
+ * string_match --
+ * Return if a string matches a byte string of len bytes.
+ */
+static bool
+byte_string_match(const char *str, const char *bytes, size_t len)
+{
+ return (strncmp(str, bytes, len) == 0 && (str)[(len)] == '\0');
+}
+
+/*
* demo_file_system_create --
* Initialization point for demo file system
*/
int
demo_file_system_create(WT_CONNECTION *conn, WT_CONFIG_ARG *config)
{
- WT_FILE_SYSTEM *file_system;
DEMO_FILE_SYSTEM *demo_fs;
+ WT_CONFIG_ITEM k, v;
+ WT_CONFIG_PARSER *config_parser;
+ WT_EXTENSION_API *wtext;
+ WT_FILE_SYSTEM *file_system;
int ret = 0;
- (void)config; /* Unused */
+ wtext = conn->get_extension_api(conn);
- if ((demo_fs = calloc(1, sizeof(DEMO_FILE_SYSTEM))) == NULL)
+ if ((demo_fs = calloc(1, sizeof(DEMO_FILE_SYSTEM))) == NULL) {
+ (void)wtext->err_printf(wtext, NULL,
+ "demo_file_system_create: %s",
+ wtext->strerror(wtext, NULL, ENOMEM));
return (ENOMEM);
+ }
+ demo_fs->wtext = wtext;
file_system = (WT_FILE_SYSTEM *)demo_fs;
+ /* Retrieve our configuration information, the "config" value. */
+ if ((ret = wtext->config_get(wtext, NULL, config, "config", &v)) != 0) {
+ (void)wtext->err_printf(wtext, NULL,
+ "WT_EXTENSION_API.config_get: config: %s",
+ wtext->strerror(wtext, NULL, ret));
+ goto err;
+ }
+
+ /* Open a WiredTiger parser on the "config" value. */
+ if ((ret = wtext->config_parser_open(
+ wtext, NULL, v.str, v.len, &config_parser)) != 0) {
+ (void)wtext->err_printf(wtext, NULL,
+ "WT_EXTENSION_API.config_parser_open: config: %s",
+ wtext->strerror(wtext, NULL, ret));
+ goto err;
+ }
+
+ /* Step through our configuration values. */
+ printf("Custom file system configuration\n");
+ while ((ret = config_parser->next(config_parser, &k, &v)) == 0) {
+ if (byte_string_match("config_string", k.str, k.len)) {
+ printf("\t" "key %.*s=\"%.*s\"\n",
+ (int)k.len, k.str, (int)v.len, v.str);
+ continue;
+ }
+ if (byte_string_match("config_value", k.str, k.len)) {
+ printf("\t" "key %.*s=%" PRId64 "\n",
+ (int)k.len, k.str, v.val);
+ continue;
+ }
+ ret = EINVAL;
+ (void)wtext->err_printf(wtext, NULL,
+ "WT_CONFIG_PARSER.next: unexpected configuration "
+ "information: %.*s=%.*s: %s",
+ (int)k.len, k.str, (int)v.len, v.str,
+ wtext->strerror(wtext, NULL, ret));
+ goto err;
+ }
+
+ /* Check for expected parser termination and close the parser. */
+ if (ret != WT_NOTFOUND) {
+ (void)wtext->err_printf(wtext, NULL,
+ "WT_CONFIG_PARSER.next: config: %s",
+ wtext->strerror(wtext, NULL, ret));
+ goto err;
+ }
+ if ((ret = config_parser->close(config_parser)) != 0) {
+ (void)wtext->err_printf(wtext, NULL,
+ "WT_CONFIG_PARSER.close: config: %s",
+ wtext->strerror(wtext, NULL, ret));
+ goto err;
+ }
+
/* Initialize the in-memory jump table. */
- file_system->directory_list = demo_fs_directory_list;
- file_system->directory_list_free = demo_fs_directory_list_free;
- file_system->directory_sync = demo_fs_directory_sync;
- file_system->exist = demo_fs_exist;
- file_system->open_file = demo_fs_open;
- file_system->remove = demo_fs_remove;
- file_system->rename = demo_fs_rename;
- file_system->size = demo_fs_size;
+ file_system->fs_directory_list = demo_fs_directory_list;
+ file_system->fs_directory_list_free = demo_fs_directory_list_free;
+ file_system->fs_directory_sync = demo_fs_directory_sync;
+ file_system->fs_exist = demo_fs_exist;
+ file_system->fs_open_file = demo_fs_open;
+ file_system->fs_remove = demo_fs_remove;
+ file_system->fs_rename = demo_fs_rename;
+ file_system->fs_size = demo_fs_size;
file_system->terminate = demo_fs_terminate;
if ((ret = conn->set_file_system(conn, file_system, NULL)) != 0) {
- fprintf(stderr, "Error setting custom file system: %s\n",
- wiredtiger_strerror(ret));
+ (void)wtext->err_printf(wtext, NULL,
+ "WT_CONNECTION.set_file_system: %s",
+ wtext->strerror(wtext, NULL, ret));
goto err;
}
-
return (0);
err: free(demo_fs);
@@ -175,16 +256,17 @@ demo_fs_open(WT_FILE_SYSTEM *file_system, WT_SESSION *session,
const char *name, WT_OPEN_FILE_TYPE file_type, uint32_t flags,
WT_FILE_HANDLE **file_handlep)
{
- WT_FILE_HANDLE *file_handle;
DEMO_FILE_HANDLE *demo_fh;
DEMO_FILE_SYSTEM *demo_fs;
+ WT_EXTENSION_API *wtext;
+ WT_FILE_HANDLE *file_handle;
(void)file_type; /* Unused */
- (void)session; /* Unused */
(void)flags; /* Unused */
demo_fs = (DEMO_FILE_SYSTEM *)file_system;
demo_fh = NULL;
+ wtext = demo_fs->wtext;
++demo_fs->opened_file_count;
@@ -195,9 +277,8 @@ demo_fs_open(WT_FILE_SYSTEM *file_system, WT_SESSION *session,
demo_fh = demo_handle_search(file_system, name);
if (demo_fh != NULL) {
if (demo_fh->ref != 0) {
- fprintf(stderr,
- "demo_file_open of already open file %s\n",
- name);
+ (void)wtext->err_printf(wtext, session,
+ "demo_fs_open: %s: file already open", name);
return (EBUSY);
}
@@ -214,11 +295,11 @@ demo_fs_open(WT_FILE_SYSTEM *file_system, WT_SESSION *session,
/* Initialize private information. */
demo_fh->ref = 1;
- demo_fh->off = 0;
+ demo_fh->off = demo_fh->size = 0;
demo_fh->demo_fs = demo_fs;
if ((demo_fh->buf = calloc(1, DEMO_FILE_SIZE_INCREMENT)) == NULL)
goto enomem;
- demo_fh->size = DEMO_FILE_SIZE_INCREMENT;
+ demo_fh->bufsize = DEMO_FILE_SIZE_INCREMENT;
/* Initialize public information. */
file_handle = (WT_FILE_HANDLE *)demo_fh;
@@ -231,20 +312,20 @@ demo_fs_open(WT_FILE_SYSTEM *file_system, WT_SESSION *session,
* the functionality.
*/
file_handle->close = demo_file_close;
- file_handle->fadvise = NULL;
- file_handle->fallocate = NULL;
- file_handle->fallocate_nolock = NULL;
- file_handle->lock = demo_file_lock;
- file_handle->map = NULL;
- file_handle->map_discard = NULL;
- file_handle->map_preload = NULL;
- file_handle->unmap = NULL;
- file_handle->read = demo_file_read;
- file_handle->size = demo_file_size;
- file_handle->sync = demo_file_sync;
- file_handle->sync_nowait = demo_file_sync_nowait;
- file_handle->truncate = demo_file_truncate;
- file_handle->write = demo_file_write;
+ file_handle->fh_advise = NULL;
+ file_handle->fh_allocate = NULL;
+ file_handle->fh_allocate_nolock = NULL;
+ file_handle->fh_lock = demo_file_lock;
+ file_handle->fh_map = NULL;
+ file_handle->fh_map_discard = NULL;
+ file_handle->fh_map_preload = NULL;
+ file_handle->fh_unmap = NULL;
+ file_handle->fh_read = demo_file_read;
+ file_handle->fh_size = demo_file_size;
+ file_handle->fh_sync = demo_file_sync;
+ file_handle->fh_sync_nowait = demo_file_sync_nowait;
+ file_handle->fh_truncate = demo_file_truncate;
+ file_handle->fh_write = demo_file_write;
TAILQ_INSERT_HEAD(&demo_fs->fileq, demo_fh, q);
++demo_fs->opened_unique_file_count;
@@ -456,12 +537,14 @@ static int
demo_file_close(WT_FILE_HANDLE *file_handle, WT_SESSION *session)
{
DEMO_FILE_HANDLE *demo_fh;
-
- (void)session; /* Unused */
+ WT_EXTENSION_API *wtext;
demo_fh = (DEMO_FILE_HANDLE *)file_handle;
+ wtext = demo_fh->demo_fs->wtext;
+
if (demo_fh->ref < 1) {
- fprintf(stderr, "Closing already closed handle: %s\n",
+ (void)wtext->err_printf(wtext, session,
+ "demo_file_close: %s: handle already closed",
demo_fh->iface.name);
return (EINVAL);
}
@@ -496,11 +579,12 @@ demo_file_read(WT_FILE_HANDLE *file_handle,
WT_SESSION *session, wt_off_t offset, size_t len, void *buf)
{
DEMO_FILE_HANDLE *demo_fh;
- int ret = 0;
+ WT_EXTENSION_API *wtext;
size_t off;
+ int ret = 0;
- (void)session; /* Unused */
demo_fh = (DEMO_FILE_HANDLE *)file_handle;
+ wtext = demo_fh->demo_fs->wtext;
off = (size_t)offset;
if (off < demo_fh->size) {
@@ -509,18 +593,19 @@ demo_file_read(WT_FILE_HANDLE *file_handle,
memcpy(buf, (uint8_t *)demo_fh->buf + off, len);
demo_fh->off = off + len;
} else
- ret = EINVAL;
+ ret = EINVAL; /* EOF */
if (ret == 0)
return (0);
+
/*
* WiredTiger should never request data past the end of a file, so
* flag an error if it does.
*/
- fprintf(stderr,
- "%s: handle-read: failed to read %zu bytes at offset %zu\n",
- demo_fh->iface.name, len, off);
- return (EINVAL);
+ (void)wtext->err_printf(wtext, session,
+ "%s: handle-read: failed to read %zu bytes at offset %zu: %s",
+ demo_fh->iface.name, len, off, wtext->strerror(wtext, NULL, ret));
+ return (ret);
}
/*
@@ -536,7 +621,6 @@ demo_file_size(
(void)session; /* Unused */
demo_fh = (DEMO_FILE_HANDLE *)file_handle;
- assert(demo_fh->size != 0);
*sizep = (wt_off_t)demo_fh->size;
return (0);
}
@@ -578,20 +662,26 @@ demo_file_truncate(
WT_FILE_HANDLE *file_handle, WT_SESSION *session, wt_off_t offset)
{
DEMO_FILE_HANDLE *demo_fh;
+ WT_EXTENSION_API *wtext;
size_t off;
- (void)session; /* Unused */
demo_fh = (DEMO_FILE_HANDLE *)file_handle;
+ wtext = demo_fh->demo_fs->wtext;
/*
* Grow the buffer as necessary, clear any new space in the file,
* and reset the file's data length.
*/
off = (size_t)offset;
- demo_fh->buf = realloc(demo_fh->buf, off);
- if (demo_fh->buf == NULL) {
- fprintf(stderr, "Failed to resize buffer in truncate\n");
- return (ENOSPC);
+ if (demo_fh->bufsize < off ) {
+ if ((demo_fh->buf = realloc(demo_fh->buf, off)) == NULL) {
+ (void)wtext->err_printf(wtext, session,
+ "demo_file_truncate: %s: failed to resize buffer",
+ demo_fh->iface.name,
+ wtext->strerror(wtext, NULL, ENOMEM));
+ return (ENOMEM);
+ }
+ demo_fh->bufsize = off;
}
if (demo_fh->size < off)
memset((uint8_t *)demo_fh->buf + demo_fh->size,
@@ -610,6 +700,7 @@ demo_file_write(WT_FILE_HANDLE *file_handle, WT_SESSION *session,
wt_off_t offset, size_t len, const void *buf)
{
DEMO_FILE_HANDLE *demo_fh;
+ size_t off;
int ret = 0;
demo_fh = (DEMO_FILE_HANDLE *)file_handle;
@@ -619,8 +710,11 @@ demo_file_write(WT_FILE_HANDLE *file_handle, WT_SESSION *session,
offset + (wt_off_t)(len + DEMO_FILE_SIZE_INCREMENT))) != 0)
return (ret);
- memcpy((uint8_t *)demo_fh->buf + offset, buf, len);
- demo_fh->off = (size_t)offset + len;
+ off = (size_t)offset;
+ memcpy((uint8_t *)demo_fh->buf + off, buf, len);
+ if (off + len > demo_fh->size)
+ demo_fh->size = off + len;
+ demo_fh->off = off + len;
return (0);
}
@@ -634,16 +728,16 @@ static int
demo_handle_remove(WT_SESSION *session, DEMO_FILE_HANDLE *demo_fh)
{
DEMO_FILE_SYSTEM *demo_fs;
+ WT_EXTENSION_API *wtext;
- (void)session; /* Unused */
demo_fs = demo_fh->demo_fs;
+ wtext = demo_fh->demo_fs->wtext;
if (demo_fh->ref != 0) {
- fprintf(stderr,
- "demo_handle_remove on file %s with non-zero reference "
- "count of %u\n",
- demo_fh->iface.name, demo_fh->ref);
- return (EINVAL);
+ (void)wtext->err_printf(wtext, session,
+ "demo_handle_remove: %s: file is currently open",
+ demo_fh->iface.name, wtext->strerror(wtext, NULL, EBUSY));
+ return (EBUSY);
}
TAILQ_REMOVE(&demo_fs->fileq, demo_fh, q);
@@ -682,8 +776,12 @@ int
main(void)
{
WT_CONNECTION *conn;
- const char *open_config;
+ WT_CURSOR *cursor;
+ WT_SESSION *session;
+ const char *key, *open_config, *uri;
+ int i;
int ret = 0;
+ char kbuf[64];
/*
* Create a clean test directory for this run of the test program if the
@@ -701,21 +799,89 @@ main(void)
* Use the special local extension to indicate that the entry point is
* in the same executable. Also enable early load for this extension,
* since WiredTiger needs to be able to find it before doing any file
- * operations.
+ * operations. Finally, pass in two pieces of configuration information
+ * to our initialization function as the "config" value.
*/
- open_config = "create,log=(enabled=true),extensions=(local="
- "{entry=demo_file_system_create,early_load=true})";
+ open_config = "create,log=(enabled=true),extensions=(local={"
+ "entry=demo_file_system_create,early_load=true,"
+ "config={config_string=\"demo-file-system\",config_value=37}"
+ "})";
/* Open a connection to the database, creating it if necessary. */
if ((ret = wiredtiger_open(home, NULL, open_config, &conn)) != 0) {
fprintf(stderr, "Error connecting to %s: %s\n",
- home, wiredtiger_strerror(ret));
- return (ret);
+ home == NULL ? "." : home, wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
}
/*! [WT_FILE_SYSTEM register] */
- if ((ret = conn->close(conn, NULL)) != 0)
+ if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0) {
+ fprintf(stderr, "WT_CONNECTION.open_session: %s\n",
+ wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
+ }
+ uri = "table:fs";
+ if ((ret = session->create(
+ session, uri, "key_format=S,value_format=S")) != 0) {
+ fprintf(stderr, "WT_SESSION.create: %s: %s\n",
+ uri, wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
+ }
+ if ((ret = session->open_cursor(
+ session, uri, NULL, NULL, &cursor)) != 0) {
+ fprintf(stderr, "WT_SESSION.open_cursor: %s: %s\n",
+ uri, wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
+ }
+ for (i = 0; i < 1000; ++i) {
+ (void)snprintf(kbuf, sizeof(kbuf), "%010d KEY -----", i);
+ cursor->set_key(cursor, kbuf);
+ cursor->set_value(cursor, "--- VALUE ---");
+ if ((ret = cursor->insert(cursor)) != 0) {
+ fprintf(stderr, "WT_CURSOR.insert: %s: %s\n",
+ kbuf, wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
+ }
+ }
+ if ((ret = cursor->close(cursor)) != 0) {
+ fprintf(stderr, "WT_CURSOR.close: %s\n",
+ wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
+ }
+ if ((ret = session->open_cursor(
+ session, uri, NULL, NULL, &cursor)) != 0) {
+ fprintf(stderr, "WT_SESSION.open_cursor: %s: %s\n",
+ uri, wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
+ }
+ for (i = 0; i < 1000; ++i) {
+ if ((ret = cursor->next(cursor)) != 0) {
+ fprintf(stderr, "WT_CURSOR.insert: %s: %s\n",
+ kbuf, wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
+ }
+ (void)snprintf(kbuf, sizeof(kbuf), "%010d KEY -----", i);
+ if ((ret = cursor->get_key(cursor, &key)) != 0) {
+ fprintf(stderr, "WT_CURSOR.get_key: %s\n",
+ wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
+ }
+ if (strcmp(kbuf, key) != 0) {
+ fprintf(stderr, "Key mismatch: %s, %s\n", kbuf, key);
+ return (EXIT_FAILURE);
+ }
+ }
+ if ((ret = cursor->next(cursor)) != WT_NOTFOUND) {
+ fprintf(stderr,
+ "WT_CURSOR.insert: expected WT_NOTFOUND, got %s\n",
+ wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
+ }
+
+ if ((ret = conn->close(conn, NULL)) != 0) {
fprintf(stderr, "Error closing connection to %s: %s\n",
- home, wiredtiger_strerror(ret));
+ home == NULL ? "." : home, wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
+ }
- return (ret);
+ return (EXIT_SUCCESS);
}
diff --git a/examples/c/ex_hello.c b/examples/c/ex_hello.c
index 345e434741f..99534ee8868 100644
--- a/examples/c/ex_hello.c
+++ b/examples/c/ex_hello.c
@@ -56,21 +56,27 @@ main(void)
home = NULL;
/* Open a connection to the database, creating it if necessary. */
- if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0)
+ if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0) {
fprintf(stderr, "Error connecting to %s: %s\n",
- home, wiredtiger_strerror(ret));
+ home == NULL ? "." : home, wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
+ }
/* Open a session for the current thread's work. */
- if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0)
+ if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0) {
fprintf(stderr, "Error opening a session on %s: %s\n",
- home, wiredtiger_strerror(ret));
+ home == NULL ? "." : home, wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
+ }
/* Do some work... */
/* Note: closing the connection implicitly closes open session(s). */
- if ((ret = conn->close(conn, NULL)) != 0)
+ if ((ret = conn->close(conn, NULL)) != 0) {
fprintf(stderr, "Error closing %s: %s\n",
- home, wiredtiger_strerror(ret));
+ home == NULL ? "." : home, wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
+ }
- return (ret);
+ return (EXIT_SUCCESS);
}
diff --git a/examples/c/ex_log.c b/examples/c/ex_log.c
index 78bd7e683cf..fdbc39412ae 100644
--- a/examples/c/ex_log.c
+++ b/examples/c/ex_log.c
@@ -295,12 +295,12 @@ main(void)
home1, home2, home1, home2);
if ((ret = system(cmd_buf)) != 0) {
fprintf(stderr, "%s: failed ret %d\n", cmd_buf, ret);
- return (ret);
+ return (EXIT_FAILURE);
}
if ((ret = wiredtiger_open(home1, NULL, CONN_CONFIG, &wt_conn)) != 0) {
fprintf(stderr, "Error connecting to %s: %s\n",
home1, wiredtiger_strerror(ret));
- return (ret);
+ return (EXIT_FAILURE);
}
ret = wt_conn->open_session(wt_conn, NULL, NULL, &session);
@@ -348,12 +348,13 @@ main(void)
if ((ret = wiredtiger_open(home1, NULL, CONN_CONFIG, &wt_conn)) != 0) {
fprintf(stderr, "Error connecting to %s: %s\n",
home1, wiredtiger_strerror(ret));
- return (ret);
+ return (EXIT_FAILURE);
}
ret = wt_conn->open_session(wt_conn, NULL, NULL, &session);
ret = simple_walk_log(session, count_min);
ret = walk_log(session);
ret = wt_conn->close(wt_conn, NULL);
- return (ret);
+
+ return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
diff --git a/examples/c/ex_pack.c b/examples/c/ex_pack.c
index 43b57880674..86725123f55 100644
--- a/examples/c/ex_pack.c
+++ b/examples/c/ex_pack.c
@@ -55,14 +55,18 @@ main(void)
home = NULL;
/* Open a connection to the database, creating it if necessary. */
- if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0)
+ if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0) {
fprintf(stderr, "Error connecting to %s: %s\n",
- home, wiredtiger_strerror(ret));
+ home == NULL ? "." : home, wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
+ }
/* Open a session for the current thread's work. */
- if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0)
+ if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0) {
fprintf(stderr, "Error opening a session on %s: %s\n",
- home, wiredtiger_strerror(ret));
+ home == NULL ? "." : home, wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
+ }
{
/*! [packing] */
@@ -81,9 +85,11 @@ main(void)
}
/* Note: closing the connection implicitly closes open session(s). */
- if ((ret = conn->close(conn, NULL)) != 0)
+ if ((ret = conn->close(conn, NULL)) != 0) {
fprintf(stderr, "Error closing %s: %s\n",
- home, wiredtiger_strerror(ret));
+ home == NULL ? "." : home, wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
+ }
- return (ret);
+ return (EXIT_SUCCESS);
}
diff --git a/examples/c/ex_process.c b/examples/c/ex_process.c
index 19f395dddaf..217730c4288 100644
--- a/examples/c/ex_process.c
+++ b/examples/c/ex_process.c
@@ -58,22 +58,28 @@ main(void)
/*! [processes] */
/* Open a connection to the database, creating it if necessary. */
if ((ret =
- wiredtiger_open(home, NULL, "create,multiprocess", &conn)) != 0)
+ wiredtiger_open(home, NULL, "create,multiprocess", &conn)) != 0) {
fprintf(stderr, "Error connecting to %s: %s\n",
- home, wiredtiger_strerror(ret));
+ home == NULL ? "." : home, wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
+ }
/* Open a session for the current thread's work. */
- if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0)
+ if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0) {
fprintf(stderr, "Error opening a session on %s: %s\n",
- home, wiredtiger_strerror(ret));
+ home == NULL ? "." : home, wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
+ }
/* XXX Do some work... */
/* Note: closing the connection implicitly closes open session(s). */
- if ((ret = conn->close(conn, NULL)) != 0)
+ if ((ret = conn->close(conn, NULL)) != 0) {
fprintf(stderr, "Error closing %s: %s\n",
- home, wiredtiger_strerror(ret));
+ home == NULL ? "." : home, wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
+ }
/*! [processes] */
- return (ret);
+ return (EXIT_SUCCESS);
}
diff --git a/examples/c/ex_schema.c b/examples/c/ex_schema.c
index 155b982bbbe..a59d9480780 100644
--- a/examples/c/ex_schema.c
+++ b/examples/c/ex_schema.c
@@ -90,8 +90,8 @@ main(void)
if ((ret = wiredtiger_open(
home, NULL, "create,statistics=(fast)", &conn)) != 0) {
fprintf(stderr, "Error connecting to %s: %s\n",
- home, wiredtiger_strerror(ret));
- return (ret);
+ home == NULL ? "." : home, wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
}
/* Note: error checking omitted for clarity. */
@@ -429,5 +429,5 @@ main(void)
ret = conn->close(conn, NULL);
- return (ret);
+ return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
diff --git a/examples/c/ex_scope.c b/examples/c/ex_scope.c
index ef4d67ad722..795ad85d57b 100644
--- a/examples/c/ex_scope.c
+++ b/examples/c/ex_scope.c
@@ -182,7 +182,7 @@ main(void)
WT_CONNECTION *conn;
WT_CURSOR *cursor;
WT_SESSION *session;
- int ret, tret;
+ int ret;
/*
* Create a clean test directory for this run of the test program if the
@@ -198,8 +198,8 @@ main(void)
if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0 ||
(ret = conn->open_session(conn, NULL, NULL, &session)) != 0) {
fprintf(stderr, "Error connecting to %s: %s\n",
- home, wiredtiger_strerror(ret));
- return (ret);
+ home == NULL ? "." : home, wiredtiger_strerror(ret));
+ return (EXIT_FAILURE);
}
ret = session->create(session,
@@ -211,8 +211,7 @@ main(void)
ret = cursor_scope_ops(cursor);
/* Close the connection and clean up. */
- if ((tret = conn->close(conn, NULL)) != 0 && ret == 0)
- ret = tret;
+ ret = conn->close(conn, NULL);
- return (ret);
+ return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
diff --git a/examples/c/ex_stat.c b/examples/c/ex_stat.c
index 6c5c15aacc6..ba473d6be04 100644
--- a/examples/c/ex_stat.c
+++ b/examples/c/ex_stat.c
@@ -235,9 +235,8 @@ main(void)
ret = wiredtiger_open(home, NULL, "create,statistics=(all)", &conn);
ret = conn->open_session(conn, NULL, NULL, &session);
- ret = session->create(
- session, "table:access",
- "key_format=S,value_format=S,columns=(k,v)");
+ ret = session->create(session,
+ "table:access", "key_format=S,value_format=S,columns=(k,v)");
ret = session->open_cursor(
session, "table:access", NULL, NULL, &cursor);
@@ -258,5 +257,7 @@ main(void)
ret = print_derived_stats(session);
- return (conn->close(conn, NULL) == 0 ? ret : EXIT_FAILURE);
+ ret = conn->close(conn, NULL);
+
+ return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
diff --git a/examples/c/ex_sync.c b/examples/c/ex_sync.c
index 8c3a6463a82..2c610b1e570 100644
--- a/examples/c/ex_sync.c
+++ b/examples/c/ex_sync.c
@@ -63,12 +63,12 @@ main(void)
home, home);
if ((ret = system(cmd_buf)) != 0) {
fprintf(stderr, "%s: failed ret %d\n", cmd_buf, ret);
- return (ret);
+ return (EXIT_FAILURE);
}
if ((ret = wiredtiger_open(home, NULL, CONN_CONFIG, &wt_conn)) != 0) {
fprintf(stderr, "Error connecting to %s: %s\n",
home, wiredtiger_strerror(ret));
- return (ret);
+ return (EXIT_FAILURE);
}
ret = wt_conn->open_session(wt_conn, NULL, NULL, &session);
@@ -149,5 +149,6 @@ main(void)
ret = session->log_flush(session, "sync=on");
ret = wt_conn->close(wt_conn, NULL);
- return (ret);
+
+ return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
diff --git a/examples/c/ex_thread.c b/examples/c/ex_thread.c
index a72211b6243..7c52d3b8189 100644
--- a/examples/c/ex_thread.c
+++ b/examples/c/ex_thread.c
@@ -101,7 +101,7 @@ main(void)
if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0)
fprintf(stderr, "Error connecting to %s: %s\n",
- home, wiredtiger_strerror(ret));
+ home == NULL ? "." : home, wiredtiger_strerror(ret));
/* Note: further error checking omitted for clarity. */
ret = conn->open_session(conn, NULL, NULL, &session);
@@ -122,6 +122,6 @@ main(void)
ret = conn->close(conn, NULL);
- return (ret);
+ return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
/*! [thread main] */
diff --git a/src/block/block_map.c b/src/block/block_map.c
index ce6fe8602f5..d2c70fb4c49 100644
--- a/src/block/block_map.c
+++ b/src/block/block_map.c
@@ -46,7 +46,7 @@ __wt_block_map(WT_SESSION_IMPL *session, WT_BLOCK *block,
* There may be no underlying functionality.
*/
handle = block->fh->handle;
- if (handle->map == NULL)
+ if (handle->fh_map == NULL)
return (0);
/*
@@ -54,7 +54,7 @@ __wt_block_map(WT_SESSION_IMPL *session, WT_BLOCK *block,
* Ignore not-supported errors, we'll read the file through the cache
* if map fails.
*/
- ret = handle->map(handle,
+ ret = handle->fh_map(handle,
(WT_SESSION *)session, mapped_regionp, lengthp, mapped_cookiep);
if (ret == ENOTSUP) {
*(void **)mapped_regionp = NULL;
@@ -76,6 +76,6 @@ __wt_block_unmap(WT_SESSION_IMPL *session,
/* Unmap the file from memory. */
handle = block->fh->handle;
- return (handle->unmap(handle,
+ return (handle->fh_unmap(handle,
(WT_SESSION *)session, mapped_region, length, mapped_cookie));
}
diff --git a/src/block/block_mgr.c b/src/block/block_mgr.c
index 465952d8ca5..971fe713f83 100644
--- a/src/block/block_mgr.c
+++ b/src/block/block_mgr.c
@@ -311,7 +311,7 @@ __bm_map_discard(WT_BM *bm, WT_SESSION_IMPL *session, void *map, size_t len)
WT_FILE_HANDLE *handle;
handle = bm->block->fh->handle;
- return (handle->map_discard(
+ return (handle->fh_map_discard(
handle, (WT_SESSION *)session, map, len, bm->mapped_cookie));
}
diff --git a/src/block/block_read.c b/src/block/block_read.c
index 7304f6ff4bc..97157e4a0f1 100644
--- a/src/block/block_read.c
+++ b/src/block/block_read.c
@@ -35,11 +35,11 @@ __wt_bm_preload(
handle = block->fh->handle;
mapped = bm->map != NULL && offset + size <= (wt_off_t)bm->maplen;
- if (mapped && handle->map_preload != NULL)
- ret = handle->map_preload(handle, (WT_SESSION *)session,
+ if (mapped && handle->fh_map_preload != NULL)
+ ret = handle->fh_map_preload(handle, (WT_SESSION *)session,
(uint8_t *)bm->map + offset, size, bm->mapped_cookie);
- if (!mapped && handle->fadvise != NULL)
- ret = handle->fadvise(handle, (WT_SESSION *)session,
+ if (!mapped && handle->fh_advise != NULL)
+ ret = handle->fh_advise(handle, (WT_SESSION *)session,
(wt_off_t)offset, (wt_off_t)size, WT_FILE_HANDLE_WILLNEED);
if (ret != EBUSY && ret != ENOTSUP)
return (ret);
@@ -78,10 +78,10 @@ __wt_bm_read(WT_BM *bm, WT_SESSION_IMPL *session,
*/
handle = block->fh->handle;
mapped = bm->map != NULL && offset + size <= (wt_off_t)bm->maplen;
- if (mapped && handle->map_preload != NULL) {
+ if (mapped && handle->fh_map_preload != NULL) {
buf->data = (uint8_t *)bm->map + offset;
buf->size = size;
- ret = handle->map_preload(handle, (WT_SESSION *)session,
+ ret = handle->fh_map_preload(handle, (WT_SESSION *)session,
buf->data, buf->size,bm->mapped_cookie);
WT_STAT_FAST_CONN_INCR(session, block_map_read);
diff --git a/src/block/block_write.c b/src/block/block_write.c
index 4f1224f3c13..1fefeee09da 100644
--- a/src/block/block_write.c
+++ b/src/block/block_write.c
@@ -52,7 +52,7 @@ __wt_block_discard(WT_SESSION_IMPL *session, WT_BLOCK *block, size_t added_size)
/* The file may not support this call. */
handle = block->fh->handle;
- if (handle->fadvise == NULL)
+ if (handle->fh_advise == NULL)
return (0);
/* The call may not be configured. */
@@ -67,7 +67,7 @@ __wt_block_discard(WT_SESSION_IMPL *session, WT_BLOCK *block, size_t added_size)
return (0);
block->os_cache = 0;
- ret = handle->fadvise(handle, (WT_SESSION *)session,
+ ret = handle->fh_advise(handle, (WT_SESSION *)session,
(wt_off_t)0, (wt_off_t)0, WT_FILE_HANDLE_DONTNEED);
return (ret == EBUSY || ret == ENOTSUP ? 0 : ret);
}
@@ -128,7 +128,8 @@ __wt_block_extend(WT_SESSION_IMPL *session, WT_BLOCK *block,
* and remember that ftruncate requires locking.
*/
handle = fh->handle;
- if (handle->fallocate != NULL || handle->fallocate_nolock != NULL) {
+ if (handle->fh_allocate != NULL ||
+ handle->fh_allocate_nolock != NULL) {
/*
* Release any locally acquired lock if not needed to extend the
* file, extending the file may require updating on-disk file's
@@ -136,7 +137,7 @@ __wt_block_extend(WT_SESSION_IMPL *session, WT_BLOCK *block,
* configure for file extension on systems that require locking
* over the extend call.)
*/
- if (handle->fallocate_nolock != NULL && *release_lockp) {
+ if (handle->fh_allocate_nolock != NULL && *release_lockp) {
*release_lockp = locked = false;
__wt_spin_unlock(session, &block->live_lock);
}
diff --git a/src/checksum/power8/crc32.S b/src/checksum/power8/crc32.S
index c0b81143f07..f990acb7b12 100644
--- a/src/checksum/power8/crc32.S
+++ b/src/checksum/power8/crc32.S
@@ -769,3 +769,10 @@ FUNC_START(__crc32_vpmsum)
FUNC_END(__crc32_vpmsum)
#endif
+
+/*
+ * Make sure the stack isn't executable with GCC (regardless of platform).
+ */
+#ifndef __clang__
+.section .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/config/config_collapse.c b/src/config/config_collapse.c
index 27bd6255a0a..591d22284f5 100644
--- a/src/config/config_collapse.c
+++ b/src/config/config_collapse.c
@@ -38,6 +38,8 @@ __wt_config_collapse(
WT_DECL_ITEM(tmp);
WT_DECL_RET;
+ *config_ret = NULL;
+
WT_RET(__wt_scr_alloc(session, 0, &tmp));
WT_ERR(__wt_config_init(session, &cparser, cfg[0]));
@@ -59,6 +61,8 @@ __wt_config_collapse(
WT_ERR(__wt_buf_catfmt(session, tmp, "%.*s=%.*s,",
(int)k.len, k.str, (int)v.len, v.str));
}
+
+ /* We loop until error, and the expected error is WT_NOTFOUND. */
if (ret != WT_NOTFOUND)
goto err;
diff --git a/src/config/config_def.c b/src/config/config_def.c
index c7bbdf50280..7a75db8857d 100644
--- a/src/config/config_def.c
+++ b/src/config/config_def.c
@@ -292,6 +292,7 @@ static const WT_CONFIG_CHECK confchk_WT_SESSION_create[] = {
};
static const WT_CONFIG_CHECK confchk_WT_SESSION_drop[] = {
+ { "checkpoint_wait", "boolean", NULL, NULL, NULL, 0 },
{ "force", "boolean", NULL, NULL, NULL, 0 },
{ "lock_wait", "boolean", NULL, NULL, NULL, 0 },
{ "remove_files", "boolean", NULL, NULL, NULL, 0 },
@@ -1034,8 +1035,8 @@ static const WT_CONFIG_ENTRY config_entries[] = {
confchk_WT_SESSION_create, 40
},
{ "WT_SESSION.drop",
- "force=0,lock_wait=,remove_files=",
- confchk_WT_SESSION_drop, 3
+ "checkpoint_wait=,force=0,lock_wait=,remove_files=",
+ confchk_WT_SESSION_drop, 4
},
{ "WT_SESSION.join",
"bloom_bit_count=16,bloom_hash_count=8,compare=\"eq\",count=,"
diff --git a/src/conn/conn_api.c b/src/conn/conn_api.c
index 18ad383ec74..279e3d4a8b5 100644
--- a/src/conn/conn_api.c
+++ b/src/conn/conn_api.c
@@ -1919,16 +1919,16 @@ __conn_chk_file_system(WT_SESSION_IMPL *session, bool readonly)
WT_RET_MSG(session, EINVAL, \
"a WT_FILE_SYSTEM.%s method must be configured", #name)
- WT_CONN_SET_FILE_SYSTEM_REQ(directory_list);
- WT_CONN_SET_FILE_SYSTEM_REQ(directory_list_free);
+ WT_CONN_SET_FILE_SYSTEM_REQ(fs_directory_list);
+ WT_CONN_SET_FILE_SYSTEM_REQ(fs_directory_list_free);
/* not required: directory_sync */
- WT_CONN_SET_FILE_SYSTEM_REQ(exist);
- WT_CONN_SET_FILE_SYSTEM_REQ(open_file);
+ WT_CONN_SET_FILE_SYSTEM_REQ(fs_exist);
+ WT_CONN_SET_FILE_SYSTEM_REQ(fs_open_file);
if (!readonly) {
- WT_CONN_SET_FILE_SYSTEM_REQ(remove);
- WT_CONN_SET_FILE_SYSTEM_REQ(rename);
+ WT_CONN_SET_FILE_SYSTEM_REQ(fs_remove);
+ WT_CONN_SET_FILE_SYSTEM_REQ(fs_rename);
}
- WT_CONN_SET_FILE_SYSTEM_REQ(size);
+ WT_CONN_SET_FILE_SYSTEM_REQ(fs_size);
return (0);
}
@@ -2012,6 +2012,14 @@ wiredtiger_open(const char *home, WT_EVENT_HANDLER *event_handler,
WT_ERR(__wt_os_stdio(session));
__wt_event_handler_set(session, event_handler);
+ /*
+ * Set the default session's strerror method. If one of the extensions
+ * being loaded reports an error via the WT_EXTENSION_API strerror
+ * method, but doesn't supply that method a WT_SESSION handle, we'll
+ * use the WT_CONNECTION_IMPL's default session and its strerror method.
+ */
+ conn->default_session->iface.strerror = __wt_session_strerror;
+
/* Basic initialization of the connection structure. */
WT_ERR(__wt_connection_init(conn));
diff --git a/src/conn/conn_cache_pool.c b/src/conn/conn_cache_pool.c
index 1e34b514aa7..898bd09ece9 100644
--- a/src/conn/conn_cache_pool.c
+++ b/src/conn/conn_cache_pool.c
@@ -571,6 +571,7 @@ __cache_pool_adjust(WT_SESSION_IMPL *session,
cp = __wt_process.cache_pool;
grow = false;
pool_full = cp->currently_used >= cp->size;
+ pct_full = 0;
/* Highest as a percentage, avoid 0 */
highest_percentile = (highest / 100) + 1;
diff --git a/src/cursor/cur_join.c b/src/cursor/cur_join.c
index fd7de53c981..b35558e04b3 100644
--- a/src/cursor/cur_join.c
+++ b/src/cursor/cur_join.c
@@ -45,7 +45,6 @@ __wt_curjoin_joined(WT_CURSOR *cursor)
/*
* __curjoin_iter_init --
* Initialize an iteration for the index managed by a join entry.
- *
*/
static int
__curjoin_iter_init(WT_SESSION_IMPL *session, WT_CURSOR_JOIN *cjoin,
@@ -66,7 +65,6 @@ __curjoin_iter_init(WT_SESSION_IMPL *session, WT_CURSOR_JOIN *cjoin,
/*
* __curjoin_iter_close --
* Close the iteration, release resources.
- *
*/
static int
__curjoin_iter_close(WT_CURSOR_JOIN_ITER *iter)
@@ -82,7 +80,6 @@ __curjoin_iter_close(WT_CURSOR_JOIN_ITER *iter)
/*
* __curjoin_iter_close_all --
* Free the iterator and all of its children recursively.
- *
*/
static int
__curjoin_iter_close_all(WT_CURSOR_JOIN_ITER *iter)
@@ -105,7 +102,6 @@ __curjoin_iter_close_all(WT_CURSOR_JOIN_ITER *iter)
/*
* __curjoin_iter_reset --
* Reset an iteration to the starting point.
- *
*/
static int
__curjoin_iter_reset(WT_CURSOR_JOIN_ITER *iter)
@@ -120,7 +116,6 @@ __curjoin_iter_reset(WT_CURSOR_JOIN_ITER *iter)
/*
* __curjoin_iter_ready --
* Check the positioned flag for all nested iterators.
- *
*/
static bool
__curjoin_iter_ready(WT_CURSOR_JOIN_ITER *iter)
@@ -136,7 +131,6 @@ __curjoin_iter_ready(WT_CURSOR_JOIN_ITER *iter)
/*
* __curjoin_iter_set_entry --
* Set the current entry for an iterator.
- *
*/
static int
__curjoin_iter_set_entry(WT_CURSOR_JOIN_ITER *iter, u_int entry_pos)
@@ -146,13 +140,13 @@ __curjoin_iter_set_entry(WT_CURSOR_JOIN_ITER *iter, u_int entry_pos)
WT_CURSOR_JOIN_ENTRY *entry;
WT_DECL_RET;
WT_SESSION_IMPL *session;
- char *uri;
+ size_t size;
const char *raw_cfg[] = { WT_CONFIG_BASE(
iter->session, WT_SESSION_open_cursor), "raw", NULL };
const char *def_cfg[] = { WT_CONFIG_BASE(
iter->session, WT_SESSION_open_cursor), NULL };
const char **config;
- size_t size;
+ char *uri;
session = iter->session;
cjoin = iter->cjoin;
@@ -402,8 +396,7 @@ __curjoin_endpoint_init_key(WT_SESSION_IMPL *session,
endpoint->recno_buf,
sizeof(endpoint->recno_buf),
&endpoint->key));
- }
- else
+ } else
endpoint->key = *k;
}
}
@@ -422,8 +415,8 @@ __curjoin_entries_in_range(WT_SESSION_IMPL *session, WT_CURSOR_JOIN *cjoin,
WT_CURSOR_JOIN_ENTRY *entry;
WT_CURSOR_JOIN_ITER *iter;
WT_DECL_RET;
- int fastret, slowret;
u_int pos;
+ int fastret, slowret;
iter = iterarg;
if (F_ISSET(cjoin, WT_CURJOIN_DISJUNCTION)) {
@@ -459,8 +452,8 @@ __curjoin_entry_in_range(WT_SESSION_IMPL *session, WT_CURSOR_JOIN_ENTRY *entry,
WT_COLLATOR *collator;
WT_CURSOR_JOIN_ENDPOINT *end, *endmax;
bool disjunction, passed;
- int cmp;
u_int pos;
+ int cmp;
collator = (entry->index != NULL) ? entry->index->collator : NULL;
endmax = &entry->ends[entry->ends_next];
@@ -758,15 +751,15 @@ __curjoin_init_bloom(WT_SESSION_IMPL *session, WT_CURSOR_JOIN *cjoin,
WT_COLLATOR *collator;
WT_CURSOR *c;
WT_CURSOR_JOIN_ENDPOINT *end, *endmax;
- WT_DECL_RET;
WT_DECL_ITEM(uribuf);
+ WT_DECL_RET;
WT_ITEM curkey, curvalue;
- const char *raw_cfg[] = { WT_CONFIG_BASE(
- session, WT_SESSION_open_cursor), "raw", NULL };
- const char *uri;
size_t size;
u_int skip;
int cmp;
+ const char *uri;
+ const char *raw_cfg[] = { WT_CONFIG_BASE(
+ session, WT_SESSION_open_cursor), "raw", NULL };
c = NULL;
skip = 0;
@@ -905,18 +898,18 @@ __curjoin_init_next(WT_SESSION_IMPL *session, WT_CURSOR_JOIN *cjoin,
bool iterable)
{
WT_BLOOM *bloom;
- WT_DECL_RET;
WT_CURSOR *origcur;
- WT_CURSOR_JOIN_ENTRY *je, *jeend, *je2;
WT_CURSOR_JOIN_ENDPOINT *end;
+ WT_CURSOR_JOIN_ENTRY *je, *jeend, *je2;
+ WT_DECL_RET;
+ size_t size;
+ uint32_t f, k;
char *mainbuf;
const char *def_cfg[] = { WT_CONFIG_BASE(
session, WT_SESSION_open_cursor), NULL };
const char *raw_cfg[] = { WT_CONFIG_BASE(
session, WT_SESSION_open_cursor), "raw", NULL };
const char **config, *proj, *urimain;
- size_t size;
- uint32_t f, k;
mainbuf = NULL;
if (cjoin->entries_next == 0)
@@ -1140,10 +1133,10 @@ __curjoin_open_main(WT_SESSION_IMPL *session, WT_CURSOR_JOIN *cjoin,
{
WT_DECL_RET;
WT_INDEX *idx;
+ size_t len, newsize;
char *main_uri, *newformat;
const char *raw_cfg[] = { WT_CONFIG_BASE(
session, WT_SESSION_open_cursor), "raw", NULL };
- size_t len, newsize;
main_uri = NULL;
idx = entry->index;
@@ -1151,8 +1144,7 @@ __curjoin_open_main(WT_SESSION_IMPL *session, WT_CURSOR_JOIN *cjoin,
newsize = strlen(cjoin->table->name) + idx->colconf.len + 1;
WT_ERR(__wt_calloc(session, 1, newsize, &main_uri));
snprintf(main_uri, newsize, "%s%.*s",
- cjoin->table->name, (int)idx->colconf.len,
- idx->colconf.str);
+ cjoin->table->name, (int)idx->colconf.len, idx->colconf.str);
WT_ERR(__wt_open_cursor(session, main_uri,
(WT_CURSOR *)cjoin, raw_cfg, &entry->main));
if (idx->extractor == NULL) {
@@ -1165,8 +1157,7 @@ __curjoin_open_main(WT_SESSION_IMPL *session, WT_CURSOR_JOIN *cjoin,
*/
len = strlen(entry->main->value_format) + 3;
WT_ERR(__wt_calloc(session, len, 1, &newformat));
- snprintf(newformat, len, "%s0x",
- entry->main->value_format);
+ snprintf(newformat, len, "%s0x", entry->main->value_format);
__wt_free(session, entry->main->value_format);
entry->main->value_format = newformat;
}
@@ -1364,9 +1355,9 @@ __wt_curjoin_join(WT_SESSION_IMPL *session, WT_CURSOR_JOIN *cjoin,
uint64_t count, uint32_t bloom_bit_count, uint32_t bloom_hash_count)
{
WT_CURSOR_INDEX *cindex;
+ WT_CURSOR_JOIN *child;
WT_CURSOR_JOIN_ENDPOINT *end;
WT_CURSOR_JOIN_ENTRY *entry;
- WT_CURSOR_JOIN *child;
bool hasins, needbloom, nested, range_eq;
size_t len;
u_int i, ins, nonbloom;
diff --git a/src/docs/custom-file-systems.dox b/src/docs/custom-file-systems.dox
index 4b012952e15..cddec0e4258 100644
--- a/src/docs/custom-file-systems.dox
+++ b/src/docs/custom-file-systems.dox
@@ -5,21 +5,34 @@ used by WiredTiger to interact with the I/O subsystem using the
WT_FILE_SYSTEM and WT_FILE_HANDLE interfaces.
It is not necessary for all file system providers to implement all methods
-in the WT_FILE_SYSTEM and WT_FILE_HANDLE structures. The documentation for
+in the WT_FILE_SYSTEM and WT_FILE_HANDLE structures, and documentation for
those structures indicate which methods are optional. Methods which are not
-provided should be set to NULL. Generally the function pointers should not
-be changed once a handle is created. There is one exception to this, which
-are the fallocate and fallocate_nolock - for an example of how fallocate
-can be changed after create see the WiredTiger POSIX file system
-implementation.
+provided should be set to NULL.
+
+Generally, function pointers should not be changed once a handle is
+created. An exception to this are the WT_FILE_HANDLE::fallocate and
+WT_FILE_HANDLE::fallocate_nolock methods, because a file system
+implementation may not know what support the system provides until file
+allocation is attempted. See the WiredTiger POSIX file system
+implementation for an example of how the fallocate method might be
+changed after initialization.
WT_FILE_SYSTEM and WT_FILE_HANDLE methods which fail but not fatally
-(for example, a file truncation call which fails because the file is
-currently mapped into memory), should return EBUSY.
+(for example, a WT_FILE_HANDLE::truncate method call which fails because
+the file is currently mapped into memory), should return EBUSY.
+
+WT_FILE_SYSTEM and WT_FILE_HANDLE methods which fail fatally, but not
+in all cases (for example, a WT_FILE_HANDLE::fadvise method call which
+only supports ::WT_FILE_HANDLE_WILLNEED), should return ENOTSUP.
Unless explicitly stated otherwise, WiredTiger may invoke methods on the
WT_FILE_SYSTEM and WT_FILE_HANDLE interfaces from multiple threads
concurrently. It is the responsibility of the implementation to protect
any shared data.
+See @ex_ref{ex_file_system.c} for an example implementation of a custom
+file system; the WiredTiger code for a POSIX standard file system is in
+the public domain and may also be useful as a starting point for a custom
+file system implementation.
+
*/
diff --git a/src/docs/spell.ok b/src/docs/spell.ok
index d197b5517f2..96fe04d7426 100644
--- a/src/docs/spell.ok
+++ b/src/docs/spell.ok
@@ -81,6 +81,7 @@ Seward's
SiH
TXT
URIs
+WILLNEED
WiredTiger
WiredTiger's
WiredTigerCheckpoint
@@ -210,8 +211,8 @@ erlang
errno
exe
fadvise
-fallocate
failchk
+fallocate
fd's
fdatasync
fieldname
diff --git a/src/docs/wtperf.dox b/src/docs/wtperf.dox
index 6d8dcab8f65..e06272d117c 100644
--- a/src/docs/wtperf.dox
+++ b/src/docs/wtperf.dox
@@ -232,6 +232,8 @@ operation,two for every second operation, three for every third
operation etc.
@par sess_config (string, default=)
session configuration string
+@par session_count_idle (unsigned int, default=0)
+number of idle sessions to create. Default 0.
@par table_config (string, default=key_format=S,value_format=S,type=lsm,exclusive=true,allocation_size=4kb,internal_page_max=64kb,leaf_page_max=4kb,split_pct=100)
table configuration string
@par table_count (unsigned int, default=1)
diff --git a/src/include/btree.i b/src/include/btree.i
index 4c8166ca6a6..e0102a11511 100644
--- a/src/include/btree.i
+++ b/src/include/btree.i
@@ -1360,7 +1360,7 @@ __wt_page_hazard_check(WT_SESSION_IMPL *session, WT_PAGE *page)
WT_CONNECTION_IMPL *conn;
WT_HAZARD *hp;
WT_SESSION_IMPL *s;
- uint32_t i, hazard_size, session_cnt;
+ uint32_t i, j, hazard_size, max, session_cnt;
conn = S2C(session);
@@ -1372,15 +1372,28 @@ __wt_page_hazard_check(WT_SESSION_IMPL *session, WT_PAGE *page)
* come or go, we'll check the slots for all of the sessions that could
* have been active when we started our check.
*/
+ WT_STAT_FAST_CONN_INCR(session, cache_hazard_checks);
WT_ORDERED_READ(session_cnt, conn->session_cnt);
- for (s = conn->sessions, i = 0; i < session_cnt; ++s, ++i) {
+ for (s = conn->sessions, i = 0, j = 0, max = 0;
+ i < session_cnt; ++s, ++i) {
if (!s->active)
continue;
WT_ORDERED_READ(hazard_size, s->hazard_size);
- for (hp = s->hazard; hp < s->hazard + hazard_size; ++hp)
- if (hp->page == page)
+ if (s->hazard_size > max) {
+ max = s->hazard_size;
+ WT_STAT_FAST_CONN_SET(session,
+ cache_hazard_max, max);
+ }
+ for (hp = s->hazard; hp < s->hazard + hazard_size; ++hp) {
+ ++j;
+ if (hp->page == page) {
+ WT_STAT_FAST_CONN_INCRV(session,
+ cache_hazard_walks, j);
return (hp);
+ }
+ }
}
+ WT_STAT_FAST_CONN_INCRV(session, cache_hazard_walks, j);
return (NULL);
}
diff --git a/src/include/cache.i b/src/include/cache.i
index 8cf7555e716..72c8307756d 100644
--- a/src/include/cache.i
+++ b/src/include/cache.i
@@ -166,6 +166,13 @@ __wt_eviction_needed(WT_SESSION_IMPL *session, u_int *pct_fullp)
cache = conn->cache;
/*
+ * If the connection is closing we do not need eviction from an
+ * application thread. The eviction subsystem is already closed.
+ */
+ if (F_ISSET(conn, WT_CONN_CLOSING))
+ return (false);
+
+ /*
* Avoid division by zero if the cache size has not yet been set in a
* shared cache.
*/
@@ -179,6 +186,15 @@ __wt_eviction_needed(WT_SESSION_IMPL *session, u_int *pct_fullp)
pct_full = (u_int)((100 * bytes_inuse) / bytes_max);
if (pct_fullp != NULL)
*pct_fullp = pct_full;
+ /*
+ * If the connection is closing we do not need eviction from an
+ * application thread. The eviction subsystem is already closed.
+ * We return here because some callers depend on the percent full
+ * having been filled in.
+ */
+ if (F_ISSET(conn, WT_CONN_CLOSING))
+ return (false);
+
if (pct_full > cache->eviction_trigger)
return (true);
diff --git a/src/include/extern.h b/src/include/extern.h
index 53e49e51a26..e8c20930aaf 100644
--- a/src/include/extern.h
+++ b/src/include/extern.h
@@ -570,6 +570,7 @@ extern int __wt_open_cursor(WT_SESSION_IMPL *session, const char *uri, WT_CURSOR
extern int __wt_session_create( WT_SESSION_IMPL *session, const char *uri, const char *config);
extern int __wt_session_drop(WT_SESSION_IMPL *session, const char *uri, const char *cfg[]);
extern int __wt_session_range_truncate(WT_SESSION_IMPL *session, const char *uri, WT_CURSOR *start, WT_CURSOR *stop);
+extern const char *__wt_session_strerror(WT_SESSION *wt_session, int error);
extern int __wt_open_session(WT_CONNECTION_IMPL *conn, WT_EVENT_HANDLER *event_handler, const char *config, bool open_metadata, WT_SESSION_IMPL **sessionp);
extern int __wt_open_internal_session(WT_CONNECTION_IMPL *conn, const char *name, bool open_metadata, uint32_t session_flags, WT_SESSION_IMPL **sessionp);
extern int __wt_session_compact( WT_SESSION *wt_session, const char *uri, const char *config);
@@ -730,7 +731,7 @@ extern int __wt_dlsym(WT_SESSION_IMPL *session, WT_DLH *dlh, const char *name, b
extern int __wt_epoch(WT_SESSION_IMPL *session, struct timespec *tsp);
extern int __wt_errno(void);
extern int __wt_filename(WT_SESSION_IMPL *session, const char *name, char **path);
-extern int __wt_fopen(WT_SESSION_IMPL *session, const char *name, uint32_t open_flags, uint32_t flags, WT_FSTREAM **fsp);
+extern int __wt_fopen(WT_SESSION_IMPL *session, const char *name, uint32_t open_flags, uint32_t flags, WT_FSTREAM **fstrp);
extern int __wt_get_vm_pagesize(void);
extern int __wt_getenv(WT_SESSION_IMPL *session, const char *variable, const char **envp);
extern int __wt_getlasterror(void);
diff --git a/src/include/os.h b/src/include/os.h
index bf60f32f764..1e08683bc83 100644
--- a/src/include/os.h
+++ b/src/include/os.h
@@ -141,7 +141,8 @@ struct __wt_fstream {
uint32_t flags;
int (*close)(WT_SESSION_IMPL *, WT_FSTREAM *);
- int (*flush)(WT_SESSION_IMPL *, WT_FSTREAM *);
- int (*getline)(WT_SESSION_IMPL *, WT_FSTREAM *, WT_ITEM *);
- int (*printf)(WT_SESSION_IMPL *, WT_FSTREAM *, const char *, va_list);
+ int (*fstr_flush)(WT_SESSION_IMPL *, WT_FSTREAM *);
+ int (*fstr_getline)(WT_SESSION_IMPL *, WT_FSTREAM *, WT_ITEM *);
+ int (*fstr_printf)(
+ WT_SESSION_IMPL *, WT_FSTREAM *, const char *, va_list);
};
diff --git a/src/include/os_fhandle.i b/src/include/os_fhandle.i
index 8d2cda4b305..cf790d6bc4d 100644
--- a/src/include/os_fhandle.i
+++ b/src/include/os_fhandle.i
@@ -22,11 +22,11 @@ __wt_fsync(WT_SESSION_IMPL *session, WT_FH *fh, bool block)
handle = fh->handle;
if (block)
- return (handle->sync == NULL ? 0 :
- handle->sync(handle, (WT_SESSION *)session));
+ return (handle->fh_sync == NULL ? 0 :
+ handle->fh_sync(handle, (WT_SESSION *)session));
else
- return (handle->sync_nowait == NULL ? 0 :
- handle->sync_nowait(handle, (WT_SESSION *)session));
+ return (handle->fh_sync_nowait == NULL ? 0 :
+ handle->fh_sync_nowait(handle, (WT_SESSION *)session));
}
/*
@@ -55,14 +55,14 @@ __wt_fallocate(
* flavor, that failed, and we have to fallback to the locking flavor.
*/
handle = fh->handle;
- if (handle->fallocate_nolock != NULL) {
- if ((ret = handle->fallocate_nolock(
+ if (handle->fh_allocate_nolock != NULL) {
+ if ((ret = handle->fh_allocate_nolock(
handle, (WT_SESSION *)session, offset, len)) == 0)
return (0);
WT_RET_ERROR_OK(ret, ENOTSUP);
}
- if (handle->fallocate != NULL)
- return (handle->fallocate(
+ if (handle->fh_allocate != NULL)
+ return (handle->fh_allocate(
handle, (WT_SESSION *)session, offset, len));
return (ENOTSUP);
}
@@ -80,8 +80,8 @@ __wt_file_lock(WT_SESSION_IMPL * session, WT_FH *fh, bool lock)
"%s: handle-lock: %s", fh->handle->name, lock ? "lock" : "unlock"));
handle = fh->handle;
- return (handle->lock == NULL ? 0 :
- handle->lock(handle, (WT_SESSION*)session, lock));
+ return (handle->fh_lock == NULL ? 0 :
+ handle->fh_lock(handle, (WT_SESSION*)session, lock));
}
/*
@@ -98,7 +98,7 @@ __wt_read(
WT_STAT_FAST_CONN_INCR(session, read_io);
- return (fh->handle->read(
+ return (fh->handle->fh_read(
fh->handle, (WT_SESSION *)session, offset, len, buf));
}
@@ -112,7 +112,7 @@ __wt_filesize(WT_SESSION_IMPL *session, WT_FH *fh, wt_off_t *sizep)
WT_RET(__wt_verbose(
session, WT_VERB_HANDLEOPS, "%s: handle-size", fh->handle->name));
- return (fh->handle->size(fh->handle, (WT_SESSION *)session, sizep));
+ return (fh->handle->fh_size(fh->handle, (WT_SESSION *)session, sizep));
}
/*
@@ -128,7 +128,8 @@ __wt_ftruncate(WT_SESSION_IMPL *session, WT_FH *fh, wt_off_t len)
"%s: handle-truncate: %" PRIuMAX,
fh->handle->name, (uintmax_t)len));
- return (fh->handle->truncate(fh->handle, (WT_SESSION *)session, len));
+ return (fh->handle->fh_truncate(
+ fh->handle, (WT_SESSION *)session, len));
}
/*
@@ -149,6 +150,6 @@ __wt_write(WT_SESSION_IMPL *session,
WT_STAT_FAST_CONN_INCR(session, write_io);
- return (fh->handle->write(
+ return (fh->handle->fh_write(
fh->handle, (WT_SESSION *)session, offset, len, buf));
}
diff --git a/src/include/os_fs.i b/src/include/os_fs.i
index 151898711d8..88ee71d953a 100644
--- a/src/include/os_fs.i
+++ b/src/include/os_fs.i
@@ -30,7 +30,7 @@ __wt_fs_directory_list(WT_SESSION_IMPL *session,
file_system = S2C(session)->file_system;
wt_session = (WT_SESSION *)session;
- ret = file_system->directory_list(
+ ret = file_system->fs_directory_list(
file_system, wt_session, path, prefix, dirlistp, countp);
__wt_free(session, path);
@@ -52,7 +52,7 @@ __wt_fs_directory_list_free(
if (*dirlistp != NULL) {
file_system = S2C(session)->file_system;
wt_session = (WT_SESSION *)session;
- ret = file_system->directory_list_free(
+ ret = file_system->fs_directory_list_free(
file_system, wt_session, *dirlistp, count);
}
@@ -88,7 +88,7 @@ __wt_fs_directory_sync(WT_SESSION_IMPL *session, const char *name)
* needed.
*/
file_system = S2C(session)->file_system;
- if (file_system->directory_sync == NULL)
+ if (file_system->fs_directory_sync == NULL)
return (0);
copy = NULL;
@@ -109,7 +109,7 @@ __wt_fs_directory_sync(WT_SESSION_IMPL *session, const char *name)
}
wt_session = (WT_SESSION *)session;
- ret = file_system->directory_sync(file_system, wt_session, name);
+ ret = file_system->fs_directory_sync(file_system, wt_session, name);
__wt_free(session, copy);
return (ret);
@@ -133,7 +133,7 @@ __wt_fs_exist(WT_SESSION_IMPL *session, const char *name, bool *existp)
file_system = S2C(session)->file_system;
wt_session = (WT_SESSION *)session;
- ret = file_system->exist(file_system, wt_session, path, existp);
+ ret = file_system->fs_exist(file_system, wt_session, path, existp);
__wt_free(session, path);
return (ret);
@@ -169,7 +169,7 @@ __wt_fs_remove(WT_SESSION_IMPL *session, const char *name)
file_system = S2C(session)->file_system;
wt_session = (WT_SESSION *)session;
- ret = file_system->remove(file_system, wt_session, path);
+ ret = file_system->fs_remove(file_system, wt_session, path);
__wt_free(session, path);
return (ret);
@@ -211,7 +211,8 @@ __wt_fs_rename(WT_SESSION_IMPL *session, const char *from, const char *to)
file_system = S2C(session)->file_system;
wt_session = (WT_SESSION *)session;
- ret = file_system->rename(file_system, wt_session, from_path, to_path);
+ ret = file_system->fs_rename(
+ file_system, wt_session, from_path, to_path);
err: __wt_free(session, from_path);
__wt_free(session, to_path);
@@ -236,7 +237,7 @@ __wt_fs_size(WT_SESSION_IMPL *session, const char *name, wt_off_t *sizep)
file_system = S2C(session)->file_system;
wt_session = (WT_SESSION *)session;
- ret = file_system->size(file_system, wt_session, path, sizep);
+ ret = file_system->fs_size(file_system, wt_session, path, sizep);
__wt_free(session, path);
return (ret);
diff --git a/src/include/os_fstream.i b/src/include/os_fstream.i
index 37a6039d1b7..8c0fdadbdb0 100644
--- a/src/include/os_fstream.i
+++ b/src/include/os_fstream.i
@@ -11,9 +11,9 @@
* Get a line from a stream.
*/
static inline int
-__wt_getline(WT_SESSION_IMPL *session, WT_FSTREAM *fs, WT_ITEM *buf)
+__wt_getline(WT_SESSION_IMPL *session, WT_FSTREAM *fstr, WT_ITEM *buf)
{
- return (fs->getline(session, fs, buf));
+ return (fstr->fstr_getline(session, fstr, buf));
}
/*
@@ -21,14 +21,14 @@ __wt_getline(WT_SESSION_IMPL *session, WT_FSTREAM *fs, WT_ITEM *buf)
* Close a stream.
*/
static inline int
-__wt_fclose(WT_SESSION_IMPL *session, WT_FSTREAM **fsp)
+__wt_fclose(WT_SESSION_IMPL *session, WT_FSTREAM **fstrp)
{
- WT_FSTREAM *fs;
+ WT_FSTREAM *fstr;
- if ((fs = *fsp) == NULL)
+ if ((fstr = *fstrp) == NULL)
return (0);
- *fsp = NULL;
- return (fs->close(session, fs));
+ *fstrp = NULL;
+ return (fstr->close(session, fstr));
}
/*
@@ -36,9 +36,9 @@ __wt_fclose(WT_SESSION_IMPL *session, WT_FSTREAM **fsp)
* Flush a stream.
*/
static inline int
-__wt_fflush(WT_SESSION_IMPL *session, WT_FSTREAM *fs)
+__wt_fflush(WT_SESSION_IMPL *session, WT_FSTREAM *fstr)
{
- return (fs->flush(session, fs));
+ return (fstr->fstr_flush(session, fstr));
}
/*
@@ -47,12 +47,12 @@ __wt_fflush(WT_SESSION_IMPL *session, WT_FSTREAM *fs)
*/
static inline int
__wt_vfprintf(
- WT_SESSION_IMPL *session, WT_FSTREAM *fs, const char *fmt, va_list ap)
+ WT_SESSION_IMPL *session, WT_FSTREAM *fstr, const char *fmt, va_list ap)
{
WT_RET(__wt_verbose(
- session, WT_VERB_HANDLEOPS, "%s: handle-printf", fs->name));
+ session, WT_VERB_HANDLEOPS, "%s: handle-printf", fstr->name));
- return (fs->printf(session, fs, fmt, ap));
+ return (fstr->fstr_printf(session, fstr, fmt, ap));
}
/*
@@ -60,14 +60,14 @@ __wt_vfprintf(
* ANSI C fprintf.
*/
static inline int
-__wt_fprintf(WT_SESSION_IMPL *session, WT_FSTREAM *fs, const char *fmt, ...)
+__wt_fprintf(WT_SESSION_IMPL *session, WT_FSTREAM *fstr, const char *fmt, ...)
WT_GCC_FUNC_ATTRIBUTE((format (printf, 3, 4)))
{
WT_DECL_RET;
va_list ap;
va_start(ap, fmt);
- ret = __wt_vfprintf(session, fs, fmt, ap);
+ ret = __wt_vfprintf(session, fstr, fmt, ap);
va_end(ap);
return (ret);
@@ -79,18 +79,18 @@ __wt_fprintf(WT_SESSION_IMPL *session, WT_FSTREAM *fs, const char *fmt, ...)
*/
static inline int
__wt_sync_and_rename(WT_SESSION_IMPL *session,
- WT_FSTREAM **fsp, const char *from, const char *to)
+ WT_FSTREAM **fstrp, const char *from, const char *to)
{
WT_DECL_RET;
- WT_FSTREAM *fs;
+ WT_FSTREAM *fstr;
- fs = *fsp;
- *fsp = NULL;
+ fstr = *fstrp;
+ *fstrp = NULL;
/* Flush to disk and close the handle. */
- WT_TRET(__wt_fflush(session, fs));
- WT_TRET(__wt_fsync(session, fs->fh, true));
- WT_TRET(__wt_fclose(session, &fs));
+ WT_TRET(__wt_fflush(session, fstr));
+ WT_TRET(__wt_fsync(session, fstr->fh, true));
+ WT_TRET(__wt_fclose(session, &fstr));
WT_RET(ret);
return (__wt_rename_and_sync_directory(session, from, to));
diff --git a/src/include/session.h b/src/include/session.h
index 7fdb7fc2548..aa51dae58c4 100644
--- a/src/include/session.h
+++ b/src/include/session.h
@@ -198,7 +198,7 @@ struct WT_COMPILER_TYPE_ALIGN(WT_CACHE_LINE_ALIGNMENT) __wt_session_impl {
((s)->hazard == NULL)
/* The number of hazard pointers grows dynamically. */
-#define WT_HAZARD_INCR 10
+#define WT_HAZARD_INCR 1
uint32_t hazard_size; /* Allocated slots in hazard array. */
uint32_t nhazard; /* Count of active hazard pointers */
WT_HAZARD *hazard; /* Hazard pointer array */
diff --git a/src/include/stat.h b/src/include/stat.h
index 18461b1ee38..a71e0fa208e 100644
--- a/src/include/stat.h
+++ b/src/include/stat.h
@@ -275,6 +275,9 @@ struct __wt_connection_stats {
int64_t cache_eviction_worker_evicting;
int64_t cache_eviction_force_fail;
int64_t cache_eviction_hazard;
+ int64_t cache_hazard_checks;
+ int64_t cache_hazard_walks;
+ int64_t cache_hazard_max;
int64_t cache_inmem_splittable;
int64_t cache_inmem_split;
int64_t cache_eviction_internal;
diff --git a/src/include/wiredtiger.in b/src/include/wiredtiger.in
index 007df44f257..6de92b72051 100644
--- a/src/include/wiredtiger.in
+++ b/src/include/wiredtiger.in
@@ -1229,9 +1229,6 @@ struct __wt_session {
* @configstart{WT_SESSION.drop, see dist/api_data.py}
* @config{force, return success if the object does not exist., a
* boolean flag; default \c false.}
- * @config{lock_wait, wait for locks\, if \c lock_wait=false\, fail if
- * any required locks are not available immediately., a boolean flag;
- * default \c true.}
* @config{remove_files, should the underlying files be removed?., a
* boolean flag; default \c true.}
* @configend
@@ -3756,9 +3753,9 @@ struct __wt_file_system {
* directory.
* @param[out] countp the method the number of entries returned
*/
- int (*directory_list)(WT_FILE_SYSTEM *file_system, WT_SESSION *session,
- const char *directory, const char *prefix, char ***dirlist,
- uint32_t *countp);
+ int (*fs_directory_list)(WT_FILE_SYSTEM *file_system,
+ WT_SESSION *session, const char *directory, const char *prefix,
+ char ***dirlist, uint32_t *countp);
/*!
* Free memory allocated by WT_FILE_SYSTEM::directory_list.
@@ -3770,7 +3767,7 @@ struct __wt_file_system {
* @param dirlist array returned by WT_FILE_SYSTEM::directory_list
* @param count count returned by WT_FILE_SYSTEM::directory_list
*/
- int (*directory_list_free)(WT_FILE_SYSTEM *file_system,
+ int (*fs_directory_list_free)(WT_FILE_SYSTEM *file_system,
WT_SESSION *session, char **dirlist, uint32_t count);
/*!
@@ -3787,7 +3784,7 @@ struct __wt_file_system {
* @param session the current WiredTiger session
* @param directory the name of the directory
*/
- int (*directory_sync)(WT_FILE_SYSTEM *file_system,
+ int (*fs_directory_sync)(WT_FILE_SYSTEM *file_system,
WT_SESSION *session, const char *directory);
/*!
@@ -3800,7 +3797,7 @@ struct __wt_file_system {
* @param name the name of the file
* @param[out] existp If the named file system object exists
*/
- int (*exist)(WT_FILE_SYSTEM *file_system,
+ int (*fs_exist)(WT_FILE_SYSTEM *file_system,
WT_SESSION *session, const char *name, bool *existp);
/*!
@@ -3824,7 +3821,7 @@ struct __wt_file_system {
* with the WT_FILE_HANDLE:: structure should declare and allocate
* their own structure as a superset of a WT_FILE_HANDLE:: structure.
*/
- int (*open_file)(WT_FILE_SYSTEM *file_system, WT_SESSION *session,
+ int (*fs_open_file)(WT_FILE_SYSTEM *file_system, WT_SESSION *session,
const char *name, WT_OPEN_FILE_TYPE file_type, uint32_t flags,
WT_FILE_HANDLE **file_handlep);
@@ -3840,7 +3837,7 @@ struct __wt_file_system {
* @param session the current WiredTiger session
* @param name the name of the file system object
*/
- int (*remove)(
+ int (*fs_remove)(
WT_FILE_SYSTEM *file_system, WT_SESSION *session, const char *name);
/*!
@@ -3856,7 +3853,7 @@ struct __wt_file_system {
* @param from the original name of the object
* @param to the new name for the object
*/
- int (*rename)(WT_FILE_SYSTEM *file_system,
+ int (*fs_rename)(WT_FILE_SYSTEM *file_system,
WT_SESSION *session, const char *from, const char *to);
/*!
@@ -3869,7 +3866,7 @@ struct __wt_file_system {
* @param name the name of the file system object
* @param[out] sizep the size of the file system entry
*/
- int (*size)(WT_FILE_SYSTEM *file_system,
+ int (*fs_size)(WT_FILE_SYSTEM *file_system,
WT_SESSION *session, const char *name, wt_off_t *sizep);
/*!
@@ -3938,7 +3935,7 @@ struct __wt_file_handle {
* @param advice one of ::WT_FILE_HANDLE_WILLNEED or
* ::WT_FILE_HANDLE_DONTNEED.
*/
- int (*fadvise)(WT_FILE_HANDLE *file_handle,
+ int (*fh_advise)(WT_FILE_HANDLE *file_handle,
WT_SESSION *session, wt_off_t offset, wt_off_t len, int advice);
/*!
@@ -3960,7 +3957,7 @@ struct __wt_file_handle {
* @param offset the file offset
* @param len the size of the advisory
*/
- int (*fallocate)(WT_FILE_HANDLE *file_handle,
+ int (*fh_allocate)(WT_FILE_HANDLE *file_handle,
WT_SESSION *session, wt_off_t, wt_off_t);
/*!
@@ -3982,7 +3979,7 @@ struct __wt_file_handle {
* @param offset the file offset
* @param len the size of the advisory
*/
- int (*fallocate_nolock)(WT_FILE_HANDLE *file_handle,
+ int (*fh_allocate_nolock)(WT_FILE_HANDLE *file_handle,
WT_SESSION *session, wt_off_t, wt_off_t);
/*!
@@ -3995,7 +3992,7 @@ struct __wt_file_handle {
* @param session the current WiredTiger session
* @param lock whether to lock or unlock
*/
- int (*lock)(
+ int (*fh_lock)(
WT_FILE_HANDLE *file_handle, WT_SESSION *session, bool lock);
/*!
@@ -4016,7 +4013,7 @@ struct __wt_file_handle {
* which can be optionally stored a pointer to an opaque cookie
* which is subsequently passed to WT_FILE_HANDLE::unmap.
*/
- int (*map)(WT_FILE_HANDLE *file_handle, WT_SESSION *session,
+ int (*fh_map)(WT_FILE_HANDLE *file_handle, WT_SESSION *session,
void *mapped_regionp, size_t *lengthp, void *mapped_cookiep);
/*!
@@ -4035,7 +4032,7 @@ struct __wt_file_handle {
* @param length the length of the mapped region to discard
* @param mapped_cookie any cookie set by the WT_FILE_HANDLE::map method
*/
- int (*map_discard)(WT_FILE_HANDLE *file_handle,
+ int (*fh_map_discard)(WT_FILE_HANDLE *file_handle,
WT_SESSION *session, void *map, size_t length, void *mapped_cookie);
/*!
@@ -4054,7 +4051,7 @@ struct __wt_file_handle {
* @param length the size of the mapped region to preload
* @param mapped_cookie any cookie set by the WT_FILE_HANDLE::map method
*/
- int (*map_preload)(WT_FILE_HANDLE *file_handle, WT_SESSION *session,
+ int (*fh_map_preload)(WT_FILE_HANDLE *file_handle, WT_SESSION *session,
const void *map, size_t length, void *mapped_cookie);
/*!
@@ -4072,7 +4069,7 @@ struct __wt_file_handle {
* @param length the length of the mapped region
* @param mapped_cookie any cookie set by the WT_FILE_HANDLE::map method
*/
- int (*unmap)(WT_FILE_HANDLE *file_handle, WT_SESSION *session,
+ int (*fh_unmap)(WT_FILE_HANDLE *file_handle, WT_SESSION *session,
void *mapped_region, size_t length, void *mapped_cookie);
/*!
@@ -4086,7 +4083,7 @@ struct __wt_file_handle {
* @param len the amount to read
* @param[out] buf buffer to hold the content read from file
*/
- int (*read)(WT_FILE_HANDLE *file_handle,
+ int (*fh_read)(WT_FILE_HANDLE *file_handle,
WT_SESSION *session, wt_off_t offset, size_t len, void *buf);
/*!
@@ -4098,7 +4095,7 @@ struct __wt_file_handle {
* @param session the current WiredTiger session
* @param sizep the size of the file
*/
- int (*size)(
+ int (*fh_size)(
WT_FILE_HANDLE *file_handle, WT_SESSION *session, wt_off_t *sizep);
/*!
@@ -4113,7 +4110,7 @@ struct __wt_file_handle {
* @param file_handle the WT_FILE_HANDLE
* @param session the current WiredTiger session
*/
- int (*sync)(WT_FILE_HANDLE *file_handle, WT_SESSION *session);
+ int (*fh_sync)(WT_FILE_HANDLE *file_handle, WT_SESSION *session);
/*!
* Schedule the outstanding file writes required for durability and
@@ -4127,7 +4124,7 @@ struct __wt_file_handle {
* @param file_handle the WT_FILE_HANDLE
* @param session the current WiredTiger session
*/
- int (*sync_nowait)(WT_FILE_HANDLE *file_handle, WT_SESSION *session);
+ int (*fh_sync_nowait)(WT_FILE_HANDLE *file_handle, WT_SESSION *session);
/*!
* Lengthen or shorten a file to the specified length, based on the
@@ -4142,7 +4139,7 @@ struct __wt_file_handle {
* @param session the current WiredTiger session
* @param length desired file size after truncate
*/
- int (*truncate)(
+ int (*fh_truncate)(
WT_FILE_HANDLE *file_handle, WT_SESSION *session, wt_off_t length);
/*!
@@ -4159,7 +4156,7 @@ struct __wt_file_handle {
* @param length amount of data to write
* @param buf content to be written to the file
*/
- int (*write)(WT_FILE_HANDLE *file_handle, WT_SESSION *session,
+ int (*fh_write)(WT_FILE_HANDLE *file_handle, WT_SESSION *session,
wt_off_t offset, size_t length, const void *buf);
};
#endif /* !defined(SWIG) */
@@ -4303,257 +4300,263 @@ extern int wiredtiger_extension_terminate(WT_CONNECTION *connection);
#define WT_STAT_CONN_CACHE_EVICTION_FORCE_FAIL 1046
/*! cache: hazard pointer blocked page eviction */
#define WT_STAT_CONN_CACHE_EVICTION_HAZARD 1047
+/*! cache: hazard pointer check calls */
+#define WT_STAT_CONN_CACHE_HAZARD_CHECKS 1048
+/*! cache: hazard pointer check entries walked */
+#define WT_STAT_CONN_CACHE_HAZARD_WALKS 1049
+/*! cache: hazard pointer maximum array length */
+#define WT_STAT_CONN_CACHE_HAZARD_MAX 1050
/*! cache: in-memory page passed criteria to be split */
-#define WT_STAT_CONN_CACHE_INMEM_SPLITTABLE 1048
+#define WT_STAT_CONN_CACHE_INMEM_SPLITTABLE 1051
/*! cache: in-memory page splits */
-#define WT_STAT_CONN_CACHE_INMEM_SPLIT 1049
+#define WT_STAT_CONN_CACHE_INMEM_SPLIT 1052
/*! cache: internal pages evicted */
-#define WT_STAT_CONN_CACHE_EVICTION_INTERNAL 1050
+#define WT_STAT_CONN_CACHE_EVICTION_INTERNAL 1053
/*! cache: internal pages split during eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_SPLIT_INTERNAL 1051
+#define WT_STAT_CONN_CACHE_EVICTION_SPLIT_INTERNAL 1054
/*! cache: leaf pages split during eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_SPLIT_LEAF 1052
+#define WT_STAT_CONN_CACHE_EVICTION_SPLIT_LEAF 1055
/*! cache: lookaside table insert calls */
-#define WT_STAT_CONN_CACHE_LOOKASIDE_INSERT 1053
+#define WT_STAT_CONN_CACHE_LOOKASIDE_INSERT 1056
/*! cache: lookaside table remove calls */
-#define WT_STAT_CONN_CACHE_LOOKASIDE_REMOVE 1054
+#define WT_STAT_CONN_CACHE_LOOKASIDE_REMOVE 1057
/*! cache: maximum bytes configured */
-#define WT_STAT_CONN_CACHE_BYTES_MAX 1055
+#define WT_STAT_CONN_CACHE_BYTES_MAX 1058
/*! cache: maximum page size at eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_MAXIMUM_PAGE_SIZE 1056
+#define WT_STAT_CONN_CACHE_EVICTION_MAXIMUM_PAGE_SIZE 1059
/*! cache: modified pages evicted */
-#define WT_STAT_CONN_CACHE_EVICTION_DIRTY 1057
+#define WT_STAT_CONN_CACHE_EVICTION_DIRTY 1060
/*! cache: page split during eviction deepened the tree */
-#define WT_STAT_CONN_CACHE_EVICTION_DEEPEN 1058
+#define WT_STAT_CONN_CACHE_EVICTION_DEEPEN 1061
/*! cache: page written requiring lookaside records */
-#define WT_STAT_CONN_CACHE_WRITE_LOOKASIDE 1059
+#define WT_STAT_CONN_CACHE_WRITE_LOOKASIDE 1062
/*! cache: pages currently held in the cache */
-#define WT_STAT_CONN_CACHE_PAGES_INUSE 1060
+#define WT_STAT_CONN_CACHE_PAGES_INUSE 1063
/*! cache: pages evicted because they exceeded the in-memory maximum */
-#define WT_STAT_CONN_CACHE_EVICTION_FORCE 1061
+#define WT_STAT_CONN_CACHE_EVICTION_FORCE 1064
/*! cache: pages evicted because they had chains of deleted items */
-#define WT_STAT_CONN_CACHE_EVICTION_FORCE_DELETE 1062
+#define WT_STAT_CONN_CACHE_EVICTION_FORCE_DELETE 1065
/*! cache: pages evicted by application threads */
-#define WT_STAT_CONN_CACHE_EVICTION_APP 1063
+#define WT_STAT_CONN_CACHE_EVICTION_APP 1066
/*! cache: pages read into cache */
-#define WT_STAT_CONN_CACHE_READ 1064
+#define WT_STAT_CONN_CACHE_READ 1067
/*! cache: pages read into cache requiring lookaside entries */
-#define WT_STAT_CONN_CACHE_READ_LOOKASIDE 1065
+#define WT_STAT_CONN_CACHE_READ_LOOKASIDE 1068
/*! cache: pages requested from the cache */
-#define WT_STAT_CONN_CACHE_PAGES_REQUESTED 1066
+#define WT_STAT_CONN_CACHE_PAGES_REQUESTED 1069
/*! cache: pages selected for eviction unable to be evicted */
-#define WT_STAT_CONN_CACHE_EVICTION_FAIL 1067
+#define WT_STAT_CONN_CACHE_EVICTION_FAIL 1070
/*! cache: pages walked for eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_WALK 1068
+#define WT_STAT_CONN_CACHE_EVICTION_WALK 1071
/*! cache: pages written from cache */
-#define WT_STAT_CONN_CACHE_WRITE 1069
+#define WT_STAT_CONN_CACHE_WRITE 1072
/*! cache: pages written requiring in-memory restoration */
-#define WT_STAT_CONN_CACHE_WRITE_RESTORE 1070
+#define WT_STAT_CONN_CACHE_WRITE_RESTORE 1073
/*! cache: percentage overhead */
-#define WT_STAT_CONN_CACHE_OVERHEAD 1071
+#define WT_STAT_CONN_CACHE_OVERHEAD 1074
/*! cache: tracked bytes belonging to internal pages in the cache */
-#define WT_STAT_CONN_CACHE_BYTES_INTERNAL 1072
+#define WT_STAT_CONN_CACHE_BYTES_INTERNAL 1075
/*! cache: tracked bytes belonging to leaf pages in the cache */
-#define WT_STAT_CONN_CACHE_BYTES_LEAF 1073
+#define WT_STAT_CONN_CACHE_BYTES_LEAF 1076
/*! cache: tracked bytes belonging to overflow pages in the cache */
-#define WT_STAT_CONN_CACHE_BYTES_OVERFLOW 1074
+#define WT_STAT_CONN_CACHE_BYTES_OVERFLOW 1077
/*! cache: tracked dirty bytes in the cache */
-#define WT_STAT_CONN_CACHE_BYTES_DIRTY 1075
+#define WT_STAT_CONN_CACHE_BYTES_DIRTY 1078
/*! cache: tracked dirty pages in the cache */
-#define WT_STAT_CONN_CACHE_PAGES_DIRTY 1076
+#define WT_STAT_CONN_CACHE_PAGES_DIRTY 1079
/*! cache: unmodified pages evicted */
-#define WT_STAT_CONN_CACHE_EVICTION_CLEAN 1077
+#define WT_STAT_CONN_CACHE_EVICTION_CLEAN 1080
/*! connection: auto adjusting condition resets */
-#define WT_STAT_CONN_COND_AUTO_WAIT_RESET 1078
+#define WT_STAT_CONN_COND_AUTO_WAIT_RESET 1081
/*! connection: auto adjusting condition wait calls */
-#define WT_STAT_CONN_COND_AUTO_WAIT 1079
+#define WT_STAT_CONN_COND_AUTO_WAIT 1082
/*! connection: files currently open */
-#define WT_STAT_CONN_FILE_OPEN 1080
+#define WT_STAT_CONN_FILE_OPEN 1083
/*! connection: memory allocations */
-#define WT_STAT_CONN_MEMORY_ALLOCATION 1081
+#define WT_STAT_CONN_MEMORY_ALLOCATION 1084
/*! connection: memory frees */
-#define WT_STAT_CONN_MEMORY_FREE 1082
+#define WT_STAT_CONN_MEMORY_FREE 1085
/*! connection: memory re-allocations */
-#define WT_STAT_CONN_MEMORY_GROW 1083
+#define WT_STAT_CONN_MEMORY_GROW 1086
/*! connection: pthread mutex condition wait calls */
-#define WT_STAT_CONN_COND_WAIT 1084
+#define WT_STAT_CONN_COND_WAIT 1087
/*! connection: pthread mutex shared lock read-lock calls */
-#define WT_STAT_CONN_RWLOCK_READ 1085
+#define WT_STAT_CONN_RWLOCK_READ 1088
/*! connection: pthread mutex shared lock write-lock calls */
-#define WT_STAT_CONN_RWLOCK_WRITE 1086
+#define WT_STAT_CONN_RWLOCK_WRITE 1089
/*! connection: total read I/Os */
-#define WT_STAT_CONN_READ_IO 1087
+#define WT_STAT_CONN_READ_IO 1090
/*! connection: total write I/Os */
-#define WT_STAT_CONN_WRITE_IO 1088
+#define WT_STAT_CONN_WRITE_IO 1091
/*! cursor: cursor create calls */
-#define WT_STAT_CONN_CURSOR_CREATE 1089
+#define WT_STAT_CONN_CURSOR_CREATE 1092
/*! cursor: cursor insert calls */
-#define WT_STAT_CONN_CURSOR_INSERT 1090
+#define WT_STAT_CONN_CURSOR_INSERT 1093
/*! cursor: cursor next calls */
-#define WT_STAT_CONN_CURSOR_NEXT 1091
+#define WT_STAT_CONN_CURSOR_NEXT 1094
/*! cursor: cursor prev calls */
-#define WT_STAT_CONN_CURSOR_PREV 1092
+#define WT_STAT_CONN_CURSOR_PREV 1095
/*! cursor: cursor remove calls */
-#define WT_STAT_CONN_CURSOR_REMOVE 1093
+#define WT_STAT_CONN_CURSOR_REMOVE 1096
/*! cursor: cursor reset calls */
-#define WT_STAT_CONN_CURSOR_RESET 1094
+#define WT_STAT_CONN_CURSOR_RESET 1097
/*! cursor: cursor restarted searches */
-#define WT_STAT_CONN_CURSOR_RESTART 1095
+#define WT_STAT_CONN_CURSOR_RESTART 1098
/*! cursor: cursor search calls */
-#define WT_STAT_CONN_CURSOR_SEARCH 1096
+#define WT_STAT_CONN_CURSOR_SEARCH 1099
/*! cursor: cursor search near calls */
-#define WT_STAT_CONN_CURSOR_SEARCH_NEAR 1097
+#define WT_STAT_CONN_CURSOR_SEARCH_NEAR 1100
/*! cursor: cursor update calls */
-#define WT_STAT_CONN_CURSOR_UPDATE 1098
+#define WT_STAT_CONN_CURSOR_UPDATE 1101
/*! cursor: truncate calls */
-#define WT_STAT_CONN_CURSOR_TRUNCATE 1099
+#define WT_STAT_CONN_CURSOR_TRUNCATE 1102
/*! data-handle: connection data handles currently active */
-#define WT_STAT_CONN_DH_CONN_HANDLE_COUNT 1100
+#define WT_STAT_CONN_DH_CONN_HANDLE_COUNT 1103
/*! data-handle: connection sweep candidate became referenced */
-#define WT_STAT_CONN_DH_SWEEP_REF 1101
+#define WT_STAT_CONN_DH_SWEEP_REF 1104
/*! data-handle: connection sweep dhandles closed */
-#define WT_STAT_CONN_DH_SWEEP_CLOSE 1102
+#define WT_STAT_CONN_DH_SWEEP_CLOSE 1105
/*! data-handle: connection sweep dhandles removed from hash list */
-#define WT_STAT_CONN_DH_SWEEP_REMOVE 1103
+#define WT_STAT_CONN_DH_SWEEP_REMOVE 1106
/*! data-handle: connection sweep time-of-death sets */
-#define WT_STAT_CONN_DH_SWEEP_TOD 1104
+#define WT_STAT_CONN_DH_SWEEP_TOD 1107
/*! data-handle: connection sweeps */
-#define WT_STAT_CONN_DH_SWEEPS 1105
+#define WT_STAT_CONN_DH_SWEEPS 1108
/*! data-handle: session dhandles swept */
-#define WT_STAT_CONN_DH_SESSION_HANDLES 1106
+#define WT_STAT_CONN_DH_SESSION_HANDLES 1109
/*! data-handle: session sweep attempts */
-#define WT_STAT_CONN_DH_SESSION_SWEEPS 1107
+#define WT_STAT_CONN_DH_SESSION_SWEEPS 1110
/*! log: busy returns attempting to switch slots */
-#define WT_STAT_CONN_LOG_SLOT_SWITCH_BUSY 1108
+#define WT_STAT_CONN_LOG_SLOT_SWITCH_BUSY 1111
/*! log: consolidated slot closures */
-#define WT_STAT_CONN_LOG_SLOT_CLOSES 1109
+#define WT_STAT_CONN_LOG_SLOT_CLOSES 1112
/*! log: consolidated slot join races */
-#define WT_STAT_CONN_LOG_SLOT_RACES 1110
+#define WT_STAT_CONN_LOG_SLOT_RACES 1113
/*! log: consolidated slot join transitions */
-#define WT_STAT_CONN_LOG_SLOT_TRANSITIONS 1111
+#define WT_STAT_CONN_LOG_SLOT_TRANSITIONS 1114
/*! log: consolidated slot joins */
-#define WT_STAT_CONN_LOG_SLOT_JOINS 1112
+#define WT_STAT_CONN_LOG_SLOT_JOINS 1115
/*! log: consolidated slot unbuffered writes */
-#define WT_STAT_CONN_LOG_SLOT_UNBUFFERED 1113
+#define WT_STAT_CONN_LOG_SLOT_UNBUFFERED 1116
/*! log: log bytes of payload data */
-#define WT_STAT_CONN_LOG_BYTES_PAYLOAD 1114
+#define WT_STAT_CONN_LOG_BYTES_PAYLOAD 1117
/*! log: log bytes written */
-#define WT_STAT_CONN_LOG_BYTES_WRITTEN 1115
+#define WT_STAT_CONN_LOG_BYTES_WRITTEN 1118
/*! log: log files manually zero-filled */
-#define WT_STAT_CONN_LOG_ZERO_FILLS 1116
+#define WT_STAT_CONN_LOG_ZERO_FILLS 1119
/*! log: log flush operations */
-#define WT_STAT_CONN_LOG_FLUSH 1117
+#define WT_STAT_CONN_LOG_FLUSH 1120
/*! log: log force write operations */
-#define WT_STAT_CONN_LOG_FORCE_WRITE 1118
+#define WT_STAT_CONN_LOG_FORCE_WRITE 1121
/*! log: log force write operations skipped */
-#define WT_STAT_CONN_LOG_FORCE_WRITE_SKIP 1119
+#define WT_STAT_CONN_LOG_FORCE_WRITE_SKIP 1122
/*! log: log records compressed */
-#define WT_STAT_CONN_LOG_COMPRESS_WRITES 1120
+#define WT_STAT_CONN_LOG_COMPRESS_WRITES 1123
/*! log: log records not compressed */
-#define WT_STAT_CONN_LOG_COMPRESS_WRITE_FAILS 1121
+#define WT_STAT_CONN_LOG_COMPRESS_WRITE_FAILS 1124
/*! log: log records too small to compress */
-#define WT_STAT_CONN_LOG_COMPRESS_SMALL 1122
+#define WT_STAT_CONN_LOG_COMPRESS_SMALL 1125
/*! log: log release advances write LSN */
-#define WT_STAT_CONN_LOG_RELEASE_WRITE_LSN 1123
+#define WT_STAT_CONN_LOG_RELEASE_WRITE_LSN 1126
/*! log: log scan operations */
-#define WT_STAT_CONN_LOG_SCANS 1124
+#define WT_STAT_CONN_LOG_SCANS 1127
/*! log: log scan records requiring two reads */
-#define WT_STAT_CONN_LOG_SCAN_REREADS 1125
+#define WT_STAT_CONN_LOG_SCAN_REREADS 1128
/*! log: log server thread advances write LSN */
-#define WT_STAT_CONN_LOG_WRITE_LSN 1126
+#define WT_STAT_CONN_LOG_WRITE_LSN 1129
/*! log: log server thread write LSN walk skipped */
-#define WT_STAT_CONN_LOG_WRITE_LSN_SKIP 1127
+#define WT_STAT_CONN_LOG_WRITE_LSN_SKIP 1130
/*! log: log sync operations */
-#define WT_STAT_CONN_LOG_SYNC 1128
+#define WT_STAT_CONN_LOG_SYNC 1131
/*! log: log sync_dir operations */
-#define WT_STAT_CONN_LOG_SYNC_DIR 1129
+#define WT_STAT_CONN_LOG_SYNC_DIR 1132
/*! log: log write operations */
-#define WT_STAT_CONN_LOG_WRITES 1130
+#define WT_STAT_CONN_LOG_WRITES 1133
/*! log: logging bytes consolidated */
-#define WT_STAT_CONN_LOG_SLOT_CONSOLIDATED 1131
+#define WT_STAT_CONN_LOG_SLOT_CONSOLIDATED 1134
/*! log: maximum log file size */
-#define WT_STAT_CONN_LOG_MAX_FILESIZE 1132
+#define WT_STAT_CONN_LOG_MAX_FILESIZE 1135
/*! log: number of pre-allocated log files to create */
-#define WT_STAT_CONN_LOG_PREALLOC_MAX 1133
+#define WT_STAT_CONN_LOG_PREALLOC_MAX 1136
/*! log: pre-allocated log files not ready and missed */
-#define WT_STAT_CONN_LOG_PREALLOC_MISSED 1134
+#define WT_STAT_CONN_LOG_PREALLOC_MISSED 1137
/*! log: pre-allocated log files prepared */
-#define WT_STAT_CONN_LOG_PREALLOC_FILES 1135
+#define WT_STAT_CONN_LOG_PREALLOC_FILES 1138
/*! log: pre-allocated log files used */
-#define WT_STAT_CONN_LOG_PREALLOC_USED 1136
+#define WT_STAT_CONN_LOG_PREALLOC_USED 1139
/*! log: records processed by log scan */
-#define WT_STAT_CONN_LOG_SCAN_RECORDS 1137
+#define WT_STAT_CONN_LOG_SCAN_RECORDS 1140
/*! log: total in-memory size of compressed records */
-#define WT_STAT_CONN_LOG_COMPRESS_MEM 1138
+#define WT_STAT_CONN_LOG_COMPRESS_MEM 1141
/*! log: total log buffer size */
-#define WT_STAT_CONN_LOG_BUFFER_SIZE 1139
+#define WT_STAT_CONN_LOG_BUFFER_SIZE 1142
/*! log: total size of compressed records */
-#define WT_STAT_CONN_LOG_COMPRESS_LEN 1140
+#define WT_STAT_CONN_LOG_COMPRESS_LEN 1143
/*! log: written slots coalesced */
-#define WT_STAT_CONN_LOG_SLOT_COALESCED 1141
+#define WT_STAT_CONN_LOG_SLOT_COALESCED 1144
/*! log: yields waiting for previous log file close */
-#define WT_STAT_CONN_LOG_CLOSE_YIELDS 1142
+#define WT_STAT_CONN_LOG_CLOSE_YIELDS 1145
/*! reconciliation: fast-path pages deleted */
-#define WT_STAT_CONN_REC_PAGE_DELETE_FAST 1143
+#define WT_STAT_CONN_REC_PAGE_DELETE_FAST 1146
/*! reconciliation: page reconciliation calls */
-#define WT_STAT_CONN_REC_PAGES 1144
+#define WT_STAT_CONN_REC_PAGES 1147
/*! reconciliation: page reconciliation calls for eviction */
-#define WT_STAT_CONN_REC_PAGES_EVICTION 1145
+#define WT_STAT_CONN_REC_PAGES_EVICTION 1148
/*! reconciliation: pages deleted */
-#define WT_STAT_CONN_REC_PAGE_DELETE 1146
+#define WT_STAT_CONN_REC_PAGE_DELETE 1149
/*! reconciliation: split bytes currently awaiting free */
-#define WT_STAT_CONN_REC_SPLIT_STASHED_BYTES 1147
+#define WT_STAT_CONN_REC_SPLIT_STASHED_BYTES 1150
/*! reconciliation: split objects currently awaiting free */
-#define WT_STAT_CONN_REC_SPLIT_STASHED_OBJECTS 1148
+#define WT_STAT_CONN_REC_SPLIT_STASHED_OBJECTS 1151
/*! session: open cursor count */
-#define WT_STAT_CONN_SESSION_CURSOR_OPEN 1149
+#define WT_STAT_CONN_SESSION_CURSOR_OPEN 1152
/*! session: open session count */
-#define WT_STAT_CONN_SESSION_OPEN 1150
+#define WT_STAT_CONN_SESSION_OPEN 1153
/*! thread-yield: page acquire busy blocked */
-#define WT_STAT_CONN_PAGE_BUSY_BLOCKED 1151
+#define WT_STAT_CONN_PAGE_BUSY_BLOCKED 1154
/*! thread-yield: page acquire eviction blocked */
-#define WT_STAT_CONN_PAGE_FORCIBLE_EVICT_BLOCKED 1152
+#define WT_STAT_CONN_PAGE_FORCIBLE_EVICT_BLOCKED 1155
/*! thread-yield: page acquire locked blocked */
-#define WT_STAT_CONN_PAGE_LOCKED_BLOCKED 1153
+#define WT_STAT_CONN_PAGE_LOCKED_BLOCKED 1156
/*! thread-yield: page acquire read blocked */
-#define WT_STAT_CONN_PAGE_READ_BLOCKED 1154
+#define WT_STAT_CONN_PAGE_READ_BLOCKED 1157
/*! thread-yield: page acquire time sleeping (usecs) */
-#define WT_STAT_CONN_PAGE_SLEEP 1155
+#define WT_STAT_CONN_PAGE_SLEEP 1158
/*! transaction: number of named snapshots created */
-#define WT_STAT_CONN_TXN_SNAPSHOTS_CREATED 1156
+#define WT_STAT_CONN_TXN_SNAPSHOTS_CREATED 1159
/*! transaction: number of named snapshots dropped */
-#define WT_STAT_CONN_TXN_SNAPSHOTS_DROPPED 1157
+#define WT_STAT_CONN_TXN_SNAPSHOTS_DROPPED 1160
/*! transaction: transaction begins */
-#define WT_STAT_CONN_TXN_BEGIN 1158
+#define WT_STAT_CONN_TXN_BEGIN 1161
/*! transaction: transaction checkpoint currently running */
-#define WT_STAT_CONN_TXN_CHECKPOINT_RUNNING 1159
+#define WT_STAT_CONN_TXN_CHECKPOINT_RUNNING 1162
/*! transaction: transaction checkpoint generation */
-#define WT_STAT_CONN_TXN_CHECKPOINT_GENERATION 1160
+#define WT_STAT_CONN_TXN_CHECKPOINT_GENERATION 1163
/*! transaction: transaction checkpoint max time (msecs) */
-#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_MAX 1161
+#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_MAX 1164
/*! transaction: transaction checkpoint min time (msecs) */
-#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_MIN 1162
+#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_MIN 1165
/*! transaction: transaction checkpoint most recent time (msecs) */
-#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_RECENT 1163
+#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_RECENT 1166
/*! transaction: transaction checkpoint total time (msecs) */
-#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_TOTAL 1164
+#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_TOTAL 1167
/*! transaction: transaction checkpoints */
-#define WT_STAT_CONN_TXN_CHECKPOINT 1165
+#define WT_STAT_CONN_TXN_CHECKPOINT 1168
/*! transaction: transaction failures due to cache overflow */
-#define WT_STAT_CONN_TXN_FAIL_CACHE 1166
+#define WT_STAT_CONN_TXN_FAIL_CACHE 1169
/*! transaction: transaction range of IDs currently pinned */
-#define WT_STAT_CONN_TXN_PINNED_RANGE 1167
+#define WT_STAT_CONN_TXN_PINNED_RANGE 1170
/*! transaction: transaction range of IDs currently pinned by a checkpoint */
-#define WT_STAT_CONN_TXN_PINNED_CHECKPOINT_RANGE 1168
+#define WT_STAT_CONN_TXN_PINNED_CHECKPOINT_RANGE 1171
/*! transaction: transaction range of IDs currently pinned by named
* snapshots */
-#define WT_STAT_CONN_TXN_PINNED_SNAPSHOT_RANGE 1169
+#define WT_STAT_CONN_TXN_PINNED_SNAPSHOT_RANGE 1172
/*! transaction: transaction sync calls */
-#define WT_STAT_CONN_TXN_SYNC 1170
+#define WT_STAT_CONN_TXN_SYNC 1173
/*! transaction: transactions committed */
-#define WT_STAT_CONN_TXN_COMMIT 1171
+#define WT_STAT_CONN_TXN_COMMIT 1174
/*! transaction: transactions rolled back */
-#define WT_STAT_CONN_TXN_ROLLBACK 1172
+#define WT_STAT_CONN_TXN_ROLLBACK 1175
/*!
* @}
diff --git a/src/meta/meta_turtle.c b/src/meta/meta_turtle.c
index 635daf63d7f..4d2b359bbed 100644
--- a/src/meta/meta_turtle.c
+++ b/src/meta/meta_turtle.c
@@ -18,12 +18,9 @@ __metadata_config(WT_SESSION_IMPL *session, char **metaconfp)
WT_DECL_ITEM(buf);
WT_DECL_RET;
const char *cfg[] = { WT_CONFIG_BASE(session, file_meta), NULL, NULL };
- char *metaconf;
*metaconfp = NULL;
- metaconf = NULL;
-
/* Create a turtle file with default values. */
WT_RET(__wt_scr_alloc(session, 0, &buf));
WT_ERR(__wt_buf_fmt(session, buf,
@@ -31,14 +28,9 @@ __metadata_config(WT_SESSION_IMPL *session, char **metaconfp)
WT_METAFILE_ID,
WT_BTREE_MAJOR_VERSION_MAX, WT_BTREE_MINOR_VERSION_MAX));
cfg[1] = buf->data;
- WT_ERR(__wt_config_collapse(session, cfg, &metaconf));
+ ret = __wt_config_collapse(session, cfg, metaconfp);
- *metaconfp = metaconf;
-
- if (0) {
-err: __wt_free(session, metaconf);
- }
- __wt_scr_free(session, &buf);
+err: __wt_scr_free(session, &buf);
return (ret);
}
diff --git a/src/os_common/os_fhandle.c b/src/os_common/os_fhandle.c
index 818829203e0..50404c8b354 100644
--- a/src/os_common/os_fhandle.c
+++ b/src/os_common/os_fhandle.c
@@ -32,13 +32,13 @@ __fhandle_method_finalize(
/* not required: map_discard */
/* not required: map_preload */
/* not required: map_unmap */
- WT_HANDLE_METHOD_REQ(read);
- WT_HANDLE_METHOD_REQ(size);
+ WT_HANDLE_METHOD_REQ(fh_read);
+ WT_HANDLE_METHOD_REQ(fh_size);
/* not required: sync */
/* not required: sync_nowait */
if (!readonly) {
- WT_HANDLE_METHOD_REQ(truncate);
- WT_HANDLE_METHOD_REQ(write);
+ WT_HANDLE_METHOD_REQ(fh_truncate);
+ WT_HANDLE_METHOD_REQ(fh_write);
}
return (0);
@@ -255,7 +255,7 @@ __wt_open(WT_SESSION_IMPL *session,
WT_ERR(__wt_filename(session, name, &path));
/* Call the underlying open function. */
- WT_ERR(file_system->open_file(file_system, &session->iface,
+ WT_ERR(file_system->fs_open_file(file_system, &session->iface,
path == NULL ? name : path, file_type, flags, &fh->handle));
open_called = true;
diff --git a/src/os_common/os_fs_inmemory.c b/src/os_common/os_fs_inmemory.c
index 53da3f10e5c..3e4fe628892 100644
--- a/src/os_common/os_fs_inmemory.c
+++ b/src/os_common/os_fs_inmemory.c
@@ -512,10 +512,10 @@ __im_file_open(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
WT_FILE_HANDLE_INSERT(im_fs, im_fh, bucket);
file_handle->close = __im_file_close;
- file_handle->read = __im_file_read;
- file_handle->size = __im_file_size;
- file_handle->truncate = __im_file_truncate;
- file_handle->write = __im_file_write;
+ file_handle->fh_read = __im_file_read;
+ file_handle->fh_size = __im_file_size;
+ file_handle->fh_truncate = __im_file_truncate;
+ file_handle->fh_write = __im_file_write;
*file_handlep = file_handle;
@@ -576,13 +576,13 @@ __wt_os_inmemory(WT_SESSION_IMPL *session)
/* Initialize the in-memory jump table. */
file_system = (WT_FILE_SYSTEM *)im_fs;
- file_system->directory_list = __im_fs_directory_list;
- file_system->directory_list_free = __im_fs_directory_list_free;
- file_system->exist = __im_fs_exist;
- file_system->open_file = __im_file_open;
- file_system->remove = __im_fs_remove;
- file_system->rename = __im_fs_rename;
- file_system->size = __im_fs_size;
+ file_system->fs_directory_list = __im_fs_directory_list;
+ file_system->fs_directory_list_free = __im_fs_directory_list_free;
+ file_system->fs_exist = __im_fs_exist;
+ file_system->fs_open_file = __im_file_open;
+ file_system->fs_remove = __im_fs_remove;
+ file_system->fs_rename = __im_fs_rename;
+ file_system->fs_size = __im_fs_size;
file_system->terminate = __im_terminate;
/* Switch the file system into place. */
diff --git a/src/os_common/os_fstream.c b/src/os_common/os_fstream.c
index fc0daf1c211..0b199529e19 100644
--- a/src/os_common/os_fstream.c
+++ b/src/os_common/os_fstream.c
@@ -16,16 +16,16 @@
* Close a stream handle.
*/
static int
-__fstream_close(WT_SESSION_IMPL *session, WT_FSTREAM *fs)
+__fstream_close(WT_SESSION_IMPL *session, WT_FSTREAM *fstr)
{
WT_DECL_RET;
- if (!F_ISSET(fs, WT_STREAM_READ))
- WT_TRET(fs->flush(session, fs));
+ if (!F_ISSET(fstr, WT_STREAM_READ))
+ WT_TRET(fstr->fstr_flush(session, fstr));
- WT_TRET(__wt_close(session, &fs->fh));
- __wt_buf_free(session, &fs->buf);
- __wt_free(session, fs);
+ WT_TRET(__wt_close(session, &fstr->fh));
+ __wt_buf_free(session, &fstr->buf);
+ __wt_free(session, fstr);
return (ret);
}
@@ -34,13 +34,13 @@ __fstream_close(WT_SESSION_IMPL *session, WT_FSTREAM *fs)
* Flush the data from a stream.
*/
static int
-__fstream_flush(WT_SESSION_IMPL *session, WT_FSTREAM *fs)
+__fstream_flush(WT_SESSION_IMPL *session, WT_FSTREAM *fstr)
{
- if (fs->buf.size > 0) {
- WT_RET(__wt_write(
- session, fs->fh, fs->off, fs->buf.size, fs->buf.data));
- fs->off += (wt_off_t)fs->buf.size;
- fs->buf.size = 0;
+ if (fstr->buf.size > 0) {
+ WT_RET(__wt_write(session,
+ fstr->fh, fstr->off, fstr->buf.size, fstr->buf.data));
+ fstr->off += (wt_off_t)fstr->buf.size;
+ fstr->buf.size = 0;
}
return (0);
@@ -51,9 +51,9 @@ __fstream_flush(WT_SESSION_IMPL *session, WT_FSTREAM *fs)
* Stream flush unsupported.
*/
static int
-__fstream_flush_notsup(WT_SESSION_IMPL *session, WT_FSTREAM *fs)
+__fstream_flush_notsup(WT_SESSION_IMPL *session, WT_FSTREAM *fstr)
{
- WT_RET_MSG(session, ENOTSUP, "%s: flush", fs->name);
+ WT_RET_MSG(session, ENOTSUP, "%s: flush", fstr->name);
}
/*
@@ -68,7 +68,7 @@ __fstream_flush_notsup(WT_SESSION_IMPL *session, WT_FSTREAM *fs)
* (so the caller's EOF marker is a returned line length of 0).
*/
static int
-__fstream_getline(WT_SESSION_IMPL *session, WT_FSTREAM *fs, WT_ITEM *buf)
+__fstream_getline(WT_SESSION_IMPL *session, WT_FSTREAM *fstr, WT_ITEM *buf)
{
const char *p;
size_t len;
@@ -82,19 +82,20 @@ __fstream_getline(WT_SESSION_IMPL *session, WT_FSTREAM *fs, WT_ITEM *buf)
for (;;) {
/* Check if we need to refill the buffer. */
- if (WT_PTRDIFF(fs->buf.data, fs->buf.mem) >= fs->buf.size) {
+ if (WT_PTRDIFF(fstr->buf.data, fstr->buf.mem) >=
+ fstr->buf.size) {
len = WT_MIN(WT_STREAM_BUFSIZE,
- (size_t)(fs->size - fs->off));
+ (size_t)(fstr->size - fstr->off));
if (len == 0)
break; /* EOF */
- WT_RET(__wt_buf_initsize(session, &fs->buf, len));
+ WT_RET(__wt_buf_initsize(session, &fstr->buf, len));
WT_RET(__wt_read(
- session, fs->fh, fs->off, len, fs->buf.mem));
- fs->off += (wt_off_t)len;
+ session, fstr->fh, fstr->off, len, fstr->buf.mem));
+ fstr->off += (wt_off_t)len;
}
- c = *(p = fs->buf.data);
- fs->buf.data = ++p;
+ c = *(p = fstr->buf.data);
+ fstr->buf.data = ++p;
/* Leave space for a trailing NUL. */
WT_RET(__wt_buf_extend(session, buf, buf->size + 2));
@@ -116,10 +117,11 @@ __fstream_getline(WT_SESSION_IMPL *session, WT_FSTREAM *fs, WT_ITEM *buf)
* Stream getline unsupported.
*/
static int
-__fstream_getline_notsup(WT_SESSION_IMPL *session, WT_FSTREAM *fs, WT_ITEM *buf)
+__fstream_getline_notsup(
+ WT_SESSION_IMPL *session, WT_FSTREAM *fstr, WT_ITEM *buf)
{
WT_UNUSED(buf);
- WT_RET_MSG(session, ENOTSUP, "%s: getline", fs->name);
+ WT_RET_MSG(session, ENOTSUP, "%s: getline", fstr->name);
}
/*
@@ -128,14 +130,14 @@ __fstream_getline_notsup(WT_SESSION_IMPL *session, WT_FSTREAM *fs, WT_ITEM *buf)
*/
static int
__fstream_printf(
- WT_SESSION_IMPL *session, WT_FSTREAM *fs, const char *fmt, va_list ap)
+ WT_SESSION_IMPL *session, WT_FSTREAM *fstr, const char *fmt, va_list ap)
{
WT_ITEM *buf;
va_list ap_copy;
size_t len, space;
char *p;
- buf = &fs->buf;
+ buf = &fstr->buf;
for (;;) {
va_copy(ap_copy, ap);
@@ -149,7 +151,7 @@ __fstream_printf(
buf->size += len;
return (buf->size >= WT_STREAM_BUFSIZE ?
- __wt_fflush(session, fs) : 0);
+ __wt_fflush(session, fstr) : 0);
}
WT_RET(__wt_buf_extend(session, buf, buf->size + len + 1));
}
@@ -161,11 +163,11 @@ __fstream_printf(
*/
static int
__fstream_printf_notsup(
- WT_SESSION_IMPL *session, WT_FSTREAM *fs, const char *fmt, va_list ap)
+ WT_SESSION_IMPL *session, WT_FSTREAM *fstr, const char *fmt, va_list ap)
{
WT_UNUSED(fmt);
WT_UNUSED(ap);
- WT_RET_MSG(session, ENOTSUP, "%s: printf", fs->name);
+ WT_RET_MSG(session, ENOTSUP, "%s: printf", fstr->name);
}
/*
@@ -174,40 +176,42 @@ __fstream_printf_notsup(
*/
int
__wt_fopen(WT_SESSION_IMPL *session,
- const char *name, uint32_t open_flags, uint32_t flags, WT_FSTREAM **fsp)
+ const char *name, uint32_t open_flags, uint32_t flags, WT_FSTREAM **fstrp)
{
WT_DECL_RET;
WT_FH *fh;
- WT_FSTREAM *fs;
+ WT_FSTREAM *fstr;
- fs = NULL;
+ *fstrp = NULL;
+
+ fstr = NULL;
WT_RET(__wt_open(
session, name, WT_OPEN_FILE_TYPE_REGULAR, open_flags, &fh));
- WT_ERR(__wt_calloc_one(session, &fs));
- fs->fh = fh;
- fs->name = fh->name;
- fs->flags = flags;
+ WT_ERR(__wt_calloc_one(session, &fstr));
+ fstr->fh = fh;
+ fstr->name = fh->name;
+ fstr->flags = flags;
- fs->close = __fstream_close;
- WT_ERR(__wt_filesize(session, fh, &fs->size));
+ fstr->close = __fstream_close;
+ WT_ERR(__wt_filesize(session, fh, &fstr->size));
if (LF_ISSET(WT_STREAM_APPEND))
- fs->off = fs->size;
+ fstr->off = fstr->size;
if (LF_ISSET(WT_STREAM_APPEND | WT_STREAM_WRITE)) {
- fs->flush = __fstream_flush;
- fs->getline = __fstream_getline_notsup;
- fs->printf = __fstream_printf;
+ fstr->fstr_flush = __fstream_flush;
+ fstr->fstr_getline = __fstream_getline_notsup;
+ fstr->fstr_printf = __fstream_printf;
} else {
WT_ASSERT(session, LF_ISSET(WT_STREAM_READ));
- fs->flush = __fstream_flush_notsup;
- fs->getline = __fstream_getline;
- fs->printf = __fstream_printf_notsup;
+ fstr->fstr_flush = __fstream_flush_notsup;
+ fstr->fstr_getline = __fstream_getline;
+ fstr->fstr_printf = __fstream_printf_notsup;
}
- *fsp = fs;
+ *fstrp = fstr;
return (0);
err: WT_TRET(__wt_close(session, &fh));
- __wt_free(session, *fsp);
+ __wt_free(session, fstr);
return (ret);
}
diff --git a/src/os_common/os_fstream_stdio.c b/src/os_common/os_fstream_stdio.c
index 4b0c761024b..eea2c80ff0e 100644
--- a/src/os_common/os_fstream_stdio.c
+++ b/src/os_common/os_fstream_stdio.c
@@ -65,9 +65,9 @@ __stdio_init(WT_FSTREAM *fs, const char *name, FILE *fp)
fs->fp = fp;
fs->close = __stdio_close;
- fs->flush = __stdio_flush;
- fs->getline = __stdio_getline;
- fs->printf = __stdio_printf;
+ fs->fstr_flush = __stdio_flush;
+ fs->fstr_getline = __stdio_getline;
+ fs->fstr_printf = __stdio_printf;
}
/*
diff --git a/src/os_posix/os_fallocate.c b/src/os_posix/os_fallocate.c
index a162dbe01a1..9e5d9519900 100644
--- a/src/os_posix/os_fallocate.c
+++ b/src/os_posix/os_fallocate.c
@@ -125,28 +125,28 @@ __wt_posix_file_fallocate(WT_FILE_HANDLE *file_handle,
* avoid locking on Linux if at all possible.
*/
if (__posix_std_fallocate(file_handle, wt_session, offset, len) == 0) {
- file_handle->fallocate_nolock = __posix_std_fallocate;
- WT_PUBLISH(file_handle->fallocate, NULL);
+ file_handle->fh_allocate_nolock = __posix_std_fallocate;
+ WT_PUBLISH(file_handle->fh_allocate, NULL);
return (0);
}
if (__posix_sys_fallocate(file_handle, wt_session, offset, len) == 0) {
- file_handle->fallocate_nolock = __posix_sys_fallocate;
- WT_PUBLISH(file_handle->fallocate, NULL);
+ file_handle->fh_allocate_nolock = __posix_sys_fallocate;
+ WT_PUBLISH(file_handle->fh_allocate, NULL);
return (0);
}
if (__posix_posix_fallocate(
file_handle, wt_session, offset, len) == 0) {
#if defined(__linux__)
- file_handle->fallocate = __posix_posix_fallocate;
+ file_handle->fh_allocate = __posix_posix_fallocate;
WT_WRITE_BARRIER();
#else
- file_handle->fallocate_nolock = __posix_posix_fallocate;
- WT_PUBLISH(file_handle->fallocate, NULL);
+ file_handle->fh_allocate_nolock = __posix_posix_fallocate;
+ WT_PUBLISH(file_handle->fh_allocate, NULL);
#endif
return (0);
}
- file_handle->fallocate = NULL;
+ file_handle->fh_allocate = NULL;
WT_WRITE_BARRIER();
return (ENOTSUP);
}
diff --git a/src/os_posix/os_fs.c b/src/os_posix/os_fs.c
index ab9c82613d6..c05f75f2bd5 100644
--- a/src/os_posix/os_fs.c
+++ b/src/os_posix/os_fs.c
@@ -1,9 +1,29 @@
/*-
- * Copyright (c) 2014-2016 MongoDB, Inc.
- * Copyright (c) 2008-2014 WiredTiger, Inc.
- * All rights reserved.
+ * Public Domain 2014-2016 MongoDB, Inc.
+ * Public Domain 2008-2014 WiredTiger, Inc.
*
- * See the file LICENSE for redistribution information.
+ * 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 "wt_internal.h"
@@ -208,7 +228,7 @@ __posix_file_advise(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session,
* handle method to prevent future calls.
*/
if (ret == EINVAL) {
- file_handle->fadvise = NULL;
+ file_handle->fh_advise = NULL;
return (ENOTSUP);
}
@@ -603,31 +623,31 @@ directory_open:
* interesting.
*/
if (!pfh->direct_io)
- file_handle->fadvise = __posix_file_advise;
+ file_handle->fh_advise = __posix_file_advise;
#endif
- file_handle->fallocate = __wt_posix_file_fallocate;
- file_handle->lock = __posix_file_lock;
+ file_handle->fh_allocate = __wt_posix_file_fallocate;
+ file_handle->fh_lock = __posix_file_lock;
#ifdef WORDS_BIGENDIAN
/*
* The underlying objects are little-endian, mapping objects isn't
* currently supported on big-endian systems.
*/
#else
- file_handle->map = __wt_posix_map;
+ file_handle->fh_map = __wt_posix_map;
#ifdef HAVE_POSIX_MADVISE
- file_handle->map_discard = __wt_posix_map_discard;
- file_handle->map_preload = __wt_posix_map_preload;
+ file_handle->fh_map_discard = __wt_posix_map_discard;
+ file_handle->fh_map_preload = __wt_posix_map_preload;
#endif
- file_handle->unmap = __wt_posix_unmap;
+ file_handle->fh_unmap = __wt_posix_unmap;
#endif
- file_handle->read = __posix_file_read;
- file_handle->size = __posix_file_size;
- file_handle->sync = __posix_file_sync;
+ file_handle->fh_read = __posix_file_read;
+ file_handle->fh_size = __posix_file_size;
+ file_handle->fh_sync = __posix_file_sync;
#ifdef HAVE_SYNC_FILE_RANGE
- file_handle->sync_nowait = __posix_file_sync_nowait;
+ file_handle->fh_sync_nowait = __posix_file_sync_nowait;
#endif
- file_handle->truncate = __posix_file_truncate;
- file_handle->write = __posix_file_write;
+ file_handle->fh_truncate = __posix_file_truncate;
+ file_handle->fh_write = __posix_file_write;
*file_handlep = file_handle;
@@ -669,16 +689,16 @@ __wt_os_posix(WT_SESSION_IMPL *session)
WT_RET(__wt_calloc_one(session, &file_system));
/* Initialize the POSIX jump table. */
- file_system->directory_list = __wt_posix_directory_list;
- file_system->directory_list_free = __wt_posix_directory_list_free;
+ file_system->fs_directory_list = __wt_posix_directory_list;
+ file_system->fs_directory_list_free = __wt_posix_directory_list_free;
#ifdef __linux__
- file_system->directory_sync = __posix_directory_sync;
+ file_system->fs_directory_sync = __posix_directory_sync;
#endif
- file_system->exist = __posix_fs_exist;
- file_system->open_file = __posix_open_file;
- file_system->remove = __posix_fs_remove;
- file_system->rename = __posix_fs_rename;
- file_system->size = __posix_fs_size;
+ file_system->fs_exist = __posix_fs_exist;
+ file_system->fs_open_file = __posix_open_file;
+ file_system->fs_remove = __posix_fs_remove;
+ file_system->fs_rename = __posix_fs_rename;
+ file_system->fs_size = __posix_fs_size;
file_system->terminate = __posix_terminate;
/* Switch it into place. */
diff --git a/src/os_posix/os_map.c b/src/os_posix/os_map.c
index 7fde4037250..9cdb58b95c8 100644
--- a/src/os_posix/os_map.c
+++ b/src/os_posix/os_map.c
@@ -40,7 +40,7 @@ __wt_posix_map(WT_FILE_HANDLE *fh, WT_SESSION *wt_session,
* underneath us, our caller needs to ensure consistency of the mapped
* region vs. any other file activity.
*/
- WT_RET(fh->size(fh, wt_session, &file_size));
+ WT_RET(fh->fh_size(fh, wt_session, &file_size));
len = (size_t)file_size;
(void)__wt_verbose(session, WT_VERB_HANDLEOPS,
diff --git a/src/os_win/os_fs.c b/src/os_win/os_fs.c
index 33e281bf8ae..c4a1235b61b 100644
--- a/src/os_win/os_fs.c
+++ b/src/os_win/os_fs.c
@@ -498,21 +498,21 @@ directory_open:
WT_ERR(__wt_strdup(session, name, &file_handle->name));
file_handle->close = __win_file_close;
- file_handle->lock = __win_file_lock;
+ file_handle->fh_lock = __win_file_lock;
#ifdef WORDS_BIGENDIAN
/*
* The underlying objects are little-endian, mapping objects isn't
* currently supported on big-endian systems.
*/
#else
- file_handle->map = __wt_win_map;
- file_handle->unmap = __wt_win_unmap;
+ file_handle->fh_map = __wt_win_map;
+ file_handle->fh_unmap = __wt_win_unmap;
#endif
- file_handle->read = __win_file_read;
- file_handle->size = __win_file_size;
- file_handle->sync = __win_file_sync;
- file_handle->truncate = __win_file_truncate;
- file_handle->write = __win_file_write;
+ file_handle->fh_read = __win_file_read;
+ file_handle->fh_size = __win_file_size;
+ file_handle->fh_sync = __win_file_sync;
+ file_handle->fh_truncate = __win_file_truncate;
+ file_handle->fh_write = __win_file_write;
*file_handlep = file_handle;
@@ -552,13 +552,13 @@ __wt_os_win(WT_SESSION_IMPL *session)
WT_RET(__wt_calloc_one(session, &file_system));
/* Initialize the Windows jump table. */
- file_system->directory_list = __wt_win_directory_list;
- file_system->directory_list_free = __wt_win_directory_list_free;
- file_system->exist = __win_fs_exist;
- file_system->open_file = __win_open_file;
- file_system->remove = __win_fs_remove;
- file_system->rename = __win_fs_rename;
- file_system->size = __wt_win_fs_size;
+ file_system->fs_directory_list = __wt_win_directory_list;
+ file_system->fs_directory_list_free = __wt_win_directory_list_free;
+ file_system->fs_exist = __win_fs_exist;
+ file_system->fs_open_file = __win_open_file;
+ file_system->fs_remove = __win_fs_remove;
+ file_system->fs_rename = __win_fs_rename;
+ file_system->fs_size = __wt_win_fs_size;
file_system->terminate = __win_terminate;
/* Switch it into place. */
diff --git a/src/reconcile/rec_write.c b/src/reconcile/rec_write.c
index a46662b4b9d..6e406fc7180 100644
--- a/src/reconcile/rec_write.c
+++ b/src/reconcile/rec_write.c
@@ -383,8 +383,11 @@ __wt_reconcile(WT_SESSION_IMPL *session,
mod->last_oldest_id = oldest_id;
/* Initialize the reconciliation structure for each new run. */
- WT_RET(__rec_write_init(
- session, ref, flags, salvage, &session->reconcile));
+ if ((ret = __rec_write_init(
+ session, ref, flags, salvage, &session->reconcile)) != 0) {
+ WT_TRET(__wt_fair_unlock(session, &page->page_lock));
+ return (ret);
+ }
r = session->reconcile;
/* Reconcile the page. */
@@ -4269,14 +4272,14 @@ __rec_col_var(WT_SESSION_IMPL *session,
last = r->last;
vpack = &_vpack;
+ WT_RET(__rec_split_init(
+ session, r, page, pageref->ref_recno, btree->maxleafpage));
+
WT_RET(__wt_scr_alloc(session, 0, &orig));
data = NULL;
size = 0;
upd = NULL;
- WT_RET(__rec_split_init(
- session, r, page, pageref->ref_recno, btree->maxleafpage));
-
/*
* The salvage code may be calling us to reconcile a page where there
* were missing records in the column-store name space. If taking the
@@ -5019,8 +5022,8 @@ __rec_row_leaf(WT_SESSION_IMPL *session,
* Temporary buffers in which to instantiate any uninstantiated keys
* or value items we need.
*/
- WT_RET(__wt_scr_alloc(session, 0, &tmpkey));
- WT_RET(__wt_scr_alloc(session, 0, &tmpval));
+ WT_ERR(__wt_scr_alloc(session, 0, &tmpkey));
+ WT_ERR(__wt_scr_alloc(session, 0, &tmpval));
/* For each entry in the page... */
WT_ROW_FOREACH(page, rip, i) {
@@ -5180,7 +5183,7 @@ __rec_row_leaf(WT_SESSION_IMPL *session,
* can't remove them from the in-memory
* tree; if an overflow key was deleted
* without being instantiated (for
- * example, cursor-based truncation, do
+ * example, cursor-based truncation), do
* it now.
*/
if (ikey == NULL)
diff --git a/src/session/session_api.c b/src/session/session_api.c
index 933f2273902..77d1dc74c84 100644
--- a/src/session/session_api.c
+++ b/src/session/session_api.c
@@ -722,18 +722,29 @@ __wt_session_drop(WT_SESSION_IMPL *session, const char *uri, const char *cfg[])
{
WT_DECL_RET;
WT_CONFIG_ITEM cval;
- bool lock_wait;
+ bool checkpoint_wait, lock_wait;
+ WT_RET(__wt_config_gets_def(session, cfg, "checkpoint_wait", 1, &cval));
+ checkpoint_wait = cval.val != 0;
WT_RET(__wt_config_gets_def(session, cfg, "lock_wait", 1, &cval));
lock_wait = cval.val != 0 || F_ISSET(session, WT_SESSION_LOCK_NO_WAIT);
if (!lock_wait)
F_SET(session, WT_SESSION_LOCK_NO_WAIT);
- WT_WITH_CHECKPOINT_LOCK(session, ret,
- WT_WITH_SCHEMA_LOCK(session, ret,
- WT_WITH_TABLE_LOCK(session, ret,
- ret = __wt_schema_drop(session, uri, cfg))));
+ /*
+ * The checkpoint lock only is needed to avoid a spurious EBUSY error
+ * return.
+ */
+ if (checkpoint_wait)
+ WT_WITH_CHECKPOINT_LOCK(session, ret,
+ WT_WITH_SCHEMA_LOCK(session, ret,
+ WT_WITH_TABLE_LOCK(session, ret,
+ ret = __wt_schema_drop(session, uri, cfg))));
+ else
+ WT_WITH_SCHEMA_LOCK(session, ret,
+ WT_WITH_TABLE_LOCK(session, ret,
+ ret = __wt_schema_drop(session, uri, cfg)));
if (!lock_wait)
F_CLR(session, WT_SESSION_LOCK_NO_WAIT);
@@ -1512,11 +1523,11 @@ err: WT_TRET(__wt_writeunlock(session, txn_global->nsnap_rwlock));
}
/*
- * __session_strerror --
+ * __wt_session_strerror --
* WT_SESSION->strerror method.
*/
-static const char *
-__session_strerror(WT_SESSION *wt_session, int error)
+const char *
+__wt_session_strerror(WT_SESSION *wt_session, int error)
{
WT_SESSION_IMPL *session;
@@ -1539,7 +1550,7 @@ __open_session(WT_CONNECTION_IMPL *conn,
NULL,
__session_close,
__session_reconfigure,
- __session_strerror,
+ __wt_session_strerror,
__session_open_cursor,
__session_create,
__wt_session_compact,
@@ -1566,7 +1577,7 @@ __open_session(WT_CONNECTION_IMPL *conn,
NULL,
__session_close,
__session_reconfigure,
- __session_strerror,
+ __wt_session_strerror,
__session_open_cursor,
__session_create_readonly,
__wt_session_compact_readonly,
@@ -1675,7 +1686,7 @@ __open_session(WT_CONNECTION_IMPL *conn,
* __wt_hazard_close ensures the array is cleared - so it is safe to
* reset the starting size on each open.
*/
- session_ret->hazard_size = WT_HAZARD_INCR;
+ session_ret->hazard_size = 0;
/*
* Configuration: currently, the configuration for open_session is the
diff --git a/src/support/stat.c b/src/support/stat.c
index bb46ad03e43..7514aac56c4 100644
--- a/src/support/stat.c
+++ b/src/support/stat.c
@@ -562,6 +562,9 @@ static const char * const __stats_connection_desc[] = {
"cache: eviction worker thread evicting pages",
"cache: failed eviction of pages that exceeded the in-memory maximum",
"cache: hazard pointer blocked page eviction",
+ "cache: hazard pointer check calls",
+ "cache: hazard pointer check entries walked",
+ "cache: hazard pointer maximum array length",
"cache: in-memory page passed criteria to be split",
"cache: in-memory page splits",
"cache: internal pages evicted",
@@ -765,6 +768,9 @@ __wt_stat_connection_clear_single(WT_CONNECTION_STATS *stats)
stats->cache_eviction_worker_evicting = 0;
stats->cache_eviction_force_fail = 0;
stats->cache_eviction_hazard = 0;
+ stats->cache_hazard_checks = 0;
+ stats->cache_hazard_walks = 0;
+ stats->cache_hazard_max = 0;
stats->cache_inmem_splittable = 0;
stats->cache_inmem_split = 0;
stats->cache_eviction_internal = 0;
@@ -905,6 +911,8 @@ void
__wt_stat_connection_aggregate(
WT_CONNECTION_STATS **from, WT_CONNECTION_STATS *to)
{
+ int64_t v;
+
to->lsm_work_queue_app += WT_STAT_READ(from, lsm_work_queue_app);
to->lsm_work_queue_manager +=
WT_STAT_READ(from, lsm_work_queue_manager);
@@ -972,6 +980,10 @@ __wt_stat_connection_aggregate(
WT_STAT_READ(from, cache_eviction_force_fail);
to->cache_eviction_hazard +=
WT_STAT_READ(from, cache_eviction_hazard);
+ to->cache_hazard_checks += WT_STAT_READ(from, cache_hazard_checks);
+ to->cache_hazard_walks += WT_STAT_READ(from, cache_hazard_walks);
+ if ((v = WT_STAT_READ(from, cache_hazard_max)) > to->cache_hazard_max)
+ to->cache_hazard_max = v;
to->cache_inmem_splittable +=
WT_STAT_READ(from, cache_inmem_splittable);
to->cache_inmem_split += WT_STAT_READ(from, cache_inmem_split);
diff --git a/src/utilities/util_load.c b/src/utilities/util_load.c
index 696dc68630a..a81d06c6866 100644
--- a/src/utilities/util_load.c
+++ b/src/utilities/util_load.c
@@ -366,6 +366,7 @@ config_update(WT_SESSION *session, char **list)
if (WT_PREFIX_MATCH(*listp, "colgroup:") ||
WT_PREFIX_MATCH(*listp, "file:") ||
WT_PREFIX_MATCH(*listp, "index:") ||
+ WT_PREFIX_MATCH(*listp, "lsm:") ||
WT_PREFIX_MATCH(*listp, "table:"))
if (config_rename(session, listp, cmdname))
return (1);
diff --git a/test/bloom/Makefile.am b/test/bloom/Makefile.am
index 0592cec7e42..81a21f59882 100644
--- a/test/bloom/Makefile.am
+++ b/test/bloom/Makefile.am
@@ -1,9 +1,12 @@
-AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir)/src/include \
- -I$(top_srcdir)/test/utility
+AM_CPPFLAGS = -I$(top_builddir)
+AM_CPPFLAGS +=-I$(top_srcdir)/src/include
+AM_CPPFLAGS +=-I$(top_srcdir)/test/utility
noinst_PROGRAMS = t
t_SOURCES = test_bloom.c
-t_LDADD = $(top_builddir)/libwiredtiger.la
+
+t_LDADD = $(top_builddir)/test/utility/libtest_util.la
+t_LDADD +=$(top_builddir)/libwiredtiger.la
t_LDFLAGS = -static
# Run this during a "make check" smoke test.
diff --git a/test/bloom/test_bloom.c b/test/bloom/test_bloom.c
index 6955813dc68..e9980cd53cb 100644
--- a/test/bloom/test_bloom.c
+++ b/test/bloom/test_bloom.c
@@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "test_util.i"
+#include "test_util.h"
static struct {
char *progname; /* Program name */
diff --git a/test/checkpoint/Makefile.am b/test/checkpoint/Makefile.am
index cf879d046bf..2b5ba800c9c 100644
--- a/test/checkpoint/Makefile.am
+++ b/test/checkpoint/Makefile.am
@@ -1,9 +1,12 @@
-AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir)/src/include \
- -I$(top_srcdir)/test/utility
+AM_CPPFLAGS = -I$(top_builddir)
+AM_CPPFLAGS +=-I$(top_srcdir)/src/include
+AM_CPPFLAGS +=-I$(top_srcdir)/test/utility
noinst_PROGRAMS = t
-t_LDADD = $(top_builddir)/libwiredtiger.la
t_SOURCES = checkpointer.c workers.c test_checkpoint.c
+
+t_LDADD = $(top_builddir)/test/utility/libtest_util.la
+t_LDADD +=$(top_builddir)/libwiredtiger.la
t_LDFLAGS = -static
TESTS = smoke.sh
diff --git a/test/checkpoint/test_checkpoint.h b/test/checkpoint/test_checkpoint.h
index 10e21289dd3..0d0d02447d5 100644
--- a/test/checkpoint/test_checkpoint.h
+++ b/test/checkpoint/test_checkpoint.h
@@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "test_util.i"
+#include "test_util.h"
#include <signal.h>
diff --git a/test/csuite/Makefile.am b/test/csuite/Makefile.am
new file mode 100644
index 00000000000..6058a05431b
--- /dev/null
+++ b/test/csuite/Makefile.am
@@ -0,0 +1,21 @@
+AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir)/src/include \
+ -I$(top_srcdir)/test/utility
+LDADD = $(top_builddir)/test/utility/libtest_util.la \
+ $(top_builddir)/libwiredtiger.la
+AM_LDFLAGS = -static
+
+test_wt1965_col_efficiency_SOURCES = wt1965_col_efficiency/main.c
+noinst_PROGRAMS = test_wt1965_col_efficiency
+
+test_wt2246_col_append_SOURCES = wt2246_col_append/main.c
+noinst_PROGRAMS += test_wt2246_col_append
+
+test_wt2535_insert_race_SOURCES = wt2535_insert_race/main.c
+noinst_PROGRAMS += test_wt2535_insert_race
+
+# Run this during a "make check" smoke test.
+TESTS = $(noinst_PROGRAMS)
+LOG_COMPILER = $(TEST_WRAPPER)
+
+clean-local:
+ rm -rf WT_TEST.* *.core
diff --git a/test/csuite/wt1965_col_efficiency/main.c b/test/csuite/wt1965_col_efficiency/main.c
new file mode 100644
index 00000000000..2882ce9cdf5
--- /dev/null
+++ b/test/csuite/wt1965_col_efficiency/main.c
@@ -0,0 +1,186 @@
+/*-
+ * Public Domain 2014-2016 MongoDB, Inc.
+ * Public Domain 2008-2014 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 "test_util.h"
+
+/*
+ * JIRA ticket reference: WT-1965
+ * Test case description: The reported issue was that column store tables
+ * exhibit high CPU usage when populated with sparse record IDs.
+ * Failure mode: It isn't simple to make this test case failure explicit since
+ * it is demonstrating an inefficiency rather than a correctness bug.
+ */
+
+void (*custom_die)(void) = NULL;
+
+/* If changing field count also need to change set_value and get_value calls */
+#define NR_FIELDS 8
+#define NR_OBJECTS 100
+#define NR_THREADS 4
+
+static uint64_t g_ts = 0;
+
+/*
+ * Each thread inserts a set of keys into the record store database. The keys
+ * are generated in such a way that there are large gaps in the key range.
+ */
+static void *
+thread_func(void *arg)
+{
+ TEST_OPTS *opts;
+ WT_CURSOR *cursor, *idx_cursor;
+ WT_SESSION *session;
+ uint64_t i, ins_rotor, ins_thr_idx, thr_idx, ts;
+ uint64_t *obj_data;
+
+ opts = (TEST_OPTS *)arg;
+ thr_idx = __wt_atomic_fetch_addv64(&opts->next_threadid, 1);
+ ts = g_ts;
+ obj_data = dcalloc(
+ (NR_OBJECTS/NR_THREADS + 1) * NR_FIELDS, sizeof(*obj_data));
+
+ testutil_check(opts->conn->open_session(
+ opts->conn, NULL, NULL, &session));
+
+ testutil_check(session->open_cursor(
+ session, opts->uri, NULL, NULL, &cursor));
+ testutil_check(session->open_cursor(
+ session, "table:index", NULL, NULL, &idx_cursor));
+
+ for (ins_rotor = 1; ins_rotor < 10; ++ins_rotor) {
+ for (ins_thr_idx = thr_idx, i = 0; ins_thr_idx < NR_OBJECTS;
+ ins_thr_idx += NR_THREADS, i += NR_FIELDS) {
+
+ testutil_check(
+ session->begin_transaction(session, "sync=false"));
+
+ cursor->set_key(cursor, ins_thr_idx << 40 | ins_rotor);
+ cursor->set_value(cursor, ts,
+ obj_data[i+0], obj_data[i+1], obj_data[i+2],
+ obj_data[i+3], obj_data[i+4], obj_data[i+5],
+ obj_data[i+6], obj_data[i+7]);
+ testutil_check(cursor->insert(cursor));
+
+ idx_cursor->set_key(
+ idx_cursor, ins_thr_idx << 40 | ts);
+ idx_cursor->set_value(idx_cursor, ins_rotor);
+ testutil_check(idx_cursor->insert(idx_cursor));
+
+ testutil_check(
+ session->commit_transaction(session, NULL));
+
+ /* change object fields */
+ ++obj_data[i + ((ins_thr_idx + ins_rotor) % NR_FIELDS)];
+ ++obj_data[i +
+ ((ins_thr_idx + ins_rotor + 1) % NR_FIELDS)];
+
+ ++g_ts;
+ /* 5K updates/sec */
+ (void)usleep(1000000ULL * NR_THREADS / 5000);
+ }
+ }
+
+ testutil_check(session->close(session, NULL));
+ free(obj_data);
+ return (NULL);
+}
+
+int
+main(int argc, char *argv[])
+{
+ TEST_OPTS *opts, _opts;
+ WT_CURSOR *cursor;
+ WT_SESSION *session;
+ pthread_t thr[NR_THREADS];
+ size_t t;
+ uint64_t f[NR_FIELDS], r, ts;
+ int i, ret;
+ char table_format[256];
+
+ opts = &_opts;
+ memset(opts, 0, sizeof(*opts));
+ testutil_check(testutil_parse_opts(argc, argv, opts));
+ testutil_make_work_dir(opts->home);
+
+ testutil_check(wiredtiger_open(opts->home, NULL,
+ "create,cache_size=1G,checkpoint=(wait=30),"
+ "eviction_trigger=80,eviction_target=64,eviction_dirty_target=65,"
+ "log=(enabled,file_max=10M),"
+ "transaction_sync=(enabled=true,method=none)", &opts->conn));
+ testutil_check(opts->conn->open_session(
+ opts->conn, NULL, NULL, &session));
+
+ sprintf(table_format, "key_format=r,value_format=");
+ for (i = 0; i < NR_FIELDS; i++)
+ strcat(table_format, "Q");
+
+ /* recno -> timestamp + NR_FIELDS * Q */
+ testutil_check(session->create(
+ session, opts->uri, table_format));
+ /* timestamp -> recno */
+ testutil_check(session->create(session,
+ "table:index", "key_format=Q,value_format=Q"));
+
+ testutil_check(session->close(session, NULL));
+
+ for (t = 0; t < NR_THREADS; ++t)
+ testutil_check(pthread_create(
+ &thr[t], NULL, thread_func, (void *)opts));
+
+ for (t = 0; t < NR_THREADS; ++t)
+ (void)pthread_join(thr[t], NULL);
+
+ testutil_check(opts->conn->open_session(
+ opts->conn, NULL, NULL, &session));
+
+ /* recno -> timestamp + NR_FIELDS * Q */
+ testutil_check(session->create(session, opts->uri, table_format));
+
+ testutil_check(session->open_cursor(
+ session, opts->uri, NULL, NULL, &cursor));
+
+ while ((ret = cursor->next(cursor)) == 0) {
+ testutil_check(cursor->get_key(cursor, &r));
+ testutil_check(cursor->get_value(cursor, &ts,
+ &f[0], &f[1], &f[2], &f[3], &f[4], &f[5], &f[6], &f[7]));
+
+ if (!opts->verbose)
+ continue;
+
+ printf("(%" PRIu64 ",%llu)\t\t%" PRIu64,
+ (r >> 40), r & ((1ULL << 40) - 1), ts);
+
+ for (i = 0; i < NR_FIELDS; i++)
+ printf("\t%" PRIu64, f[i]);
+ printf("\n");
+ }
+ testutil_assert(ret == WT_NOTFOUND);
+
+ testutil_cleanup(opts);
+
+ return (0);
+}
diff --git a/test/csuite/wt2246_col_append/main.c b/test/csuite/wt2246_col_append/main.c
new file mode 100644
index 00000000000..3ac96677ed0
--- /dev/null
+++ b/test/csuite/wt2246_col_append/main.c
@@ -0,0 +1,158 @@
+/*-
+ * Public Domain 2014-2016 MongoDB, Inc.
+ * Public Domain 2008-2014 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 "test_util.h"
+
+/*
+ * JIRA ticket reference: WT-2246
+ * Test case description: The column-store search routine used to search the
+ * target leaf page even when the cursor is configured with append and we're
+ * allocating a record number. That was inefficient, this test case
+ * demonstrates the inefficiency.
+ * Failure mode: It isn't simple to make this test case failure explicit since
+ * it is demonstrating an inefficiency rather than a correctness bug.
+ */
+
+/* Don't move into shared function there is a cross platform solution */
+#include <signal.h>
+
+#define MILLION 1000000
+
+void (*custom_die)(void) = NULL;
+
+/* Needs to be global for signal handling. */
+TEST_OPTS *opts, _opts;
+
+static void
+page_init(uint64_t n)
+{
+ WT_CONNECTION *conn;
+ WT_CURSOR *cursor;
+ WT_SESSION *session;
+ uint64_t recno, vrecno;
+ char buf[64];
+
+ conn = opts->conn;
+
+ testutil_check(conn->open_session(conn, NULL, NULL, &session));
+ testutil_check(
+ session->open_cursor(session, opts->uri, NULL, "append", &cursor));
+
+ vrecno = 0;
+ buf[0] = '\2';
+ for (recno = 1;; ++recno) {
+ if (opts->table_type == TABLE_FIX)
+ cursor->set_value(cursor, buf[0]);
+ else {
+ if (recno % 3 == 0)
+ ++vrecno;
+ snprintf(buf,
+ sizeof(buf), "%" PRIu64 " VALUE ------", vrecno);
+ cursor->set_value(cursor, buf);
+ }
+ testutil_check(cursor->insert(cursor));
+ testutil_check(cursor->get_key(cursor, &opts->max_inserted_id));
+ if (opts->max_inserted_id >= n)
+ break;
+ }
+}
+
+/*
+ * TODO: Platform specific?
+ */
+static void
+onsig(int signo)
+{
+ WT_UNUSED(signo);
+ opts->running = false;
+}
+
+#define N_APPEND_THREADS 6
+#define N_RECORDS (20 * WT_MILLION)
+
+int
+main(int argc, char *argv[])
+{
+ WT_SESSION *session;
+ clock_t ce, cs;
+ pthread_t idlist[100];
+ uint64_t i, id;
+ char buf[100];
+
+ opts = &_opts;
+ memset(opts, 0, sizeof(*opts));
+ opts->table_type = TABLE_ROW;
+ opts->n_append_threads = N_APPEND_THREADS;
+ opts->nrecords = N_RECORDS;
+ testutil_check(testutil_parse_opts(argc, argv, opts));
+ testutil_make_work_dir(opts->home);
+
+ snprintf(buf, sizeof(buf),
+ "create,"
+ "cache_size=%s,"
+ "eviction=(threads_max=5),"
+ "statistics=(fast)",
+ opts->table_type == TABLE_FIX ? "500MB" : "2GB");
+ testutil_check(wiredtiger_open(opts->home, NULL, buf, &opts->conn));
+ testutil_check(
+ opts->conn->open_session(opts->conn, NULL, NULL, &session));
+ snprintf(buf, sizeof(buf),
+ "key_format=r,value_format=%s,"
+ "allocation_size=4K,leaf_page_max=64K",
+ opts->table_type == TABLE_FIX ? "8t" : "S");
+ testutil_check(session->create(session, opts->uri, buf));
+ testutil_check(session->close(session, NULL));
+
+ page_init(5000);
+
+ /* Force to disk and re-open. */
+ testutil_check(opts->conn->close(opts->conn, NULL));
+ testutil_check(wiredtiger_open(opts->home, NULL, NULL, &opts->conn));
+
+ (void)signal(SIGINT, onsig);
+
+ cs = clock();
+ id = 0;
+ for (i = 0; i < opts->n_append_threads; ++i, ++id) {
+ printf("append: %" PRIu64 "\n", id);
+ testutil_check(pthread_create(
+ &idlist[id], NULL, thread_append, (void *)opts));
+ }
+
+ for (i = 0; i < id; ++i)
+ testutil_check(pthread_join(idlist[i], NULL));
+
+ ce = clock();
+ printf("%" PRIu64 "M records: %.2lf processor seconds\n",
+ opts->max_inserted_id / MILLION,
+ (ce - cs) / (double)CLOCKS_PER_SEC);
+
+ testutil_cleanup(opts);
+ /* NOTREACHED */
+
+ return (0);
+}
diff --git a/test/csuite/wt2535_insert_race/main.c b/test/csuite/wt2535_insert_race/main.c
new file mode 100644
index 00000000000..5eaca3279b6
--- /dev/null
+++ b/test/csuite/wt2535_insert_race/main.c
@@ -0,0 +1,159 @@
+/*-
+ * Public Domain 2014-2016 MongoDB, Inc.
+ * Public Domain 2008-2014 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 "test_util.h"
+
+/*
+ * JIRA ticket reference: WT-2535
+ * Test case description: This is a test case that looks for lost updates to
+ * a single record. That is multiple threads each do the same number of read
+ * modify write operations on a single record. At the end verify that the
+ * data contains the expected value.
+ * Failure mode: Check that the data is correct at the end of the run.
+ */
+
+void (*custom_die)(void) = NULL;
+
+void *thread_insert_race(void *);
+
+int
+main(int argc, char *argv[])
+{
+ TEST_OPTS *opts, _opts;
+ WT_CURSOR *c;
+ WT_SESSION *session;
+ clock_t ce, cs;
+ pthread_t id[100];
+ uint64_t current_value;
+ int i;
+
+ opts = &_opts;
+ memset(opts, 0, sizeof(*opts));
+ opts->nthreads = 10;
+ opts->nrecords = 1000;
+ opts->table_type = TABLE_ROW;
+ testutil_check(testutil_parse_opts(argc, argv, opts));
+ testutil_make_work_dir(opts->home);
+
+ testutil_check(wiredtiger_open(opts->home, NULL,
+ "create,"
+ "cache_size=2G,"
+ "eviction=(threads_max=5),"
+ "statistics=(fast)", &opts->conn));
+ testutil_check(
+ opts->conn->open_session(opts->conn, NULL, NULL, &session));
+ testutil_check(session->create(session, opts->uri,
+ "key_format=Q,value_format=Q,"
+ "leaf_page_max=32k,"));
+
+ /* Create the single record. */
+ testutil_check(
+ session->open_cursor(session, opts->uri, NULL, NULL, &c));
+ c->set_key(c, 1);
+ c->set_value(c, 0);
+ testutil_check(c->insert(c));
+ testutil_check(c->close(c));
+ cs = clock();
+ for (i = 0; i < (int)opts->nthreads; ++i) {
+ testutil_check(pthread_create(
+ &id[i], NULL, thread_insert_race, (void *)opts));
+ }
+ while (--i >= 0)
+ testutil_check(pthread_join(id[i], NULL));
+ testutil_check(
+ session->open_cursor(session, opts->uri, NULL, NULL, &c));
+ c->set_key(c, 1);
+ testutil_check(c->search(c));
+ testutil_check(c->get_value(c, &current_value));
+ if (current_value != opts->nthreads * opts->nrecords) {
+ fprintf(stderr,
+ "ERROR: didn't get expected number of changes\n");
+ fprintf(stderr, "got: %" PRIu64 ", expected: %" PRIu64 "\n",
+ current_value, opts->nthreads * opts->nrecords);
+ return (EXIT_FAILURE);
+ }
+ testutil_check(session->close(session, NULL));
+ ce = clock();
+ printf("%" PRIu64 ": %.2lf\n",
+ opts->nrecords, (ce - cs) / (double)CLOCKS_PER_SEC);
+
+ testutil_cleanup(opts);
+ return (EXIT_SUCCESS);
+}
+
+/*
+ * Append to a table in a "racy" fashion - that is attempt to insert the
+ * same record another thread is likely to also be inserting.
+ */
+void *
+thread_insert_race(void *arg)
+{
+ TEST_OPTS *opts;
+ WT_CONNECTION *conn;
+ WT_CURSOR *cursor;
+ WT_SESSION *session;
+ uint64_t i, value;
+ int ret;
+
+ opts = (TEST_OPTS *)arg;
+ conn = opts->conn;
+
+ testutil_check(conn->open_session(conn, NULL, NULL, &session));
+ testutil_check(session->open_cursor(
+ session, opts->uri, NULL, NULL, &cursor));
+
+ printf("Running insert thread\n");
+ for (i = 0; i < opts->nrecords; ++i) {
+ testutil_check(
+ session->begin_transaction(session, "isolation=snapshot"));
+ cursor->set_key(cursor, 1);
+ testutil_check(cursor->search(cursor));
+ testutil_check(cursor->get_value(cursor, &value));
+ cursor->set_key(cursor, 1);
+ cursor->set_value(cursor, value + 1);
+ if ((ret = cursor->update(cursor)) != 0) {
+ if (ret == WT_ROLLBACK) {
+ testutil_check(session->rollback_transaction(
+ session, NULL));
+ i--;
+ continue;
+ }
+ printf("Error in update: %d\n", ret);
+ }
+ testutil_check(session->commit_transaction(session, NULL));
+ if (i % 10000 == 0) {
+ printf("insert: %" PRIu64 "\r", i);
+ fflush(stdout);
+ }
+ }
+ if (i > 10000)
+ printf("\n");
+
+ opts->running = false;
+
+ return (NULL);
+}
diff --git a/test/cursor_order/Makefile.am b/test/cursor_order/Makefile.am
index 8afb8f122d8..c98cf1fa047 100644
--- a/test/cursor_order/Makefile.am
+++ b/test/cursor_order/Makefile.am
@@ -1,10 +1,12 @@
-AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir)/src/include \
- -I$(top_srcdir)/test/utility
+AM_CPPFLAGS = -I$(top_builddir)
+AM_CPPFLAGS +=-I$(top_srcdir)/src/include
+AM_CPPFLAGS +=-I$(top_srcdir)/test/utility
noinst_PROGRAMS = cursor_order
-cursor_order_LDADD = $(top_builddir)/libwiredtiger.la
-
cursor_order_SOURCES = cursor_order_file.c cursor_order_ops.c cursor_order.c
+
+cursor_order_LDADD = $(top_builddir)/test/utility/libtest_util.la
+cursor_order_LDADD +=$(top_builddir)/libwiredtiger.la
cursor_order_LDFLAGS = -static
TESTS = $(noinst_PROGRAMS)
diff --git a/test/cursor_order/cursor_order.h b/test/cursor_order/cursor_order.h
index dd49fce124b..98a7d03c6f3 100644
--- a/test/cursor_order/cursor_order.h
+++ b/test/cursor_order/cursor_order.h
@@ -28,7 +28,7 @@
#include <signal.h>
-#include "test_util.i"
+#include "test_util.h"
#define FNAME "file:cursor_order.%03d" /* File name */
diff --git a/test/fops/Makefile.am b/test/fops/Makefile.am
index a4fa7175f1b..f8a76de82bc 100644
--- a/test/fops/Makefile.am
+++ b/test/fops/Makefile.am
@@ -1,10 +1,13 @@
-AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir)/src/include \
- -I$(top_srcdir)/test/utility
+AM_CPPFLAGS = -I$(top_builddir)
+AM_CPPFLAGS +=-I$(top_srcdir)/src/include
+AM_CPPFLAGS +=-I$(top_srcdir)/test/utility
noinst_PROGRAMS = t
-t_LDADD = $(top_builddir)/libwiredtiger.la
t_SOURCES = thread.h file.c fops.c t.c
+
+t_LDADD = $(top_builddir)/test/utility/libtest_util.la
+t_LDADD +=$(top_builddir)/libwiredtiger.la
t_LDFLAGS = -static
# Run this during a "make check" smoke test.
diff --git a/test/fops/thread.h b/test/fops/thread.h
index 630c2061285..89b7984a166 100644
--- a/test/fops/thread.h
+++ b/test/fops/thread.h
@@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "test_util.i"
+#include "test_util.h"
#include <signal.h>
diff --git a/test/format/Makefile.am b/test/format/Makefile.am
index 8a2e2b49e4b..5d946e5b63d 100644
--- a/test/format/Makefile.am
+++ b/test/format/Makefile.am
@@ -1,21 +1,24 @@
-AM_CPPFLAGS = -I$(top_builddir) \
- -I$(top_srcdir)/src/include -I$(top_srcdir)/test/utility
+AM_CPPFLAGS = -I$(top_builddir)
+AM_CPPFLAGS +=-I$(top_srcdir)/src/include
+AM_CPPFLAGS +=-I$(top_srcdir)/test/utility
if HAVE_BERKELEY_DB
-AM_CPPFLAGS += -DHAVE_BERKELEY_DB \
- -DBERKELEY_DB_PATH=\"$(BERKELEY_DB_PATH)\" -I$(BERKELEY_DB_PATH)/include
+AM_CPPFLAGS +=-DHAVE_BERKELEY_DB
+AM_CPPFLAGS +=-DBERKELEY_DB_PATH=\"$(BERKELEY_DB_PATH)\"
+AM_CPPFLAGS +=-I$(BERKELEY_DB_PATH)/include
endif
noinst_PROGRAMS = t
noinst_SCRIPTS = s_dumpcmp
t_SOURCES =\
- config.h format.h backup.c bulk.c compact.c config.c lrt.c ops.c \
- rebalance.c salvage.c t.c util.c wts.c
+ backup.c bulk.c compact.c config.c lrt.c ops.c rebalance.c \
+ salvage.c t.c util.c wts.c
if HAVE_BERKELEY_DB
t_SOURCES += bdb.c
endif
-t_LDADD = $(top_builddir)/libwiredtiger.la
+t_LDADD = $(top_builddir)/test/utility/libtest_util.la
+t_LDADD +=$(top_builddir)/libwiredtiger.la
if HAVE_BERKELEY_DB
t_LDADD += -L$(BERKELEY_DB_PATH)/lib -ldb
endif
diff --git a/test/format/format.h b/test/format/format.h
index beaabe7e83c..8fd9b113311 100644
--- a/test/format/format.h
+++ b/test/format/format.h
@@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "test_util.i"
+#include "test_util.h"
#ifdef BDB
#include <assert.h>
diff --git a/test/format/ops.c b/test/format/ops.c
index 9275d7f3856..7fd5563f486 100644
--- a/test/format/ops.c
+++ b/test/format/ops.c
@@ -530,9 +530,16 @@ ops(void *arg)
ckpt_config = ckpt_name;
}
- testutil_checkfmt(
- session->checkpoint(session, ckpt_config),
- "%s", ckpt_config == NULL ? "" : ckpt_config);
+ ret = session->checkpoint(session, ckpt_config);
+ /*
+ * We may be trying to create a named checkpoint while
+ * we hold a cursor open to the previous checkpoint.
+ * Tolerate EBUSY.
+ */
+ if (ret != 0 && ret != EBUSY)
+ testutil_die(ret, "%s",
+ ckpt_config == NULL ? "" : ckpt_config);
+ ret = 0;
if (ckpt_config != NULL)
testutil_check(
diff --git a/test/format/util.c b/test/format/util.c
index f2b4d18029e..cebe2153b3e 100644
--- a/test/format/util.c
+++ b/test/format/util.c
@@ -213,16 +213,10 @@ val_gen(WT_RAND_STATE *rnd, WT_ITEM *value, uint64_t keyno)
}
/*
- * Start the data with a 10-digit number.
- *
- * For row and non-repeated variable-length column-stores, change the
- * leading number to ensure every data item is unique. For repeated
- * variable-length column-stores (that is, to test run-length encoding),
- * use the same data value all the time.
+ * Data items have unique leading numbers by default and random lengths;
+ * variable-length column-stores use a duplicate data value to test RLE.
*/
- if ((g.type == ROW || g.type == VAR) &&
- g.c_repeat_data_pct != 0 &&
- mmrand(rnd, 1, 100) < g.c_repeat_data_pct) {
+ if (g.type == VAR && mmrand(rnd, 1, 100) < g.c_repeat_data_pct) {
(void)strcpy(p, "DUPLICATEV");
p[10] = '/';
value->size = val_dup_data_len;
diff --git a/test/huge/Makefile.am b/test/huge/Makefile.am
index 151d3a40dd4..894bff5eace 100644
--- a/test/huge/Makefile.am
+++ b/test/huge/Makefile.am
@@ -1,9 +1,12 @@
-AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir)/src/include \
- -I$(top_srcdir)/test/utility
+AM_CPPFLAGS = -I$(top_builddir)
+AM_CPPFLAGS +=-I$(top_srcdir)/src/include
+AM_CPPFLAGS +=-I$(top_srcdir)/test/utility
noinst_PROGRAMS = t
t_SOURCES = huge.c
-t_LDADD = $(top_builddir)/libwiredtiger.la
+
+t_LDADD = $(top_builddir)/test/utility/libtest_util.la
+t_LDADD +=$(top_builddir)/libwiredtiger.la
t_LDFLAGS = -static
# Run this during a "make check" smoke test.
diff --git a/test/huge/huge.c b/test/huge/huge.c
index e7bfd08882f..1e104a705f2 100644
--- a/test/huge/huge.c
+++ b/test/huge/huge.c
@@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "test_util.i"
+#include "test_util.h"
static char home[512]; /* Program working dir */
static const char *progname; /* Program name */
diff --git a/test/manydbs/Makefile.am b/test/manydbs/Makefile.am
index d347868aa4f..2bc47ad7f2e 100644
--- a/test/manydbs/Makefile.am
+++ b/test/manydbs/Makefile.am
@@ -1,9 +1,12 @@
-AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir)/src/include \
- -I$(top_srcdir)/test/utility
+AM_CPPFLAGS = -I$(top_builddir)
+AM_CPPFLAGS +=-I$(top_srcdir)/src/include
+AM_CPPFLAGS +=-I$(top_srcdir)/test/utility
noinst_PROGRAMS = t
t_SOURCES = manydbs.c
-t_LDADD = $(top_builddir)/libwiredtiger.la
+
+t_LDADD = $(top_builddir)/test/utility/libtest_util.la
+t_LDADD +=$(top_builddir)/libwiredtiger.la
t_LDFLAGS = -static
# Run this during a "make check" smoke test.
diff --git a/test/manydbs/manydbs.c b/test/manydbs/manydbs.c
index 4ab455f3620..d9639198c34 100644
--- a/test/manydbs/manydbs.c
+++ b/test/manydbs/manydbs.c
@@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "test_util.i"
+#include "test_util.h"
#define HOME_SIZE 512
#define HOME_BASE "WT_TEST"
diff --git a/test/packing/Makefile.am b/test/packing/Makefile.am
index 0e7c8cc8b2e..c9128100cc3 100644
--- a/test/packing/Makefile.am
+++ b/test/packing/Makefile.am
@@ -1,8 +1,11 @@
-AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir)/src/include \
- -I$(top_srcdir)/test/utility
+AM_CPPFLAGS = -I$(top_builddir)
+AM_CPPFLAGS +=-I$(top_srcdir)/src/include
+AM_CPPFLAGS +=-I$(top_srcdir)/test/utility
noinst_PROGRAMS = intpack-test intpack-test2 intpack-test3 packing-test
-LDADD = $(top_builddir)/libwiredtiger.la
+
+LDADD = $(top_builddir)/test/utility/libtest_util.la
+LDADD +=$(top_builddir)/libwiredtiger.la
LDFLAGS = -static
TESTS = smoke.sh
diff --git a/test/packing/intpack-test.c b/test/packing/intpack-test.c
index 6412ed296aa..76851b38e35 100644
--- a/test/packing/intpack-test.c
+++ b/test/packing/intpack-test.c
@@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "test_util.i"
+#include "test_util.h"
void (*custom_die)(void) = NULL;
diff --git a/test/packing/intpack-test2.c b/test/packing/intpack-test2.c
index e9443ad7ed1..a7d31329069 100644
--- a/test/packing/intpack-test2.c
+++ b/test/packing/intpack-test2.c
@@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "test_util.i"
+#include "test_util.h"
void (*custom_die)(void) = NULL;
diff --git a/test/packing/intpack-test3.c b/test/packing/intpack-test3.c
index 328b45d1bf7..aac0178578f 100644
--- a/test/packing/intpack-test3.c
+++ b/test/packing/intpack-test3.c
@@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "test_util.i"
+#include "test_util.h"
void (*custom_die)(void) = NULL;
@@ -42,6 +42,7 @@ test_value(int64_t val)
uint64_t uinput, uoutput;
size_t used_len;
+ soutput = 0; /* -Werror=maybe-uninitialized */
sinput = val;
soutput = 0; /* Make GCC happy. */
p = buf;
diff --git a/test/packing/packing-test.c b/test/packing/packing-test.c
index 706eeb0935c..f251c17eb67 100644
--- a/test/packing/packing-test.c
+++ b/test/packing/packing-test.c
@@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "test_util.i"
+#include "test_util.h"
void (*custom_die)(void) = NULL;
diff --git a/test/readonly/Makefile.am b/test/readonly/Makefile.am
index 8028e2ab845..84092e76f02 100644
--- a/test/readonly/Makefile.am
+++ b/test/readonly/Makefile.am
@@ -1,9 +1,12 @@
-AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir)/src/include \
- -I$(top_srcdir)/test/utility
+AM_CPPFLAGS = -I$(top_builddir)
+AM_CPPFLAGS +=-I$(top_srcdir)/src/include
+AM_CPPFLAGS +=-I$(top_srcdir)/test/utility
noinst_PROGRAMS = t
t_SOURCES = readonly.c
-t_LDADD = $(top_builddir)/libwiredtiger.la
+
+t_LDADD = $(top_builddir)/test/utility/libtest_util.la
+t_LDADD +=$(top_builddir)/libwiredtiger.la
t_LDFLAGS = -static
# Run this during a "make check" smoke test.
diff --git a/test/readonly/readonly.c b/test/readonly/readonly.c
index a35e7ee23fc..402b99d7d29 100644
--- a/test/readonly/readonly.c
+++ b/test/readonly/readonly.c
@@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "test_util.i"
+#include "test_util.h"
#include <sys/wait.h>
diff --git a/test/recovery/Makefile.am b/test/recovery/Makefile.am
index 6865d5edf3e..19fc48dce47 100644
--- a/test/recovery/Makefile.am
+++ b/test/recovery/Makefile.am
@@ -1,13 +1,16 @@
-AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir)/src/include \
- -I$(top_srcdir)/test/utility
+AM_CPPFLAGS = -I$(top_builddir)
+AM_CPPFLAGS +=-I$(top_srcdir)/src/include
+AM_CPPFLAGS +=-I$(top_srcdir)/test/utility
noinst_PROGRAMS = random-abort truncated-log
random_abort_SOURCES = random-abort.c
-random_abort_LDADD = $(top_builddir)/libwiredtiger.la
+random_abort_LDADD = $(top_builddir)/test/utility/libtest_util.la
+random_abort_LDADD +=$(top_builddir)/libwiredtiger.la
random_abort_LDFLAGS = -static
truncated_log_SOURCES = truncated-log.c
-truncated_log_LDADD = $(top_builddir)/libwiredtiger.la
+truncated_log_LDADD = $(top_builddir)/test/utility/libtest_util.la
+truncated_log_LDADD +=$(top_builddir)/libwiredtiger.la
truncated_log_LDFLAGS = -static
# Run this during a "make check" smoke test.
diff --git a/test/recovery/random-abort.c b/test/recovery/random-abort.c
index cd7d1b08708..33597245966 100644
--- a/test/recovery/random-abort.c
+++ b/test/recovery/random-abort.c
@@ -26,19 +26,10 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include "test_util.h"
+
#include <sys/wait.h>
-#include <errno.h>
#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifndef _WIN32
-#include <unistd.h>
-#endif
-
-#include <wiredtiger.h>
-
-#include "test_util.i"
static char home[512]; /* Program working dir */
static const char *progname; /* Program name */
diff --git a/test/recovery/truncated-log.c b/test/recovery/truncated-log.c
index e099873e5b9..3b99ea2c932 100644
--- a/test/recovery/truncated-log.c
+++ b/test/recovery/truncated-log.c
@@ -26,23 +26,15 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include "test_util.h"
+
#include <sys/wait.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifndef _WIN32
-#include <unistd.h>
-#else
+
+#ifdef _WIN32
/* snprintf is not supported on <= VS2013 */
#define snprintf _snprintf
#endif
-#include <wiredtiger.h>
-
-#include "test_util.i"
-
static char home[512]; /* Program working dir */
static const char *progname; /* Program name */
static const char * const uri = "table:main";
diff --git a/test/salvage/Makefile.am b/test/salvage/Makefile.am
index 0fd46aefcb1..a3c49b9c41a 100644
--- a/test/salvage/Makefile.am
+++ b/test/salvage/Makefile.am
@@ -1,9 +1,12 @@
-AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir)/src/include \
- -I$(top_srcdir)/test/utility
+AM_CPPFLAGS = -I$(top_builddir)
+AM_CPPFLAGS +=-I$(top_srcdir)/src/include
+AM_CPPFLAGS +=-I$(top_srcdir)/test/utility
noinst_PROGRAMS = t
t_SOURCES = salvage.c
-t_LDADD = $(top_builddir)/libwiredtiger.la
+
+t_LDADD = $(top_builddir)/test/utility/libtest_util.la
+t_LDADD +=$(top_builddir)/libwiredtiger.la
t_LDFLAGS = -static
# Run this during a "make check" smoke test.
diff --git a/test/salvage/salvage.c b/test/salvage/salvage.c
index f264be99e2b..497902e07b8 100644
--- a/test/salvage/salvage.c
+++ b/test/salvage/salvage.c
@@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "test_util.i"
+#include "test_util.h"
#include <assert.h>
diff --git a/test/suite/test_dump.py b/test/suite/test_dump.py
index fc1422155e2..d0163066639 100644
--- a/test/suite/test_dump.py
+++ b/test/suite/test_dump.py
@@ -26,7 +26,7 @@
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
-import os
+import os, shutil
import wiredtiger, wttest
from helper import \
complex_populate, complex_populate_check, \
@@ -42,6 +42,7 @@ class test_dump(wttest.WiredTigerTestCase, suite_subprocess):
dir='dump.dir' # Backup directory name
name = 'test_dump'
+ name2 = 'test_dumpb'
nentries = 2500
dumpfmt = [
@@ -109,6 +110,7 @@ class test_dump(wttest.WiredTigerTestCase, suite_subprocess):
# Create the object.
uri = self.uri + self.name
+ uri2 = self.uri + self.name2
self.populate(self, uri,
self.config + ',key_format=' + self.keyfmt, self.nentries)
@@ -130,19 +132,15 @@ class test_dump(wttest.WiredTigerTestCase, suite_subprocess):
self.assertEqual(not s1.symmetric_difference(s2), True)
# Check the object's contents
- conn = self.wiredtiger_open(self.dir)
- session = conn.open_session()
+ self.reopen_conn(self.dir)
self.populate_check(self, uri, self.nentries)
- conn.close()
- # Re-load the object again.
+ # Re-load the object again in the original directory.
+ self.reopen_conn('.')
self.runWt(['-h', self.dir, 'load', '-f', 'dump.out'])
# Check the contents, they shouldn't have changed.
- conn = self.wiredtiger_open(self.dir)
- session = conn.open_session()
self.populate_check(self, uri, self.nentries)
- conn.close()
# Re-load the object again, but confirm -n (no overwrite) fails.
self.runWt(['-h', self.dir,
@@ -158,5 +156,14 @@ class test_dump(wttest.WiredTigerTestCase, suite_subprocess):
self.check_non_empty_file('dumpidx.out')
self.compare_dump_values('dump.out', 'dumpidx.out')
+ # Re-load the object into a different table uri
+ shutil.rmtree(self.dir)
+ os.mkdir(self.dir)
+ self.runWt(['-h', self.dir, 'load', '-r', self.name2, '-f', 'dump.out'])
+
+ # Check the contents in the new table.
+ self.reopen_conn(self.dir)
+ self.populate_check(self, uri2, self.nentries)
+
if __name__ == '__main__':
wttest.run()
diff --git a/test/suite/wttest.py b/test/suite/wttest.py
index a1945b4325d..f7a2a5c8890 100644
--- a/test/suite/wttest.py
+++ b/test/suite/wttest.py
@@ -259,20 +259,20 @@ class WiredTigerTestCase(unittest.TestCase):
self.conn.close()
self.conn = None
- def open_conn(self):
+ def open_conn(self, directory="."):
"""
Open the connection if already closed.
"""
if self.conn == None:
- self.conn = self.setUpConnectionOpen(".")
+ self.conn = self.setUpConnectionOpen(directory)
self.session = self.setUpSessionOpen(self.conn)
- def reopen_conn(self):
+ def reopen_conn(self, directory="."):
"""
Reopen the connection.
"""
self.close_conn()
- self.open_conn()
+ self.open_conn(directory)
def setUp(self):
if not hasattr(self.__class__, 'wt_ntests'):
diff --git a/test/thread/Makefile.am b/test/thread/Makefile.am
index ead783185f8..58b715d4a80 100644
--- a/test/thread/Makefile.am
+++ b/test/thread/Makefile.am
@@ -1,9 +1,12 @@
-AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir)/src/include \
- -I$(top_srcdir)/test/utility
+AM_CPPFLAGS = -I$(top_builddir)
+AM_CPPFLAGS +=-I$(top_srcdir)/src/include
+AM_CPPFLAGS +=-I$(top_srcdir)/test/utility
noinst_PROGRAMS = t
-t_LDADD = $(top_builddir)/libwiredtiger.la
-t_SOURCES = thread.h file.c rw.c stats.c t.c
+t_SOURCES = file.c rw.c stats.c t.c
+
+t_LDADD = $(top_builddir)/test/utility/libtest_util.la
+t_LDADD +=$(top_builddir)/libwiredtiger.la
t_LDFLAGS = -static
TESTS = smoke.sh
diff --git a/test/thread/thread.h b/test/thread/thread.h
index d5f0f42ea35..edcb919ec32 100644
--- a/test/thread/thread.h
+++ b/test/thread/thread.h
@@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "test_util.i"
+#include "test_util.h"
#include <signal.h>
diff --git a/test/utility/Makefile.am b/test/utility/Makefile.am
new file mode 100644
index 00000000000..a2923eb41a8
--- /dev/null
+++ b/test/utility/Makefile.am
@@ -0,0 +1,4 @@
+AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir)/src/include
+
+libtest_util_la_SOURCES = misc.c parse_opts.c thread.c
+noinst_LTLIBRARIES = libtest_util.la
diff --git a/test/utility/test_util.i b/test/utility/misc.c
index 833eddd87aa..dfc655dec1a 100644
--- a/test/utility/test_util.i
+++ b/test/utility/misc.c
@@ -25,37 +25,13 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "wt_internal.h" /* For __wt_XXX */
-
-#ifdef _WIN32
-#include "windows_shim.h"
-#endif
-
-#ifdef _WIN32
- #define DIR_DELIM '\\'
- #define RM_COMMAND "rd /s /q "
-#else
- #define DIR_DELIM '/'
- #define RM_COMMAND "rm -rf "
-#endif
-
-#define DEFAULT_DIR "WT_TEST"
-#define MKDIR_COMMAND "mkdir "
-
-/* Allow tests to add their own death handling. */
-extern void (*custom_die)(void);
-
-static void testutil_die(int, const char *, ...)
-#if defined(__GNUC__)
-__attribute__((__noreturn__))
-#endif
-;
+#include "test_util.h"
/*
* die --
* Report an error and quit.
*/
-static void
+void
testutil_die(int e, const char *fmt, ...)
{
va_list ap;
@@ -77,32 +53,11 @@ testutil_die(int e, const char *fmt, ...)
}
/*
- * testutil_check --
- * Complain and quit if a function call fails.
- */
-#define testutil_check(call) do { \
- int __r; \
- if ((__r = (call)) != 0) \
- testutil_die(__r, "%s/%d: %s", __func__, __LINE__, #call);\
-} while (0)
-
-/*
- * testutil_checkfmt --
- * Complain and quit if a function call fails, with additional arguments.
- */
-#define testutil_checkfmt(call, fmt, ...) do { \
- int __r; \
- if ((__r = (call)) != 0) \
- testutil_die(__r, "%s/%d: %s: " fmt, \
- __func__, __LINE__, #call, __VA_ARGS__); \
-} while (0)
-
-/*
* testutil_work_dir_from_path --
* Takes a buffer, its size and the intended work directory.
* Creates the full intended work directory in buffer.
*/
-static inline void
+void
testutil_work_dir_from_path(char *buffer, size_t len, const char *dir)
{
/* If no directory is provided, use the default. */
@@ -120,7 +75,7 @@ testutil_work_dir_from_path(char *buffer, size_t len, const char *dir)
* testutil_clean_work_dir --
* Remove the work directory.
*/
-static inline void
+void
testutil_clean_work_dir(char *dir)
{
size_t len;
@@ -143,7 +98,7 @@ testutil_clean_work_dir(char *dir)
* testutil_make_work_dir --
* Delete the existing work directory, then create a new one.
*/
-static inline void
+void
testutil_make_work_dir(char *dir)
{
size_t len;
@@ -165,10 +120,29 @@ testutil_make_work_dir(char *dir)
}
/*
+ * testutil_cleanup --
+ * Delete the existing work directory and free the options structure.
+ */
+void
+testutil_cleanup(TEST_OPTS *opts)
+{
+ if (opts->conn != NULL)
+ testutil_check(opts->conn->close(opts->conn, NULL));
+
+ if (!opts->preserve)
+ testutil_clean_work_dir(opts->home);
+
+ free(opts->conn_config);
+ free(opts->table_config);
+ free(opts->uri);
+ free(opts->home);
+}
+
+/*
* dcalloc --
* Call calloc, dying on failure.
*/
-static inline void *
+void *
dcalloc(size_t number, size_t size)
{
void *p;
@@ -182,7 +156,7 @@ dcalloc(size_t number, size_t size)
* dmalloc --
* Call malloc, dying on failure.
*/
-static inline void *
+void *
dmalloc(size_t len)
{
void *p;
@@ -196,7 +170,7 @@ dmalloc(size_t len)
* drealloc --
* Call realloc, dying on failure.
*/
-static inline void *
+void *
drealloc(void *p, size_t len)
{
void *t;
@@ -209,7 +183,7 @@ drealloc(void *p, size_t len)
* dstrdup --
* Call strdup, dying on failure.
*/
-static inline void *
+void *
dstrdup(const void *str)
{
char *p;
diff --git a/test/utility/parse_opts.c b/test/utility/parse_opts.c
new file mode 100644
index 00000000000..4054f318259
--- /dev/null
+++ b/test/utility/parse_opts.c
@@ -0,0 +1,132 @@
+/*-
+ * Public Domain 2014-2016 MongoDB, Inc.
+ * Public Domain 2008-2014 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 "test_util.h"
+
+extern int __wt_opterr; /* if error message should be printed */
+extern int __wt_optind; /* index into parent argv vector */
+extern int __wt_optopt; /* character checked for validity */
+extern int __wt_optreset; /* reset getopt */
+extern char *__wt_optarg; /* argument associated with option */
+
+/*
+ * testutil_parse_opts --
+ * Parse command line options for a test case.
+ */
+int
+testutil_parse_opts(int argc, char * const *argv, TEST_OPTS *opts)
+{
+ int ch;
+ size_t len;
+
+ opts->preserve = false;
+ opts->running = true;
+ opts->verbose = false;
+
+ if ((opts->progname = strrchr(argv[0], '/')) == NULL)
+ opts->progname = argv[0];
+ else
+ ++opts->progname;
+
+ while ((ch = __wt_getopt(opts->progname,
+ argc, argv, "A:h:n:o:pR:T:t:vW:")) != EOF)
+ switch (ch) {
+ case 'A': /* Number of append threads */
+ opts->n_append_threads = (uint64_t)atoll(__wt_optarg);
+ break;
+ case 'h': /* Home directory */
+ opts->home = __wt_optarg;
+ break;
+ case 'n': /* Number of records */
+ opts->nrecords = (uint64_t)atoll(__wt_optarg);
+ break;
+ case 'o': /* Number of operations */
+ opts->nops = (uint64_t)atoll(__wt_optarg);
+ break;
+ case 'p': /* Preserve directory contents */
+ opts->preserve = true;
+ break;
+ case 'R': /* Number of reader threads */
+ opts->n_read_threads = (uint64_t)atoll(__wt_optarg);
+ break;
+ case 'T': /* Number of threads */
+ opts->nthreads = (uint64_t)atoll(__wt_optarg);
+ break;
+ case 't': /* Table type */
+ switch (__wt_optarg[0]) {
+ case 'C':
+ case 'c':
+ opts->table_type = TABLE_COL;
+ break;
+ case 'F':
+ case 'f':
+ opts->table_type = TABLE_FIX;
+ break;
+ case 'R':
+ case 'r':
+ opts->table_type = TABLE_ROW;
+ break;
+ }
+ break;
+ case 'v':
+ opts->verbose = true;
+ break;
+ case 'W': /* Number of writer threads */
+ opts->n_write_threads = (uint64_t)atoll(__wt_optarg);
+ break;
+ case '?':
+ default:
+ (void)fprintf(stderr, "usage: %s "
+ "[-A append thread count] "
+ "[-h home] "
+ "[-n record count] "
+ "[-o op count] "
+ "[-p] "
+ "[-R read thread count] "
+ "[-T thread count] "
+ "[-t c|f|r table type] "
+ "[-v] "
+ "[-W write thread count] ",
+ opts->progname);
+ return (1);
+ }
+
+ /*
+ * Setup the home directory. It needs to be unique for every test
+ * or the auto make parallel tester gets upset.
+ */
+ len = strlen("WT_TEST.") + strlen(opts->progname) + 10;
+ opts->home = dmalloc(len);
+ snprintf(opts->home, len, "WT_TEST.%s", opts->progname);
+
+ /* Setup the default URI string */
+ len = strlen("table:") + strlen(opts->progname) + 10;
+ opts->uri = dmalloc(len);
+ snprintf(opts->uri, len, "table:%s", opts->progname);
+
+ return (0);
+}
diff --git a/test/utility/test_util.h b/test/utility/test_util.h
new file mode 100644
index 00000000000..6417c5a326b
--- /dev/null
+++ b/test/utility/test_util.h
@@ -0,0 +1,128 @@
+/*-
+ * Public Domain 2014-2016 MongoDB, Inc.
+ * Public Domain 2008-2014 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 "wt_internal.h" /* For __wt_XXX */
+
+#ifdef _WIN32
+ #define DIR_DELIM '\\'
+ #define RM_COMMAND "rd /s /q "
+#else
+ #define DIR_DELIM '/'
+ #define RM_COMMAND "rm -rf "
+#endif
+
+#define DEFAULT_DIR "WT_TEST"
+#define MKDIR_COMMAND "mkdir "
+
+#ifdef _WIN32
+#include "windows_shim.h"
+#endif
+
+/* Generic option parsing structure shared by all test cases. */
+typedef struct {
+ char *home;
+ char *progname;
+ enum { TABLE_COL=1, /* Fixed-length column store */
+ TABLE_FIX=2, /* Variable-length column store */
+ TABLE_ROW=3 /* Row-store */
+ } table_type;
+ bool preserve; /* Don't remove files on exit */
+ bool verbose; /* Run in verbose mode */
+ uint64_t nrecords; /* Number of records */
+ uint64_t nops; /* Number of operations */
+ uint64_t nthreads; /* Number of threads */
+ uint64_t n_append_threads; /* Number of append threads */
+ uint64_t n_read_threads; /* Number of read threads */
+ uint64_t n_write_threads; /* Number of write threads */
+
+ /*
+ * Fields commonly shared within a test program. The test cleanup
+ * function will attempt to automatically free and close non-null
+ * resources.
+ */
+ WT_CONNECTION *conn;
+ char *conn_config;
+ WT_SESSION *session;
+ bool running;
+ char *table_config;
+ char *uri;
+ volatile uint64_t next_threadid;
+ uint64_t max_inserted_id;
+} TEST_OPTS;
+
+/*
+ * testutil_assert --
+ * Complain and quit if something isn't true.
+ */
+#define testutil_assert(a) do { \
+ if (!(a)) \
+ testutil_die(0, "%s/%d: %s", __func__, __LINE__, #a); \
+} while (0)
+
+/*
+ * testutil_check --
+ * Complain and quit if a function call fails.
+ */
+#define testutil_check(call) do { \
+ int __r; \
+ if ((__r = (call)) != 0) \
+ testutil_die( \
+ __r, "%s/%d: %s", __func__, __LINE__, #call); \
+} while (0)
+
+/*
+ * testutil_checkfmt --
+ * Complain and quit if a function call fails, with additional arguments.
+ */
+#define testutil_checkfmt(call, fmt, ...) do { \
+ int __r; \
+ if ((__r = (call)) != 0) \
+ testutil_die(__r, "%s/%d: %s: " fmt, \
+ __func__, __LINE__, #call, __VA_ARGS__); \
+} while (0)
+
+/* Allow tests to add their own death handling. */
+extern void (*custom_die)(void);
+
+void testutil_die(int, const char *, ...)
+#if defined(__GNUC__)
+__attribute__((__noreturn__))
+#endif
+;
+
+void *dcalloc(size_t, size_t);
+void *dmalloc(size_t);
+void *drealloc(void *, size_t);
+void *dstrdup(const void *);
+void testutil_clean_work_dir(char *);
+void testutil_cleanup(TEST_OPTS *);
+void testutil_make_work_dir(char *);
+int testutil_parse_opts(int, char * const *, TEST_OPTS *);
+void testutil_work_dir_from_path(char *, size_t, const char *);
+void *thread_append(void *);
+void *thread_insert_append(void *);
+void *thread_prev(void *);
diff --git a/test/utility/thread.c b/test/utility/thread.c
new file mode 100644
index 00000000000..38465b2f02b
--- /dev/null
+++ b/test/utility/thread.c
@@ -0,0 +1,141 @@
+/*-
+ * Public Domain 2014-2016 MongoDB, Inc.
+ * Public Domain 2008-2014 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 "test_util.h"
+
+/*
+ * A thread dedicated to appending records into a table. Works with fixed
+ * length column stores and variable length column stores.
+ * One thread (the first thread created by an application) checks for a
+ * terminating condition after each insert.
+ */
+void *
+thread_append(void *arg)
+{
+ TEST_OPTS *opts;
+ WT_CONNECTION *conn;
+ WT_CURSOR *cursor;
+ WT_SESSION *session;
+ uint64_t id, recno;
+ char buf[64];
+
+ opts = (TEST_OPTS *)arg;
+ conn = opts->conn;
+
+ id = __wt_atomic_fetch_addv64(&opts->next_threadid, 1);
+ testutil_check(conn->open_session(conn, NULL, NULL, &session));
+ testutil_check(
+ session->open_cursor(session, opts->uri, NULL, "append", &cursor));
+
+ buf[0] = '\2';
+ for (recno = 1; opts->running; ++recno) {
+ if (opts->table_type == TABLE_FIX)
+ cursor->set_value(cursor, buf[0]);
+ else {
+ snprintf(buf, sizeof(buf),
+ "%" PRIu64 " VALUE ------", recno);
+ cursor->set_value(cursor, buf);
+ }
+ testutil_check(cursor->insert(cursor));
+ if (id == 0) {
+ testutil_check(
+ cursor->get_key(cursor, &opts->max_inserted_id));
+ if (opts->max_inserted_id >= opts->nrecords)
+ opts->running = false;
+ }
+ }
+
+ return (NULL);
+}
+
+/*
+ * Append into a row store table.
+ */
+void *
+thread_insert_append(void *arg)
+{
+ TEST_OPTS *opts;
+ WT_CONNECTION *conn;
+ WT_CURSOR *cursor;
+ WT_SESSION *session;
+ uint64_t i;
+ char kbuf[64];
+
+ opts = (TEST_OPTS *)arg;
+ conn = opts->conn;
+
+ testutil_check(conn->open_session(conn, NULL, NULL, &session));
+ testutil_check(session->open_cursor(
+ session, opts->uri, NULL, NULL, &cursor));
+
+ for (i = 0; i < opts->nrecords; ++i) {
+ snprintf(kbuf, sizeof(kbuf), "%010d KEY------", (int)i);
+ cursor->set_key(cursor, kbuf);
+ cursor->set_value(cursor, "========== VALUE =======");
+ testutil_check(cursor->insert(cursor));
+ if (i % 100000 == 0) {
+ printf("insert: %" PRIu64 "\r", i);
+ fflush(stdout);
+ }
+ }
+ printf("\n");
+
+ opts->running = false;
+
+ return (NULL);
+}
+
+/*
+ * Repeatedly walk backwards through the records in a table.
+ */
+void *
+thread_prev(void *arg)
+{
+ TEST_OPTS *opts;
+ WT_CURSOR *cursor;
+ WT_SESSION *session;
+ int ret;
+
+ opts = (TEST_OPTS *)arg;
+ ret = 0;
+
+ testutil_check(
+ opts->conn->open_session(opts->conn, NULL, NULL, &session));
+ testutil_check(
+ session->open_cursor(session, opts->uri, NULL, NULL, &cursor));
+ while (opts->running) {
+ while (opts->running && (ret = cursor->prev(cursor)) == 0)
+ ;
+ if (ret == WT_NOTFOUND)
+ ret = 0;
+ testutil_check(ret);
+ }
+
+ testutil_check(session->close(session, NULL));
+ return (NULL);
+}
diff --git a/tools/wtstats/stat_data.py b/tools/wtstats/stat_data.py
index c75e4f194dd..eca3c137738 100644
--- a/tools/wtstats/stat_data.py
+++ b/tools/wtstats/stat_data.py
@@ -5,6 +5,7 @@ no_scale_per_second_list = [
'async: maximum work queue length',
'cache: bytes currently in the cache',
'cache: eviction currently operating in aggressive mode',
+ 'cache: hazard pointer maximum array length',
'cache: maximum bytes configured',
'cache: maximum page size at eviction',
'cache: pages currently held in the cache',