summaryrefslogtreecommitdiff
path: root/src/third_party/wiredtiger
diff options
context:
space:
mode:
authorAlex Gorrod <alexander.gorrod@mongodb.com>2017-07-20 12:20:46 +1000
committerAlex Gorrod <alexander.gorrod@mongodb.com>2017-07-20 12:24:11 +1000
commit5a2533ebc3606973fbe237228b9bacdcb21a532b (patch)
tree66805f578f761446f1cdd6637dcfaa90c60e1388 /src/third_party/wiredtiger
parent634435949c4b855b9cc5bfbf5cf481d8158fd996 (diff)
downloadmongo-5a2533ebc3606973fbe237228b9bacdcb21a532b.tar.gz
Import wiredtiger: 6173a98979715ed727c432c1a31da64ea8a37048 from branch mongodb-3.6
ref: ff10db8811..6173a98979 for: 3.5.11 WT-3039 Enhance logging so new log files no longer need to wait for the previous log file to be synced WT-3138 Enhance eviction statistics WT-3140 Enhance json mode statistics to better support per-dhandle statistics WT-3310 Add support to WT_SESSION::alter to change table log setting WT-3329 With a uniform workload and a number of small collections, eviction does a poor job of selecting candidates for eviction. WT-3381 Improve concurrency in the transaction subsystem WT-3394 Build WiredTiger with gcc7 WT-3396 test/csuite/wt3363_checkpoint_op_races, test_utility cleanups WT-3397 Coverity lint WT-3398 in-memory configurations don't support schema_worker operations WT-3401 Lint and minor cleanup WT-3402 Move cached overflow records to the update list. WT-3403 Automated tests timeout running csuite WT-3409 WiredTiger generations can silently self-deadlock. WT-3413 Add more aggressive compile warning flags to Jenkins Windows job WT-3415 setting timestamp in txn_state requires the global write lock WT-3421 Compilation error unreachable code in test/csuite/wt3363_checkpoint_op_races WT-3424 additional gcc 7.1 compile warnings. WT-3425 workgen: add ability to reopen cursors WT-3426 Add new wtperf configuration to automated performance testing WT-3438 Don't tune eviction thread count when the count is fixed Also explicitly disable v2 log records via a configuration setting in MongoDB - this will later be plumbed into the feature compatability version mechanism.
Diffstat (limited to 'src/third_party/wiredtiger')
-rw-r--r--src/third_party/wiredtiger/.gitignore37
-rw-r--r--src/third_party/wiredtiger/SConstruct7
-rw-r--r--src/third_party/wiredtiger/bench/workgen/runner/small_btree_reopen.py56
-rw-r--r--src/third_party/wiredtiger/bench/workgen/workgen.cxx65
-rw-r--r--src/third_party/wiredtiger/bench/workgen/workgen.h8
-rw-r--r--src/third_party/wiredtiger/bench/workgen/workgen.swig2
-rw-r--r--src/third_party/wiredtiger/bench/workgen/workgen_int.h2
-rw-r--r--src/third_party/wiredtiger/bench/wtperf/config.c2
-rw-r--r--src/third_party/wiredtiger/bench/wtperf/runners/update-only-btree.wtperf10
-rw-r--r--src/third_party/wiredtiger/bench/wtperf/wtperf.c2
-rw-r--r--src/third_party/wiredtiger/build_posix/Make.base1
-rw-r--r--src/third_party/wiredtiger/build_posix/aclocal/strict.m429
-rw-r--r--src/third_party/wiredtiger/build_win/wiredtiger_config.h3
-rw-r--r--src/third_party/wiredtiger/dist/api_data.py22
-rw-r--r--src/third_party/wiredtiger/dist/filelist1
-rw-r--r--src/third_party/wiredtiger/dist/log.py2
-rw-r--r--src/third_party/wiredtiger/dist/log_data.py4
-rw-r--r--src/third_party/wiredtiger/dist/s_funcs.list1
-rw-r--r--src/third_party/wiredtiger/dist/s_string.ok6
-rw-r--r--src/third_party/wiredtiger/dist/stat_data.py34
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_backup.c4
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_encrypt.c2
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_log.c2
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_sync.c2
-rw-r--r--src/third_party/wiredtiger/import.data2
-rw-r--r--src/third_party/wiredtiger/src/async/async_op.c1
-rw-r--r--src/third_party/wiredtiger/src/async/async_worker.c2
-rw-r--r--src/third_party/wiredtiger/src/block/block_compact.c6
-rw-r--r--src/third_party/wiredtiger/src/block/block_vrfy.c18
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_debug.c56
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_discard.c3
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_handle.c5
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_ovfl.c125
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_page.c1
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_read.c2
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_slvg.c2
-rw-r--r--src/third_party/wiredtiger/src/btree/row_srch.c4
-rw-r--r--src/third_party/wiredtiger/src/config/config_def.c90
-rw-r--r--src/third_party/wiredtiger/src/conn/conn_api.c46
-rw-r--r--src/third_party/wiredtiger/src/conn/conn_cache_pool.c14
-rw-r--r--src/third_party/wiredtiger/src/conn/conn_log.c127
-rw-r--r--src/third_party/wiredtiger/src/conn/conn_stat.c120
-rw-r--r--src/third_party/wiredtiger/src/cursor/cur_backup.c2
-rw-r--r--src/third_party/wiredtiger/src/cursor/cur_log.c22
-rw-r--r--src/third_party/wiredtiger/src/docs/upgrading.dox31
-rw-r--r--src/third_party/wiredtiger/src/evict/evict_lru.c116
-rw-r--r--src/third_party/wiredtiger/src/evict/evict_stat.c64
-rw-r--r--src/third_party/wiredtiger/src/include/api.h2
-rw-r--r--src/third_party/wiredtiger/src/include/bitstring.i140
-rw-r--r--src/third_party/wiredtiger/src/include/btmem.h45
-rw-r--r--src/third_party/wiredtiger/src/include/btree.h27
-rw-r--r--src/third_party/wiredtiger/src/include/btree_cmp.i66
-rw-r--r--src/third_party/wiredtiger/src/include/connection.h21
-rw-r--r--src/third_party/wiredtiger/src/include/error.h25
-rw-r--r--src/third_party/wiredtiger/src/include/extern.h22
-rw-r--r--src/third_party/wiredtiger/src/include/gcc.h2
-rw-r--r--src/third_party/wiredtiger/src/include/log.h39
-rw-r--r--src/third_party/wiredtiger/src/include/misc.i33
-rw-r--r--src/third_party/wiredtiger/src/include/stat.h32
-rw-r--r--src/third_party/wiredtiger/src/include/txn.h17
-rw-r--r--src/third_party/wiredtiger/src/include/txn.i24
-rw-r--r--src/third_party/wiredtiger/src/include/wiredtiger.in685
-rw-r--r--src/third_party/wiredtiger/src/include/wt_internal.h2
-rw-r--r--src/third_party/wiredtiger/src/log/log.c677
-rw-r--r--src/third_party/wiredtiger/src/log/log_slot.c12
-rw-r--r--src/third_party/wiredtiger/src/log/log_sys.c97
-rw-r--r--src/third_party/wiredtiger/src/lsm/lsm_cursor.c4
-rw-r--r--src/third_party/wiredtiger/src/lsm/lsm_merge.c2
-rw-r--r--src/third_party/wiredtiger/src/lsm/lsm_tree.c123
-rw-r--r--src/third_party/wiredtiger/src/meta/meta_ckpt.c4
-rw-r--r--src/third_party/wiredtiger/src/os_win/os_map.c2
-rw-r--r--src/third_party/wiredtiger/src/reconcile/rec_track.c334
-rw-r--r--src/third_party/wiredtiger/src/reconcile/rec_write.c125
-rw-r--r--src/third_party/wiredtiger/src/schema/schema_alter.c132
-rw-r--r--src/third_party/wiredtiger/src/session/session_api.c38
-rw-r--r--src/third_party/wiredtiger/src/session/session_compact.c2
-rw-r--r--src/third_party/wiredtiger/src/support/err.c32
-rw-r--r--src/third_party/wiredtiger/src/support/generation.c6
-rw-r--r--src/third_party/wiredtiger/src/support/rand.c12
-rw-r--r--src/third_party/wiredtiger/src/support/stat.c155
-rw-r--r--src/third_party/wiredtiger/src/txn/txn.c42
-rw-r--r--src/third_party/wiredtiger/src/txn/txn_ckpt.c10
-rw-r--r--src/third_party/wiredtiger/src/txn/txn_log.c13
-rw-r--r--src/third_party/wiredtiger/src/txn/txn_recover.c5
-rw-r--r--src/third_party/wiredtiger/src/txn/txn_timestamp.c172
-rw-r--r--src/third_party/wiredtiger/src/utilities/util.h1
-rw-r--r--src/third_party/wiredtiger/src/utilities/util_downgrade.c57
-rw-r--r--src/third_party/wiredtiger/src/utilities/util_list.c3
-rw-r--r--src/third_party/wiredtiger/src/utilities/util_main.c19
-rw-r--r--src/third_party/wiredtiger/test/csuite/rwlock/main.c7
-rw-r--r--src/third_party/wiredtiger/test/csuite/wt1965_col_efficiency/main.c4
-rw-r--r--src/third_party/wiredtiger/test/csuite/wt2246_col_append/main.c4
-rw-r--r--src/third_party/wiredtiger/test/csuite/wt2323_join_visibility/main.c8
-rw-r--r--src/third_party/wiredtiger/test/csuite/wt2535_insert_race/main.c4
-rw-r--r--src/third_party/wiredtiger/test/csuite/wt2853_perf/main.c8
-rw-r--r--src/third_party/wiredtiger/test/csuite/wt3363_checkpoint_op_races/main.c95
-rw-r--r--src/third_party/wiredtiger/test/fops/fops.c2
-rw-r--r--src/third_party/wiredtiger/test/format/bulk.c10
-rw-r--r--src/third_party/wiredtiger/test/format/compact.c8
-rw-r--r--src/third_party/wiredtiger/test/format/config.c59
-rw-r--r--src/third_party/wiredtiger/test/format/config.h4
-rw-r--r--src/third_party/wiredtiger/test/format/format.h7
-rw-r--r--src/third_party/wiredtiger/test/format/lrt.c10
-rw-r--r--src/third_party/wiredtiger/test/format/ops.c38
-rw-r--r--src/third_party/wiredtiger/test/format/t.c2
-rw-r--r--src/third_party/wiredtiger/test/format/util.c69
-rw-r--r--src/third_party/wiredtiger/test/format/wts.c34
-rw-r--r--src/third_party/wiredtiger/test/packing/intpack-test.c15
-rw-r--r--src/third_party/wiredtiger/test/packing/intpack-test2.c2
-rw-r--r--src/third_party/wiredtiger/test/packing/intpack-test3.c10
-rw-r--r--src/third_party/wiredtiger/test/packing/packing-test.c2
-rw-r--r--src/third_party/wiredtiger/test/recovery/random-abort.c26
-rwxr-xr-xsrc/third_party/wiredtiger/test/recovery/smoke.sh2
-rw-r--r--src/third_party/wiredtiger/test/recovery/truncated-log.c12
-rw-r--r--src/third_party/wiredtiger/test/suite/suite_subprocess.py8
-rw-r--r--src/third_party/wiredtiger/test/suite/test_alter02.py234
-rw-r--r--src/third_party/wiredtiger/test/suite/test_compat01.py182
-rw-r--r--src/third_party/wiredtiger/test/suite/test_cursor07.py34
-rw-r--r--src/third_party/wiredtiger/test/suite/test_reconfig02.py6
-rw-r--r--src/third_party/wiredtiger/test/suite/test_stat_log02.py111
-rw-r--r--src/third_party/wiredtiger/test/suite/test_txn02.py6
-rw-r--r--src/third_party/wiredtiger/test/suite/test_txn05.py6
-rw-r--r--src/third_party/wiredtiger/test/suite/test_txn11.py4
-rw-r--r--src/third_party/wiredtiger/test/suite/test_txn16.py6
-rw-r--r--src/third_party/wiredtiger/test/thread/rw.c2
-rw-r--r--src/third_party/wiredtiger/test/utility/test_util.h28
-rw-r--r--src/third_party/wiredtiger/test/utility/thread.c96
-rw-r--r--src/third_party/wiredtiger/tools/wtstats/stat_data.py8
128 files changed, 3724 insertions, 1873 deletions
diff --git a/src/third_party/wiredtiger/.gitignore b/src/third_party/wiredtiger/.gitignore
index cc2aad047be..082145e66d0 100644
--- a/src/third_party/wiredtiger/.gitignore
+++ b/src/third_party/wiredtiger/.gitignore
@@ -95,28 +95,31 @@ _wiredtiger.pyd
**/examples/c/ex_pack
**/examples/c/ex_process
**/examples/c/ex_schema
+**/examples/c/ex_smoke
**/examples/c/ex_stat
**/examples/c/ex_sync
**/examples/c/ex_thread
**/test/bloom/t
**/test/checkpoint/t
-**/test_scope
-**/test_wt1965_col_efficiency
-**/test_wt2246_col_append
-**/test_wt2323_join_visibility
-**/test_wt2403_lsm_workload
-**/test_wt2447_join_main_table
-**/test_wt2535_insert_race
-**/test_wt2592_join_schema
-**/test_wt2695_checksum
-**/test_wt2719_reconfig
-**/test_wt2834_join_bloom_fix
-**/test_wt2853_perf
-**/test_wt2909_checkpoint_integrity
-**/test_wt2999_join_extractor
-**/test_wt3120_filesys
-**/test_wt3135_search_near_collator
-**/test_wt3184_dup_index_collator
+**/test/csuite/test_rwlock
+**/test/csuite/test_scope
+**/test/csuite/test_wt1965_col_efficiency
+**/test/csuite/test_wt2246_col_append
+**/test/csuite/test_wt2323_join_visibility
+**/test/csuite/test_wt2403_lsm_workload
+**/test/csuite/test_wt2447_join_main_table
+**/test/csuite/test_wt2535_insert_race
+**/test/csuite/test_wt2592_join_schema
+**/test/csuite/test_wt2695_checksum
+**/test/csuite/test_wt2719_reconfig
+**/test/csuite/test_wt2834_join_bloom_fix
+**/test/csuite/test_wt2853_perf
+**/test/csuite/test_wt2909_checkpoint_integrity
+**/test/csuite/test_wt2999_join_extractor
+**/test/csuite/test_wt3120_filesys
+**/test/csuite/test_wt3135_search_near_collator
+**/test/csuite/test_wt3184_dup_index_collator
+**/test/csuite/test_wt3363_checkpoint_op_races
**/test/cursor_order/cursor_order
**/test/fops/t
**/test/format/s_dumpcmp
diff --git a/src/third_party/wiredtiger/SConstruct b/src/third_party/wiredtiger/SConstruct
index 748bf18db00..501dae2ad9f 100644
--- a/src/third_party/wiredtiger/SConstruct
+++ b/src/third_party/wiredtiger/SConstruct
@@ -67,10 +67,11 @@ var.Add('CPPPATH', 'C Preprocessor include path', [
])
var.Add('CFLAGS', 'C Compiler Flags', [
- "/wd4090", # Ignore warning about mismatched const qualifiers
- "/wd4996", # Ignore deprecated functions
"/W3", # Warning level 3
"/WX", # Warnings are fatal
+ "/wd4090", # Ignore warning about mismatched const qualifiers
+ "/wd4996", # Ignore deprecated functions
+ "/we4100", # Complain about unreferenced format parameter
"/Z7", # Generate debugging symbols
"/TC", # Compile as C code
#"/Od", # Disable optimization
@@ -295,6 +296,7 @@ wtbin = env.Program("wt", [
"src/utilities/util_cpyright.c",
"src/utilities/util_compact.c",
"src/utilities/util_create.c",
+ "src/utilities/util_downgrade.c",
"src/utilities/util_drop.c",
"src/utilities/util_dump.c",
"src/utilities/util_list.c",
@@ -336,6 +338,7 @@ if GetOption("lang-python"):
])
# Ignore warnings in swig-generated code.
pythonEnv['CFLAGS'].remove("/WX")
+ pythonEnv['CFLAGS'].remove("/we4100")
swiglib = pythonEnv.SharedLibrary('_wiredtiger',
[ 'lang\python\wiredtiger.i'],
diff --git a/src/third_party/wiredtiger/bench/workgen/runner/small_btree_reopen.py b/src/third_party/wiredtiger/bench/workgen/runner/small_btree_reopen.py
new file mode 100644
index 00000000000..252dd02aae9
--- /dev/null
+++ b/src/third_party/wiredtiger/bench/workgen/runner/small_btree_reopen.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+#
+# Public Domain 2014-2017 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.
+#
+
+from runner import *
+from wiredtiger import *
+from workgen import *
+
+context = Context()
+conn = wiredtiger_open("WT_TEST", "create,cache_size=500MB")
+s = conn.open_session()
+tname = "file:test.wt"
+s.create(tname, 'key_format=S,value_format=S')
+table = Table(tname)
+table.options.key_size = 20
+table.options.value_size = 100
+
+op = Operation(Operation.OP_INSERT, table)
+thread = Thread(op * 500000)
+pop_workload = Workload(context, thread)
+print('populate:')
+pop_workload.run(conn)
+
+op = Operation(Operation.OP_SEARCH, table)
+op._config = 'reopen'
+t = Thread(op)
+workload = Workload(context, t * 8)
+workload.options.run_time = 120
+workload.options.report_interval = 5
+print('read workload:')
+workload.run(conn)
diff --git a/src/third_party/wiredtiger/bench/workgen/workgen.cxx b/src/third_party/wiredtiger/bench/workgen/workgen.cxx
index 880b8ca6467..1a0735f9adc 100644
--- a/src/third_party/wiredtiger/bench/workgen/workgen.cxx
+++ b/src/third_party/wiredtiger/bench/workgen/workgen.cxx
@@ -534,7 +534,7 @@ void ThreadRunner::op_create_all(Operation *op, size_t &keysize,
size_t &valuesize) {
tint_t tint;
- op->size_check();
+ op->create_all();
if (op->_optype != Operation::OP_NONE) {
op->kv_compute_max(true);
if (OP_HAS_VALUE(op))
@@ -579,6 +579,7 @@ uint64_t ThreadRunner::op_get_key_recno(Operation *op, tint_t tint) {
uint64_t recno_count;
uint32_t rand;
+ (void)op;
recno_count = _icontext->_recno[tint];
if (recno_count == 0)
// The file has no entries, returning 0 forces a WT_NOTFOUND return.
@@ -590,13 +591,15 @@ uint64_t ThreadRunner::op_get_key_recno(Operation *op, tint_t tint) {
int ThreadRunner::op_run(Operation *op) {
Track *track;
tint_t tint = op->_table._internal->_tint;
- WT_CURSOR *cursor = _cursors[tint];
+ WT_CURSOR *cursor;
WT_DECL_RET;
uint64_t recno;
- bool measure_latency;
+ bool measure_latency, own_cursor;
- recno = 0;
track = NULL;
+ cursor = NULL;
+ recno = 0;
+ own_cursor = false;
if (_throttle != NULL) {
if (_throttle_ops >= _throttle_limit && !_in_transaction) {
WT_ERR(_throttle->throttle(_throttle_ops,
@@ -636,6 +639,13 @@ int ThreadRunner::op_run(Operation *op) {
recno = 0;
break;
}
+ if ((op->_flags & WORKGEN_OP_REOPEN) != 0 &&
+ op->_optype != Operation::OP_NONE) {
+ WT_ERR(_session->open_cursor(_session, op->_table._uri.c_str(), NULL,
+ NULL, &cursor));
+ own_cursor = true;
+ } else
+ cursor = _cursors[tint];
measure_latency = track != NULL && track->ops != 0 &&
track->track_latency() &&
@@ -676,6 +686,7 @@ int ThreadRunner::op_run(Operation *op) {
ASSERT(false);
}
if (ret != 0) {
+ ASSERT(ret == WT_NOTFOUND);
track = &_stats.not_found;
ret = 0; // WT_NOTFOUND allowed.
}
@@ -694,6 +705,8 @@ int ThreadRunner::op_run(Operation *op) {
i != op->_group->end(); i++)
WT_ERR(op_run(&*i));
err:
+ if (own_cursor)
+ WT_TRET(cursor->close(cursor));
if (op->_transaction != NULL) {
if (ret != 0 || op->_transaction->_rollback)
WT_TRET(_session->rollback_transaction(_session, NULL));
@@ -716,8 +729,8 @@ Throttle::Throttle(ThreadRunner &runner, double throttle,
_burst(throttle_burst), _next_div(), _ops_delta(0), _ops_prev(0),
_ops_per_div(0), _ms_per_div(0), _started(false) {
ts_clear(_next_div);
- _ms_per_div = ceill(1000.0 / THROTTLE_PER_SEC);
- _ops_per_div = ceill(_throttle / THROTTLE_PER_SEC);
+ _ms_per_div = (uint64_t)ceill(1000.0 / THROTTLE_PER_SEC);
+ _ops_per_div = (uint64_t)ceill(_throttle / THROTTLE_PER_SEC);
}
Throttle::~Throttle() {}
@@ -835,36 +848,37 @@ void Thread::describe(std::ostream &os) const {
}
Operation::Operation() :
- _optype(OP_NONE), _table(), _key(), _value(), _transaction(NULL),
- _group(NULL), _repeatgroup(0),
+ _optype(OP_NONE), _table(), _key(), _value(), _config(), _transaction(NULL),
+ _group(NULL), _repeatgroup(0), _flags(0),
_keysize(0), _valuesize(0), _keymax(0), _valuemax(0) {
}
Operation::Operation(OpType optype, Table table, Key key, Value value) :
- _optype(optype), _table(table), _key(key), _value(value),
- _transaction(NULL), _group(NULL), _repeatgroup(0),
+ _optype(optype), _table(table), _key(key), _value(value), _config(),
+ _transaction(NULL), _group(NULL), _repeatgroup(0), _flags(0),
_keysize(0), _valuesize(0), _keymax(0), _valuemax(0) {
size_check();
}
Operation::Operation(OpType optype, Table table, Key key) :
- _optype(optype), _table(table), _key(key), _value(), _transaction(NULL),
- _group(NULL), _repeatgroup(0),
+ _optype(optype), _table(table), _key(key), _value(), _config(),
+ _transaction(NULL), _group(NULL), _repeatgroup(0), _flags(0),
_keysize(0), _valuesize(0), _keymax(0), _valuemax(0) {
size_check();
}
Operation::Operation(OpType optype, Table table) :
- _optype(optype), _table(table), _key(), _value(), _transaction(NULL),
- _group(NULL), _repeatgroup(0),
+ _optype(optype), _table(table), _key(), _value(), _config(),
+ _transaction(NULL), _group(NULL), _repeatgroup(0), _flags(0),
_keysize(0), _valuesize(0), _keymax(0), _valuemax(0) {
size_check();
}
Operation::Operation(const Operation &other) :
_optype(other._optype), _table(other._table), _key(other._key),
- _value(other._value), _transaction(other._transaction),
- _group(other._group), _repeatgroup(other._repeatgroup),
+ _value(other._value), _config(other._config),
+ _transaction(other._transaction), _group(other._group),
+ _repeatgroup(other._repeatgroup), _flags(other._flags),
_keysize(other._keysize), _valuesize(other._valuesize),
_keymax(other._keymax), _valuemax(other._valuemax) {
// Creation and destruction of _group and _transaction is managed
@@ -890,6 +904,18 @@ Operation& Operation::operator=(const Operation &other) {
return (*this);
}
+void Operation::create_all() {
+ size_check();
+
+ _flags = 0;
+ if (!_config.empty()) {
+ if (_config == "reopen")
+ _flags |= WORKGEN_OP_REOPEN;
+ else
+ THROW("operation has illegal config: \"" << _config << "\"");
+ }
+}
+
void Operation::describe(std::ostream &os) const {
os << "Operation: " << _optype;
if (_optype != OP_NONE) {
@@ -897,9 +923,10 @@ void Operation::describe(std::ostream &os) const {
os << ", "; _key.describe(os);
os << ", "; _value.describe(os);
}
- if (_transaction != NULL) {
+ if (!_config.empty())
+ os << ", '" << _config;
+ if (_transaction != NULL)
os << ", ["; _transaction->describe(os); os << "]";
- }
if (_group != NULL) {
os << ", group[" << _repeatgroup << "]: {";
bool first = true;
@@ -1648,4 +1675,4 @@ int WorkloadRunner::run_all() {
return (ret);
}
-};
+}
diff --git a/src/third_party/wiredtiger/bench/workgen/workgen.h b/src/third_party/wiredtiger/bench/workgen/workgen.h
index c7be8ee0035..a12e4dc4c89 100644
--- a/src/third_party/wiredtiger/bench/workgen/workgen.h
+++ b/src/third_party/wiredtiger/bench/workgen/workgen.h
@@ -33,6 +33,7 @@
namespace workgen {
struct ContextInternal;
+struct OperationInternal;
struct TableInternal;
struct Thread;
struct Transaction;
@@ -245,11 +246,15 @@ struct Operation {
Table _table;
Key _key;
Value _value;
+ std::string _config;
Transaction *_transaction;
std::vector<Operation> *_group;
int _repeatgroup;
#ifndef SWIG
+#define WORKGEN_OP_REOPEN 0x0001 // reopen cursor for each op
+ uint32_t _flags;
+
int _keysize; // derived from Key._size and Table.options.key_size
int _valuesize;
uint64_t _keymax;
@@ -266,6 +271,7 @@ struct Operation {
void describe(std::ostream &os) const;
#ifndef SWIG
Operation& operator=(const Operation &other);
+ void create_all();
void get_static_counts(Stats &stats, int multiplier);
void kv_compute_max(bool);
void kv_gen(bool, uint64_t, char *) const;
@@ -408,4 +414,4 @@ struct Workload {
int run(WT_CONNECTION *conn);
};
-};
+}
diff --git a/src/third_party/wiredtiger/bench/workgen/workgen.swig b/src/third_party/wiredtiger/bench/workgen/workgen.swig
index 0f74942169c..a33705f4350 100644
--- a/src/third_party/wiredtiger/bench/workgen/workgen.swig
+++ b/src/third_party/wiredtiger/bench/workgen/workgen.swig
@@ -158,7 +158,7 @@ WorkgenFrozenClass(WorkloadOptions)
def __add__(self, other):
if not isinstance(other, Operation):
raise Exception('Operation.__sum__ requires an Operation')
- if self._group == None or self._repeatgroup != 1 or self._transaction != None:
+ if self._group == None or self._repeatgroup != 1 or self._transaction != None or self._config != '':
op = Operation()
op._group = OpList([self, other])
op._repeatgroup = 1
diff --git a/src/third_party/wiredtiger/bench/workgen/workgen_int.h b/src/third_party/wiredtiger/bench/workgen/workgen_int.h
index 9283aea1d7b..a8d008a3bc5 100644
--- a/src/third_party/wiredtiger/bench/workgen/workgen_int.h
+++ b/src/third_party/wiredtiger/bench/workgen/workgen_int.h
@@ -203,4 +203,4 @@ private:
WorkloadRunner& operator=(const WorkloadRunner &other); // disallowed
};
-};
+}
diff --git a/src/third_party/wiredtiger/bench/wtperf/config.c b/src/third_party/wiredtiger/bench/wtperf/config.c
index c5a3dd40032..1a4f46f5c37 100644
--- a/src/third_party/wiredtiger/bench/wtperf/config.c
+++ b/src/third_party/wiredtiger/bench/wtperf/config.c
@@ -798,7 +798,7 @@ config_sanity(WTPERF *wtperf)
workp->table_index >= (int32_t)opts->table_count) {
fprintf(stderr,
"Workload table index %" PRId32
- " is larger than table count %" PRId32,
+ " is larger than table count %" PRIu32,
workp->table_index, opts->table_count);
return (EINVAL);
}
diff --git a/src/third_party/wiredtiger/bench/wtperf/runners/update-only-btree.wtperf b/src/third_party/wiredtiger/bench/wtperf/runners/update-only-btree.wtperf
new file mode 100644
index 00000000000..ea37a4d13d1
--- /dev/null
+++ b/src/third_party/wiredtiger/bench/wtperf/runners/update-only-btree.wtperf
@@ -0,0 +1,10 @@
+# wtperf options file: btree with updates, in memory. The goal here is to
+# have a workload that uses a lot of transaction IDs, so stresses the ID
+# allocation/release code performance.
+conn_config="cache_size=5G"
+table_config="type=file"
+icount=5000000
+report_interval=5
+run_time=120
+populate_threads=1
+threads=((count=16,updates=1))
diff --git a/src/third_party/wiredtiger/bench/wtperf/wtperf.c b/src/third_party/wiredtiger/bench/wtperf/wtperf.c
index a8d3f135280..9e18df9a0e3 100644
--- a/src/third_party/wiredtiger/bench/wtperf/wtperf.c
+++ b/src/third_party/wiredtiger/bench/wtperf/wtperf.c
@@ -1750,7 +1750,7 @@ execute_workload(WTPERF *wtperf)
lprintf(wtperf, 0, 1,
"Starting workload #%u: %" PRId64 " threads, inserts=%"
PRId64 ", reads=%" PRId64 ", updates=%" PRId64
- ", truncate=%" PRId64 ", throttle=%" PRId64,
+ ", truncate=%" PRId64 ", throttle=%" PRIu64,
i + 1, workp->threads, workp->insert,
workp->read, workp->update, workp->truncate,
workp->throttle);
diff --git a/src/third_party/wiredtiger/build_posix/Make.base b/src/third_party/wiredtiger/build_posix/Make.base
index e5228fac885..08d64440ff0 100644
--- a/src/third_party/wiredtiger/build_posix/Make.base
+++ b/src/third_party/wiredtiger/build_posix/Make.base
@@ -22,6 +22,7 @@ wt_SOURCES =\
src/utilities/util_cpyright.c \
src/utilities/util_compact.c \
src/utilities/util_create.c \
+ src/utilities/util_downgrade.c \
src/utilities/util_drop.c \
src/utilities/util_dump.c \
src/utilities/util_list.c \
diff --git a/src/third_party/wiredtiger/build_posix/aclocal/strict.m4 b/src/third_party/wiredtiger/build_posix/aclocal/strict.m4
index 8c15a22d575..f9509df26bf 100644
--- a/src/third_party/wiredtiger/build_posix/aclocal/strict.m4
+++ b/src/third_party/wiredtiger/build_posix/aclocal/strict.m4
@@ -18,7 +18,6 @@ AC_DEFUN([AM_GCC_WARNINGS], [
w="$w -Wjump-misses-init"
w="$w -Wmissing-declarations"
w="$w -Wmissing-field-initializers"
- w="$w -Wmissing-parameter-type"
w="$w -Wmissing-prototypes"
w="$w -Wnested-externs"
w="$w -Wold-style-definition"
@@ -33,7 +32,6 @@ AC_DEFUN([AM_GCC_WARNINGS], [
w="$w -Wundef"
w="$w -Wuninitialized"
w="$w -Wunreachable-code"
- w="$w -Wunsafe-loop-optimizations"
w="$w -Wunused"
w="$w -Wwrite-strings"
@@ -48,10 +46,33 @@ AC_DEFUN([AM_GCC_WARNINGS], [
# Additional warning messages.
case "$1" in
[*4.7.[0-9]*]) # gcc4.7
- w="$w -Wno-c11-extensions";;
+ w="$w -Wno-c11-extensions"
+ w="$w -Wunsafe-loop-optimizations";;
[*6.[0-9].[0-9]*]) # gcc6.X
w="$w -Wduplicated-cond"
- w="$w -Wmisleading-indentation";;
+ w="$w -Wformat-signedness"
+ w="$w -Wjump-misses-init"
+ w="$w -Wlogical-op"
+ w="$w -Wredundant-decls"
+ w="$w -Wunsafe-loop-optimizations"
+ w="$w -Wunused-const-variable=2"
+ w="$w -Wunused-macros"
+ w="$w -Wvariadic-macros";;
+ [*7.[0-9].[0-9]*]) # gcc7.X
+ w="$w -Walloca"
+ w="$w -Walloc-zero"
+ w="$w -Wduplicated-branches"
+ w="$w -Wduplicated-cond"
+ w="$w -Wformat-overflow=2"
+ w="$w -Wformat-signedness"
+ w="$w -Wformat-truncation=2"
+ w="$w -Wjump-misses-init"
+ w="$w -Wlogical-op"
+ w="$w -Wredundant-decls"
+ w="$w -Wrestrict"
+ w="$w -Wunused-const-variable=2"
+ w="$w -Wunused-macros"
+ w="$w -Wvariadic-macros";;
esac
wt_cv_strict_warnings="$w"
diff --git a/src/third_party/wiredtiger/build_win/wiredtiger_config.h b/src/third_party/wiredtiger/build_win/wiredtiger_config.h
index 90cd40f1fae..b118cfa9882 100644
--- a/src/third_party/wiredtiger/build_win/wiredtiger_config.h
+++ b/src/third_party/wiredtiger/build_win/wiredtiger_config.h
@@ -151,9 +151,6 @@
/* Default alignment of buffers used for I/O */
#define WT_BUFFER_ALIGNMENT_DEFAULT 0
-/* Size of a transaction timestamp in bytes */
-#define WT_TIMESTAMP_SIZE 8
-
/* Enable large inode numbers on Mac OS X 10.5. */
/* #ifndef _DARWIN_USE_64_BIT_INODE */
/* # define _DARWIN_USE_64_BIT_INODE 1 */
diff --git a/src/third_party/wiredtiger/dist/api_data.py b/src/third_party/wiredtiger/dist/api_data.py
index 4a4ffae535d..9e873198f33 100644
--- a/src/third_party/wiredtiger/dist/api_data.py
+++ b/src/third_party/wiredtiger/dist/api_data.py
@@ -131,6 +131,14 @@ file_runtime_config = [
do not ever evict the object's pages from cache. Not compatible with
LSM tables; see @ref tuning_cache_resident for more information''',
type='boolean'),
+ Config('log', '', r'''
+ the transaction log configuration for this object. Only valid if
+ log is enabled in ::wiredtiger_open''',
+ type='category', subconfig=[
+ Config('enabled', 'true', r'''
+ if false, this object has checkpoint-level durability''',
+ type='boolean'),
+ ]),
]
# Per-file configuration
@@ -252,14 +260,6 @@ file_config = format_meta + file_runtime_config + [
Config('leaf_item_max', '0', r'''
historic term for leaf_key_max and leaf_value_max''',
min=0, undoc=True),
- Config('log', '', r'''
- the transaction log configuration for this object. Only valid if
- log is enabled in ::wiredtiger_open''',
- type='category', subconfig=[
- Config('enabled', 'true', r'''
- if false, this object has checkpoint-level durability''',
- type='boolean'),
- ]),
Config('memory_page_max', '5MB', r'''
the maximum size a page can grow to in memory before being
reconciled to disk. The specified size will be adjusted to a lower
@@ -401,6 +401,12 @@ connection_runtime_config = [
above 0 configures periodic checkpoints''',
min='0', max='100000'),
]),
+ Config('compatibility', '', r'''
+ set compatibility version of database''',
+ type='category', subconfig=[
+ Config('release', '', r'''
+ compatibility release version string'''),
+ ]),
Config('diagnostic_timing_stress', '', r'''
enable insertion of code that interrupts the usual timing of
operations with a goal of uncovering race conditions and unexpected
diff --git a/src/third_party/wiredtiger/dist/filelist b/src/third_party/wiredtiger/dist/filelist
index a81d693cb4e..309339ac877 100644
--- a/src/third_party/wiredtiger/dist/filelist
+++ b/src/third_party/wiredtiger/dist/filelist
@@ -95,6 +95,7 @@ src/evict/evict_stat.c
src/log/log.c
src/log/log_auto.c
src/log/log_slot.c
+src/log/log_sys.c
src/lsm/lsm_cursor.c
src/lsm/lsm_cursor_bulk.c
src/lsm/lsm_manager.c
diff --git a/src/third_party/wiredtiger/dist/log.py b/src/third_party/wiredtiger/dist/log.py
index ac35d884eac..81dc8bd35d7 100644
--- a/src/third_party/wiredtiger/dist/log.py
+++ b/src/third_party/wiredtiger/dist/log.py
@@ -10,6 +10,8 @@ tmp_file = '__tmp'
# Map log record types to:
# (C type, pack type, printf format, printf arg(s), list of setup functions)
field_types = {
+ 'WT_LSN' : ('WT_LSN *', 'II', '%" PRIu32 "%" PRIu32 "',
+ 'arg->l.file, arg->l.offset', [ '' ]),
'string' : ('const char *', 'S', '%s', 'arg', [ '' ]),
'item' : ('WT_ITEM *', 'u', '%s', 'escaped',
[ 'WT_ERR(__logrec_make_json_str(session, &escaped, &arg));',
diff --git a/src/third_party/wiredtiger/dist/log_data.py b/src/third_party/wiredtiger/dist/log_data.py
index bbfb51708bf..1782d2aadf0 100644
--- a/src/third_party/wiredtiger/dist/log_data.py
+++ b/src/third_party/wiredtiger/dist/log_data.py
@@ -40,6 +40,10 @@ rectypes = [
# Debugging message in the log
LogRecordType('message', 'message', [('string', 'message')]),
+
+ # System record
+ LogRecordType('system', 'system', [
+ ('WT_LSN','prev_lsn'), ('item', 'unused')]),
]
class LogOperationType:
diff --git a/src/third_party/wiredtiger/dist/s_funcs.list b/src/third_party/wiredtiger/dist/s_funcs.list
index b73767cad13..42eacf9c068 100644
--- a/src/third_party/wiredtiger/dist/s_funcs.list
+++ b/src/third_party/wiredtiger/dist/s_funcs.list
@@ -7,7 +7,6 @@ __bit_ffs
__bit_nclr
__ovfl_discard_dump
__ovfl_reuse_dump
-__ovfl_txnc_dump
__wt_bloom_drop
__wt_bloom_get
__wt_bulk_insert_fix
diff --git a/src/third_party/wiredtiger/dist/s_string.ok b/src/third_party/wiredtiger/dist/s_string.ok
index e0899bfeedf..723f6d18858 100644
--- a/src/third_party/wiredtiger/dist/s_string.ok
+++ b/src/third_party/wiredtiger/dist/s_string.ok
@@ -690,6 +690,7 @@ extern
extlist
fadvise
fallocate
+fallthrough
fblocks
fc
fclose
@@ -803,6 +804,7 @@ initn
initsize
initval
inline
+inlined
inmem
inmemory
insertK
@@ -1033,6 +1035,7 @@ prepended
prepending
presize
presync
+prevlsn
primary's
printf
printlog
@@ -1238,6 +1241,7 @@ unregister
unsized
unterminated
untyped
+unvisited
upd
update's
upg
@@ -1261,6 +1265,7 @@ valuep
valuev
vanishingly
variable's
+variadic
vectorized
versa
vfprintf
@@ -1284,6 +1289,7 @@ wb
wcursor
whitespace
wiredTiger
+wiredTigerTables
wiredtiger
workFactor
workgen
diff --git a/src/third_party/wiredtiger/dist/stat_data.py b/src/third_party/wiredtiger/dist/stat_data.py
index 7b919848003..2e344e0fbef 100644
--- a/src/third_party/wiredtiger/dist/stat_data.py
+++ b/src/third_party/wiredtiger/dist/stat_data.py
@@ -205,12 +205,12 @@ connection_stats = [
CacheStat('cache_eviction_empty_score', 'eviction empty score', 'no_clear,no_scale'),
CacheStat('cache_eviction_fail', 'pages selected for eviction unable to be evicted'),
CacheStat('cache_eviction_force', 'pages evicted because they exceeded the in-memory maximum count'),
- CacheStat('cache_eviction_force_time', 'pages evicted because they exceeded the in-memory maximum time (usecs)'),
CacheStat('cache_eviction_force_delete', 'pages evicted because they had chains of deleted items count'),
CacheStat('cache_eviction_force_delete_time', 'pages evicted because they had chains of deleted items time (usecs)'),
CacheStat('cache_eviction_force_fail', 'failed eviction of pages that exceeded the in-memory maximum count'),
CacheStat('cache_eviction_force_fail_time', 'failed eviction of pages that exceeded the in-memory maximum time (usecs)'),
CacheStat('cache_eviction_force_retune', 'force re-tuning of eviction workers once in a while'),
+ CacheStat('cache_eviction_force_time', 'pages evicted because they exceeded the in-memory maximum time (usecs)'),
CacheStat('cache_eviction_get_ref', 'eviction calls to get a page'),
CacheStat('cache_eviction_get_ref_empty', 'eviction calls to get a page found queue empty'),
CacheStat('cache_eviction_get_ref_empty2', 'eviction calls to get a page found queue empty after locking'),
@@ -230,10 +230,22 @@ connection_stats = [
CacheStat('cache_eviction_split_leaf', 'leaf pages split during eviction'),
CacheStat('cache_eviction_stable_state_workers', 'eviction worker thread stable number', 'no_clear'),
CacheStat('cache_eviction_state', 'eviction state', 'no_clear,no_scale'),
+ CacheStat('cache_eviction_target_page_ge128', 'eviction walk target pages histogram - 128 and higher'),
+ CacheStat('cache_eviction_target_page_lt10', 'eviction walk target pages histogram - 0-9'),
+ CacheStat('cache_eviction_target_page_lt32', 'eviction walk target pages histogram - 10-31'),
+ CacheStat('cache_eviction_target_page_lt64', 'eviction walk target pages histogram - 32-63'),
+ CacheStat('cache_eviction_target_page_lt128', 'eviction walk target pages histogram - 64-128'),
CacheStat('cache_eviction_walk', 'pages walked for eviction'),
+ CacheStat('cache_eviction_walk_from_root', 'eviction walks started from root of tree'),
+ CacheStat('cache_eviction_walk_passes', 'eviction passes of a file'),
+ CacheStat('cache_eviction_walk_saved_pos', 'eviction walks started from saved location in tree'),
CacheStat('cache_eviction_walks_abandoned', 'eviction walks abandoned'),
CacheStat('cache_eviction_walks_active', 'files with active eviction walks', 'no_clear,no_scale'),
+ CacheStat('cache_eviction_walks_ended', 'eviction walks reached end of tree'),
+ CacheStat('cache_eviction_walks_gave_up_no_targets', 'eviction walks gave up because they saw too many pages and found no candidates'),
+ CacheStat('cache_eviction_walks_gave_up_ratio', 'eviction walks gave up because they saw too many pages and found too few candidates'),
CacheStat('cache_eviction_walks_started', 'files with new eviction walks started'),
+ CacheStat('cache_eviction_walks_stopped', 'eviction walks gave up because they restarted their walk twice'),
CacheStat('cache_eviction_worker_created', 'eviction worker thread created'),
CacheStat('cache_eviction_worker_evicting', 'eviction worker thread evicting pages'),
CacheStat('cache_eviction_worker_removed', 'eviction worker thread removed'),
@@ -244,7 +256,6 @@ connection_stats = [
CacheStat('cache_inmem_splittable', 'in-memory page passed criteria to be split'),
CacheStat('cache_lookaside_insert', 'lookaside table insert calls'),
CacheStat('cache_lookaside_remove', 'lookaside table remove calls'),
- CacheStat('cache_overflow_value', 'overflow values cached in memory', 'no_scale'),
CacheStat('cache_overhead', 'percentage overhead', 'no_clear,no_scale'),
CacheStat('cache_pages_dirty', 'tracked dirty pages in the cache', 'no_clear,no_scale'),
CacheStat('cache_pages_inuse', 'pages currently held in the cache', 'no_clear,no_scale'),
@@ -323,6 +334,7 @@ connection_stats = [
LogStat('log_compress_write_fails', 'log records not compressed'),
LogStat('log_compress_writes', 'log records compressed'),
LogStat('log_flush', 'log flush operations'),
+ LogStat('log_force_ckpt_sleep', 'force checkpoint calls slept'),
LogStat('log_force_write', 'log force write operations'),
LogStat('log_force_write_skip', 'log force write operations skipped'),
LogStat('log_max_filesize', 'maximum log file size', 'no_clear,no_scale,size'),
@@ -510,11 +522,24 @@ dsrc_stats = [
CacheStat('cache_eviction_fail', 'data source pages selected for eviction unable to be evicted'),
CacheStat('cache_eviction_hazard', 'hazard pointer blocked page eviction'),
CacheStat('cache_eviction_internal', 'internal pages evicted'),
+ CacheStat('cache_eviction_pages_seen', 'pages seen by eviction walk'),
CacheStat('cache_eviction_split_internal', 'internal pages split during eviction'),
CacheStat('cache_eviction_split_leaf', 'leaf pages split during eviction'),
+ CacheStat('cache_eviction_target_page_ge128', 'eviction walk target pages histogram - 128 and higher'),
+ CacheStat('cache_eviction_target_page_lt10', 'eviction walk target pages histogram - 0-9'),
+ CacheStat('cache_eviction_target_page_lt32', 'eviction walk target pages histogram - 10-31'),
+ CacheStat('cache_eviction_target_page_lt64', 'eviction walk target pages histogram - 32-63'),
+ CacheStat('cache_eviction_target_page_lt128', 'eviction walk target pages histogram - 64-128'),
+ CacheStat('cache_eviction_walk_from_root', 'eviction walks started from root of tree'),
+ CacheStat('cache_eviction_walk_passes', 'eviction walk passes of a file'),
+ CacheStat('cache_eviction_walk_saved_pos', 'eviction walks started from saved location in tree'),
+ CacheStat('cache_eviction_walks_abandoned', 'eviction walks abandoned'),
+ CacheStat('cache_eviction_walks_ended', 'eviction walks reached end of tree'),
+ CacheStat('cache_eviction_walks_gave_up_no_targets', 'eviction walks gave up because they saw too many pages and found no candidates'),
+ CacheStat('cache_eviction_walks_gave_up_ratio', 'eviction walks gave up because they saw too many pages and found too few candidates'),
+ CacheStat('cache_eviction_walks_stopped', 'eviction walks gave up because they restarted their walk twice'),
CacheStat('cache_inmem_split', 'in-memory page splits'),
CacheStat('cache_inmem_splittable', 'in-memory page passed criteria to be split'),
- CacheStat('cache_overflow_value', 'overflow values cached in memory', 'no_scale'),
CacheStat('cache_pages_requested', 'pages requested from the cache'),
CacheStat('cache_read', 'pages read into cache'),
CacheStat('cache_read_lookaside', 'pages read into cache requiring lookaside entries'),
@@ -526,6 +551,8 @@ dsrc_stats = [
##########################################
# Cache content statistics
##########################################
+ CacheWalkStat('cache_state_avg_unvisited_age', 'Average time in cache for pages that have not been visited by the eviction server', 'no_clear,no_scale'),
+ CacheWalkStat('cache_state_avg_visited_age', 'Average time in cache for pages that have been visited by the eviction server', 'no_clear,no_scale'),
CacheWalkStat('cache_state_avg_written_size', 'Average on-disk page image size seen', 'no_clear,no_scale'),
CacheWalkStat('cache_state_gen_avg_gap', 'Average difference between current eviction generation when the page was last considered', 'no_clear,no_scale'),
CacheWalkStat('cache_state_gen_current', 'Current eviction generation', 'no_clear,no_scale'),
@@ -544,6 +571,7 @@ dsrc_stats = [
CacheWalkStat('cache_state_root_entries', 'Entries in the root page', 'no_clear,no_scale'),
CacheWalkStat('cache_state_root_size', 'Size of the root page', 'no_clear,no_scale'),
CacheWalkStat('cache_state_smaller_alloc_size', 'On-disk page image sizes smaller than a single allocation unit', 'no_clear,no_scale'),
+ CacheWalkStat('cache_state_unvisited_count', 'Number of pages never visited by eviction server', 'no_clear,no_scale'),
##########################################
# Compression statistics
diff --git a/src/third_party/wiredtiger/examples/c/ex_backup.c b/src/third_party/wiredtiger/examples/c/ex_backup.c
index 9cd9d5cf2a0..bf40d7573d8 100644
--- a/src/third_party/wiredtiger/examples/c/ex_backup.c
+++ b/src/third_party/wiredtiger/examples/c/ex_backup.c
@@ -48,7 +48,7 @@ static int
compare_backups(int i)
{
int ret;
- char buf[1024], msg[8];
+ char buf[1024], msg[32];
/*
* We run 'wt dump' on both the full backup directory and the
@@ -83,7 +83,7 @@ compare_backups(int i)
full_out, i, incr_out, i);
ret = system(buf);
if (i == 0)
- (void)strncpy(msg, "MAIN", sizeof(msg));
+ (void)snprintf(msg, sizeof(msg), "%s", "MAIN");
else
(void)snprintf(msg, sizeof(msg), "%d", i);
printf(
diff --git a/src/third_party/wiredtiger/examples/c/ex_encrypt.c b/src/third_party/wiredtiger/examples/c/ex_encrypt.c
index b6277ede084..3fdfa9a6d33 100644
--- a/src/third_party/wiredtiger/examples/c/ex_encrypt.c
+++ b/src/third_party/wiredtiger/examples/c/ex_encrypt.c
@@ -427,7 +427,7 @@ main(int argc, char *argv[])
WT_CURSOR *c1, *c2, *nc;
WT_SESSION *session;
int i, ret;
- char keybuf[16], valbuf[16];
+ char keybuf[32], valbuf[32];
char *key1, *key2, *key3, *val1, *val2, *val3;
home = example_setup(argc, argv);
diff --git a/src/third_party/wiredtiger/examples/c/ex_log.c b/src/third_party/wiredtiger/examples/c/ex_log.c
index 3cf6ff6df23..1912ffca8a6 100644
--- a/src/third_party/wiredtiger/examples/c/ex_log.c
+++ b/src/third_party/wiredtiger/examples/c/ex_log.c
@@ -269,7 +269,7 @@ main(int argc, char *argv[])
WT_CURSOR *cursor;
WT_SESSION *session;
int count_min, i, record_count;
- char cmd_buf[256], k[16], v[16];
+ char cmd_buf[256], k[32], v[32];
(void)argc; /* Unused variable */
(void)testutil_set_progname(argv);
diff --git a/src/third_party/wiredtiger/examples/c/ex_sync.c b/src/third_party/wiredtiger/examples/c/ex_sync.c
index 2dcd332c51f..975ba3b928c 100644
--- a/src/third_party/wiredtiger/examples/c/ex_sync.c
+++ b/src/third_party/wiredtiger/examples/c/ex_sync.c
@@ -43,7 +43,7 @@ main(int argc, char *argv[])
WT_CURSOR *cursor;
WT_SESSION *session;
int i, record_count, ret;
- char k[16], v[16];
+ char k[32], v[32];
const char *conf;
home = example_setup(argc, argv);
diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data
index e6068334d42..ee82256992f 100644
--- a/src/third_party/wiredtiger/import.data
+++ b/src/third_party/wiredtiger/import.data
@@ -1,5 +1,5 @@
{
- "commit": "ff10db881161bbd1bc23e40ac385ff0de18f68ff",
+ "commit": "6173a98979715ed727c432c1a31da64ea8a37048",
"github": "wiredtiger/wiredtiger.git",
"vendor": "wiredtiger",
"branch": "mongodb-3.6"
diff --git a/src/third_party/wiredtiger/src/async/async_op.c b/src/third_party/wiredtiger/src/async/async_op.c
index d4ca754b95f..dc8a3cdf348 100644
--- a/src/third_party/wiredtiger/src/async/async_op.c
+++ b/src/third_party/wiredtiger/src/async/async_op.c
@@ -7,6 +7,7 @@
*/
#include "wt_internal.h"
+
/*
* __async_get_key --
* WT_ASYNC_OP->get_key implementation for op handles.
diff --git a/src/third_party/wiredtiger/src/async/async_worker.c b/src/third_party/wiredtiger/src/async/async_worker.c
index 57ebe5d8bb1..2626a21435f 100644
--- a/src/third_party/wiredtiger/src/async/async_worker.c
+++ b/src/third_party/wiredtiger/src/async/async_worker.c
@@ -215,7 +215,7 @@ __async_worker_execop(WT_SESSION_IMPL *session, WT_ASYNC_OP_IMPL *op,
break;
case WT_AOP_NONE:
WT_RET_MSG(session, EINVAL,
- "Unknown async optype %d", op->optype);
+ "Unknown async optype %d", (int)op->optype);
}
return (0);
}
diff --git a/src/third_party/wiredtiger/src/block/block_compact.c b/src/third_party/wiredtiger/src/block/block_compact.c
index e7b9beafb01..76c4b1de3ec 100644
--- a/src/third_party/wiredtiger/src/block/block_compact.c
+++ b/src/third_party/wiredtiger/src/block/block_compact.c
@@ -8,7 +8,9 @@
#include "wt_internal.h"
+#ifdef HAVE_VERBOSE
static void __block_dump_avail(WT_SESSION_IMPL *, WT_BLOCK *, bool);
+#endif
/*
* __wt_block_compact_start --
@@ -78,9 +80,11 @@ __wt_block_compact_skip(WT_SESSION_IMPL *session, WT_BLOCK *block, bool *skipp)
__wt_spin_lock(session, &block->live_lock);
+#ifdef HAVE_VERBOSE
/* Dump the current state of the file. */
if (WT_VERBOSE_ISSET(session, WT_VERB_COMPACT))
__block_dump_avail(session, block, true);
+#endif
/* Sum the available bytes in the initial 80% and 90% of the file. */
avail_eighty = avail_ninety = 0;
@@ -195,6 +199,7 @@ __wt_block_compact_page_skip(WT_SESSION_IMPL *session,
return (0);
}
+#ifdef HAVE_VERBOSE
/*
* __block_dump_avail --
* Dump out the avail list so we can see what compaction will look like.
@@ -271,3 +276,4 @@ __block_dump_avail(WT_SESSION_IMPL *session, WT_BLOCK *block, bool start)
(uintmax_t)((v * 100) / (wt_off_t)el->bytes));
}
}
+#endif
diff --git a/src/third_party/wiredtiger/src/block/block_vrfy.c b/src/third_party/wiredtiger/src/block/block_vrfy.c
index 1058f16bde6..d2ca561fe82 100644
--- a/src/third_party/wiredtiger/src/block/block_vrfy.c
+++ b/src/third_party/wiredtiger/src/block/block_vrfy.c
@@ -33,7 +33,7 @@ int
__wt_block_verify_start(WT_SESSION_IMPL *session,
WT_BLOCK *block, WT_CKPT *ckptbase, const char *cfg[])
{
- WT_CKPT *ckpt;
+ WT_CKPT *ckpt, *t;
WT_CONFIG_ITEM cval;
wt_off_t size;
@@ -50,14 +50,12 @@ __wt_block_verify_start(WT_SESSION_IMPL *session,
* checkpoint we have is fake, there's no work to do. Don't complain,
* that's not our problem to solve.
*/
- WT_CKPT_FOREACH(ckptbase, ckpt)
- ;
- for (;; --ckpt) {
- if (ckpt->name != NULL && !F_ISSET(ckpt, WT_CKPT_FAKE))
- break;
- if (ckpt == ckptbase)
- return (0);
- }
+ ckpt = NULL;
+ WT_CKPT_FOREACH(ckptbase, t)
+ if (t->name != NULL && !F_ISSET(t, WT_CKPT_FAKE))
+ ckpt = t;
+ if (ckpt == NULL)
+ return (0);
/* Set the size of the file to the size of the last checkpoint. */
WT_RET(__verify_set_file_size(session, block, ckpt));
@@ -387,6 +385,8 @@ __verify_filefrag_add(WT_SESSION_IMPL *session, WT_BLOCK *block,
{
uint64_t f, frag, frags, i;
+ WT_UNUSED(type); /* !HAVE_VERBOSE */
+
__wt_verbose(session, WT_VERB_VERIFY,
"add file block%s%s%s at %" PRIuMAX "-%" PRIuMAX " (%" PRIuMAX ")",
type == NULL ? "" : " (",
diff --git a/src/third_party/wiredtiger/src/btree/bt_debug.c b/src/third_party/wiredtiger/src/btree/bt_debug.c
index 394ac6c7b84..c0aaf3f42d9 100644
--- a/src/third_party/wiredtiger/src/btree/bt_debug.c
+++ b/src/third_party/wiredtiger/src/btree/bt_debug.c
@@ -445,18 +445,28 @@ static char *
__debug_tree_shape_info(WT_PAGE *page)
{
uint64_t v;
- static char buf[32];
+ static char buf[128];
+ const char *unit;
v = page->memory_footprint;
- if (v >= WT_GIGABYTE)
- (void)__wt_snprintf(buf, sizeof(buf),
- "(%p %" PRIu64 "G)", (void *)page, v / WT_GIGABYTE);
- else if (v >= WT_MEGABYTE)
- (void)__wt_snprintf(buf, sizeof(buf),
- "(%p %" PRIu64 "M)", (void *)page, v / WT_MEGABYTE);
- else
- (void)__wt_snprintf(buf, sizeof(buf),
- "(%p %" PRIu64 ")", (void *)page, v);
+
+ if (v > WT_GIGABYTE) {
+ v /= WT_GIGABYTE;
+ unit = "G";
+ } else if (v > WT_MEGABYTE) {
+ v /= WT_MEGABYTE;
+ unit = "M";
+ } else if (v > WT_KILOBYTE) {
+ v /= WT_KILOBYTE;
+ unit = "K";
+ } else {
+ unit = "B";
+ }
+
+ (void)__wt_snprintf(buf, sizeof(buf), "(%p, %" PRIu64
+ "%s, evict gen %" PRIu64 ", create gen %" PRIu64 ")",
+ (void *)page, v, unit,
+ page->evict_pass_gen, page->cache_create_gen);
return (buf);
}
@@ -982,7 +992,7 @@ __debug_row_skip(WT_DBG *ds, WT_INSERT_HEAD *head)
static int
__debug_update(WT_DBG *ds, WT_UPDATE *upd, bool hexbyte)
{
- for (; upd != NULL; upd = upd->next)
+ for (; upd != NULL; upd = upd->next) {
if (upd->type == WT_UPDATE_DELETED)
WT_RET(ds->f(ds, "\tvalue {deleted}\n"));
else if (upd->type == WT_UPDATE_RESERVED)
@@ -995,6 +1005,30 @@ __debug_update(WT_DBG *ds, WT_UPDATE *upd, bool hexbyte)
} else
WT_RET(__debug_item(ds,
"value", WT_UPDATE_DATA(upd), upd->size));
+ WT_RET(ds->f(ds, "\t" "txn id %" PRIu64, upd->txnid));
+
+#ifdef HAVE_TIMESTAMPS
+ if (!__wt_timestamp_iszero(upd->timestamp)) {
+#if WT_TIMESTAMP_SIZE == 8
+ {
+ uint64_t ts;
+ __wt_timestamp_set(
+ (uint8_t *)&ts, (uint8_t *)&upd->timestamp[0]);
+ ts = __wt_bswap64(ts);
+ WT_RET(ds->f(ds, ", stamp %" PRIu64, ts));
+ }
+#else
+ {
+ int i;
+ WT_RET(ds->f(ds, ", stamp 0x"));
+ for (i = 0; i < WT_TIMESTAMP_SIZE; ++i)
+ WT_RET(ds->f(ds, "%" PRIx8, upd->timestamp[i]));
+ }
+#endif
+ }
+#endif
+ WT_RET(ds->f(ds, "\n"));
+ }
return (0);
}
diff --git a/src/third_party/wiredtiger/src/btree/bt_discard.c b/src/third_party/wiredtiger/src/btree/bt_discard.c
index bfa8eb25aac..bc9356e2669 100644
--- a/src/third_party/wiredtiger/src/btree/bt_discard.c
+++ b/src/third_party/wiredtiger/src/btree/bt_discard.c
@@ -249,7 +249,8 @@ __free_page_modify(WT_SESSION_IMPL *session, WT_PAGE *page)
/* Free the overflow on-page, reuse and transaction-cache skiplists. */
__wt_ovfl_reuse_free(session, page);
- __wt_ovfl_txnc_free(session, page);
+ if (mod->ovfl_track != NULL)
+ __wt_free(session, mod->ovfl_track->remove);
__wt_ovfl_discard_free(session, page);
__wt_free(session, page->modify->ovfl_track);
diff --git a/src/third_party/wiredtiger/src/btree/bt_handle.c b/src/third_party/wiredtiger/src/btree/bt_handle.c
index 06fbd6b74c7..5fad76849dc 100644
--- a/src/third_party/wiredtiger/src/btree/bt_handle.c
+++ b/src/third_party/wiredtiger/src/btree/bt_handle.c
@@ -279,6 +279,9 @@ __btree_conf(WT_SESSION_IMPL *session, WT_CKPT *ckpt)
bool fixed;
const char **cfg, *enc_cfg[] = { NULL, NULL };
+ WT_UNUSED(maj_version); /* !HAVE_VERBOSE */
+ WT_UNUSED(min_version); /* !HAVE_VERBOSE */
+
btree = S2BT(session);
cfg = btree->dhandle->cfg;
conn = S2C(session);
@@ -290,7 +293,7 @@ __btree_conf(WT_SESSION_IMPL *session, WT_CKPT *ckpt)
WT_RET(__wt_config_gets(session, cfg, "version.minor", &cval));
min_version = cval.val;
__wt_verbose(session, WT_VERB_VERSION,
- "%" PRIu64 ".%" PRIu64, maj_version, min_version);
+ "%" PRId64 ".%" PRId64, maj_version, min_version);
}
/* Get the file ID. */
diff --git a/src/third_party/wiredtiger/src/btree/bt_ovfl.c b/src/third_party/wiredtiger/src/btree/bt_ovfl.c
index 76d1bfd121c..a0b1ff65006 100644
--- a/src/third_party/wiredtiger/src/btree/bt_ovfl.c
+++ b/src/third_party/wiredtiger/src/btree/bt_ovfl.c
@@ -48,6 +48,9 @@ __wt_ovfl_read(WT_SESSION_IMPL *session,
WT_PAGE *page, WT_CELL_UNPACK *unpack, WT_ITEM *store)
{
WT_DECL_RET;
+ WT_OVFL_TRACK *track;
+ WT_UPDATE *upd;
+ size_t i;
/*
* If no page specified, there's no need to lock and there's no cache
@@ -61,16 +64,24 @@ __wt_ovfl_read(WT_SESSION_IMPL *session,
* WT_CELL_VALUE_OVFL_RM cells: If reconciliation deleted an overflow
* value, but there was still a reader in the system that might need it,
* the on-page cell type will have been reset to WT_CELL_VALUE_OVFL_RM
- * and we will be passed a page so we can look-aside into the cache of
- * such values.
+ * and we will be passed a page so we can check the on-page cell.
*
* Acquire the overflow lock, and retest the on-page cell's value inside
* the lock.
*/
__wt_readlock(session, &S2BT(session)->ovfl_lock);
- ret = __wt_cell_type_raw(unpack->cell) == WT_CELL_VALUE_OVFL_RM ?
- __wt_ovfl_txnc_search(page, unpack->data, unpack->size, store) :
- __ovfl_read(session, unpack->data, unpack->size, store);
+ if (__wt_cell_type_raw(unpack->cell) == WT_CELL_VALUE_OVFL_RM) {
+ track = page->modify->ovfl_track;
+ for (upd = NULL, i = 0; i < track->remove_next; ++i)
+ if (track->remove[i].cell == unpack->cell) {
+ upd = track->remove[i].upd;
+ break;
+ }
+ WT_ASSERT(session, i < track->remove_next);
+ store->data = WT_UPDATE_DATA(upd);
+ store->size = upd->size;
+ } else
+ ret = __ovfl_read(session, unpack->data, unpack->size, store);
__wt_readunlock(session, &S2BT(session)->ovfl_lock);
return (ret);
@@ -98,8 +109,7 @@ __ovfl_cache_col_visible(
* the value.
*/
if (__wt_cell_rle(unpack) == 1 &&
- upd != NULL && /* Sanity: upd should always be set. */
- __wt_txn_upd_visible_all(session, upd))
+ WT_UPDATE_DATA_VALUE(upd) && __wt_txn_upd_visible_all(session, upd))
return (true);
return (false);
}
@@ -109,51 +119,99 @@ __ovfl_cache_col_visible(
* row-store: check for a globally visible update.
*/
static bool
-__ovfl_cache_row_visible(WT_SESSION_IMPL *session, WT_PAGE *page, WT_ROW *rip)
+__ovfl_cache_row_visible(WT_SESSION_IMPL *session, WT_UPDATE *upd)
{
- WT_UPDATE *upd;
-
/* Check to see if there's a globally visible update. */
- for (upd = WT_ROW_UPDATE(page, rip); upd != NULL; upd = upd->next)
- if (__wt_txn_upd_visible_all(session, upd))
+ for (; upd != NULL; upd = upd->next)
+ if (WT_UPDATE_DATA_VALUE(upd) &&
+ __wt_txn_upd_visible_all(session, upd))
return (true);
return (false);
}
/*
- * __ovfl_cache --
- * Cache a deleted overflow value.
+ * __ovfl_cache_append_update --
+ * Append an overflow value to the update list.
*/
static int
-__ovfl_cache(WT_SESSION_IMPL *session, WT_PAGE *page, WT_CELL_UNPACK *unpack)
+__ovfl_cache_append_update(WT_SESSION_IMPL *session, WT_PAGE *page,
+ WT_UPDATE *upd_list, WT_CELL_UNPACK *unpack, WT_UPDATE **updp)
{
WT_DECL_ITEM(tmp);
WT_DECL_RET;
- size_t addr_size;
- const uint8_t *addr;
+ WT_UPDATE *append, *upd;
+ size_t size;
- addr = unpack->data;
- addr_size = unpack->size;
+ *updp = NULL;
+ /* Read the overflow value. */
WT_RET(__wt_scr_alloc(session, 1024, &tmp));
+ WT_ERR(__ovfl_read(session, unpack->data, unpack->size, tmp));
+
+ /*
+ * Create an update entry with no transaction ID to ensure global
+ * visibility, append it to the update list.
+ *
+ * We don't need locks or barriers in this function: any thread reading
+ * the update list will see our newly appended record or not, it doesn't
+ * matter until the on-page cell is set to WT_CELL_VALUE_OVFL_RM. That
+ * involves atomic operations which will act as our barrier. Regardless,
+ * we update the page footprint as part of this operation, which acts as
+ * a barrier as well.
+ */
+ WT_ERR(__wt_update_alloc(
+ session, tmp, &append, &size, WT_UPDATE_STANDARD));
+ append->txnid = WT_TXN_NONE;
+ for (upd = upd_list; upd->next != NULL; upd = upd->next)
+ ;
+ WT_PUBLISH(upd->next, append);
+
+ __wt_cache_page_inmem_incr(session, page, size);
- /* Enter the value into the overflow cache. */
- WT_ERR(__ovfl_read(session, addr, addr_size, tmp));
- WT_ERR(__wt_ovfl_txnc_add(
- session, page, addr, addr_size, tmp->data, tmp->size));
+ *updp = append;
err: __wt_scr_free(session, &tmp);
return (ret);
}
/*
- * __wt_ovfl_cache --
- * Handle deletion of an overflow value.
+ * __ovfl_cache --
+ * Cache an overflow value.
+ */
+static int
+__ovfl_cache(WT_SESSION_IMPL *session,
+ WT_PAGE *page, WT_UPDATE *upd_list, WT_CELL_UNPACK *unpack)
+{
+ WT_OVFL_TRACK *track;
+ WT_UPDATE *upd;
+
+ /* Append a copy of the overflow value to the update list. */
+ WT_RET(__ovfl_cache_append_update(
+ session, page, upd_list, unpack, &upd));
+
+ /* Allocating tracking structures as necessary. */
+ if (page->modify->ovfl_track == NULL)
+ WT_RET(__wt_ovfl_track_init(session, page));
+ track = page->modify->ovfl_track;
+
+ /* Add the value's information to the update list. */
+ WT_RET(__wt_realloc_def(session,
+ &track->remove_allocated, track->remove_next + 1, &track->remove));
+ track->remove[track->remove_next].cell = unpack->cell;
+ track->remove[track->remove_next].upd = upd;
+ ++track->remove_next;
+
+ return (0);
+}
+
+/*
+ * __wt_ovfl_remove --
+ * Remove an overflow value.
*/
int
-__wt_ovfl_cache(WT_SESSION_IMPL *session,
- WT_PAGE *page, void *cookie, WT_CELL_UNPACK *vpack)
+__wt_ovfl_remove(WT_SESSION_IMPL *session,
+ WT_PAGE *page, WT_UPDATE *upd_list, WT_CELL_UNPACK *unpack)
{
bool visible;
@@ -195,10 +253,10 @@ __wt_ovfl_cache(WT_SESSION_IMPL *session,
*/
switch (page->type) {
case WT_PAGE_COL_VAR:
- visible = __ovfl_cache_col_visible(session, cookie, vpack);
+ visible = __ovfl_cache_col_visible(session, upd_list, unpack);
break;
case WT_PAGE_ROW_LEAF:
- visible = __ovfl_cache_row_visible(session, page, cookie);
+ visible = __ovfl_cache_row_visible(session, upd_list);
break;
WT_ILLEGAL_VALUE(session);
}
@@ -207,18 +265,15 @@ __wt_ovfl_cache(WT_SESSION_IMPL *session,
* If there's no globally visible update, there's a reader in the system
* that might try and read the old value, cache it.
*/
- if (!visible) {
- WT_RET(__ovfl_cache(session, page, vpack));
- WT_STAT_CONN_INCR(session, cache_overflow_value);
- WT_STAT_DATA_INCR(session, cache_overflow_value);
- }
+ if (!visible)
+ WT_RET(__ovfl_cache(session, page, upd_list, unpack));
/*
* Queue the on-page cell to be set to WT_CELL_VALUE_OVFL_RM and the
* underlying overflow value's blocks to be freed when reconciliation
* completes.
*/
- return (__wt_ovfl_discard_add(session, page, vpack->cell));
+ return (__wt_ovfl_discard_add(session, page, unpack->cell));
}
/*
diff --git a/src/third_party/wiredtiger/src/btree/bt_page.c b/src/third_party/wiredtiger/src/btree/bt_page.c
index ca5f05fe3dc..d7643e9ad26 100644
--- a/src/third_party/wiredtiger/src/btree/bt_page.c
+++ b/src/third_party/wiredtiger/src/btree/bt_page.c
@@ -116,6 +116,7 @@ err: if ((pindex = WT_INTL_INDEX_GET_SAFE(page)) != NULL) {
__wt_cache_page_inmem_incr(session, page, size);
(void)__wt_atomic_add64(&cache->bytes_read, size);
(void)__wt_atomic_add64(&cache->pages_inmem, 1);
+ page->cache_create_gen = cache->evict_pass_gen;
*pagep = page;
return (0);
diff --git a/src/third_party/wiredtiger/src/btree/bt_read.c b/src/third_party/wiredtiger/src/btree/bt_read.c
index 5f8cf3a45e1..6a89f505c31 100644
--- a/src/third_party/wiredtiger/src/btree/bt_read.c
+++ b/src/third_party/wiredtiger/src/btree/bt_read.c
@@ -710,7 +710,7 @@ __btree_verbose_lookaside_read(WT_SESSION_IMPL *session)
if (__wt_atomic_casv64(&conn->las_verb_gen_read,
ckpt_gen_last, ckpt_gen_current)) {
__wt_verbose(session, WT_VERB_LOOKASIDE,
- "Read from lookaside file triggered.");
+ "%s", "Read from lookaside file triggered.");
}
}
#else
diff --git a/src/third_party/wiredtiger/src/btree/bt_slvg.c b/src/third_party/wiredtiger/src/btree/bt_slvg.c
index eb39301abc7..1f686d904ec 100644
--- a/src/third_party/wiredtiger/src/btree/bt_slvg.c
+++ b/src/third_party/wiredtiger/src/btree/bt_slvg.c
@@ -1885,6 +1885,8 @@ __slvg_row_build_leaf(
uint32_t i, skip_start, skip_stop;
int cmp;
+ WT_UNUSED(ss); /* !HAVE_VERBOSE */
+
btree = S2BT(session);
page = NULL;
diff --git a/src/third_party/wiredtiger/src/btree/row_srch.c b/src/third_party/wiredtiger/src/btree/row_srch.c
index 76bebde7de7..3a9a6eb0f9b 100644
--- a/src/third_party/wiredtiger/src/btree/row_srch.c
+++ b/src/third_party/wiredtiger/src/btree/row_srch.c
@@ -591,13 +591,13 @@ leaf_match: cbt->compare = 0;
*/
if (base == 0) {
cbt->compare = 1;
- cbt->slot = WT_ROW_SLOT(page, page->pg_row);
+ cbt->slot = 0;
F_SET(cbt, WT_CBT_SEARCH_SMALLEST);
ins_head = WT_ROW_INSERT_SMALLEST(page);
} else {
cbt->compare = -1;
- cbt->slot = WT_ROW_SLOT(page, page->pg_row + (base - 1));
+ cbt->slot = base - 1;
ins_head = WT_ROW_INSERT_SLOT(page, cbt->slot);
}
diff --git a/src/third_party/wiredtiger/src/config/config_def.c b/src/third_party/wiredtiger/src/config/config_def.c
index 30b2b3e0e4d..dda27fec57c 100644
--- a/src/third_party/wiredtiger/src/config/config_def.c
+++ b/src/third_party/wiredtiger/src/config/config_def.c
@@ -55,6 +55,12 @@ static const WT_CONFIG_CHECK
};
static const WT_CONFIG_CHECK
+ confchk_wiredtiger_open_compatibility_subconfigs[] = {
+ { "release", "string", NULL, NULL, NULL, 0 },
+ { NULL, NULL, NULL, NULL, NULL, 0 }
+};
+
+static const WT_CONFIG_CHECK
confchk_wiredtiger_open_eviction_subconfigs[] = {
{ "threads_max", "int", NULL, "min=1,max=20", NULL, 0 },
{ "threads_min", "int", NULL, "min=1,max=20", NULL, 0 },
@@ -117,6 +123,9 @@ static const WT_CONFIG_CHECK confchk_WT_CONNECTION_reconfigure[] = {
{ "checkpoint", "category",
NULL, NULL,
confchk_wiredtiger_open_checkpoint_subconfigs, 2 },
+ { "compatibility", "category",
+ NULL, NULL,
+ confchk_wiredtiger_open_compatibility_subconfigs, 1 },
{ "diagnostic_timing_stress", "list",
NULL, "choices=[\"checkpoint_slow\"]",
NULL, 0 },
@@ -179,11 +188,20 @@ static const WT_CONFIG_CHECK confchk_WT_CURSOR_reconfigure[] = {
{ NULL, NULL, NULL, NULL, NULL, 0 }
};
+static const WT_CONFIG_CHECK
+ confchk_WT_SESSION_create_log_subconfigs[] = {
+ { "enabled", "boolean", NULL, NULL, NULL, 0 },
+ { NULL, NULL, NULL, NULL, NULL, 0 }
+};
+
static const WT_CONFIG_CHECK confchk_WT_SESSION_alter[] = {
{ "access_pattern_hint", "string",
NULL, "choices=[\"none\",\"random\",\"sequential\"]",
NULL, 0 },
{ "cache_resident", "boolean", NULL, NULL, NULL, 0 },
+ { "log", "category",
+ NULL, NULL,
+ confchk_WT_SESSION_create_log_subconfigs, 1 },
{ NULL, NULL, NULL, NULL, NULL, 0 }
};
@@ -230,12 +248,6 @@ static const WT_CONFIG_CHECK
};
static const WT_CONFIG_CHECK
- confchk_WT_SESSION_create_log_subconfigs[] = {
- { "enabled", "boolean", NULL, NULL, NULL, 0 },
- { NULL, NULL, NULL, NULL, NULL, 0 }
-};
-
-static const WT_CONFIG_CHECK
confchk_WT_SESSION_create_lsm_subconfigs[] = {
{ "auto_throttle", "boolean", NULL, NULL, NULL, 0 },
{ "bloom", "boolean", NULL, NULL, NULL, 0 },
@@ -712,6 +724,9 @@ static const WT_CONFIG_CHECK confchk_wiredtiger_open[] = {
NULL, NULL,
confchk_wiredtiger_open_checkpoint_subconfigs, 2 },
{ "checkpoint_sync", "boolean", NULL, NULL, NULL, 0 },
+ { "compatibility", "category",
+ NULL, NULL,
+ confchk_wiredtiger_open_compatibility_subconfigs, 1 },
{ "config_base", "boolean", NULL, NULL, NULL, 0 },
{ "create", "boolean", NULL, NULL, NULL, 0 },
{ "diagnostic_timing_stress", "list",
@@ -803,6 +818,9 @@ static const WT_CONFIG_CHECK confchk_wiredtiger_open_all[] = {
NULL, NULL,
confchk_wiredtiger_open_checkpoint_subconfigs, 2 },
{ "checkpoint_sync", "boolean", NULL, NULL, NULL, 0 },
+ { "compatibility", "category",
+ NULL, NULL,
+ confchk_wiredtiger_open_compatibility_subconfigs, 1 },
{ "config_base", "boolean", NULL, NULL, NULL, 0 },
{ "create", "boolean", NULL, NULL, NULL, 0 },
{ "diagnostic_timing_stress", "list",
@@ -895,6 +913,9 @@ static const WT_CONFIG_CHECK confchk_wiredtiger_open_basecfg[] = {
NULL, NULL,
confchk_wiredtiger_open_checkpoint_subconfigs, 2 },
{ "checkpoint_sync", "boolean", NULL, NULL, NULL, 0 },
+ { "compatibility", "category",
+ NULL, NULL,
+ confchk_wiredtiger_open_compatibility_subconfigs, 1 },
{ "diagnostic_timing_stress", "list",
NULL, "choices=[\"checkpoint_slow\"]",
NULL, 0 },
@@ -981,6 +1002,9 @@ static const WT_CONFIG_CHECK confchk_wiredtiger_open_usercfg[] = {
NULL, NULL,
confchk_wiredtiger_open_checkpoint_subconfigs, 2 },
{ "checkpoint_sync", "boolean", NULL, NULL, NULL, 0 },
+ { "compatibility", "category",
+ NULL, NULL,
+ confchk_wiredtiger_open_compatibility_subconfigs, 1 },
{ "diagnostic_timing_stress", "list",
NULL, "choices=[\"checkpoint_slow\"]",
NULL, 0 },
@@ -1099,18 +1123,18 @@ static const WT_CONFIG_ENTRY config_entries[] = {
{ "WT_CONNECTION.reconfigure",
"async=(enabled=false,ops_max=1024,threads=2),cache_overhead=8,"
"cache_size=100MB,checkpoint=(log_size=0,wait=0),"
- "diagnostic_timing_stress=,error_prefix=,eviction=(threads_max=8,"
- "threads_min=1),eviction_checkpoint_target=5,"
- "eviction_dirty_target=5,eviction_dirty_trigger=20,"
- "eviction_target=80,eviction_trigger=95,"
- "file_manager=(close_handle_minimum=250,close_idle_time=30,"
+ "compatibility=(release=),diagnostic_timing_stress=,error_prefix="
+ ",eviction=(threads_max=8,threads_min=1),"
+ "eviction_checkpoint_target=5,eviction_dirty_target=5,"
+ "eviction_dirty_trigger=20,eviction_target=80,eviction_trigger=95"
+ ",file_manager=(close_handle_minimum=250,close_idle_time=30,"
"close_scan_interval=10),log=(archive=true,prealloc=true,"
"zero_fill=false),lsm_manager=(merge=true,worker_thread_max=4),"
"lsm_merge=true,shared_cache=(chunk=10MB,name=,quota=0,reserve=0,"
"size=500MB),statistics=none,statistics_log=(json=false,"
"on_close=false,sources=,timestamp=\"%b %d %H:%M:%S\",wait=0),"
"verbose=",
- confchk_WT_CONNECTION_reconfigure, 20
+ confchk_WT_CONNECTION_reconfigure, 21
},
{ "WT_CONNECTION.set_file_system",
"",
@@ -1129,8 +1153,8 @@ static const WT_CONFIG_ENTRY config_entries[] = {
confchk_WT_CURSOR_reconfigure, 2
},
{ "WT_SESSION.alter",
- "access_pattern_hint=none,cache_resident=false",
- confchk_WT_SESSION_alter, 2
+ "access_pattern_hint=none,cache_resident=false,log=(enabled=true)",
+ confchk_WT_SESSION_alter, 3
},
{ "WT_SESSION.begin_transaction",
"isolation=,name=,priority=0,read_timestamp=,snapshot=,sync=",
@@ -1318,10 +1342,10 @@ static const WT_CONFIG_ENTRY config_entries[] = {
"async=(enabled=false,ops_max=1024,threads=2),buffer_alignment=-1"
",builtin_extension_config=,cache_overhead=8,cache_size=100MB,"
"checkpoint=(log_size=0,wait=0),checkpoint_sync=true,"
- "config_base=true,create=false,diagnostic_timing_stress=,"
- "direct_io=,encryption=(keyid=,name=,secretkey=),error_prefix=,"
- "eviction=(threads_max=8,threads_min=1),"
- "eviction_checkpoint_target=5,eviction_dirty_target=5,"
+ "compatibility=(release=),config_base=true,create=false,"
+ "diagnostic_timing_stress=,direct_io=,encryption=(keyid=,name=,"
+ "secretkey=),error_prefix=,eviction=(threads_max=8,threads_min=1)"
+ ",eviction_checkpoint_target=5,eviction_dirty_target=5,"
"eviction_dirty_trigger=20,eviction_target=80,eviction_trigger=95"
",exclusive=false,extensions=,file_extend=,"
"file_manager=(close_handle_minimum=250,close_idle_time=30,"
@@ -1336,16 +1360,16 @@ static const WT_CONFIG_ENTRY config_entries[] = {
",wait=0),transaction_sync=(enabled=false,method=fsync),"
"use_environment=true,use_environment_priv=false,verbose=,"
"write_through=",
- confchk_wiredtiger_open, 41
+ confchk_wiredtiger_open, 42
},
{ "wiredtiger_open_all",
"async=(enabled=false,ops_max=1024,threads=2),buffer_alignment=-1"
",builtin_extension_config=,cache_overhead=8,cache_size=100MB,"
"checkpoint=(log_size=0,wait=0),checkpoint_sync=true,"
- "config_base=true,create=false,diagnostic_timing_stress=,"
- "direct_io=,encryption=(keyid=,name=,secretkey=),error_prefix=,"
- "eviction=(threads_max=8,threads_min=1),"
- "eviction_checkpoint_target=5,eviction_dirty_target=5,"
+ "compatibility=(release=),config_base=true,create=false,"
+ "diagnostic_timing_stress=,direct_io=,encryption=(keyid=,name=,"
+ "secretkey=),error_prefix=,eviction=(threads_max=8,threads_min=1)"
+ ",eviction_checkpoint_target=5,eviction_dirty_target=5,"
"eviction_dirty_trigger=20,eviction_target=80,eviction_trigger=95"
",exclusive=false,extensions=,file_extend=,"
"file_manager=(close_handle_minimum=250,close_idle_time=30,"
@@ -1360,15 +1384,16 @@ static const WT_CONFIG_ENTRY config_entries[] = {
",wait=0),transaction_sync=(enabled=false,method=fsync),"
"use_environment=true,use_environment_priv=false,verbose=,"
"version=(major=0,minor=0),write_through=",
- confchk_wiredtiger_open_all, 42
+ confchk_wiredtiger_open_all, 43
},
{ "wiredtiger_open_basecfg",
"async=(enabled=false,ops_max=1024,threads=2),buffer_alignment=-1"
",builtin_extension_config=,cache_overhead=8,cache_size=100MB,"
"checkpoint=(log_size=0,wait=0),checkpoint_sync=true,"
- "diagnostic_timing_stress=,direct_io=,encryption=(keyid=,name=,"
- "secretkey=),error_prefix=,eviction=(threads_max=8,threads_min=1)"
- ",eviction_checkpoint_target=5,eviction_dirty_target=5,"
+ "compatibility=(release=),diagnostic_timing_stress=,direct_io=,"
+ "encryption=(keyid=,name=,secretkey=),error_prefix=,"
+ "eviction=(threads_max=8,threads_min=1),"
+ "eviction_checkpoint_target=5,eviction_dirty_target=5,"
"eviction_dirty_trigger=20,eviction_target=80,eviction_trigger=95"
",extensions=,file_extend=,file_manager=(close_handle_minimum=250"
",close_idle_time=30,close_scan_interval=10),hazard_max=1000,"
@@ -1381,15 +1406,16 @@ static const WT_CONFIG_ENTRY config_entries[] = {
",on_close=false,path=\".\",sources=,timestamp=\"%b %d %H:%M:%S\""
",wait=0),transaction_sync=(enabled=false,method=fsync),verbose=,"
"version=(major=0,minor=0),write_through=",
- confchk_wiredtiger_open_basecfg, 36
+ confchk_wiredtiger_open_basecfg, 37
},
{ "wiredtiger_open_usercfg",
"async=(enabled=false,ops_max=1024,threads=2),buffer_alignment=-1"
",builtin_extension_config=,cache_overhead=8,cache_size=100MB,"
"checkpoint=(log_size=0,wait=0),checkpoint_sync=true,"
- "diagnostic_timing_stress=,direct_io=,encryption=(keyid=,name=,"
- "secretkey=),error_prefix=,eviction=(threads_max=8,threads_min=1)"
- ",eviction_checkpoint_target=5,eviction_dirty_target=5,"
+ "compatibility=(release=),diagnostic_timing_stress=,direct_io=,"
+ "encryption=(keyid=,name=,secretkey=),error_prefix=,"
+ "eviction=(threads_max=8,threads_min=1),"
+ "eviction_checkpoint_target=5,eviction_dirty_target=5,"
"eviction_dirty_trigger=20,eviction_target=80,eviction_trigger=95"
",extensions=,file_extend=,file_manager=(close_handle_minimum=250"
",close_idle_time=30,close_scan_interval=10),hazard_max=1000,"
@@ -1402,7 +1428,7 @@ static const WT_CONFIG_ENTRY config_entries[] = {
",on_close=false,path=\".\",sources=,timestamp=\"%b %d %H:%M:%S\""
",wait=0),transaction_sync=(enabled=false,method=fsync),verbose=,"
"write_through=",
- confchk_wiredtiger_open_usercfg, 35
+ confchk_wiredtiger_open_usercfg, 36
},
{ NULL, NULL, NULL, 0 }
};
diff --git a/src/third_party/wiredtiger/src/conn/conn_api.c b/src/third_party/wiredtiger/src/conn/conn_api.c
index cb0aa17791e..09eceac0a3b 100644
--- a/src/third_party/wiredtiger/src/conn/conn_api.c
+++ b/src/third_party/wiredtiger/src/conn/conn_api.c
@@ -190,6 +190,45 @@ __wt_conn_remove_collator(WT_SESSION_IMPL *session)
}
/*
+ * __conn_compat_config --
+ * Configure compatibility version.
+ */
+static int
+__conn_compat_config(WT_SESSION_IMPL *session, const char **cfg)
+{
+ WT_CONFIG_ITEM cval;
+ WT_CONNECTION_IMPL *conn;
+ uint16_t patch;
+
+ conn = S2C(session);
+ WT_RET(__wt_config_gets(session, cfg,
+ "compatibility.release", &cval));
+ if (cval.len != 0) {
+ /*
+ * Accept either a major.minor release string or a
+ * major.minor.patch release string. We ignore the patch
+ * value, but allow it in the string.
+ */
+ if (sscanf(cval.str, "%" SCNu16 ".%" SCNu16,
+ &conn->compat_major, &conn->compat_minor) != 2 &&
+ sscanf(cval.str, "%" SCNu16 ".%" SCNu16 ".%" SCNu16,
+ &conn->compat_major, &conn->compat_minor, &patch) != 3)
+ WT_RET_MSG(session,
+ EINVAL, "illegal compatibility release");
+ if (conn->compat_major > WIREDTIGER_VERSION_MAJOR)
+ WT_RET_MSG(session, EINVAL, "unknown major version");
+ if (conn->compat_major == WIREDTIGER_VERSION_MAJOR &&
+ conn->compat_minor > WIREDTIGER_VERSION_MINOR)
+ WT_RET_MSG(session,
+ EINVAL, "illegal compatibility version");
+ } else {
+ conn->compat_major = WIREDTIGER_VERSION_MAJOR;
+ conn->compat_minor = WIREDTIGER_VERSION_MINOR;
+ }
+ return (0);
+}
+
+/*
* __compressor_confchk --
* Validate the compressor.
*/
@@ -1134,6 +1173,7 @@ __conn_reconfigure(WT_CONNECTION *wt_conn, const char *config)
cfg[1] = config;
/* Second, reconfigure the system. */
+ WT_ERR(__conn_compat_config(session, cfg));
WT_ERR(__conn_statistics_config(session, cfg));
WT_ERR(__wt_async_reconfig(session, cfg));
WT_ERR(__wt_cache_config(session, true, cfg));
@@ -2018,6 +2058,7 @@ __conn_write_base_config(WT_SESSION_IMPL *session, const char *cfg[])
* merge the rest to be written.
*/
WT_ERR(__wt_config_merge(session, cfg + 1,
+ "compatibility=(release=),"
"config_base=,"
"create=,"
"encryption=(secretkey=),"
@@ -2287,6 +2328,11 @@ wiredtiger_open(const char *home, WT_EVENT_HANDLER *event_handler,
WT_ERR(__conn_load_extensions(session, cfg, true));
/*
+ * Set compatibility versions early so that any subsystem sees it.
+ */
+ WT_ERR(__conn_compat_config(session, cfg));
+
+ /*
* If the application didn't configure its own file system, configure
* one of ours. Check to ensure we have a valid file system.
*/
diff --git a/src/third_party/wiredtiger/src/conn/conn_cache_pool.c b/src/third_party/wiredtiger/src/conn/conn_cache_pool.c
index adc2e2bffc3..55393a86ba1 100644
--- a/src/third_party/wiredtiger/src/conn/conn_cache_pool.c
+++ b/src/third_party/wiredtiger/src/conn/conn_cache_pool.c
@@ -372,8 +372,8 @@ __wt_conn_cache_pool_destroy(WT_SESSION_IMPL *session)
}
if (!F_ISSET(cp, WT_CACHE_POOL_ACTIVE)) {
- __wt_verbose(
- session, WT_VERB_SHARED_CACHE, "Destroying cache pool");
+ __wt_verbose(session,
+ WT_VERB_SHARED_CACHE, "%s", "Destroying cache pool");
__wt_spin_lock(session, &__wt_process.spinlock);
/*
* We have been holding the pool lock - no connections could
@@ -401,7 +401,7 @@ __wt_conn_cache_pool_destroy(WT_SESSION_IMPL *session)
/* Notify other participants if we were managing */
if (FLD_ISSET(cache->pool_flags, WT_CACHE_POOL_MANAGER)) {
cp->pool_managed = 0;
- __wt_verbose(session, WT_VERB_SHARED_CACHE,
+ __wt_verbose(session, WT_VERB_SHARED_CACHE, "%s",
"Shutting down shared cache manager connection");
}
}
@@ -585,8 +585,8 @@ __cache_pool_adjust(WT_SESSION_IMPL *session,
if (WT_VERBOSE_ISSET(session, WT_VERB_SHARED_CACHE)) {
__wt_verbose(session,
- WT_VERB_SHARED_CACHE, "Cache pool distribution: ");
- __wt_verbose(session, WT_VERB_SHARED_CACHE,
+ WT_VERB_SHARED_CACHE, "%s", "Cache pool distribution: ");
+ __wt_verbose(session, WT_VERB_SHARED_CACHE, "%s",
"\t" "cache (MB), pressure, skips, busy, %% full:");
}
@@ -731,7 +731,7 @@ __cache_pool_adjust(WT_SESSION_IMPL *session,
cp->currently_used -= adjustment;
}
__wt_verbose(session, WT_VERB_SHARED_CACHE,
- "Allocated %s%" PRId64 " to %s",
+ "Allocated %s%" PRIu64 " to %s",
grow ? "" : "-", adjustment, entry->home);
/*
@@ -778,7 +778,7 @@ __wt_cache_pool_server(void *arg)
if (__wt_atomic_cas8(&cp->pool_managed, 0, 1)) {
FLD_SET(cache->pool_flags, WT_CACHE_POOL_MANAGER);
__wt_verbose(session, WT_VERB_SHARED_CACHE,
- "Cache pool switched manager thread");
+ "%s", "Cache pool switched manager thread");
}
/*
diff --git a/src/third_party/wiredtiger/src/conn/conn_log.c b/src/third_party/wiredtiger/src/conn/conn_log.c
index 37acbe4a1a4..a6290e4ed92 100644
--- a/src/third_party/wiredtiger/src/conn/conn_log.c
+++ b/src/third_party/wiredtiger/src/conn/conn_log.c
@@ -40,6 +40,114 @@ __logmgr_sync_cfg(WT_SESSION_IMPL *session, const char **cfg)
}
/*
+ * __logmgr_force_ckpt --
+ * Force a checkpoint out, waiting for the checkpoint LSN in the log
+ * is up to the given log number.
+ */
+static int
+__logmgr_force_ckpt(WT_SESSION_IMPL *session, uint32_t lognum)
+{
+ WT_CONNECTION_IMPL *conn;
+ WT_LOG *log;
+ WT_SESSION_IMPL *tmp_session;
+ int yield;
+
+ conn = S2C(session);
+ log = conn->log;
+ yield = 0;
+ WT_RET(__wt_open_internal_session(conn,
+ "compatibility-reconfig", true, 0, &tmp_session));
+ while (log->ckpt_lsn.l.file < lognum) {
+ /*
+ * Force a checkpoint to be written in the new log file and
+ * force the archiving of all previous log files. We do the
+ * checkpoint in the loop because the checkpoint LSN in the
+ * log record could still reflect the previous log file in
+ * cases such as the write LSN has not yet advanced into the
+ * new log file due to another group of threads still in
+ * progress with their slot copies or writes.
+ */
+ WT_RET(tmp_session->iface.checkpoint(
+ &tmp_session->iface, "force=1"));
+ WT_RET(WT_SESSION_CHECK_PANIC(tmp_session));
+ /*
+ * Only sleep in the rare case that we had to come through
+ * this loop more than once.
+ */
+ if (yield++) {
+ WT_STAT_CONN_INCR(session, log_force_ckpt_sleep);
+ __wt_sleep(0, WT_THOUSAND);
+ }
+ }
+ WT_RET(tmp_session->iface.close(&tmp_session->iface, NULL));
+ return (0);
+}
+
+/*
+ * __logmgr_version --
+ * Set up the versions in the log manager.
+ */
+static int
+__logmgr_version(WT_SESSION_IMPL *session, bool reconfig)
+{
+ WT_CONNECTION_IMPL *conn;
+ WT_LOG *log;
+ bool downgrade;
+ uint32_t first_record, lognum;
+ uint16_t new_version;
+
+ conn = S2C(session);
+ log = conn->log;
+ if (log == NULL)
+ return (0);
+
+ /*
+ * Set the log file format versions based on compatibility versions
+ * set in the connection. We must set this before we call log_open
+ * to open or create a log file.
+ *
+ * Since the log version changed at a major release number we only need
+ * to check the major number, not the minor number in the compatibility
+ * setting.
+ */
+ if (conn->compat_major < WT_LOG_V2) {
+ new_version = 1;
+ first_record = WT_LOG_END_HEADER;
+ downgrade = true;
+ } else {
+ new_version = WT_LOG_VERSION;
+ first_record = WT_LOG_END_HEADER + log->allocsize;
+ downgrade = false;
+ }
+
+ /*
+ * If the version is the same, there is nothing to do.
+ */
+ if (log->log_version == new_version)
+ return (0);
+ /*
+ * If we are reconfiguring and at a new version we need to force
+ * the log file to advance so that we write out a log file at the
+ * correct version. When we are downgrading we must force a checkpoint
+ * and finally archive, even if disabled, so that all new version log
+ * files are gone.
+ *
+ * All of the version changes must be handled with locks on reconfigure
+ * because other threads may be changing log files, using pre-allocated
+ * files.
+ */
+ /*
+ * Set the version. If it is a live change the logging subsystem will
+ * do other work as well to move to a new log file.
+ */
+ WT_RET(__wt_log_set_version(session, new_version,
+ first_record, downgrade, reconfig, &lognum));
+ if (reconfig && FLD_ISSET(conn->log_flags, WT_CONN_LOG_DOWNGRADED))
+ WT_RET(__logmgr_force_ckpt(session, lognum));
+ return (0);
+}
+
+/*
* __logmgr_config --
* Parse and setup the logging server options.
*/
@@ -187,7 +295,8 @@ __wt_logmgr_reconfig(WT_SESSION_IMPL *session, const char **cfg)
{
bool dummy;
- return (__logmgr_config(session, cfg, &dummy, true));
+ WT_RET(__logmgr_config(session, cfg, &dummy, true));
+ return (__logmgr_version(session, true));
}
/*
@@ -329,19 +438,17 @@ err: __wt_err(session, ret, "log pre-alloc server error");
* currently running.
*/
int
-__wt_log_truncate_files(
- WT_SESSION_IMPL *session, WT_CURSOR *cursor, const char *cfg[])
+__wt_log_truncate_files(WT_SESSION_IMPL *session, WT_CURSOR *cursor, bool force)
{
WT_CONNECTION_IMPL *conn;
WT_DECL_RET;
WT_LOG *log;
uint32_t backup_file;
- WT_UNUSED(cfg);
conn = S2C(session);
if (!FLD_ISSET(conn->log_flags, WT_CONN_LOG_ENABLED))
return (0);
- if (F_ISSET(conn, WT_CONN_SERVER_LOG) &&
+ if (!force && F_ISSET(conn, WT_CONN_SERVER_LOG) &&
FLD_ISSET(conn->log_flags, WT_CONN_LOG_ARCHIVE))
WT_RET_MSG(session, EINVAL,
"Attempt to archive manually while a server is running");
@@ -349,8 +456,10 @@ __wt_log_truncate_files(
log = conn->log;
backup_file = 0;
- if (cursor != NULL)
+ if (cursor != NULL) {
+ WT_ASSERT(session, force == false);
backup_file = WT_CURSOR_BACKUP_ID(cursor);
+ }
WT_ASSERT(session, backup_file <= log->alloc_lsn.l.file);
__wt_verbose(session, WT_VERB_LOG,
"log_truncate_files: Archive once up to %" PRIu32, backup_file);
@@ -828,7 +937,7 @@ __log_server(void *arg)
session, &log->log_archive_lock);
WT_ERR(ret);
} else
- __wt_verbose(session, WT_VERB_LOG,
+ __wt_verbose(session, WT_VERB_LOG, "%s",
"log_archive: Blocked due to open "
"log cursor holding archive lock");
}
@@ -875,6 +984,7 @@ __wt_logmgr_create(WT_SESSION_IMPL *session, const char *cfg[])
WT_RET(__wt_calloc_one(session, &conn->log));
log = conn->log;
WT_RET(__wt_spin_init(session, &log->log_lock, "log"));
+ WT_RET(__wt_spin_init(session, &log->log_fs_lock, "log files"));
WT_RET(__wt_spin_init(session, &log->log_slot_lock, "log slot"));
WT_RET(__wt_spin_init(session, &log->log_sync_lock, "log sync"));
WT_RET(__wt_spin_init(session, &log->log_writelsn_lock,
@@ -898,6 +1008,8 @@ __wt_logmgr_create(WT_SESSION_IMPL *session, const char *cfg[])
WT_INIT_LSN(&log->write_lsn);
WT_INIT_LSN(&log->write_start_lsn);
log->fileid = 0;
+ WT_RET(__logmgr_version(session, false));
+
WT_RET(__wt_cond_alloc(session, "log sync", &log->log_sync_cond));
WT_RET(__wt_cond_alloc(session, "log write", &log->log_write_cond));
WT_RET(__wt_log_open(session));
@@ -1050,6 +1162,7 @@ __wt_logmgr_destroy(WT_SESSION_IMPL *session)
__wt_cond_destroy(session, &conn->log->log_write_cond);
__wt_rwlock_destroy(session, &conn->log->log_archive_lock);
__wt_spin_destroy(session, &conn->log->log_lock);
+ __wt_spin_destroy(session, &conn->log->log_fs_lock);
__wt_spin_destroy(session, &conn->log->log_slot_lock);
__wt_spin_destroy(session, &conn->log->log_sync_lock);
__wt_spin_destroy(session, &conn->log->log_writelsn_lock);
diff --git a/src/third_party/wiredtiger/src/conn/conn_stat.c b/src/third_party/wiredtiger/src/conn/conn_stat.c
index f38d81a7f7a..4559a72a46e 100644
--- a/src/third_party/wiredtiger/src/conn/conn_stat.c
+++ b/src/third_party/wiredtiger/src/conn/conn_stat.c
@@ -221,6 +221,101 @@ err: __stat_sources_free(session, &sources);
}
/*
+ * __statlog_print_header --
+ * Write the header for statistics when running in JSON mode.
+ */
+static int
+__statlog_print_header(WT_SESSION_IMPL *session)
+{
+ WT_CONNECTION_IMPL *conn;
+
+ conn = S2C(session);
+
+ if (!FLD_ISSET(conn->stat_flags, WT_STAT_JSON))
+ return (0);
+
+ /*
+ * This flag is required in order to generate correct JSON when printing
+ * out stats for individual tables. When we are about to print the first
+ * table's stats we must print out the wiredTigerTables header once
+ * only and add a correct closing brace when we finish the tables
+ * section. To do this we maintain a flag variable to note when we have
+ * printed the first table. Unfortunately, the mechanism which we use
+ * to print stats for each table does not allow passing of variables
+ * by reference, this necessitates the use of a variable on the
+ * connection. The variable is safe as the JSON printing logic is only
+ * performed by the single threaded stat server.
+ */
+ conn->stat_json_tables = false;
+ WT_RET(__wt_fprintf(session, conn->stat_fs,
+ "{\"version\":\"%s\",\"localTime\":\"%s\"",
+ WIREDTIGER_VERSION_STRING, conn->stat_stamp));
+ return (0);
+}
+
+/*
+ * __statlog_print_table_name --
+ * Write the header for the wiredTigerTables section of statistics if
+ * running in JSON mode and the header has not been written this round,
+ * then print the name of the table.
+ */
+static int
+__statlog_print_table_name(
+ WT_SESSION_IMPL *session, const char *name, bool conn_stats)
+{
+ WT_CONNECTION_IMPL *conn;
+
+ conn = S2C(session);
+
+ /*
+ * If printing the connection stats, write that header and we are done.
+ */
+ if (conn_stats) {
+ WT_RET(__wt_fprintf(
+ session, conn->stat_fs, ",\"wiredTiger\":{"));
+ return (0);
+ }
+
+ /*
+ * If this is the first table we are printing stats for print the header
+ * for the wiredTigerTables section. Otherwise print a comma as this
+ * is a subsequent table.
+ */
+ if (conn->stat_json_tables)
+ WT_RET(__wt_fprintf(session, conn->stat_fs,","));
+ else {
+ conn->stat_json_tables = true;
+ WT_RET(__wt_fprintf(session,
+ conn->stat_fs,",\"wiredTigerTables\":{"));
+ }
+ WT_RET(__wt_fprintf(session, conn->stat_fs, "\"%s\":{", name));
+ return (0);
+}
+
+/*
+ * __statlog_print_footer --
+ * Write the footer for statistics when running in JSON mode.
+ */
+static int
+__statlog_print_footer(WT_SESSION_IMPL *session)
+{
+ WT_CONNECTION_IMPL *conn;
+
+ conn = S2C(session);
+
+ if (!FLD_ISSET(conn->stat_flags, WT_STAT_JSON))
+ return (0);
+
+ /* If we have printed a tables stats, then close that section. */
+ if (conn->stat_json_tables) {
+ WT_RET(__wt_fprintf(session, conn->stat_fs, "}"));
+ conn->stat_json_tables = false;
+ }
+ WT_RET(__wt_fprintf(session, conn->stat_fs, "}\n"));
+ return (0);
+}
+
+/*
* __statlog_dump --
* Dump out handle/connection statistics.
*/
@@ -264,14 +359,10 @@ __statlog_dump(WT_SESSION_IMPL *session, const char *name, bool conn_stats)
goto err;
}
- if (FLD_ISSET(conn->stat_flags, WT_STAT_JSON)) {
- WT_ERR(__wt_fprintf(session, conn->stat_fs,
- "{\"version\":\"%s\",\"localTime\":\"%s\"",
- WIREDTIGER_VERSION_STRING, conn->stat_stamp));
- WT_ERR(__wt_fprintf(
- session, conn->stat_fs, ",\"wiredTiger\":{"));
- while ((ret = cursor->next(cursor)) == 0) {
- WT_ERR(cursor->get_value(cursor, &desc, &valstr, &val));
+ WT_ERR(__statlog_print_table_name(session, name, conn_stats));
+ while ((ret = cursor->next(cursor)) == 0) {
+ WT_ERR(cursor->get_value(cursor, &desc, &valstr, &val));
+ if (FLD_ISSET(conn->stat_flags, WT_STAT_JSON)) {
/* Check if we are starting a new section. */
endprefix = strchr(desc, ':');
prefixlen = WT_PTRDIFF(endprefix, desc);
@@ -291,18 +382,15 @@ __statlog_dump(WT_SESSION_IMPL *session, const char *name, bool conn_stats)
"%s\"%s\":%" PRId64,
groupfirst ? "" : ",", endprefix + 2, val));
groupfirst = false;
- }
- WT_ERR_NOTFOUND_OK(ret);
- WT_ERR(__wt_fprintf(session, conn->stat_fs, "}}}\n"));
- } else {
- while ((ret = cursor->next(cursor)) == 0) {
- WT_ERR(cursor->get_value(cursor, &desc, &valstr, &val));
+ } else {
WT_ERR(__wt_fprintf(session, conn->stat_fs,
"%s %" PRId64 " %s %s\n",
conn->stat_stamp, val, name, desc));
}
- WT_ERR_NOTFOUND_OK(ret);
}
+ WT_ERR_NOTFOUND_OK(ret);
+ if (FLD_ISSET(conn->stat_flags, WT_STAT_JSON))
+ WT_ERR(__wt_fprintf(session, conn->stat_fs, "}}"));
err: __wt_scr_free(session, &tmp);
if (cursor != NULL)
@@ -437,6 +525,7 @@ __statlog_log_one(WT_SESSION_IMPL *session, WT_ITEM *path, WT_ITEM *tmp)
if (strftime(tmp->mem, tmp->memsize, conn->stat_format, tm) == 0)
WT_RET_MSG(session, ENOMEM, "strftime timestamp conversion");
conn->stat_stamp = tmp->mem;
+ WT_RET(__statlog_print_header(session));
/* Dump the connection statistics. */
WT_RET(__statlog_dump(session, conn->home, true));
@@ -459,6 +548,7 @@ __statlog_log_one(WT_SESSION_IMPL *session, WT_ITEM *path, WT_ITEM *tmp)
*/
if (conn->stat_sources != NULL)
WT_RET(__statlog_lsm_apply(session));
+ WT_RET(__statlog_print_footer(session));
/* Flush. */
return (__wt_fflush(session, conn->stat_fs));
diff --git a/src/third_party/wiredtiger/src/cursor/cur_backup.c b/src/third_party/wiredtiger/src/cursor/cur_backup.c
index 60750b88900..490c3813cad 100644
--- a/src/third_party/wiredtiger/src/cursor/cur_backup.c
+++ b/src/third_party/wiredtiger/src/cursor/cur_backup.c
@@ -210,6 +210,8 @@ __backup_start(
cb->list = NULL;
cb->list_next = 0;
+ WT_RET(__wt_inmem_unsupported_op(session, "backup cursor"));
+
/*
* Single thread hot backups: we're holding the schema lock, so we
* know we'll serialize with other attempts to start a hot backup.
diff --git a/src/third_party/wiredtiger/src/cursor/cur_log.c b/src/third_party/wiredtiger/src/cursor/cur_log.c
index 38e9d4a1784..d1166c5d402 100644
--- a/src/third_party/wiredtiger/src/cursor/cur_log.c
+++ b/src/third_party/wiredtiger/src/cursor/cur_log.c
@@ -303,7 +303,6 @@ __curlog_close(WT_CURSOR *cursor)
cl = (WT_CURSOR_LOG *)cursor;
conn = S2C(session);
- WT_ASSERT(session, FLD_ISSET(conn->log_flags, WT_CONN_LOG_ENABLED));
if (F_ISSET(cl, WT_CURLOG_ARCHIVE_LOCK))
__wt_readunlock(session, &conn->log->log_archive_lock);
@@ -355,9 +354,6 @@ __wt_curlog_open(WT_SESSION_IMPL *session,
WT_STATIC_ASSERT(offsetof(WT_CURSOR_LOG, iface) == 0);
conn = S2C(session);
- if (!FLD_ISSET(conn->log_flags, WT_CONN_LOG_ENABLED))
- WT_RET_MSG(session, EINVAL,
- "Cannot open a log cursor without logging enabled");
log = conn->log;
cl = NULL;
@@ -378,15 +374,17 @@ __wt_curlog_open(WT_SESSION_IMPL *session,
WT_ERR(__wt_cursor_init(cursor, uri, NULL, cfg, cursorp));
- /*
- * The user may be trying to read a log record they just wrote.
- * Log records may be buffered, so force out any now.
- */
- WT_ERR(__wt_log_force_write(session, 1, NULL));
+ if (log != NULL) {
+ /*
+ * The user may be trying to read a log record they just wrote.
+ * Log records may be buffered, so force out any now.
+ */
+ WT_ERR(__wt_log_force_write(session, 1, NULL));
- /* Log cursors block archiving. */
- __wt_readlock(session, &log->log_archive_lock);
- F_SET(cl, WT_CURLOG_ARCHIVE_LOCK);
+ /* Log cursors block archiving. */
+ __wt_readlock(session, &log->log_archive_lock);
+ F_SET(cl, WT_CURLOG_ARCHIVE_LOCK);
+ }
if (0) {
err: WT_TRET(__curlog_close(cursor));
diff --git a/src/third_party/wiredtiger/src/docs/upgrading.dox b/src/third_party/wiredtiger/src/docs/upgrading.dox
index 8640991e7cd..fc0fc4e022a 100644
--- a/src/third_party/wiredtiger/src/docs/upgrading.dox
+++ b/src/third_party/wiredtiger/src/docs/upgrading.dox
@@ -1,6 +1,29 @@
/*! @page upgrading Upgrading WiredTiger applications
-@section version_293 Upgrading to Version 2.9.3
+@section version_300 Upgrading to Version 3.0.0
+<dl>
+
+<dt>WiredTiger on-disk log file format change</dt>
+<dd>
+The WiredTiger on-disk file format for write-ahead log files has changed
+to include a new internal system log record.
+</dd>
+
+<dt>Addition of compatibility configuration setting</dt>
+<dd>
+There is now a compatibility setting that allows the user to upgrade or
+downgrade the log files generated so that they can be run with an older
+release.
+</dd>
+
+<dt>Cached overflow record statistics</dt>
+<dd>
+The \c cache_overflow_value ("overflow values cached in memory") statistic
+has been removed, it no longer has any meaning.
+</dd>
+
+</dl><hr>
+@section version_292 Upgrading to Version 2.9.2
<dl>
<dt>Logging subsystem statistics</dt>
@@ -12,11 +35,7 @@ are no longer present. They were duplicates of \c log_writes and
been added.
</dd>
-</dl><hr>
-@section version_292 Upgrading to Version 2.9.2
-<dl>
-
-<dt>WiredTiger utility now supports truncate</dt>
+<dt>WiredTiger Utility now supports truncate</dt>
<dd>
The WiredTiger utility \c wt can now \c truncate objects, removing all
contents from the specified object.
diff --git a/src/third_party/wiredtiger/src/evict/evict_lru.c b/src/third_party/wiredtiger/src/evict/evict_lru.c
index 4f4ecdf286c..1f26949c94f 100644
--- a/src/third_party/wiredtiger/src/evict/evict_lru.c
+++ b/src/third_party/wiredtiger/src/evict/evict_lru.c
@@ -305,12 +305,14 @@ __wt_evict_thread_run(WT_SESSION_IMPL *session, WT_THREAD *thread)
F_ISSET(thread, WT_THREAD_RUN))
__wt_yield();
else {
- __wt_verbose(session, WT_VERB_EVICTSERVER, "sleeping");
+ __wt_verbose(session,
+ WT_VERB_EVICTSERVER, "%s", "sleeping");
/* Don't rely on signals: check periodically. */
__wt_cond_auto_wait(session,
cache->evict_cond, did_work, NULL);
- __wt_verbose(session, WT_VERB_EVICTSERVER, "waking");
+ __wt_verbose(session,
+ WT_VERB_EVICTSERVER, "%s", "waking");
}
} else
WT_ERR(__evict_lru_pages(session, false));
@@ -351,8 +353,8 @@ __wt_evict_thread_stop(WT_SESSION_IMPL *session, WT_THREAD *thread)
*/
WT_ASSERT(session, F_ISSET(conn, WT_CONN_CLOSING | WT_CONN_RECOVERING));
- __wt_verbose(
- session, WT_VERB_EVICTSERVER, "cache eviction thread exiting");
+ __wt_verbose(session,
+ WT_VERB_EVICTSERVER, "%s", "cache eviction thread exiting");
if (0) {
err: WT_PANIC_MSG(session, ret, "cache eviction thread error");
@@ -515,7 +517,7 @@ __wt_evict_destroy(WT_SESSION_IMPL *session)
__wt_evict_server_wake(session);
__wt_verbose(
- session, WT_VERB_EVICTSERVER, "waiting for helper threads");
+ session, WT_VERB_EVICTSERVER, "%s", "waiting for helper threads");
/*
* We call the destroy function still holding the write lock.
@@ -740,7 +742,7 @@ __evict_pass(WT_SESSION_IMPL *session)
WT_STAT_CONN_INCR(session, cache_eviction_slow);
__wt_verbose(session, WT_VERB_EVICTSERVER,
- "unable to reach eviction goal");
+ "%s", "unable to reach eviction goal");
break;
} else {
if (cache->evict_aggressive_score > 0) {
@@ -779,6 +781,7 @@ __evict_clear_walk(WT_SESSION_IMPL *session)
return (0);
WT_STAT_CONN_INCR(session, cache_eviction_walks_abandoned);
+ WT_STAT_DATA_INCR(session, cache_eviction_walks_abandoned);
/*
* Clear evict_ref before releasing it in case that forces eviction (we
@@ -957,6 +960,13 @@ __evict_tune_workers(WT_SESSION_IMPL *session)
conn = S2C(session);
cache = conn->cache;
+ /*
+ * If we have a fixed number of eviction threads, there is no value in
+ * calculating if we should do any tuning.
+ */
+ if (conn->evict_threads_max == conn->evict_threads_min)
+ return;
+
WT_ASSERT(session, conn->evict_threads.threads[0]->session == session);
pgs_evicted_cur = 0;
@@ -1106,8 +1116,8 @@ __evict_tune_workers(WT_SESSION_IMPL *session)
&conn->evict_threads, false);
WT_STAT_CONN_INCR(session,
cache_eviction_worker_created);
- __wt_verbose(session, WT_VERB_EVICTSERVER,
- "added worker thread");
+ __wt_verbose(session,
+ WT_VERB_EVICTSERVER, "%s", "added worker thread");
}
conn->evict_tune_last_action_time = current_time;
}
@@ -1641,26 +1651,16 @@ __evict_walk_file(WT_SESSION_IMPL *session,
QUEUE_FILLS_PER_PASS;
/*
- * Randomly walk trees with a small fraction of the cache in case there
- * are so many trees that none of them use enough of the cache to be
- * allocated slots.
- *
- * The chance of walking a tree is equal to the chance that a random
- * byte in cache belongs to the tree, weighted by how many times we
- * want to fill queues during a pass through all the trees in cache.
+ * Walk trees with a small fraction of the cache in case there are so
+ * many trees that none of them use enough of the cache to be allocated
+ * slots. Only skip a tree if it has no bytes of interest.
*/
if (target_pages == 0) {
- if (F_ISSET(cache, WT_CACHE_EVICT_CLEAN)) {
- btree_inuse = __wt_btree_bytes_evictable(session);
- cache_inuse = __wt_cache_bytes_inuse(cache);
- } else {
- btree_inuse = __wt_btree_dirty_leaf_inuse(session);
- cache_inuse = __wt_cache_dirty_leaf_inuse(cache);
- }
- if (btree_inuse == 0 || cache_inuse == 0)
- return (0);
- if (__wt_random64(&session->rnd) % cache_inuse >
- btree_inuse * QUEUE_FILLS_PER_PASS)
+ btree_inuse = F_ISSET(cache, WT_CACHE_EVICT_CLEAN) ?
+ __wt_btree_bytes_evictable(session) :
+ __wt_btree_dirty_leaf_inuse(session);
+
+ if (btree_inuse == 0)
return (0);
}
@@ -1678,6 +1678,32 @@ __evict_walk_file(WT_SESSION_IMPL *session,
if (F_ISSET(session->dhandle, WT_DHANDLE_DEAD) ||
target_pages > remaining_slots)
target_pages = remaining_slots;
+
+ /*
+ * These statistics generate a histogram of the number of pages targeted
+ * for eviction each round. The range of values here start at
+ * MIN_PAGES_PER_TREE as this is the smallest number of pages we can
+ * target, unless there are fewer slots available. The aim is to cover
+ * the likely ranges of target pages in as few statistics as possible to
+ * reduce the overall overhead.
+ */
+ if (target_pages < MIN_PAGES_PER_TREE) {
+ WT_STAT_CONN_INCR(session, cache_eviction_target_page_lt10);
+ WT_STAT_DATA_INCR(session, cache_eviction_target_page_lt10);
+ } else if (target_pages < 32) {
+ WT_STAT_CONN_INCR(session, cache_eviction_target_page_lt32);
+ WT_STAT_DATA_INCR(session, cache_eviction_target_page_lt32);
+ } else if (target_pages < 64) {
+ WT_STAT_CONN_INCR(session, cache_eviction_target_page_lt64);
+ WT_STAT_DATA_INCR(session, cache_eviction_target_page_lt64);
+ } else if (target_pages < 128) {
+ WT_STAT_CONN_INCR(session, cache_eviction_target_page_lt128);
+ WT_STAT_DATA_INCR(session, cache_eviction_target_page_lt128);
+ } else {
+ WT_STAT_CONN_INCR(session, cache_eviction_target_page_ge128);
+ WT_STAT_DATA_INCR(session, cache_eviction_target_page_ge128);
+ }
+
end = start + target_pages;
/*
@@ -1690,6 +1716,14 @@ __evict_walk_file(WT_SESSION_IMPL *session,
!F_ISSET(cache, WT_CACHE_EVICT_CLEAN))
min_pages *= 10;
+ if (btree->evict_ref == NULL) {
+ WT_STAT_CONN_INCR(session, cache_eviction_walk_from_root);
+ WT_STAT_DATA_INCR(session, cache_eviction_walk_from_root);
+ } else {
+ WT_STAT_CONN_INCR(session, cache_eviction_walk_saved_pos);
+ WT_STAT_DATA_INCR(session, cache_eviction_walk_saved_pos);
+ }
+
walk_flags =
WT_READ_CACHE | WT_READ_NO_EVICT | WT_READ_NO_GEN | WT_READ_NO_WAIT;
@@ -1760,12 +1794,37 @@ __evict_walk_file(WT_SESSION_IMPL *session,
btree->evict_start_type =
(btree->evict_start_type + 1) %
WT_EVICT_WALK_START_NUM;
+ /*
+ * We differentiate the reasons we gave up on this walk
+ * and increment the stats accordingly.
+ */
+ if (pages_queued == 0) {
+ WT_STAT_CONN_INCR(session,
+ cache_eviction_walks_gave_up_no_targets);
+ WT_STAT_DATA_INCR(session,
+ cache_eviction_walks_gave_up_no_targets);
+ } else {
+ WT_STAT_CONN_INCR(session,
+ cache_eviction_walks_gave_up_ratio);
+ WT_STAT_DATA_INCR(session,
+ cache_eviction_walks_gave_up_ratio);
+ }
break;
}
if (ref == NULL) {
- if (++restarts == 2)
+ WT_STAT_CONN_INCR(
+ session, cache_eviction_walks_ended);
+ WT_STAT_DATA_INCR(
+ session, cache_eviction_walks_ended);
+
+ if (++restarts == 2) {
+ WT_STAT_CONN_INCR(
+ session, cache_eviction_walks_stopped);
+ WT_STAT_DATA_INCR(
+ session, cache_eviction_walks_stopped);
break;
+ }
WT_STAT_CONN_INCR(
session, cache_eviction_walks_started);
continue;
@@ -1919,6 +1978,9 @@ fast: /* If the page can't be evicted, give up. */
WT_STAT_CONN_INCRV(session, cache_eviction_walk, refs_walked);
WT_STAT_CONN_INCRV(session, cache_eviction_pages_seen, pages_seen);
+ WT_STAT_DATA_INCRV(session, cache_eviction_pages_seen, pages_seen);
+ WT_STAT_CONN_INCRV(session, cache_eviction_walk_passes, 1);
+ WT_STAT_DATA_INCRV(session, cache_eviction_walk_passes, 1);
return (0);
}
diff --git a/src/third_party/wiredtiger/src/evict/evict_stat.c b/src/third_party/wiredtiger/src/evict/evict_stat.c
index 276e737ebbb..63d0aff60f1 100644
--- a/src/third_party/wiredtiger/src/evict/evict_stat.c
+++ b/src/third_party/wiredtiger/src/evict/evict_stat.c
@@ -16,28 +16,30 @@ static void
__evict_stat_walk(WT_SESSION_IMPL *session)
{
WT_BTREE *btree;
+ WT_CACHE *cache;
WT_PAGE *page;
WT_REF *next_walk;
- uint64_t dsk_size, gen_gap, size;
- uint64_t written_size_cnt, written_size_sum;
- uint64_t gen_gap_cnt, gen_gap_max, gen_gap_sum;
- uint64_t max_pagesize, min_written_size;
- uint64_t num_memory, num_queued, num_not_queueable, num_smaller_allocsz;
- uint64_t pages_clean, pages_dirty, pages_internal, pages_leaf;
- uint64_t seen_count, walk_count;
+ uint64_t dsk_size, gen_gap, gen_gap_max, gen_gap_sum, max_pagesize;
+ uint64_t min_written_size, num_memory, num_not_queueable, num_queued;
+ uint64_t num_smaller_allocsz, pages_clean, pages_dirty, pages_internal;
+ uint64_t pages_leaf, seen_count, size, visited_count;
+ uint64_t visited_age_gap_sum, unvisited_count, unvisited_age_gap_sum;
+ uint64_t walk_count, written_size_cnt, written_size_sum;
btree = S2BT(session);
+ cache = S2C(session)->cache;
next_walk = NULL;
- written_size_cnt = written_size_sum = 0;
- gen_gap_cnt = gen_gap_max = gen_gap_sum = 0;
- max_pagesize = 0;
- num_memory = num_queued = num_not_queueable = num_smaller_allocsz = 0;
- pages_clean = pages_dirty = pages_internal = pages_leaf = 0;
- seen_count = walk_count = 0;
+ dsk_size = gen_gap = gen_gap_max = gen_gap_sum = max_pagesize = 0;
+ num_memory = num_not_queueable = num_queued = 0;
+ num_smaller_allocsz = pages_clean = pages_dirty = pages_internal = 0;
+ pages_leaf = seen_count = size = visited_count = 0;
+ visited_age_gap_sum = unvisited_count = unvisited_age_gap_sum = 0;
+ walk_count = written_size_cnt = written_size_sum = 0;
min_written_size = UINT64_MAX;
while (__wt_tree_walk_count(session, &next_walk, &walk_count,
- WT_READ_CACHE | WT_READ_NO_EVICT | WT_READ_NO_WAIT) == 0 &&
+ WT_READ_CACHE | WT_READ_NO_EVICT |
+ WT_READ_NO_GEN | WT_READ_NO_WAIT) == 0 &&
next_walk != NULL) {
++seen_count;
page = next_walk->page;
@@ -78,19 +80,29 @@ __evict_stat_walk(WT_SESSION_IMPL *session)
if (__wt_ref_is_root(next_walk))
continue;
- gen_gap =
- S2C(session)->cache->evict_pass_gen - page->evict_pass_gen;
- if (gen_gap > gen_gap_max)
- gen_gap_max = gen_gap;
- gen_gap_sum += gen_gap;
- ++gen_gap_cnt;
+ if (page->evict_pass_gen == 0) {
+ unvisited_age_gap_sum +=
+ (cache->evict_pass_gen - page->cache_create_gen);
+ ++unvisited_count;
+ } else {
+ visited_age_gap_sum +=
+ (cache->evict_pass_gen - page->cache_create_gen);
+ gen_gap = cache->evict_pass_gen - page->evict_pass_gen;
+ if (gen_gap > gen_gap_max)
+ gen_gap_max = gen_gap;
+ gen_gap_sum += gen_gap;
+ ++visited_count;
+ }
}
+ WT_STAT_DATA_SET(session, cache_state_gen_avg_gap,
+ visited_count == 0 ? 0 : gen_gap_sum / visited_count);
+ WT_STAT_DATA_SET(session, cache_state_avg_unvisited_age,
+ unvisited_count == 0 ? 0 : unvisited_age_gap_sum / unvisited_count);
+ WT_STAT_DATA_SET(session, cache_state_avg_visited_age,
+ visited_count == 0 ? 0 : visited_age_gap_sum / visited_count);
WT_STAT_DATA_SET(session, cache_state_avg_written_size,
written_size_cnt == 0 ? 0 : written_size_sum / written_size_cnt);
- WT_STAT_DATA_SET(session, cache_state_gen_avg_gap,
- gen_gap_cnt == 0 ? 0 : gen_gap_sum / gen_gap_cnt);
-
WT_STAT_DATA_SET(session, cache_state_gen_max_gap, gen_gap_max);
WT_STAT_DATA_SET(session, cache_state_max_pagesize, max_pagesize);
WT_STAT_DATA_SET(session,
@@ -98,8 +110,6 @@ __evict_stat_walk(WT_SESSION_IMPL *session)
WT_STAT_DATA_SET(session, cache_state_memory, num_memory);
WT_STAT_DATA_SET(session, cache_state_queued, num_queued);
WT_STAT_DATA_SET(session, cache_state_not_queueable, num_not_queueable);
- WT_STAT_DATA_SET(session,
- cache_state_smaller_alloc_size, num_smaller_allocsz);
WT_STAT_DATA_SET(session, cache_state_pages, walk_count);
WT_STAT_DATA_SET(session, cache_state_pages_clean, pages_clean);
WT_STAT_DATA_SET(session, cache_state_pages_dirty, pages_dirty);
@@ -107,6 +117,10 @@ __evict_stat_walk(WT_SESSION_IMPL *session)
WT_STAT_DATA_SET(session, cache_state_pages_leaf, pages_leaf);
WT_STAT_DATA_SET(session,
cache_state_refs_skipped, walk_count - seen_count);
+ WT_STAT_DATA_SET(session,
+ cache_state_smaller_alloc_size, num_smaller_allocsz);
+ WT_STAT_DATA_SET(session,
+ cache_state_unvisited_count, unvisited_count);
}
/*
diff --git a/src/third_party/wiredtiger/src/include/api.h b/src/third_party/wiredtiger/src/include/api.h
index 372ba063cd3..60ed31b64e8 100644
--- a/src/third_party/wiredtiger/src/include/api.h
+++ b/src/third_party/wiredtiger/src/include/api.h
@@ -13,7 +13,7 @@
(s)->dhandle = (dh); \
(s)->name = (s)->lastop = #h "." #n; \
WT_ERR(WT_SESSION_CHECK_PANIC(s)); \
- __wt_verbose((s), WT_VERB_API, "CALL: " #h ":" #n)
+ __wt_verbose((s), WT_VERB_API, "%s", "CALL: " #h ":" #n)
#define API_CALL_NOCONF(s, h, n, dh) do { \
API_SESSION_INIT(s, h, n, dh)
diff --git a/src/third_party/wiredtiger/src/include/bitstring.i b/src/third_party/wiredtiger/src/include/bitstring.i
index d3dc3bebd0f..a9ec91d49ff 100644
--- a/src/third_party/wiredtiger/src/include/bitstring.i
+++ b/src/third_party/wiredtiger/src/include/bitstring.i
@@ -171,16 +171,18 @@ __bit_ffc(uint8_t *bitf, uint64_t nbits, uint64_t *retp)
if (nbits == 0)
return (-1);
- for (byte = 0,
- stopbyte = __bit_byte(nbits - 1); byte <= stopbyte; ++byte)
+ for (byte = 0, stopbyte = __bit_byte(nbits - 1);; ++byte) {
if (bitf[byte] != 0xff) {
value = byte << 3;
for (lb = bitf[byte]; lb & 0x01; ++value, lb >>= 1)
;
break;
}
+ if (byte == stopbyte)
+ return (-1);
+ }
- if (byte > stopbyte || value >= nbits)
+ if (value >= nbits)
return (-1);
*retp = value;
@@ -201,16 +203,18 @@ __bit_ffs(uint8_t *bitf, uint64_t nbits, uint64_t *retp)
if (nbits == 0)
return (-1);
- for (byte = 0,
- stopbyte = __bit_byte(nbits - 1); byte <= stopbyte; ++byte)
+ for (byte = 0, stopbyte = __bit_byte(nbits - 1);; ++byte) {
if (bitf[byte] != 0) {
value = byte << 3;
for (lb = bitf[byte]; !(lb & 0x01); ++value, lb >>= 1)
;
break;
}
+ if (byte == stopbyte)
+ return (-1);
+ }
- if (byte > stopbyte || value >= nbits)
+ if (value >= nbits)
return (-1);
*retp = value;
@@ -227,13 +231,6 @@ __bit_getv(uint8_t *bitf, uint64_t entry, uint8_t width)
uint8_t value;
uint64_t bit;
-#define __BIT_GET(len, mask) \
- case len: \
- if (__bit_test(bitf, bit)) \
- value |= (mask); \
- ++bit \
- /* FALLTHROUGH */
-
value = 0;
bit = entry * width;
@@ -241,17 +238,50 @@ __bit_getv(uint8_t *bitf, uint64_t entry, uint8_t width)
* Fast-path single bytes, do repeated tests for the rest: we could
* slice-and-dice instead, but the compiler is probably going to do
* a better job than I will.
+ *
+ * The Berkeley version of this file uses a #define to compress this
+ * case statement. This code expands the case statement because gcc7
+ * complains about implicit fallthrough and doesn't support explicit
+ * fallthrough comments in macros.
*/
switch (width) {
case 8:
return (bitf[__bit_byte(bit)]);
- __BIT_GET(7, 0x40);
- __BIT_GET(6, 0x20);
- __BIT_GET(5, 0x10);
- __BIT_GET(4, 0x08);
- __BIT_GET(3, 0x04);
- __BIT_GET(2, 0x02);
- __BIT_GET(1, 0x01);
+ case 7:
+ if (__bit_test(bitf, bit))
+ value |= 0x40;
+ ++bit;
+ /* FALLTHROUGH */
+ case 6:
+ if (__bit_test(bitf, bit))
+ value |= 0x20;
+ ++bit;
+ /* FALLTHROUGH */
+ case 5:
+ if (__bit_test(bitf, bit))
+ value |= 0x10;
+ ++bit;
+ /* FALLTHROUGH */
+ case 4:
+ if (__bit_test(bitf, bit))
+ value |= 0x08;
+ ++bit;
+ /* FALLTHROUGH */
+ case 3:
+ if (__bit_test(bitf, bit))
+ value |= 0x04;
+ ++bit;
+ /* FALLTHROUGH */
+ case 2:
+ if (__bit_test(bitf, bit))
+ value |= 0x02;
+ ++bit;
+ /* FALLTHROUGH */
+ case 1:
+ if (__bit_test(bitf, bit))
+ value |= 0x01;
+ ++bit;
+ break;
}
return (value);
}
@@ -276,32 +306,70 @@ __bit_setv(uint8_t *bitf, uint64_t entry, uint8_t width, uint8_t value)
{
uint64_t bit;
-#define __BIT_SET(len, mask) \
- case len: \
- if (value & (mask)) \
- __bit_set(bitf, bit); \
- else \
- __bit_clear(bitf, bit); \
- ++bit \
- /* FALLTHROUGH */
-
bit = entry * width;
/*
* Fast-path single bytes, do repeated tests for the rest: we could
* slice-and-dice instead, but the compiler is probably going to do
* a better job than I will.
+ *
+ * The Berkeley version of this file uses a #define to compress this
+ * case statement. This code expands the case statement because gcc7
+ * complains about implicit fallthrough and doesn't support explicit
+ * fallthrough comments in macros.
*/
switch (width) {
case 8:
bitf[__bit_byte(bit)] = value;
return;
- __BIT_SET(7, 0x40);
- __BIT_SET(6, 0x20);
- __BIT_SET(5, 0x10);
- __BIT_SET(4, 0x08);
- __BIT_SET(3, 0x04);
- __BIT_SET(2, 0x02);
- __BIT_SET(1, 0x01);
+ case 7:
+ if (value & 0x40)
+ __bit_set(bitf, bit);
+ else
+ __bit_clear(bitf, bit);
+ ++bit;
+ /* FALLTHROUGH */
+ case 6:
+ if (value & 0x20)
+ __bit_set(bitf, bit);
+ else
+ __bit_clear(bitf, bit);
+ ++bit;
+ /* FALLTHROUGH */
+ case 5:
+ if (value & 0x10)
+ __bit_set(bitf, bit);
+ else
+ __bit_clear(bitf, bit);
+ ++bit;
+ /* FALLTHROUGH */
+ case 4:
+ if (value & 0x08)
+ __bit_set(bitf, bit);
+ else
+ __bit_clear(bitf, bit);
+ ++bit;
+ /* FALLTHROUGH */
+ case 3:
+ if (value & 0x04)
+ __bit_set(bitf, bit);
+ else
+ __bit_clear(bitf, bit);
+ ++bit;
+ /* FALLTHROUGH */
+ case 2:
+ if (value & 0x02)
+ __bit_set(bitf, bit);
+ else
+ __bit_clear(bitf, bit);
+ ++bit;
+ /* FALLTHROUGH */
+ case 1:
+ if (value & 0x01)
+ __bit_set(bitf, bit);
+ else
+ __bit_clear(bitf, bit);
+ ++bit;
+ break;
}
}
diff --git a/src/third_party/wiredtiger/src/include/btmem.h b/src/third_party/wiredtiger/src/include/btmem.h
index 54a03e5762c..e8d3307b013 100644
--- a/src/third_party/wiredtiger/src/include/btmem.h
+++ b/src/third_party/wiredtiger/src/include/btmem.h
@@ -162,32 +162,6 @@ struct __wt_ovfl_reuse {
};
/*
- * Overflow tracking for cached values: When a page is reconciled, we write new
- * K/V overflow items, and discard previous underlying blocks. If there's a
- * transaction in the system that needs to read the previous value, we have to
- * cache the old value until no running transaction needs it.
- */
-struct __wt_ovfl_txnc {
- uint64_t current; /* Maximum transaction ID at store */
-
- uint32_t value_offset; /* Overflow value offset */
- uint32_t value_size; /* Overflow value size */
- uint8_t addr_offset; /* Overflow addr offset */
- uint8_t addr_size; /* Overflow addr size */
-
- /*
- * The untyped address immediately follows the WT_OVFL_TXNC
- * structure, the untyped value immediately follows the address.
- */
-#define WT_OVFL_TXNC_ADDR(p) \
- ((void *)((uint8_t *)(p) + (p)->addr_offset))
-#define WT_OVFL_TXNC_VALUE(p) \
- ((void *)((uint8_t *)(p) + (p)->value_offset))
-
- WT_OVFL_TXNC *next[0]; /* Forward-linked skip list */
-};
-
-/*
* Lookaside table support: when a page is being reconciled for eviction and has
* updates that might be required by earlier readers in the system, the updates
* are written into a lookaside table, and restored as necessary if the page is
@@ -403,18 +377,20 @@ struct __wt_page_modify {
WT_OVFL_REUSE *ovfl_reuse[WT_SKIP_MAXDEPTH];
/*
- * Overflow value address/byte-string pairs cached until no
- * running transaction will possibly read them.
- */
- WT_OVFL_TXNC *ovfl_txnc[WT_SKIP_MAXDEPTH];
-
- /*
* Overflow key/value addresses to be discarded from the block
* manager after reconciliation completes successfully.
*/
WT_CELL **discard;
size_t discard_entries;
size_t discard_allocated;
+
+ /* Cached overflow value cell/update address pairs. */
+ struct {
+ WT_CELL *cell;
+ WT_UPDATE *upd;
+ } *remove;
+ size_t remove_allocated;
+ uint32_t remove_next;
} *ovfl_track;
#define WT_PAGE_LOCK(s, p) \
@@ -644,6 +620,7 @@ struct __wt_page {
/* This is the 64 byte boundary, try to keep hot fields above here. */
+ uint64_t cache_create_gen; /* Page create timestamp */
uint64_t evict_pass_gen; /* Eviction pass generation */
};
@@ -921,6 +898,10 @@ WT_PACKED_STRUCT_BEGIN(__wt_update)
#define WT_UPDATE_RESERVED 2
uint8_t type; /* type (one byte to conserve memory) */
+ /* The update includes a complete value. */
+#define WT_UPDATE_DATA_VALUE(upd) \
+ ((upd)->type == WT_UPDATE_STANDARD || (upd)->type == WT_UPDATE_DELETED)
+
/* The untyped value immediately follows the WT_UPDATE structure. */
#define WT_UPDATE_DATA(upd) \
((void *)((uint8_t *)(upd) + sizeof(WT_UPDATE)))
diff --git a/src/third_party/wiredtiger/src/include/btree.h b/src/third_party/wiredtiger/src/include/btree.h
index e0f7570b869..4d2a4f0c4d9 100644
--- a/src/third_party/wiredtiger/src/include/btree.h
+++ b/src/third_party/wiredtiger/src/include/btree.h
@@ -165,24 +165,25 @@ struct __wt_btree {
WT_SPINLOCK flush_lock; /* Lock to flush the tree's pages */
/* Flags values up to 0xff are reserved for WT_DHANDLE_* */
-#define WT_BTREE_BULK 0x000100 /* Bulk-load handle */
-#define WT_BTREE_CLOSED 0x000200 /* Handle closed */
-#define WT_BTREE_IGNORE_CACHE 0x000400 /* Cache-resident object */
-#define WT_BTREE_IN_MEMORY 0x000800 /* Cache-resident object */
-#define WT_BTREE_LOOKASIDE 0x001000 /* Look-aside table */
-#define WT_BTREE_NO_CHECKPOINT 0x002000 /* Disable checkpoints */
-#define WT_BTREE_NO_LOGGING 0x004000 /* Disable logging */
-#define WT_BTREE_REBALANCE 0x008000 /* Handle is for rebalance */
-#define WT_BTREE_SALVAGE 0x010000 /* Handle is for salvage */
-#define WT_BTREE_SKIP_CKPT 0x020000 /* Handle skipped checkpoint */
-#define WT_BTREE_UPGRADE 0x040000 /* Handle is for upgrade */
-#define WT_BTREE_VERIFY 0x080000 /* Handle is for verify */
+#define WT_BTREE_ALTER 0x000100 /* Handle is for alter */
+#define WT_BTREE_BULK 0x000200 /* Bulk-load handle */
+#define WT_BTREE_CLOSED 0x000400 /* Handle closed */
+#define WT_BTREE_IGNORE_CACHE 0x000800 /* Cache-resident object */
+#define WT_BTREE_IN_MEMORY 0x001000 /* Cache-resident object */
+#define WT_BTREE_LOOKASIDE 0x002000 /* Look-aside table */
+#define WT_BTREE_NO_CHECKPOINT 0x004000 /* Disable checkpoints */
+#define WT_BTREE_NO_LOGGING 0x008000 /* Disable logging */
+#define WT_BTREE_REBALANCE 0x010000 /* Handle is for rebalance */
+#define WT_BTREE_SALVAGE 0x020000 /* Handle is for salvage */
+#define WT_BTREE_SKIP_CKPT 0x040000 /* Handle skipped checkpoint */
+#define WT_BTREE_UPGRADE 0x080000 /* Handle is for upgrade */
+#define WT_BTREE_VERIFY 0x100000 /* Handle is for verify */
uint32_t flags;
};
/* Flags that make a btree handle special (not for normal use). */
#define WT_BTREE_SPECIAL_FLAGS \
- (WT_BTREE_BULK | WT_BTREE_REBALANCE | \
+ (WT_BTREE_ALTER | WT_BTREE_BULK | WT_BTREE_REBALANCE | \
WT_BTREE_SALVAGE | WT_BTREE_UPGRADE | WT_BTREE_VERIFY)
/*
diff --git a/src/third_party/wiredtiger/src/include/btree_cmp.i b/src/third_party/wiredtiger/src/include/btree_cmp.i
index c1354a7ea4b..db7af8daaed 100644
--- a/src/third_party/wiredtiger/src/include/btree_cmp.i
+++ b/src/third_party/wiredtiger/src/include/btree_cmp.i
@@ -217,23 +217,61 @@ __wt_lex_compare_short(const WT_ITEM *user_item, const WT_ITEM *tree_item)
/*
* The maximum packed uint64_t is 9B, catch row-store objects using
* packed record numbers as keys.
+ *
+ * Don't use a #define to compress this case statement: gcc7 complains
+ * about implicit fallthrough and doesn't support explicit fallthrough
+ * comments in macros.
*/
#define WT_COMPARE_SHORT_MAXLEN 9
-#undef WT_COMPARE_SHORT
-#define WT_COMPARE_SHORT(n) \
- case n: \
- if (*userp != *treep) \
- break; \
- ++userp, ++treep
switch (len) {
- WT_COMPARE_SHORT(9);
- WT_COMPARE_SHORT(8);
- WT_COMPARE_SHORT(7);
- WT_COMPARE_SHORT(6);
- WT_COMPARE_SHORT(5);
- WT_COMPARE_SHORT(4);
- WT_COMPARE_SHORT(3);
- WT_COMPARE_SHORT(2);
+ case 9:
+ if (*userp != *treep)
+ break;
+ ++userp;
+ ++treep;
+ /* FALLTHROUGH */
+ case 8:
+ if (*userp != *treep)
+ break;
+ ++userp;
+ ++treep;
+ /* FALLTHROUGH */
+ case 7:
+ if (*userp != *treep)
+ break;
+ ++userp;
+ ++treep;
+ /* FALLTHROUGH */
+ case 6:
+ if (*userp != *treep)
+ break;
+ ++userp;
+ ++treep;
+ /* FALLTHROUGH */
+ case 5:
+ if (*userp != *treep)
+ break;
+ ++userp;
+ ++treep;
+ /* FALLTHROUGH */
+ case 4:
+ if (*userp != *treep)
+ break;
+ ++userp;
+ ++treep;
+ /* FALLTHROUGH */
+ case 3:
+ if (*userp != *treep)
+ break;
+ ++userp;
+ ++treep;
+ /* FALLTHROUGH */
+ case 2:
+ if (*userp != *treep)
+ break;
+ ++userp;
+ ++treep;
+ /* FALLTHROUGH */
case 1:
if (*userp != *treep)
break;
diff --git a/src/third_party/wiredtiger/src/include/connection.h b/src/third_party/wiredtiger/src/include/connection.h
index 94abe48ffe5..7bd4a818495 100644
--- a/src/third_party/wiredtiger/src/include/connection.h
+++ b/src/third_party/wiredtiger/src/include/connection.h
@@ -184,6 +184,9 @@ struct __wt_connection_impl {
const char *error_prefix; /* Database error prefix */
int is_new; /* Connection created database */
+ uint16_t compat_major; /* Compatibility major version */
+ uint16_t compat_minor; /* Compatibility minor version */
+
WT_EXTENSION_API extension_api; /* Extension API */
/* Configuration */
@@ -302,18 +305,22 @@ struct __wt_connection_impl {
WT_CONDVAR *stat_cond; /* Statistics log wait mutex */
const char *stat_format; /* Statistics log timestamp format */
WT_FSTREAM *stat_fs; /* Statistics log stream */
+ /* Statistics log json table printing state flag */
+ bool stat_json_tables;
char *stat_path; /* Statistics log path format */
char **stat_sources; /* Statistics log list of objects */
const char *stat_stamp; /* Statistics log entry timestamp */
uint64_t stat_usecs; /* Statistics log period */
-#define WT_CONN_LOG_ARCHIVE 0x01 /* Archive is enabled */
-#define WT_CONN_LOG_ENABLED 0x02 /* Logging is enabled */
-#define WT_CONN_LOG_EXISTED 0x04 /* Log files found */
-#define WT_CONN_LOG_RECOVER_DIRTY 0x08 /* Recovering unclean */
-#define WT_CONN_LOG_RECOVER_DONE 0x10 /* Recovery completed */
-#define WT_CONN_LOG_RECOVER_ERR 0x20 /* Error if recovery required */
-#define WT_CONN_LOG_ZERO_FILL 0x40 /* Manually zero files */
+#define WT_CONN_LOG_ARCHIVE 0x001 /* Archive is enabled */
+#define WT_CONN_LOG_DOWNGRADED 0x002 /* Running older version */
+#define WT_CONN_LOG_ENABLED 0x004 /* Logging is enabled */
+#define WT_CONN_LOG_EXISTED 0x008 /* Log files found */
+#define WT_CONN_LOG_FORCE_DOWNGRADE 0x010 /* Force downgrade */
+#define WT_CONN_LOG_RECOVER_DIRTY 0x020 /* Recovering unclean */
+#define WT_CONN_LOG_RECOVER_DONE 0x040 /* Recovery completed */
+#define WT_CONN_LOG_RECOVER_ERR 0x080 /* Error if recovery required */
+#define WT_CONN_LOG_ZERO_FILL 0x100 /* Manually zero files */
uint32_t log_flags; /* Global logging configuration */
WT_CONDVAR *log_cond; /* Log server wait mutex */
WT_SESSION_IMPL *log_session; /* Log server session */
diff --git a/src/third_party/wiredtiger/src/include/error.h b/src/third_party/wiredtiger/src/include/error.h
index 465ab4fa859..2d302fb6879 100644
--- a/src/third_party/wiredtiger/src/include/error.h
+++ b/src/third_party/wiredtiger/src/include/error.h
@@ -124,3 +124,28 @@
#define WT_ASSERT(session, exp) \
WT_UNUSED(session)
#endif
+
+/*
+ * __wt_verbose --
+ * Display a verbose message.
+ *
+ * Not an inlined function because you can't inline functions taking variadic
+ * arguments and we don't want to make a function call in production systems
+ * just to find out a verbose flag isn't set.
+ *
+ * The macro must take a format string and at least one additional argument,
+ * there's no portable way to remove the comma before an empty __VA_ARGS__
+ * value.
+ */
+#ifdef HAVE_VERBOSE
+#define __wt_verbose(session, flag, fmt, ...) do { \
+ if (WT_VERBOSE_ISSET(session, flag)) \
+ __wt_verbose_worker(session, fmt, __VA_ARGS__); \
+} while (0)
+#else
+#define __wt_verbose(session, flag, fmt, ...) do { \
+ WT_UNUSED(session); \
+ WT_UNUSED(flag); \
+ WT_UNUSED(fmt); \
+} while (0)
+#endif
diff --git a/src/third_party/wiredtiger/src/include/extern.h b/src/third_party/wiredtiger/src/include/extern.h
index 59e853d75f4..8b48fd587bd 100644
--- a/src/third_party/wiredtiger/src/include/extern.h
+++ b/src/third_party/wiredtiger/src/include/extern.h
@@ -148,7 +148,7 @@ extern const char *__wt_cell_type_string(uint8_t type);
extern const char *__wt_page_addr_string(WT_SESSION_IMPL *session, WT_REF *ref, WT_ITEM *buf);
extern const char *__wt_addr_string(WT_SESSION_IMPL *session, const uint8_t *addr, size_t addr_size, WT_ITEM *buf);
extern int __wt_ovfl_read(WT_SESSION_IMPL *session, WT_PAGE *page, WT_CELL_UNPACK *unpack, WT_ITEM *store) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
-extern int __wt_ovfl_cache(WT_SESSION_IMPL *session, WT_PAGE *page, void *cookie, WT_CELL_UNPACK *vpack) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
+extern int __wt_ovfl_remove(WT_SESSION_IMPL *session, WT_PAGE *page, WT_UPDATE *upd_list, WT_CELL_UNPACK *unpack) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_ovfl_discard(WT_SESSION_IMPL *session, WT_CELL *cell) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_page_alloc(WT_SESSION_IMPL *session, uint8_t type, uint32_t alloc_entries, bool alloc_refs, WT_PAGE **pagep) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_page_inmem(WT_SESSION_IMPL *session, WT_REF *ref, const void *image, size_t memsize, uint32_t flags, WT_PAGE **pagep) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
@@ -267,7 +267,7 @@ extern int __wt_conn_dhandle_discard(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_
extern int __wt_connection_init(WT_CONNECTION_IMPL *conn) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern void __wt_connection_destroy(WT_CONNECTION_IMPL *conn);
extern int __wt_logmgr_reconfig(WT_SESSION_IMPL *session, const char **cfg) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
-extern int __wt_log_truncate_files( WT_SESSION_IMPL *session, WT_CURSOR *cursor, const char *cfg[]) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
+extern int __wt_log_truncate_files(WT_SESSION_IMPL *session, WT_CURSOR *cursor, bool force) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern void __wt_log_wrlsn(WT_SESSION_IMPL *session, int *yield);
extern int __wt_logmgr_create(WT_SESSION_IMPL *session, const char *cfg[]) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_logmgr_open(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
@@ -371,6 +371,8 @@ extern void __wt_log_written_reset(WT_SESSION_IMPL *session);
extern int __wt_log_get_all_files(WT_SESSION_IMPL *session, char ***filesp, u_int *countp, uint32_t *maxid, bool active_only) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_log_extract_lognum( WT_SESSION_IMPL *session, const char *name, uint32_t *id) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_log_reset(WT_SESSION_IMPL *session, uint32_t lognum) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
+extern int __wt_log_fill(WT_SESSION_IMPL *session, WT_MYSLOT *myslot, bool force, WT_ITEM *record, WT_LSN *lsnp) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
+extern int __wt_log_set_version(WT_SESSION_IMPL *session, uint16_t version, uint32_t first_rec, bool downgrade, bool live_chg, uint32_t *lognump) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_log_acquire(WT_SESSION_IMPL *session, uint64_t recsize, WT_LOGSLOT *slot) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_log_allocfile( WT_SESSION_IMPL *session, uint32_t lognum, const char *dest) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_log_remove(WT_SESSION_IMPL *session, const char *file_prefix, uint32_t lognum) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
@@ -412,6 +414,8 @@ extern int __wt_log_slot_destroy(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTR
extern void __wt_log_slot_join(WT_SESSION_IMPL *session, uint64_t mysize, uint32_t flags, WT_MYSLOT *myslot);
extern int64_t __wt_log_slot_release(WT_MYSLOT *myslot, int64_t size);
extern void __wt_log_slot_free(WT_SESSION_IMPL *session, WT_LOGSLOT *slot);
+extern int __wt_log_system_record( WT_SESSION_IMPL *session, WT_FH *log_fh, WT_LSN *lsn) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
+extern int __wt_log_recover_system(WT_SESSION_IMPL *session, const uint8_t **pp, const uint8_t *end, WT_LSN *lsnp) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_clsm_request_switch(WT_CURSOR_LSM *clsm) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_clsm_await_switch(WT_CURSOR_LSM *clsm) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_clsm_init_merge( WT_CURSOR *cursor, u_int start_chunk, uint32_t start_id, u_int nchunks) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
@@ -443,7 +447,6 @@ extern void __wt_lsm_tree_release(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tre
extern void __wt_lsm_tree_throttle( WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree, bool decrease_only);
extern int __wt_lsm_tree_switch(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_lsm_tree_retire_chunks(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree, u_int start_chunk, u_int nchunks) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
-extern int __wt_lsm_tree_alter( WT_SESSION_IMPL *session, const char *uri, const char *cfg[]) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_lsm_tree_drop( WT_SESSION_IMPL *session, const char *name, const char *cfg[]) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_lsm_tree_rename(WT_SESSION_IMPL *session, const char *olduri, const char *newuri, const char *cfg[]) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_lsm_tree_truncate( WT_SESSION_IMPL *session, const char *name, const char *cfg[]) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
@@ -541,14 +544,12 @@ extern int __wt_ext_unpack_item(WT_EXTENSION_API *wt_api, WT_PACK_STREAM *ps, WT
extern int __wt_ext_unpack_int(WT_EXTENSION_API *wt_api, WT_PACK_STREAM *ps, int64_t *ip) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_ext_unpack_str(WT_EXTENSION_API *wt_api, WT_PACK_STREAM *ps, const char **sp) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_ext_unpack_uint(WT_EXTENSION_API *wt_api, WT_PACK_STREAM *ps, uint64_t *up) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
+extern int __wt_ovfl_track_init(WT_SESSION_IMPL *session, WT_PAGE *page) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_ovfl_discard_add(WT_SESSION_IMPL *session, WT_PAGE *page, WT_CELL *cell) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern void __wt_ovfl_discard_free(WT_SESSION_IMPL *session, WT_PAGE *page);
extern int __wt_ovfl_reuse_search(WT_SESSION_IMPL *session, WT_PAGE *page, uint8_t **addrp, size_t *addr_sizep, const void *value, size_t value_size) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_ovfl_reuse_add(WT_SESSION_IMPL *session, WT_PAGE *page, const uint8_t *addr, size_t addr_size, const void *value, size_t value_size) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern void __wt_ovfl_reuse_free(WT_SESSION_IMPL *session, WT_PAGE *page);
-extern int __wt_ovfl_txnc_search( WT_PAGE *page, const uint8_t *addr, size_t addr_size, WT_ITEM *store) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
-extern int __wt_ovfl_txnc_add(WT_SESSION_IMPL *session, WT_PAGE *page, const uint8_t *addr, size_t addr_size, const void *value, size_t value_size) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
-extern void __wt_ovfl_txnc_free(WT_SESSION_IMPL *session, WT_PAGE *page);
extern int __wt_ovfl_track_wrapup(WT_SESSION_IMPL *session, WT_PAGE *page) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_ovfl_track_wrapup_err(WT_SESSION_IMPL *session, WT_PAGE *page) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_reconcile(WT_SESSION_IMPL *session, WT_REF *ref, WT_SALVAGE_COOKIE *salvage, uint32_t flags, bool *lookaside_retryp) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
@@ -559,7 +560,7 @@ extern int __wt_bulk_insert_row(WT_SESSION_IMPL *session, WT_CURSOR_BULK *cbulk)
extern int __wt_bulk_insert_fix( WT_SESSION_IMPL *session, WT_CURSOR_BULK *cbulk, bool deleted) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_bulk_insert_fix_bitmap(WT_SESSION_IMPL *session, WT_CURSOR_BULK *cbulk) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_bulk_insert_var( WT_SESSION_IMPL *session, WT_CURSOR_BULK *cbulk, bool deleted) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
-extern int __wt_schema_alter(WT_SESSION_IMPL *session, const char *uri, const char *cfg[]) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
+extern int __wt_alter(WT_SESSION_IMPL *session, const char *newcfg[]) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_direct_io_size_check(WT_SESSION_IMPL *session, const char **cfg, const char *config_name, uint32_t *allocsizep) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_schema_colgroup_source(WT_SESSION_IMPL *session, WT_TABLE *table, const char *cgname, const char *config, WT_ITEM *buf) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_schema_index_source(WT_SESSION_IMPL *session, WT_TABLE *table, const char *idxname, const char *config, WT_ITEM *buf) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
@@ -631,6 +632,7 @@ extern int __wt_eventv(WT_SESSION_IMPL *session, bool msg_event, int error, cons
extern void __wt_err(WT_SESSION_IMPL *session, int error, const char *fmt, ...) WT_GCC_FUNC_DECL_ATTRIBUTE((cold)) WT_GCC_FUNC_DECL_ATTRIBUTE((format (printf, 3, 4))) WT_GCC_FUNC_DECL_ATTRIBUTE((visibility("default")));
extern void __wt_errx(WT_SESSION_IMPL *session, const char *fmt, ...) WT_GCC_FUNC_DECL_ATTRIBUTE((cold)) WT_GCC_FUNC_DECL_ATTRIBUTE((format (printf, 2, 3)));
extern int __wt_ext_err_printf( WT_EXTENSION_API *wt_api, WT_SESSION *wt_session, const char *fmt, ...) WT_GCC_FUNC_DECL_ATTRIBUTE((format (printf, 3, 4))) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
+extern void __wt_verbose_worker(WT_SESSION_IMPL *session, const char *fmt, ...) WT_GCC_FUNC_DECL_ATTRIBUTE((format (printf, 2, 3))) WT_GCC_FUNC_DECL_ATTRIBUTE((cold));
extern int __wt_msg(WT_SESSION_IMPL *session, const char *fmt, ...) WT_GCC_FUNC_DECL_ATTRIBUTE((cold)) WT_GCC_FUNC_DECL_ATTRIBUTE((format (printf, 2, 3))) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_ext_msg_printf( WT_EXTENSION_API *wt_api, WT_SESSION *wt_session, const char *fmt, ...) WT_GCC_FUNC_DECL_ATTRIBUTE((format (printf, 3, 4))) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern const char *__wt_ext_strerror(WT_EXTENSION_API *wt_api, WT_SESSION *wt_session, int error);
@@ -646,6 +648,7 @@ __wt_assert(WT_SESSION_IMPL *session,
WT_GCC_FUNC_DECL_ATTRIBUTE((visibility("default")));
extern int __wt_panic(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((cold)) WT_GCC_FUNC_DECL_ATTRIBUTE((visibility("default"))) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_illegal_value(WT_SESSION_IMPL *session, const char *name) WT_GCC_FUNC_DECL_ATTRIBUTE((cold)) WT_GCC_FUNC_DECL_ATTRIBUTE((visibility("default"))) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
+extern int __wt_inmem_unsupported_op(WT_SESSION_IMPL *session, const char *tag) WT_GCC_FUNC_DECL_ATTRIBUTE((cold)) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_object_unsupported(WT_SESSION_IMPL *session, const char *uri) WT_GCC_FUNC_DECL_ATTRIBUTE((cold)) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_bad_object_type(WT_SESSION_IMPL *session, const char *uri) WT_GCC_FUNC_DECL_ATTRIBUTE((cold)) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_unexpected_object_type( WT_SESSION_IMPL *session, const char *uri, const char *expect) WT_GCC_FUNC_DECL_ATTRIBUTE((cold)) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
@@ -705,7 +708,6 @@ extern uint32_t __wt_rduppo2(uint32_t n, uint32_t po2);
extern void __wt_random_init(WT_RAND_STATE volatile *rnd_state) WT_GCC_FUNC_DECL_ATTRIBUTE((visibility("default")));
extern void __wt_random_init_seed( WT_SESSION_IMPL *session, WT_RAND_STATE volatile *rnd_state) WT_GCC_FUNC_DECL_ATTRIBUTE((visibility("default")));
extern uint32_t __wt_random(WT_RAND_STATE volatile *rnd_state) WT_GCC_FUNC_DECL_ATTRIBUTE((visibility("default")));
-extern uint64_t __wt_random64(WT_RAND_STATE volatile *rnd_state) WT_GCC_FUNC_DECL_ATTRIBUTE((visibility("default")));
extern int __wt_buf_grow_worker(WT_SESSION_IMPL *session, WT_ITEM *buf, size_t size) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_buf_fmt(WT_SESSION_IMPL *session, WT_ITEM *buf, const char *fmt, ...) WT_GCC_FUNC_DECL_ATTRIBUTE((format (printf, 3, 4))) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_buf_catfmt(WT_SESSION_IMPL *session, WT_ITEM *buf, const char *fmt, ...) WT_GCC_FUNC_DECL_ATTRIBUTE((format (printf, 3, 4))) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
@@ -789,3 +791,7 @@ extern int __wt_txn_global_query_timestamp( WT_SESSION_IMPL *session, char *hex_
extern int __wt_txn_update_pinned_timestamp(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_txn_global_set_timestamp(WT_SESSION_IMPL *session, const char *cfg[]) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_txn_set_timestamp(WT_SESSION_IMPL *session, const char *cfg[]) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
+extern void __wt_txn_set_commit_timestamp(WT_SESSION_IMPL *session);
+extern void __wt_txn_clear_commit_timestamp(WT_SESSION_IMPL *session);
+extern void __wt_txn_set_read_timestamp(WT_SESSION_IMPL *session);
+extern void __wt_txn_clear_read_timestamp(WT_SESSION_IMPL *session);
diff --git a/src/third_party/wiredtiger/src/include/gcc.h b/src/third_party/wiredtiger/src/include/gcc.h
index 21eaaaef049..043d9b44356 100644
--- a/src/third_party/wiredtiger/src/include/gcc.h
+++ b/src/third_party/wiredtiger/src/include/gcc.h
@@ -21,7 +21,7 @@
* dist/s_prototypes to create extern.h.
*/
#define WT_GCC_FUNC_ATTRIBUTE(x)
-#define WT_GCC_FUNC_DECL_ATTRIBUTE(x) __attribute__(x)
+#define WT_GCC_FUNC_DECL_ATTRIBUTE(x) __attribute__(x)
/*
* Atomic writes:
diff --git a/src/third_party/wiredtiger/src/include/log.h b/src/third_party/wiredtiger/src/include/log.h
index e7bc28cd220..e6acdd1e834 100644
--- a/src/third_party/wiredtiger/src/include/log.h
+++ b/src/third_party/wiredtiger/src/include/log.h
@@ -42,7 +42,7 @@ union __wt_lsn {
#define WT_ZERO_LSN(l) WT_SET_LSN((l), 0, 0)
/*
- * Initialize LSN is (1,0). We only need to shift the 1 for comparison.
+ * Test for initial LSN. We only need to shift the 1 for comparison.
*/
#define WT_IS_INIT_LSN(l) ((l)->file_offset == ((uint64_t)1 << 32))
/*
@@ -52,6 +52,10 @@ union __wt_lsn {
#define WT_IS_MAX_LSN(lsn) \
((lsn)->l.file == UINT32_MAX && \
((lsn)->l.offset == INT32_MAX || (lsn)->l.offset == UINT32_MAX))
+/*
+ * Test for zero LSN.
+ */
+#define WT_IS_ZERO_LSN(l) ((l)->file_offset == 0)
/*
* Both of the macros below need to change if the content of __wt_lsn
@@ -198,10 +202,11 @@ struct __wt_myslot {
uint32_t flags; /* Flags */
};
-#define WT_LOG_FIRST_RECORD log->allocsize
+#define WT_LOG_END_HEADER log->allocsize
struct __wt_log {
uint32_t allocsize; /* Allocation alignment size */
+ uint32_t first_record; /* Offset of first record in file */
wt_off_t log_written; /* Amount of log written this period */
/*
* Log file information
@@ -215,6 +220,8 @@ struct __wt_log {
WT_FH *log_close_fh; /* Logging file handle to close */
WT_LSN log_close_lsn; /* LSN needed to close */
+ uint16_t log_version; /* Version of log file */
+
/*
* System LSNs
*/
@@ -232,6 +239,7 @@ struct __wt_log {
* Synchronization resources
*/
WT_SPINLOCK log_lock; /* Locked: Logging fields */
+ WT_SPINLOCK log_fs_lock; /* Locked: tmp, prep and log files */
WT_SPINLOCK log_slot_lock; /* Locked: Consolidation array */
WT_SPINLOCK log_sync_lock; /* Locked: Single-thread fsync */
WT_SPINLOCK log_writelsn_lock; /* Locked: write LSN */
@@ -261,8 +269,9 @@ struct __wt_log {
uint64_t write_calls; /* Calls to log_write */
#endif
-#define WT_LOG_OPENED 0x01 /* Log subsystem successfully open */
-#define WT_LOG_TRUNCATE_NOTSUP 0x02 /* File system truncate not supported */
+#define WT_LOG_FORCE_NEWFILE 0x01 /* Force switch to new log file */
+#define WT_LOG_OPENED 0x02 /* Log subsystem successfully open */
+#define WT_LOG_TRUNCATE_NOTSUP 0x04 /* File system truncate not supported */
uint32_t flags;
};
@@ -303,12 +312,22 @@ __wt_log_record_byteswap(WT_LOG_RECORD *record)
struct __wt_log_desc {
#define WT_LOG_MAGIC 0x101064
uint32_t log_magic; /* 00-03: Magic number */
-#define WT_LOG_MAJOR_VERSION 1
- uint16_t majorv; /* 04-05: Major version */
-#define WT_LOG_MINOR_VERSION 0
- uint16_t minorv; /* 06-07: Minor version */
+#define WT_LOG_VERSION 2
+ uint16_t version; /* 04-05: Log version */
+ uint16_t unused; /* 06-07: Unused */
uint64_t log_size; /* 08-15: Log file size */
};
+/*
+ * This is the log version that introduced the system record.
+ */
+#define WT_LOG_VERSION_SYSTEM 2
+
+/*
+ * WiredTiger release version where log format version changed.
+ * We only have to check the major version for now. It is minor
+ * version 0 once release numbers move on.
+ */
+#define WT_LOG_V2 3
/*
* __wt_log_desc_byteswap --
@@ -320,8 +339,8 @@ __wt_log_desc_byteswap(WT_LOG_DESC *desc)
{
#ifdef WORDS_BIGENDIAN
desc->log_magic = __wt_bswap32(desc->log_magic);
- desc->majorv = __wt_bswap16(desc->majorv);
- desc->minorv = __wt_bswap16(desc->minorv);
+ desc->version = __wt_bswap16(desc->version);
+ desc->unused = __wt_bswap16(desc->unused);
desc->log_size = __wt_bswap64(desc->log_size);
#else
WT_UNUSED(desc);
diff --git a/src/third_party/wiredtiger/src/include/misc.i b/src/third_party/wiredtiger/src/include/misc.i
index 36a1e1f18eb..bb785a63072 100644
--- a/src/third_party/wiredtiger/src/include/misc.i
+++ b/src/third_party/wiredtiger/src/include/misc.i
@@ -80,39 +80,6 @@ __wt_time_check_monotonic(WT_SESSION_IMPL *session, struct timespec *tsp)
}
/*
- * __wt_verbose --
- * Verbose message.
- *
- * Inline functions are not parsed for external prototypes, so in cases where we
- * want GCC attributes attached to the functions, we have to do so explicitly.
- */
-static inline void
-__wt_verbose(WT_SESSION_IMPL *session, int flag, const char *fmt, ...)
-WT_GCC_FUNC_DECL_ATTRIBUTE((format (printf, 3, 4)));
-
-/*
- * __wt_verbose --
- * Verbose message.
- */
-static inline void
-__wt_verbose(WT_SESSION_IMPL *session, int flag, const char *fmt, ...)
-{
-#ifdef HAVE_VERBOSE
- va_list ap;
-
- if (WT_VERBOSE_ISSET(session, flag)) {
- va_start(ap, fmt);
- WT_IGNORE_RET(__wt_eventv(session, true, 0, NULL, 0, fmt, ap));
- va_end(ap);
- }
-#else
- WT_UNUSED(session);
- WT_UNUSED(flag);
- WT_UNUSED(fmt);
-#endif
-}
-
-/*
* __wt_snprintf --
* snprintf convenience function, ignoring the returned size.
*/
diff --git a/src/third_party/wiredtiger/src/include/stat.h b/src/third_party/wiredtiger/src/include/stat.h
index 7d7d701590a..b340b278684 100644
--- a/src/third_party/wiredtiger/src/include/stat.h
+++ b/src/third_party/wiredtiger/src/include/stat.h
@@ -303,13 +303,25 @@ struct __wt_connection_stats {
int64_t cache_eviction_get_ref_empty2;
int64_t cache_eviction_aggressive_set;
int64_t cache_eviction_empty_score;
+ int64_t cache_eviction_walk_passes;
int64_t cache_eviction_queue_empty;
int64_t cache_eviction_queue_not_empty;
int64_t cache_eviction_server_evicting;
int64_t cache_eviction_server_slept;
int64_t cache_eviction_slow;
int64_t cache_eviction_state;
+ int64_t cache_eviction_target_page_lt10;
+ int64_t cache_eviction_target_page_lt32;
+ int64_t cache_eviction_target_page_ge128;
+ int64_t cache_eviction_target_page_lt64;
+ int64_t cache_eviction_target_page_lt128;
int64_t cache_eviction_walks_abandoned;
+ int64_t cache_eviction_walks_stopped;
+ int64_t cache_eviction_walks_gave_up_no_targets;
+ int64_t cache_eviction_walks_gave_up_ratio;
+ int64_t cache_eviction_walks_ended;
+ int64_t cache_eviction_walk_from_root;
+ int64_t cache_eviction_walk_saved_pos;
int64_t cache_eviction_active_workers;
int64_t cache_eviction_worker_created;
int64_t cache_eviction_worker_evicting;
@@ -336,7 +348,6 @@ struct __wt_connection_stats {
int64_t cache_eviction_dirty;
int64_t cache_eviction_app_dirty;
int64_t cache_read_overflow;
- int64_t cache_overflow_value;
int64_t cache_eviction_deepen;
int64_t cache_write_lookaside;
int64_t cache_pages_inuse;
@@ -414,6 +425,7 @@ struct __wt_connection_stats {
int64_t lock_table_read_count;
int64_t lock_table_write_count;
int64_t log_slot_switch_busy;
+ int64_t log_force_ckpt_sleep;
int64_t log_bytes_payload;
int64_t log_bytes_written;
int64_t log_zero_fills;
@@ -570,6 +582,19 @@ struct __wt_dsrc_stats {
int64_t cache_bytes_write;
int64_t cache_eviction_checkpoint;
int64_t cache_eviction_fail;
+ int64_t cache_eviction_walk_passes;
+ int64_t cache_eviction_target_page_lt10;
+ int64_t cache_eviction_target_page_lt32;
+ int64_t cache_eviction_target_page_ge128;
+ int64_t cache_eviction_target_page_lt64;
+ int64_t cache_eviction_target_page_lt128;
+ int64_t cache_eviction_walks_abandoned;
+ int64_t cache_eviction_walks_stopped;
+ int64_t cache_eviction_walks_gave_up_no_targets;
+ int64_t cache_eviction_walks_gave_up_ratio;
+ int64_t cache_eviction_walks_ended;
+ int64_t cache_eviction_walk_from_root;
+ int64_t cache_eviction_walk_saved_pos;
int64_t cache_eviction_hazard;
int64_t cache_inmem_splittable;
int64_t cache_inmem_split;
@@ -578,18 +603,20 @@ struct __wt_dsrc_stats {
int64_t cache_eviction_split_leaf;
int64_t cache_eviction_dirty;
int64_t cache_read_overflow;
- int64_t cache_overflow_value;
int64_t cache_eviction_deepen;
int64_t cache_write_lookaside;
int64_t cache_read;
int64_t cache_read_lookaside;
int64_t cache_pages_requested;
+ int64_t cache_eviction_pages_seen;
int64_t cache_write;
int64_t cache_write_restore;
int64_t cache_bytes_dirty;
int64_t cache_eviction_clean;
int64_t cache_state_gen_avg_gap;
int64_t cache_state_avg_written_size;
+ int64_t cache_state_avg_visited_age;
+ int64_t cache_state_avg_unvisited_age;
int64_t cache_state_pages_clean;
int64_t cache_state_gen_current;
int64_t cache_state_pages_dirty;
@@ -599,6 +626,7 @@ struct __wt_dsrc_stats {
int64_t cache_state_gen_max_gap;
int64_t cache_state_max_pagesize;
int64_t cache_state_min_written_size;
+ int64_t cache_state_unvisited_count;
int64_t cache_state_smaller_alloc_size;
int64_t cache_state_memory;
int64_t cache_state_queued;
diff --git a/src/third_party/wiredtiger/src/include/txn.h b/src/third_party/wiredtiger/src/include/txn.h
index bf2d9aa21ef..e4cc0b04046 100644
--- a/src/third_party/wiredtiger/src/include/txn.h
+++ b/src/third_party/wiredtiger/src/include/txn.h
@@ -74,9 +74,6 @@ struct __wt_txn_state {
volatile uint64_t pinned_id;
volatile uint64_t metadata_pinned;
- WT_DECL_TIMESTAMP(commit_timestamp)
- WT_DECL_TIMESTAMP(read_timestamp)
-
WT_CACHE_LINE_PAD_END
};
@@ -103,6 +100,14 @@ struct __wt_txn_global {
/* Protects the active transaction states. */
WT_RWLOCK rwlock;
+ /* List of transactions sorted by commit timestamp. */
+ WT_RWLOCK commit_timestamp_rwlock;
+ TAILQ_HEAD(__wt_txn_cts_qh, __wt_txn) commit_timestamph;
+
+ /* List of transactions sorted by read timestamp. */
+ WT_RWLOCK read_timestamp_rwlock;
+ TAILQ_HEAD(__wt_txn_rts_qh, __wt_txn) read_timestamph;
+
/*
* Track information about the running checkpoint. The transaction
* snapshot used when checkpointing are special. Checkpoints can run
@@ -117,6 +122,7 @@ struct __wt_txn_global {
volatile bool checkpoint_running; /* Checkpoint running */
volatile uint32_t checkpoint_id; /* Checkpoint's session ID */
WT_TXN_STATE checkpoint_state; /* Checkpoint's txn state */
+ WT_TXN *checkpoint_txn; /* Checkpoint's txn structure */
volatile uint64_t metadata_pinned; /* Oldest ID for metadata */
@@ -194,8 +200,11 @@ struct __wt_txn {
uint32_t snapshot_count;
uint32_t txn_logsync; /* Log sync configuration */
- WT_DECL_TIMESTAMP(read_timestamp)
WT_DECL_TIMESTAMP(commit_timestamp)
+ WT_DECL_TIMESTAMP(read_timestamp)
+
+ TAILQ_ENTRY(__wt_txn) commit_timestampq;
+ TAILQ_ENTRY(__wt_txn) read_timestampq;
/* Array of modifications by this transaction. */
WT_TXN_OP *mod;
diff --git a/src/third_party/wiredtiger/src/include/txn.i b/src/third_party/wiredtiger/src/include/txn.i
index 85d70fbde89..6de86eb0aaf 100644
--- a/src/third_party/wiredtiger/src/include/txn.i
+++ b/src/third_party/wiredtiger/src/include/txn.i
@@ -10,8 +10,6 @@ static inline int __wt_txn_id_check(WT_SESSION_IMPL *session);
static inline void __wt_txn_read_last(WT_SESSION_IMPL *session);
#ifdef HAVE_TIMESTAMPS
-static const wt_timestamp_t zero_timestamp;
-
/*
* __wt_timestamp_cmp --
* Compare two timestamps.
@@ -39,8 +37,30 @@ __wt_timestamp_set(uint8_t *dest, const uint8_t *src)
static inline bool
__wt_timestamp_iszero(const uint8_t *ts)
{
+ static const wt_timestamp_t zero_timestamp;
+
return (memcmp(ts, zero_timestamp, WT_TIMESTAMP_SIZE) == 0);
}
+
+/*
+ * __wt_timestamp_set_inf --
+ * Set a timestamp to the maximum value.
+ */
+static inline void
+__wt_timestamp_set_inf(uint8_t *ts)
+{
+ memset(ts, 0xff, WT_TIMESTAMP_SIZE);
+}
+
+/*
+ * __wt_timestamp_set_zero --
+ * Zero out a timestamp.
+ */
+static inline void
+__wt_timestamp_set_zero(uint8_t *ts)
+{
+ memset(ts, 0x00, WT_TIMESTAMP_SIZE);
+}
#endif
/*
diff --git a/src/third_party/wiredtiger/src/include/wiredtiger.in b/src/third_party/wiredtiger/src/include/wiredtiger.in
index 60bacbcf51d..d8d8b864766 100644
--- a/src/third_party/wiredtiger/src/include/wiredtiger.in
+++ b/src/third_party/wiredtiger/src/include/wiredtiger.in
@@ -921,6 +921,12 @@ struct __wt_session {
* cache. Not compatible with LSM tables; see @ref
* tuning_cache_resident for more information., a boolean flag; default
* \c false.}
+ * @config{log = (, the transaction log configuration for this object.
+ * Only valid if log is enabled in ::wiredtiger_open., a set of related
+ * configuration options defined below.}
+ * @config{&nbsp;&nbsp;&nbsp;&nbsp;enabled, if false\, this object has
+ * checkpoint-level durability., a boolean flag; default \c true.}
+ * @config{ ),,}
* @configend
* @errors
*/
@@ -1971,6 +1977,11 @@ struct __wt_connection {
* checkpoint; setting this value above 0 configures periodic
* checkpoints., an integer between 0 and 100000; default \c 0.}
* @config{ ),,}
+ * @config{compatibility = (, set compatibility version of database., a
+ * set of related configuration options defined below.}
+ * @config{&nbsp;&nbsp;&nbsp;&nbsp;release, compatibility release
+ * version string., a string; default empty.}
+ * @config{ ),,}
* @config{error_prefix, prefix string for error messages., a string;
* default empty.}
* @config{eviction = (, eviction configuration options., a set of
@@ -2454,6 +2465,11 @@ struct __wt_connection {
* @config{ ),,}
* @config{checkpoint_sync, flush files to stable storage when closing or
* writing checkpoints., a boolean flag; default \c true.}
+ * @config{compatibility = (, set compatibility version of database., a set of
+ * related configuration options defined below.}
+ * @config{&nbsp;&nbsp;&nbsp;&nbsp;release, compatibility release version
+ * string., a string; default empty.}
+ * @config{ ),,}
* @config{config_base, write the base configuration file if creating the
* database. If \c false in the config passed directly to ::wiredtiger_open\,
* will ignore any existing base configuration file in addition to not creating
@@ -4471,6 +4487,8 @@ extern int wiredtiger_extension_terminate(WT_CONNECTION *connection);
#define WT_LOGREC_FILE_SYNC 2
/*! message */
#define WT_LOGREC_MESSAGE 3
+/*! system/internal record */
+#define WT_LOGREC_SYSTEM 4
/*! invalid operation */
#define WT_LOGOP_INVALID 0
/*! column put */
@@ -4596,475 +4614,505 @@ extern int wiredtiger_extension_terminate(WT_CONNECTION *connection);
#define WT_STAT_CONN_CACHE_EVICTION_AGGRESSIVE_SET 1044
/*! cache: eviction empty score */
#define WT_STAT_CONN_CACHE_EVICTION_EMPTY_SCORE 1045
+/*! cache: eviction passes of a file */
+#define WT_STAT_CONN_CACHE_EVICTION_WALK_PASSES 1046
/*! cache: eviction server candidate queue empty when topping up */
-#define WT_STAT_CONN_CACHE_EVICTION_QUEUE_EMPTY 1046
+#define WT_STAT_CONN_CACHE_EVICTION_QUEUE_EMPTY 1047
/*! cache: eviction server candidate queue not empty when topping up */
-#define WT_STAT_CONN_CACHE_EVICTION_QUEUE_NOT_EMPTY 1047
+#define WT_STAT_CONN_CACHE_EVICTION_QUEUE_NOT_EMPTY 1048
/*! cache: eviction server evicting pages */
-#define WT_STAT_CONN_CACHE_EVICTION_SERVER_EVICTING 1048
+#define WT_STAT_CONN_CACHE_EVICTION_SERVER_EVICTING 1049
/*!
* cache: eviction server slept, because we did not make progress with
* eviction
*/
-#define WT_STAT_CONN_CACHE_EVICTION_SERVER_SLEPT 1049
+#define WT_STAT_CONN_CACHE_EVICTION_SERVER_SLEPT 1050
/*! cache: eviction server unable to reach eviction goal */
-#define WT_STAT_CONN_CACHE_EVICTION_SLOW 1050
+#define WT_STAT_CONN_CACHE_EVICTION_SLOW 1051
/*! cache: eviction state */
-#define WT_STAT_CONN_CACHE_EVICTION_STATE 1051
+#define WT_STAT_CONN_CACHE_EVICTION_STATE 1052
+/*! cache: eviction walk target pages histogram - 0-9 */
+#define WT_STAT_CONN_CACHE_EVICTION_TARGET_PAGE_LT10 1053
+/*! cache: eviction walk target pages histogram - 10-31 */
+#define WT_STAT_CONN_CACHE_EVICTION_TARGET_PAGE_LT32 1054
+/*! cache: eviction walk target pages histogram - 128 and higher */
+#define WT_STAT_CONN_CACHE_EVICTION_TARGET_PAGE_GE128 1055
+/*! cache: eviction walk target pages histogram - 32-63 */
+#define WT_STAT_CONN_CACHE_EVICTION_TARGET_PAGE_LT64 1056
+/*! cache: eviction walk target pages histogram - 64-128 */
+#define WT_STAT_CONN_CACHE_EVICTION_TARGET_PAGE_LT128 1057
/*! cache: eviction walks abandoned */
-#define WT_STAT_CONN_CACHE_EVICTION_WALKS_ABANDONED 1052
+#define WT_STAT_CONN_CACHE_EVICTION_WALKS_ABANDONED 1058
+/*! cache: eviction walks gave up because they restarted their walk twice */
+#define WT_STAT_CONN_CACHE_EVICTION_WALKS_STOPPED 1059
+/*!
+ * cache: eviction walks gave up because they saw too many pages and
+ * found no candidates
+ */
+#define WT_STAT_CONN_CACHE_EVICTION_WALKS_GAVE_UP_NO_TARGETS 1060
+/*!
+ * cache: eviction walks gave up because they saw too many pages and
+ * found too few candidates
+ */
+#define WT_STAT_CONN_CACHE_EVICTION_WALKS_GAVE_UP_RATIO 1061
+/*! cache: eviction walks reached end of tree */
+#define WT_STAT_CONN_CACHE_EVICTION_WALKS_ENDED 1062
+/*! cache: eviction walks started from root of tree */
+#define WT_STAT_CONN_CACHE_EVICTION_WALK_FROM_ROOT 1063
+/*! cache: eviction walks started from saved location in tree */
+#define WT_STAT_CONN_CACHE_EVICTION_WALK_SAVED_POS 1064
/*! cache: eviction worker thread active */
-#define WT_STAT_CONN_CACHE_EVICTION_ACTIVE_WORKERS 1053
+#define WT_STAT_CONN_CACHE_EVICTION_ACTIVE_WORKERS 1065
/*! cache: eviction worker thread created */
-#define WT_STAT_CONN_CACHE_EVICTION_WORKER_CREATED 1054
+#define WT_STAT_CONN_CACHE_EVICTION_WORKER_CREATED 1066
/*! cache: eviction worker thread evicting pages */
-#define WT_STAT_CONN_CACHE_EVICTION_WORKER_EVICTING 1055
+#define WT_STAT_CONN_CACHE_EVICTION_WORKER_EVICTING 1067
/*! cache: eviction worker thread removed */
-#define WT_STAT_CONN_CACHE_EVICTION_WORKER_REMOVED 1056
+#define WT_STAT_CONN_CACHE_EVICTION_WORKER_REMOVED 1068
/*! cache: eviction worker thread stable number */
-#define WT_STAT_CONN_CACHE_EVICTION_STABLE_STATE_WORKERS 1057
+#define WT_STAT_CONN_CACHE_EVICTION_STABLE_STATE_WORKERS 1069
/*!
* cache: failed eviction of pages that exceeded the in-memory maximum
* count
*/
-#define WT_STAT_CONN_CACHE_EVICTION_FORCE_FAIL 1058
+#define WT_STAT_CONN_CACHE_EVICTION_FORCE_FAIL 1070
/*!
* cache: failed eviction of pages that exceeded the in-memory maximum
* time (usecs)
*/
-#define WT_STAT_CONN_CACHE_EVICTION_FORCE_FAIL_TIME 1059
+#define WT_STAT_CONN_CACHE_EVICTION_FORCE_FAIL_TIME 1071
/*! cache: files with active eviction walks */
-#define WT_STAT_CONN_CACHE_EVICTION_WALKS_ACTIVE 1060
+#define WT_STAT_CONN_CACHE_EVICTION_WALKS_ACTIVE 1072
/*! cache: files with new eviction walks started */
-#define WT_STAT_CONN_CACHE_EVICTION_WALKS_STARTED 1061
+#define WT_STAT_CONN_CACHE_EVICTION_WALKS_STARTED 1073
/*! cache: force re-tuning of eviction workers once in a while */
-#define WT_STAT_CONN_CACHE_EVICTION_FORCE_RETUNE 1062
+#define WT_STAT_CONN_CACHE_EVICTION_FORCE_RETUNE 1074
/*! cache: hazard pointer blocked page eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_HAZARD 1063
+#define WT_STAT_CONN_CACHE_EVICTION_HAZARD 1075
/*! cache: hazard pointer check calls */
-#define WT_STAT_CONN_CACHE_HAZARD_CHECKS 1064
+#define WT_STAT_CONN_CACHE_HAZARD_CHECKS 1076
/*! cache: hazard pointer check entries walked */
-#define WT_STAT_CONN_CACHE_HAZARD_WALKS 1065
+#define WT_STAT_CONN_CACHE_HAZARD_WALKS 1077
/*! cache: hazard pointer maximum array length */
-#define WT_STAT_CONN_CACHE_HAZARD_MAX 1066
+#define WT_STAT_CONN_CACHE_HAZARD_MAX 1078
/*! cache: in-memory page passed criteria to be split */
-#define WT_STAT_CONN_CACHE_INMEM_SPLITTABLE 1067
+#define WT_STAT_CONN_CACHE_INMEM_SPLITTABLE 1079
/*! cache: in-memory page splits */
-#define WT_STAT_CONN_CACHE_INMEM_SPLIT 1068
+#define WT_STAT_CONN_CACHE_INMEM_SPLIT 1080
/*! cache: internal pages evicted */
-#define WT_STAT_CONN_CACHE_EVICTION_INTERNAL 1069
+#define WT_STAT_CONN_CACHE_EVICTION_INTERNAL 1081
/*! cache: internal pages split during eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_SPLIT_INTERNAL 1070
+#define WT_STAT_CONN_CACHE_EVICTION_SPLIT_INTERNAL 1082
/*! cache: leaf pages split during eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_SPLIT_LEAF 1071
+#define WT_STAT_CONN_CACHE_EVICTION_SPLIT_LEAF 1083
/*! cache: lookaside table insert calls */
-#define WT_STAT_CONN_CACHE_LOOKASIDE_INSERT 1072
+#define WT_STAT_CONN_CACHE_LOOKASIDE_INSERT 1084
/*! cache: lookaside table remove calls */
-#define WT_STAT_CONN_CACHE_LOOKASIDE_REMOVE 1073
+#define WT_STAT_CONN_CACHE_LOOKASIDE_REMOVE 1085
/*! cache: maximum bytes configured */
-#define WT_STAT_CONN_CACHE_BYTES_MAX 1074
+#define WT_STAT_CONN_CACHE_BYTES_MAX 1086
/*! cache: maximum page size at eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_MAXIMUM_PAGE_SIZE 1075
+#define WT_STAT_CONN_CACHE_EVICTION_MAXIMUM_PAGE_SIZE 1087
/*! cache: modified pages evicted */
-#define WT_STAT_CONN_CACHE_EVICTION_DIRTY 1076
+#define WT_STAT_CONN_CACHE_EVICTION_DIRTY 1088
/*! cache: modified pages evicted by application threads */
-#define WT_STAT_CONN_CACHE_EVICTION_APP_DIRTY 1077
+#define WT_STAT_CONN_CACHE_EVICTION_APP_DIRTY 1089
/*! cache: overflow pages read into cache */
-#define WT_STAT_CONN_CACHE_READ_OVERFLOW 1078
-/*! cache: overflow values cached in memory */
-#define WT_STAT_CONN_CACHE_OVERFLOW_VALUE 1079
+#define WT_STAT_CONN_CACHE_READ_OVERFLOW 1090
/*! cache: page split during eviction deepened the tree */
-#define WT_STAT_CONN_CACHE_EVICTION_DEEPEN 1080
+#define WT_STAT_CONN_CACHE_EVICTION_DEEPEN 1091
/*! cache: page written requiring lookaside records */
-#define WT_STAT_CONN_CACHE_WRITE_LOOKASIDE 1081
+#define WT_STAT_CONN_CACHE_WRITE_LOOKASIDE 1092
/*! cache: pages currently held in the cache */
-#define WT_STAT_CONN_CACHE_PAGES_INUSE 1082
+#define WT_STAT_CONN_CACHE_PAGES_INUSE 1093
/*! cache: pages evicted because they exceeded the in-memory maximum count */
-#define WT_STAT_CONN_CACHE_EVICTION_FORCE 1083
+#define WT_STAT_CONN_CACHE_EVICTION_FORCE 1094
/*!
* cache: pages evicted because they exceeded the in-memory maximum time
* (usecs)
*/
-#define WT_STAT_CONN_CACHE_EVICTION_FORCE_TIME 1084
+#define WT_STAT_CONN_CACHE_EVICTION_FORCE_TIME 1095
/*! cache: pages evicted because they had chains of deleted items count */
-#define WT_STAT_CONN_CACHE_EVICTION_FORCE_DELETE 1085
+#define WT_STAT_CONN_CACHE_EVICTION_FORCE_DELETE 1096
/*!
* cache: pages evicted because they had chains of deleted items time
* (usecs)
*/
-#define WT_STAT_CONN_CACHE_EVICTION_FORCE_DELETE_TIME 1086
+#define WT_STAT_CONN_CACHE_EVICTION_FORCE_DELETE_TIME 1097
/*! cache: pages evicted by application threads */
-#define WT_STAT_CONN_CACHE_EVICTION_APP 1087
+#define WT_STAT_CONN_CACHE_EVICTION_APP 1098
/*! cache: pages queued for eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_PAGES_QUEUED 1088
+#define WT_STAT_CONN_CACHE_EVICTION_PAGES_QUEUED 1099
/*! cache: pages queued for urgent eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_PAGES_QUEUED_URGENT 1089
+#define WT_STAT_CONN_CACHE_EVICTION_PAGES_QUEUED_URGENT 1100
/*! cache: pages queued for urgent eviction during walk */
-#define WT_STAT_CONN_CACHE_EVICTION_PAGES_QUEUED_OLDEST 1090
+#define WT_STAT_CONN_CACHE_EVICTION_PAGES_QUEUED_OLDEST 1101
/*! cache: pages read into cache */
-#define WT_STAT_CONN_CACHE_READ 1091
+#define WT_STAT_CONN_CACHE_READ 1102
/*! cache: pages read into cache requiring lookaside entries */
-#define WT_STAT_CONN_CACHE_READ_LOOKASIDE 1092
+#define WT_STAT_CONN_CACHE_READ_LOOKASIDE 1103
/*! cache: pages requested from the cache */
-#define WT_STAT_CONN_CACHE_PAGES_REQUESTED 1093
+#define WT_STAT_CONN_CACHE_PAGES_REQUESTED 1104
/*! cache: pages seen by eviction walk */
-#define WT_STAT_CONN_CACHE_EVICTION_PAGES_SEEN 1094
+#define WT_STAT_CONN_CACHE_EVICTION_PAGES_SEEN 1105
/*! cache: pages selected for eviction unable to be evicted */
-#define WT_STAT_CONN_CACHE_EVICTION_FAIL 1095
+#define WT_STAT_CONN_CACHE_EVICTION_FAIL 1106
/*! cache: pages walked for eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_WALK 1096
+#define WT_STAT_CONN_CACHE_EVICTION_WALK 1107
/*! cache: pages written from cache */
-#define WT_STAT_CONN_CACHE_WRITE 1097
+#define WT_STAT_CONN_CACHE_WRITE 1108
/*! cache: pages written requiring in-memory restoration */
-#define WT_STAT_CONN_CACHE_WRITE_RESTORE 1098
+#define WT_STAT_CONN_CACHE_WRITE_RESTORE 1109
/*! cache: percentage overhead */
-#define WT_STAT_CONN_CACHE_OVERHEAD 1099
+#define WT_STAT_CONN_CACHE_OVERHEAD 1110
/*! cache: tracked bytes belonging to internal pages in the cache */
-#define WT_STAT_CONN_CACHE_BYTES_INTERNAL 1100
+#define WT_STAT_CONN_CACHE_BYTES_INTERNAL 1111
/*! cache: tracked bytes belonging to leaf pages in the cache */
-#define WT_STAT_CONN_CACHE_BYTES_LEAF 1101
+#define WT_STAT_CONN_CACHE_BYTES_LEAF 1112
/*! cache: tracked dirty bytes in the cache */
-#define WT_STAT_CONN_CACHE_BYTES_DIRTY 1102
+#define WT_STAT_CONN_CACHE_BYTES_DIRTY 1113
/*! cache: tracked dirty pages in the cache */
-#define WT_STAT_CONN_CACHE_PAGES_DIRTY 1103
+#define WT_STAT_CONN_CACHE_PAGES_DIRTY 1114
/*! cache: unmodified pages evicted */
-#define WT_STAT_CONN_CACHE_EVICTION_CLEAN 1104
+#define WT_STAT_CONN_CACHE_EVICTION_CLEAN 1115
/*! connection: auto adjusting condition resets */
-#define WT_STAT_CONN_COND_AUTO_WAIT_RESET 1105
+#define WT_STAT_CONN_COND_AUTO_WAIT_RESET 1116
/*! connection: auto adjusting condition wait calls */
-#define WT_STAT_CONN_COND_AUTO_WAIT 1106
+#define WT_STAT_CONN_COND_AUTO_WAIT 1117
/*! connection: detected system time went backwards */
-#define WT_STAT_CONN_TIME_TRAVEL 1107
+#define WT_STAT_CONN_TIME_TRAVEL 1118
/*! connection: files currently open */
-#define WT_STAT_CONN_FILE_OPEN 1108
+#define WT_STAT_CONN_FILE_OPEN 1119
/*! connection: memory allocations */
-#define WT_STAT_CONN_MEMORY_ALLOCATION 1109
+#define WT_STAT_CONN_MEMORY_ALLOCATION 1120
/*! connection: memory frees */
-#define WT_STAT_CONN_MEMORY_FREE 1110
+#define WT_STAT_CONN_MEMORY_FREE 1121
/*! connection: memory re-allocations */
-#define WT_STAT_CONN_MEMORY_GROW 1111
+#define WT_STAT_CONN_MEMORY_GROW 1122
/*! connection: pthread mutex condition wait calls */
-#define WT_STAT_CONN_COND_WAIT 1112
+#define WT_STAT_CONN_COND_WAIT 1123
/*! connection: pthread mutex shared lock read-lock calls */
-#define WT_STAT_CONN_RWLOCK_READ 1113
+#define WT_STAT_CONN_RWLOCK_READ 1124
/*! connection: pthread mutex shared lock write-lock calls */
-#define WT_STAT_CONN_RWLOCK_WRITE 1114
+#define WT_STAT_CONN_RWLOCK_WRITE 1125
/*! connection: total fsync I/Os */
-#define WT_STAT_CONN_FSYNC_IO 1115
+#define WT_STAT_CONN_FSYNC_IO 1126
/*! connection: total read I/Os */
-#define WT_STAT_CONN_READ_IO 1116
+#define WT_STAT_CONN_READ_IO 1127
/*! connection: total write I/Os */
-#define WT_STAT_CONN_WRITE_IO 1117
+#define WT_STAT_CONN_WRITE_IO 1128
/*! cursor: cursor create calls */
-#define WT_STAT_CONN_CURSOR_CREATE 1118
+#define WT_STAT_CONN_CURSOR_CREATE 1129
/*! cursor: cursor insert calls */
-#define WT_STAT_CONN_CURSOR_INSERT 1119
+#define WT_STAT_CONN_CURSOR_INSERT 1130
/*! cursor: cursor modify calls */
-#define WT_STAT_CONN_CURSOR_MODIFY 1120
+#define WT_STAT_CONN_CURSOR_MODIFY 1131
/*! cursor: cursor next calls */
-#define WT_STAT_CONN_CURSOR_NEXT 1121
+#define WT_STAT_CONN_CURSOR_NEXT 1132
/*! cursor: cursor prev calls */
-#define WT_STAT_CONN_CURSOR_PREV 1122
+#define WT_STAT_CONN_CURSOR_PREV 1133
/*! cursor: cursor remove calls */
-#define WT_STAT_CONN_CURSOR_REMOVE 1123
+#define WT_STAT_CONN_CURSOR_REMOVE 1134
/*! cursor: cursor reserve calls */
-#define WT_STAT_CONN_CURSOR_RESERVE 1124
+#define WT_STAT_CONN_CURSOR_RESERVE 1135
/*! cursor: cursor reset calls */
-#define WT_STAT_CONN_CURSOR_RESET 1125
+#define WT_STAT_CONN_CURSOR_RESET 1136
/*! cursor: cursor restarted searches */
-#define WT_STAT_CONN_CURSOR_RESTART 1126
+#define WT_STAT_CONN_CURSOR_RESTART 1137
/*! cursor: cursor search calls */
-#define WT_STAT_CONN_CURSOR_SEARCH 1127
+#define WT_STAT_CONN_CURSOR_SEARCH 1138
/*! cursor: cursor search near calls */
-#define WT_STAT_CONN_CURSOR_SEARCH_NEAR 1128
+#define WT_STAT_CONN_CURSOR_SEARCH_NEAR 1139
/*! cursor: cursor update calls */
-#define WT_STAT_CONN_CURSOR_UPDATE 1129
+#define WT_STAT_CONN_CURSOR_UPDATE 1140
/*! cursor: truncate calls */
-#define WT_STAT_CONN_CURSOR_TRUNCATE 1130
+#define WT_STAT_CONN_CURSOR_TRUNCATE 1141
/*! data-handle: connection data handles currently active */
-#define WT_STAT_CONN_DH_CONN_HANDLE_COUNT 1131
+#define WT_STAT_CONN_DH_CONN_HANDLE_COUNT 1142
/*! data-handle: connection sweep candidate became referenced */
-#define WT_STAT_CONN_DH_SWEEP_REF 1132
+#define WT_STAT_CONN_DH_SWEEP_REF 1143
/*! data-handle: connection sweep dhandles closed */
-#define WT_STAT_CONN_DH_SWEEP_CLOSE 1133
+#define WT_STAT_CONN_DH_SWEEP_CLOSE 1144
/*! data-handle: connection sweep dhandles removed from hash list */
-#define WT_STAT_CONN_DH_SWEEP_REMOVE 1134
+#define WT_STAT_CONN_DH_SWEEP_REMOVE 1145
/*! data-handle: connection sweep time-of-death sets */
-#define WT_STAT_CONN_DH_SWEEP_TOD 1135
+#define WT_STAT_CONN_DH_SWEEP_TOD 1146
/*! data-handle: connection sweeps */
-#define WT_STAT_CONN_DH_SWEEPS 1136
+#define WT_STAT_CONN_DH_SWEEPS 1147
/*! data-handle: session dhandles swept */
-#define WT_STAT_CONN_DH_SESSION_HANDLES 1137
+#define WT_STAT_CONN_DH_SESSION_HANDLES 1148
/*! data-handle: session sweep attempts */
-#define WT_STAT_CONN_DH_SESSION_SWEEPS 1138
+#define WT_STAT_CONN_DH_SESSION_SWEEPS 1149
/*! lock: checkpoint lock acquisitions */
-#define WT_STAT_CONN_LOCK_CHECKPOINT_COUNT 1139
+#define WT_STAT_CONN_LOCK_CHECKPOINT_COUNT 1150
/*! lock: checkpoint lock application thread wait time (usecs) */
-#define WT_STAT_CONN_LOCK_CHECKPOINT_WAIT_APPLICATION 1140
+#define WT_STAT_CONN_LOCK_CHECKPOINT_WAIT_APPLICATION 1151
/*! lock: checkpoint lock internal thread wait time (usecs) */
-#define WT_STAT_CONN_LOCK_CHECKPOINT_WAIT_INTERNAL 1141
+#define WT_STAT_CONN_LOCK_CHECKPOINT_WAIT_INTERNAL 1152
/*!
* lock: dhandle lock application thread time waiting for the dhandle
* lock (usecs)
*/
-#define WT_STAT_CONN_LOCK_DHANDLE_WAIT_APPLICATION 1142
+#define WT_STAT_CONN_LOCK_DHANDLE_WAIT_APPLICATION 1153
/*!
* lock: dhandle lock internal thread time waiting for the dhandle lock
* (usecs)
*/
-#define WT_STAT_CONN_LOCK_DHANDLE_WAIT_INTERNAL 1143
+#define WT_STAT_CONN_LOCK_DHANDLE_WAIT_INTERNAL 1154
/*! lock: dhandle read lock acquisitions */
-#define WT_STAT_CONN_LOCK_DHANDLE_READ_COUNT 1144
+#define WT_STAT_CONN_LOCK_DHANDLE_READ_COUNT 1155
/*! lock: dhandle write lock acquisitions */
-#define WT_STAT_CONN_LOCK_DHANDLE_WRITE_COUNT 1145
+#define WT_STAT_CONN_LOCK_DHANDLE_WRITE_COUNT 1156
/*! lock: metadata lock acquisitions */
-#define WT_STAT_CONN_LOCK_METADATA_COUNT 1146
+#define WT_STAT_CONN_LOCK_METADATA_COUNT 1157
/*! lock: metadata lock application thread wait time (usecs) */
-#define WT_STAT_CONN_LOCK_METADATA_WAIT_APPLICATION 1147
+#define WT_STAT_CONN_LOCK_METADATA_WAIT_APPLICATION 1158
/*! lock: metadata lock internal thread wait time (usecs) */
-#define WT_STAT_CONN_LOCK_METADATA_WAIT_INTERNAL 1148
+#define WT_STAT_CONN_LOCK_METADATA_WAIT_INTERNAL 1159
/*! lock: schema lock acquisitions */
-#define WT_STAT_CONN_LOCK_SCHEMA_COUNT 1149
+#define WT_STAT_CONN_LOCK_SCHEMA_COUNT 1160
/*! lock: schema lock application thread wait time (usecs) */
-#define WT_STAT_CONN_LOCK_SCHEMA_WAIT_APPLICATION 1150
+#define WT_STAT_CONN_LOCK_SCHEMA_WAIT_APPLICATION 1161
/*! lock: schema lock internal thread wait time (usecs) */
-#define WT_STAT_CONN_LOCK_SCHEMA_WAIT_INTERNAL 1151
+#define WT_STAT_CONN_LOCK_SCHEMA_WAIT_INTERNAL 1162
/*!
* lock: table lock application thread time waiting for the table lock
* (usecs)
*/
-#define WT_STAT_CONN_LOCK_TABLE_WAIT_APPLICATION 1152
+#define WT_STAT_CONN_LOCK_TABLE_WAIT_APPLICATION 1163
/*!
* lock: table lock internal thread time waiting for the table lock
* (usecs)
*/
-#define WT_STAT_CONN_LOCK_TABLE_WAIT_INTERNAL 1153
+#define WT_STAT_CONN_LOCK_TABLE_WAIT_INTERNAL 1164
/*! lock: table read lock acquisitions */
-#define WT_STAT_CONN_LOCK_TABLE_READ_COUNT 1154
+#define WT_STAT_CONN_LOCK_TABLE_READ_COUNT 1165
/*! lock: table write lock acquisitions */
-#define WT_STAT_CONN_LOCK_TABLE_WRITE_COUNT 1155
+#define WT_STAT_CONN_LOCK_TABLE_WRITE_COUNT 1166
/*! log: busy returns attempting to switch slots */
-#define WT_STAT_CONN_LOG_SLOT_SWITCH_BUSY 1156
+#define WT_STAT_CONN_LOG_SLOT_SWITCH_BUSY 1167
+/*! log: force checkpoint calls slept */
+#define WT_STAT_CONN_LOG_FORCE_CKPT_SLEEP 1168
/*! log: log bytes of payload data */
-#define WT_STAT_CONN_LOG_BYTES_PAYLOAD 1157
+#define WT_STAT_CONN_LOG_BYTES_PAYLOAD 1169
/*! log: log bytes written */
-#define WT_STAT_CONN_LOG_BYTES_WRITTEN 1158
+#define WT_STAT_CONN_LOG_BYTES_WRITTEN 1170
/*! log: log files manually zero-filled */
-#define WT_STAT_CONN_LOG_ZERO_FILLS 1159
+#define WT_STAT_CONN_LOG_ZERO_FILLS 1171
/*! log: log flush operations */
-#define WT_STAT_CONN_LOG_FLUSH 1160
+#define WT_STAT_CONN_LOG_FLUSH 1172
/*! log: log force write operations */
-#define WT_STAT_CONN_LOG_FORCE_WRITE 1161
+#define WT_STAT_CONN_LOG_FORCE_WRITE 1173
/*! log: log force write operations skipped */
-#define WT_STAT_CONN_LOG_FORCE_WRITE_SKIP 1162
+#define WT_STAT_CONN_LOG_FORCE_WRITE_SKIP 1174
/*! log: log records compressed */
-#define WT_STAT_CONN_LOG_COMPRESS_WRITES 1163
+#define WT_STAT_CONN_LOG_COMPRESS_WRITES 1175
/*! log: log records not compressed */
-#define WT_STAT_CONN_LOG_COMPRESS_WRITE_FAILS 1164
+#define WT_STAT_CONN_LOG_COMPRESS_WRITE_FAILS 1176
/*! log: log records too small to compress */
-#define WT_STAT_CONN_LOG_COMPRESS_SMALL 1165
+#define WT_STAT_CONN_LOG_COMPRESS_SMALL 1177
/*! log: log release advances write LSN */
-#define WT_STAT_CONN_LOG_RELEASE_WRITE_LSN 1166
+#define WT_STAT_CONN_LOG_RELEASE_WRITE_LSN 1178
/*! log: log scan operations */
-#define WT_STAT_CONN_LOG_SCANS 1167
+#define WT_STAT_CONN_LOG_SCANS 1179
/*! log: log scan records requiring two reads */
-#define WT_STAT_CONN_LOG_SCAN_REREADS 1168
+#define WT_STAT_CONN_LOG_SCAN_REREADS 1180
/*! log: log server thread advances write LSN */
-#define WT_STAT_CONN_LOG_WRITE_LSN 1169
+#define WT_STAT_CONN_LOG_WRITE_LSN 1181
/*! log: log server thread write LSN walk skipped */
-#define WT_STAT_CONN_LOG_WRITE_LSN_SKIP 1170
+#define WT_STAT_CONN_LOG_WRITE_LSN_SKIP 1182
/*! log: log sync operations */
-#define WT_STAT_CONN_LOG_SYNC 1171
+#define WT_STAT_CONN_LOG_SYNC 1183
/*! log: log sync time duration (usecs) */
-#define WT_STAT_CONN_LOG_SYNC_DURATION 1172
+#define WT_STAT_CONN_LOG_SYNC_DURATION 1184
/*! log: log sync_dir operations */
-#define WT_STAT_CONN_LOG_SYNC_DIR 1173
+#define WT_STAT_CONN_LOG_SYNC_DIR 1185
/*! log: log sync_dir time duration (usecs) */
-#define WT_STAT_CONN_LOG_SYNC_DIR_DURATION 1174
+#define WT_STAT_CONN_LOG_SYNC_DIR_DURATION 1186
/*! log: log write operations */
-#define WT_STAT_CONN_LOG_WRITES 1175
+#define WT_STAT_CONN_LOG_WRITES 1187
/*! log: logging bytes consolidated */
-#define WT_STAT_CONN_LOG_SLOT_CONSOLIDATED 1176
+#define WT_STAT_CONN_LOG_SLOT_CONSOLIDATED 1188
/*! log: maximum log file size */
-#define WT_STAT_CONN_LOG_MAX_FILESIZE 1177
+#define WT_STAT_CONN_LOG_MAX_FILESIZE 1189
/*! log: number of pre-allocated log files to create */
-#define WT_STAT_CONN_LOG_PREALLOC_MAX 1178
+#define WT_STAT_CONN_LOG_PREALLOC_MAX 1190
/*! log: pre-allocated log files not ready and missed */
-#define WT_STAT_CONN_LOG_PREALLOC_MISSED 1179
+#define WT_STAT_CONN_LOG_PREALLOC_MISSED 1191
/*! log: pre-allocated log files prepared */
-#define WT_STAT_CONN_LOG_PREALLOC_FILES 1180
+#define WT_STAT_CONN_LOG_PREALLOC_FILES 1192
/*! log: pre-allocated log files used */
-#define WT_STAT_CONN_LOG_PREALLOC_USED 1181
+#define WT_STAT_CONN_LOG_PREALLOC_USED 1193
/*! log: records processed by log scan */
-#define WT_STAT_CONN_LOG_SCAN_RECORDS 1182
+#define WT_STAT_CONN_LOG_SCAN_RECORDS 1194
/*! log: slot close lost race */
-#define WT_STAT_CONN_LOG_SLOT_CLOSE_RACE 1183
+#define WT_STAT_CONN_LOG_SLOT_CLOSE_RACE 1195
/*! log: slot close unbuffered waits */
-#define WT_STAT_CONN_LOG_SLOT_CLOSE_UNBUF 1184
+#define WT_STAT_CONN_LOG_SLOT_CLOSE_UNBUF 1196
/*! log: slot closures */
-#define WT_STAT_CONN_LOG_SLOT_CLOSES 1185
+#define WT_STAT_CONN_LOG_SLOT_CLOSES 1197
/*! log: slot join atomic update races */
-#define WT_STAT_CONN_LOG_SLOT_RACES 1186
+#define WT_STAT_CONN_LOG_SLOT_RACES 1198
/*! log: slot join calls atomic updates raced */
-#define WT_STAT_CONN_LOG_SLOT_YIELD_RACE 1187
+#define WT_STAT_CONN_LOG_SLOT_YIELD_RACE 1199
/*! log: slot join calls did not yield */
-#define WT_STAT_CONN_LOG_SLOT_IMMEDIATE 1188
+#define WT_STAT_CONN_LOG_SLOT_IMMEDIATE 1200
/*! log: slot join calls found active slot closed */
-#define WT_STAT_CONN_LOG_SLOT_YIELD_CLOSE 1189
+#define WT_STAT_CONN_LOG_SLOT_YIELD_CLOSE 1201
/*! log: slot join calls slept */
-#define WT_STAT_CONN_LOG_SLOT_YIELD_SLEEP 1190
+#define WT_STAT_CONN_LOG_SLOT_YIELD_SLEEP 1202
/*! log: slot join calls yielded */
-#define WT_STAT_CONN_LOG_SLOT_YIELD 1191
+#define WT_STAT_CONN_LOG_SLOT_YIELD 1203
/*! log: slot join found active slot closed */
-#define WT_STAT_CONN_LOG_SLOT_ACTIVE_CLOSED 1192
+#define WT_STAT_CONN_LOG_SLOT_ACTIVE_CLOSED 1204
/*! log: slot joins yield time (usecs) */
-#define WT_STAT_CONN_LOG_SLOT_YIELD_DURATION 1193
+#define WT_STAT_CONN_LOG_SLOT_YIELD_DURATION 1205
/*! log: slot transitions unable to find free slot */
-#define WT_STAT_CONN_LOG_SLOT_NO_FREE_SLOTS 1194
+#define WT_STAT_CONN_LOG_SLOT_NO_FREE_SLOTS 1206
/*! log: slot unbuffered writes */
-#define WT_STAT_CONN_LOG_SLOT_UNBUFFERED 1195
+#define WT_STAT_CONN_LOG_SLOT_UNBUFFERED 1207
/*! log: total in-memory size of compressed records */
-#define WT_STAT_CONN_LOG_COMPRESS_MEM 1196
+#define WT_STAT_CONN_LOG_COMPRESS_MEM 1208
/*! log: total log buffer size */
-#define WT_STAT_CONN_LOG_BUFFER_SIZE 1197
+#define WT_STAT_CONN_LOG_BUFFER_SIZE 1209
/*! log: total size of compressed records */
-#define WT_STAT_CONN_LOG_COMPRESS_LEN 1198
+#define WT_STAT_CONN_LOG_COMPRESS_LEN 1210
/*! log: written slots coalesced */
-#define WT_STAT_CONN_LOG_SLOT_COALESCED 1199
+#define WT_STAT_CONN_LOG_SLOT_COALESCED 1211
/*! log: yields waiting for previous log file close */
-#define WT_STAT_CONN_LOG_CLOSE_YIELDS 1200
+#define WT_STAT_CONN_LOG_CLOSE_YIELDS 1212
/*! reconciliation: fast-path pages deleted */
-#define WT_STAT_CONN_REC_PAGE_DELETE_FAST 1201
+#define WT_STAT_CONN_REC_PAGE_DELETE_FAST 1213
/*! reconciliation: page reconciliation calls */
-#define WT_STAT_CONN_REC_PAGES 1202
+#define WT_STAT_CONN_REC_PAGES 1214
/*! reconciliation: page reconciliation calls for eviction */
-#define WT_STAT_CONN_REC_PAGES_EVICTION 1203
+#define WT_STAT_CONN_REC_PAGES_EVICTION 1215
/*! reconciliation: pages deleted */
-#define WT_STAT_CONN_REC_PAGE_DELETE 1204
+#define WT_STAT_CONN_REC_PAGE_DELETE 1216
/*! reconciliation: split bytes currently awaiting free */
-#define WT_STAT_CONN_REC_SPLIT_STASHED_BYTES 1205
+#define WT_STAT_CONN_REC_SPLIT_STASHED_BYTES 1217
/*! reconciliation: split objects currently awaiting free */
-#define WT_STAT_CONN_REC_SPLIT_STASHED_OBJECTS 1206
+#define WT_STAT_CONN_REC_SPLIT_STASHED_OBJECTS 1218
/*! session: open cursor count */
-#define WT_STAT_CONN_SESSION_CURSOR_OPEN 1207
+#define WT_STAT_CONN_SESSION_CURSOR_OPEN 1219
/*! session: open session count */
-#define WT_STAT_CONN_SESSION_OPEN 1208
+#define WT_STAT_CONN_SESSION_OPEN 1220
/*! session: table alter failed calls */
-#define WT_STAT_CONN_SESSION_TABLE_ALTER_FAIL 1209
+#define WT_STAT_CONN_SESSION_TABLE_ALTER_FAIL 1221
/*! session: table alter successful calls */
-#define WT_STAT_CONN_SESSION_TABLE_ALTER_SUCCESS 1210
+#define WT_STAT_CONN_SESSION_TABLE_ALTER_SUCCESS 1222
/*! session: table alter unchanged and skipped */
-#define WT_STAT_CONN_SESSION_TABLE_ALTER_SKIP 1211
+#define WT_STAT_CONN_SESSION_TABLE_ALTER_SKIP 1223
/*! session: table compact failed calls */
-#define WT_STAT_CONN_SESSION_TABLE_COMPACT_FAIL 1212
+#define WT_STAT_CONN_SESSION_TABLE_COMPACT_FAIL 1224
/*! session: table compact successful calls */
-#define WT_STAT_CONN_SESSION_TABLE_COMPACT_SUCCESS 1213
+#define WT_STAT_CONN_SESSION_TABLE_COMPACT_SUCCESS 1225
/*! session: table create failed calls */
-#define WT_STAT_CONN_SESSION_TABLE_CREATE_FAIL 1214
+#define WT_STAT_CONN_SESSION_TABLE_CREATE_FAIL 1226
/*! session: table create successful calls */
-#define WT_STAT_CONN_SESSION_TABLE_CREATE_SUCCESS 1215
+#define WT_STAT_CONN_SESSION_TABLE_CREATE_SUCCESS 1227
/*! session: table drop failed calls */
-#define WT_STAT_CONN_SESSION_TABLE_DROP_FAIL 1216
+#define WT_STAT_CONN_SESSION_TABLE_DROP_FAIL 1228
/*! session: table drop successful calls */
-#define WT_STAT_CONN_SESSION_TABLE_DROP_SUCCESS 1217
+#define WT_STAT_CONN_SESSION_TABLE_DROP_SUCCESS 1229
/*! session: table rebalance failed calls */
-#define WT_STAT_CONN_SESSION_TABLE_REBALANCE_FAIL 1218
+#define WT_STAT_CONN_SESSION_TABLE_REBALANCE_FAIL 1230
/*! session: table rebalance successful calls */
-#define WT_STAT_CONN_SESSION_TABLE_REBALANCE_SUCCESS 1219
+#define WT_STAT_CONN_SESSION_TABLE_REBALANCE_SUCCESS 1231
/*! session: table rename failed calls */
-#define WT_STAT_CONN_SESSION_TABLE_RENAME_FAIL 1220
+#define WT_STAT_CONN_SESSION_TABLE_RENAME_FAIL 1232
/*! session: table rename successful calls */
-#define WT_STAT_CONN_SESSION_TABLE_RENAME_SUCCESS 1221
+#define WT_STAT_CONN_SESSION_TABLE_RENAME_SUCCESS 1233
/*! session: table salvage failed calls */
-#define WT_STAT_CONN_SESSION_TABLE_SALVAGE_FAIL 1222
+#define WT_STAT_CONN_SESSION_TABLE_SALVAGE_FAIL 1234
/*! session: table salvage successful calls */
-#define WT_STAT_CONN_SESSION_TABLE_SALVAGE_SUCCESS 1223
+#define WT_STAT_CONN_SESSION_TABLE_SALVAGE_SUCCESS 1235
/*! session: table truncate failed calls */
-#define WT_STAT_CONN_SESSION_TABLE_TRUNCATE_FAIL 1224
+#define WT_STAT_CONN_SESSION_TABLE_TRUNCATE_FAIL 1236
/*! session: table truncate successful calls */
-#define WT_STAT_CONN_SESSION_TABLE_TRUNCATE_SUCCESS 1225
+#define WT_STAT_CONN_SESSION_TABLE_TRUNCATE_SUCCESS 1237
/*! session: table verify failed calls */
-#define WT_STAT_CONN_SESSION_TABLE_VERIFY_FAIL 1226
+#define WT_STAT_CONN_SESSION_TABLE_VERIFY_FAIL 1238
/*! session: table verify successful calls */
-#define WT_STAT_CONN_SESSION_TABLE_VERIFY_SUCCESS 1227
+#define WT_STAT_CONN_SESSION_TABLE_VERIFY_SUCCESS 1239
/*! thread-state: active filesystem fsync calls */
-#define WT_STAT_CONN_THREAD_FSYNC_ACTIVE 1228
+#define WT_STAT_CONN_THREAD_FSYNC_ACTIVE 1240
/*! thread-state: active filesystem read calls */
-#define WT_STAT_CONN_THREAD_READ_ACTIVE 1229
+#define WT_STAT_CONN_THREAD_READ_ACTIVE 1241
/*! thread-state: active filesystem write calls */
-#define WT_STAT_CONN_THREAD_WRITE_ACTIVE 1230
+#define WT_STAT_CONN_THREAD_WRITE_ACTIVE 1242
/*! thread-yield: application thread time evicting (usecs) */
-#define WT_STAT_CONN_APPLICATION_EVICT_TIME 1231
+#define WT_STAT_CONN_APPLICATION_EVICT_TIME 1243
/*! thread-yield: application thread time waiting for cache (usecs) */
-#define WT_STAT_CONN_APPLICATION_CACHE_TIME 1232
+#define WT_STAT_CONN_APPLICATION_CACHE_TIME 1244
/*! thread-yield: page acquire busy blocked */
-#define WT_STAT_CONN_PAGE_BUSY_BLOCKED 1233
+#define WT_STAT_CONN_PAGE_BUSY_BLOCKED 1245
/*! thread-yield: page acquire eviction blocked */
-#define WT_STAT_CONN_PAGE_FORCIBLE_EVICT_BLOCKED 1234
+#define WT_STAT_CONN_PAGE_FORCIBLE_EVICT_BLOCKED 1246
/*! thread-yield: page acquire locked blocked */
-#define WT_STAT_CONN_PAGE_LOCKED_BLOCKED 1235
+#define WT_STAT_CONN_PAGE_LOCKED_BLOCKED 1247
/*! thread-yield: page acquire read blocked */
-#define WT_STAT_CONN_PAGE_READ_BLOCKED 1236
+#define WT_STAT_CONN_PAGE_READ_BLOCKED 1248
/*! thread-yield: page acquire time sleeping (usecs) */
-#define WT_STAT_CONN_PAGE_SLEEP 1237
+#define WT_STAT_CONN_PAGE_SLEEP 1249
/*! transaction: number of named snapshots created */
-#define WT_STAT_CONN_TXN_SNAPSHOTS_CREATED 1238
+#define WT_STAT_CONN_TXN_SNAPSHOTS_CREATED 1250
/*! transaction: number of named snapshots dropped */
-#define WT_STAT_CONN_TXN_SNAPSHOTS_DROPPED 1239
+#define WT_STAT_CONN_TXN_SNAPSHOTS_DROPPED 1251
/*! transaction: transaction begins */
-#define WT_STAT_CONN_TXN_BEGIN 1240
+#define WT_STAT_CONN_TXN_BEGIN 1252
/*! transaction: transaction checkpoint currently running */
-#define WT_STAT_CONN_TXN_CHECKPOINT_RUNNING 1241
+#define WT_STAT_CONN_TXN_CHECKPOINT_RUNNING 1253
/*! transaction: transaction checkpoint generation */
-#define WT_STAT_CONN_TXN_CHECKPOINT_GENERATION 1242
+#define WT_STAT_CONN_TXN_CHECKPOINT_GENERATION 1254
/*! transaction: transaction checkpoint max time (msecs) */
-#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_MAX 1243
+#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_MAX 1255
/*! transaction: transaction checkpoint min time (msecs) */
-#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_MIN 1244
+#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_MIN 1256
/*! transaction: transaction checkpoint most recent time (msecs) */
-#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_RECENT 1245
+#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_RECENT 1257
/*! transaction: transaction checkpoint scrub dirty target */
-#define WT_STAT_CONN_TXN_CHECKPOINT_SCRUB_TARGET 1246
+#define WT_STAT_CONN_TXN_CHECKPOINT_SCRUB_TARGET 1258
/*! transaction: transaction checkpoint scrub time (msecs) */
-#define WT_STAT_CONN_TXN_CHECKPOINT_SCRUB_TIME 1247
+#define WT_STAT_CONN_TXN_CHECKPOINT_SCRUB_TIME 1259
/*! transaction: transaction checkpoint total time (msecs) */
-#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_TOTAL 1248
+#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_TOTAL 1260
/*! transaction: transaction checkpoints */
-#define WT_STAT_CONN_TXN_CHECKPOINT 1249
+#define WT_STAT_CONN_TXN_CHECKPOINT 1261
/*!
* transaction: transaction checkpoints skipped because database was
* clean
*/
-#define WT_STAT_CONN_TXN_CHECKPOINT_SKIPPED 1250
+#define WT_STAT_CONN_TXN_CHECKPOINT_SKIPPED 1262
/*! transaction: transaction failures due to cache overflow */
-#define WT_STAT_CONN_TXN_FAIL_CACHE 1251
+#define WT_STAT_CONN_TXN_FAIL_CACHE 1263
/*!
* transaction: transaction fsync calls for checkpoint after allocating
* the transaction ID
*/
-#define WT_STAT_CONN_TXN_CHECKPOINT_FSYNC_POST 1252
+#define WT_STAT_CONN_TXN_CHECKPOINT_FSYNC_POST 1264
/*!
* transaction: transaction fsync duration for checkpoint after
* allocating the transaction ID (usecs)
*/
-#define WT_STAT_CONN_TXN_CHECKPOINT_FSYNC_POST_DURATION 1253
+#define WT_STAT_CONN_TXN_CHECKPOINT_FSYNC_POST_DURATION 1265
/*! transaction: transaction range of IDs currently pinned */
-#define WT_STAT_CONN_TXN_PINNED_RANGE 1254
+#define WT_STAT_CONN_TXN_PINNED_RANGE 1266
/*! transaction: transaction range of IDs currently pinned by a checkpoint */
-#define WT_STAT_CONN_TXN_PINNED_CHECKPOINT_RANGE 1255
+#define WT_STAT_CONN_TXN_PINNED_CHECKPOINT_RANGE 1267
/*!
* transaction: transaction range of IDs currently pinned by named
* snapshots
*/
-#define WT_STAT_CONN_TXN_PINNED_SNAPSHOT_RANGE 1256
+#define WT_STAT_CONN_TXN_PINNED_SNAPSHOT_RANGE 1268
/*! transaction: transaction sync calls */
-#define WT_STAT_CONN_TXN_SYNC 1257
+#define WT_STAT_CONN_TXN_SYNC 1269
/*! transaction: transactions committed */
-#define WT_STAT_CONN_TXN_COMMIT 1258
+#define WT_STAT_CONN_TXN_COMMIT 1270
/*! transaction: transactions rolled back */
-#define WT_STAT_CONN_TXN_ROLLBACK 1259
+#define WT_STAT_CONN_TXN_ROLLBACK 1271
/*! transaction: update conflicts */
-#define WT_STAT_CONN_TXN_UPDATE_CONFLICT 1260
+#define WT_STAT_CONN_TXN_UPDATE_CONFLICT 1272
/*!
* @}
@@ -5192,219 +5240,268 @@ extern int wiredtiger_extension_terminate(WT_CONNECTION *connection);
#define WT_STAT_DSRC_CACHE_EVICTION_CHECKPOINT 2043
/*! cache: data source pages selected for eviction unable to be evicted */
#define WT_STAT_DSRC_CACHE_EVICTION_FAIL 2044
+/*! cache: eviction walk passes of a file */
+#define WT_STAT_DSRC_CACHE_EVICTION_WALK_PASSES 2045
+/*! cache: eviction walk target pages histogram - 0-9 */
+#define WT_STAT_DSRC_CACHE_EVICTION_TARGET_PAGE_LT10 2046
+/*! cache: eviction walk target pages histogram - 10-31 */
+#define WT_STAT_DSRC_CACHE_EVICTION_TARGET_PAGE_LT32 2047
+/*! cache: eviction walk target pages histogram - 128 and higher */
+#define WT_STAT_DSRC_CACHE_EVICTION_TARGET_PAGE_GE128 2048
+/*! cache: eviction walk target pages histogram - 32-63 */
+#define WT_STAT_DSRC_CACHE_EVICTION_TARGET_PAGE_LT64 2049
+/*! cache: eviction walk target pages histogram - 64-128 */
+#define WT_STAT_DSRC_CACHE_EVICTION_TARGET_PAGE_LT128 2050
+/*! cache: eviction walks abandoned */
+#define WT_STAT_DSRC_CACHE_EVICTION_WALKS_ABANDONED 2051
+/*! cache: eviction walks gave up because they restarted their walk twice */
+#define WT_STAT_DSRC_CACHE_EVICTION_WALKS_STOPPED 2052
+/*!
+ * cache: eviction walks gave up because they saw too many pages and
+ * found no candidates
+ */
+#define WT_STAT_DSRC_CACHE_EVICTION_WALKS_GAVE_UP_NO_TARGETS 2053
+/*!
+ * cache: eviction walks gave up because they saw too many pages and
+ * found too few candidates
+ */
+#define WT_STAT_DSRC_CACHE_EVICTION_WALKS_GAVE_UP_RATIO 2054
+/*! cache: eviction walks reached end of tree */
+#define WT_STAT_DSRC_CACHE_EVICTION_WALKS_ENDED 2055
+/*! cache: eviction walks started from root of tree */
+#define WT_STAT_DSRC_CACHE_EVICTION_WALK_FROM_ROOT 2056
+/*! cache: eviction walks started from saved location in tree */
+#define WT_STAT_DSRC_CACHE_EVICTION_WALK_SAVED_POS 2057
/*! cache: hazard pointer blocked page eviction */
-#define WT_STAT_DSRC_CACHE_EVICTION_HAZARD 2045
+#define WT_STAT_DSRC_CACHE_EVICTION_HAZARD 2058
/*! cache: in-memory page passed criteria to be split */
-#define WT_STAT_DSRC_CACHE_INMEM_SPLITTABLE 2046
+#define WT_STAT_DSRC_CACHE_INMEM_SPLITTABLE 2059
/*! cache: in-memory page splits */
-#define WT_STAT_DSRC_CACHE_INMEM_SPLIT 2047
+#define WT_STAT_DSRC_CACHE_INMEM_SPLIT 2060
/*! cache: internal pages evicted */
-#define WT_STAT_DSRC_CACHE_EVICTION_INTERNAL 2048
+#define WT_STAT_DSRC_CACHE_EVICTION_INTERNAL 2061
/*! cache: internal pages split during eviction */
-#define WT_STAT_DSRC_CACHE_EVICTION_SPLIT_INTERNAL 2049
+#define WT_STAT_DSRC_CACHE_EVICTION_SPLIT_INTERNAL 2062
/*! cache: leaf pages split during eviction */
-#define WT_STAT_DSRC_CACHE_EVICTION_SPLIT_LEAF 2050
+#define WT_STAT_DSRC_CACHE_EVICTION_SPLIT_LEAF 2063
/*! cache: modified pages evicted */
-#define WT_STAT_DSRC_CACHE_EVICTION_DIRTY 2051
+#define WT_STAT_DSRC_CACHE_EVICTION_DIRTY 2064
/*! cache: overflow pages read into cache */
-#define WT_STAT_DSRC_CACHE_READ_OVERFLOW 2052
-/*! cache: overflow values cached in memory */
-#define WT_STAT_DSRC_CACHE_OVERFLOW_VALUE 2053
+#define WT_STAT_DSRC_CACHE_READ_OVERFLOW 2065
/*! cache: page split during eviction deepened the tree */
-#define WT_STAT_DSRC_CACHE_EVICTION_DEEPEN 2054
+#define WT_STAT_DSRC_CACHE_EVICTION_DEEPEN 2066
/*! cache: page written requiring lookaside records */
-#define WT_STAT_DSRC_CACHE_WRITE_LOOKASIDE 2055
+#define WT_STAT_DSRC_CACHE_WRITE_LOOKASIDE 2067
/*! cache: pages read into cache */
-#define WT_STAT_DSRC_CACHE_READ 2056
+#define WT_STAT_DSRC_CACHE_READ 2068
/*! cache: pages read into cache requiring lookaside entries */
-#define WT_STAT_DSRC_CACHE_READ_LOOKASIDE 2057
+#define WT_STAT_DSRC_CACHE_READ_LOOKASIDE 2069
/*! cache: pages requested from the cache */
-#define WT_STAT_DSRC_CACHE_PAGES_REQUESTED 2058
+#define WT_STAT_DSRC_CACHE_PAGES_REQUESTED 2070
+/*! cache: pages seen by eviction walk */
+#define WT_STAT_DSRC_CACHE_EVICTION_PAGES_SEEN 2071
/*! cache: pages written from cache */
-#define WT_STAT_DSRC_CACHE_WRITE 2059
+#define WT_STAT_DSRC_CACHE_WRITE 2072
/*! cache: pages written requiring in-memory restoration */
-#define WT_STAT_DSRC_CACHE_WRITE_RESTORE 2060
+#define WT_STAT_DSRC_CACHE_WRITE_RESTORE 2073
/*! cache: tracked dirty bytes in the cache */
-#define WT_STAT_DSRC_CACHE_BYTES_DIRTY 2061
+#define WT_STAT_DSRC_CACHE_BYTES_DIRTY 2074
/*! cache: unmodified pages evicted */
-#define WT_STAT_DSRC_CACHE_EVICTION_CLEAN 2062
+#define WT_STAT_DSRC_CACHE_EVICTION_CLEAN 2075
/*!
* cache_walk: Average difference between current eviction generation
* when the page was last considered, only reported if cache_walk or all
* statistics are enabled
*/
-#define WT_STAT_DSRC_CACHE_STATE_GEN_AVG_GAP 2063
+#define WT_STAT_DSRC_CACHE_STATE_GEN_AVG_GAP 2076
/*!
* cache_walk: Average on-disk page image size seen, only reported if
* cache_walk or all statistics are enabled
*/
-#define WT_STAT_DSRC_CACHE_STATE_AVG_WRITTEN_SIZE 2064
+#define WT_STAT_DSRC_CACHE_STATE_AVG_WRITTEN_SIZE 2077
+/*!
+ * cache_walk: Average time in cache for pages that have been visited by
+ * the eviction server, only reported if cache_walk or all statistics are
+ * enabled
+ */
+#define WT_STAT_DSRC_CACHE_STATE_AVG_VISITED_AGE 2078
+/*!
+ * cache_walk: Average time in cache for pages that have not been visited
+ * by the eviction server, only reported if cache_walk or all statistics
+ * are enabled
+ */
+#define WT_STAT_DSRC_CACHE_STATE_AVG_UNVISITED_AGE 2079
/*!
* cache_walk: Clean pages currently in cache, only reported if
* cache_walk or all statistics are enabled
*/
-#define WT_STAT_DSRC_CACHE_STATE_PAGES_CLEAN 2065
+#define WT_STAT_DSRC_CACHE_STATE_PAGES_CLEAN 2080
/*!
* cache_walk: Current eviction generation, only reported if cache_walk
* or all statistics are enabled
*/
-#define WT_STAT_DSRC_CACHE_STATE_GEN_CURRENT 2066
+#define WT_STAT_DSRC_CACHE_STATE_GEN_CURRENT 2081
/*!
* cache_walk: Dirty pages currently in cache, only reported if
* cache_walk or all statistics are enabled
*/
-#define WT_STAT_DSRC_CACHE_STATE_PAGES_DIRTY 2067
+#define WT_STAT_DSRC_CACHE_STATE_PAGES_DIRTY 2082
/*!
* cache_walk: Entries in the root page, only reported if cache_walk or
* all statistics are enabled
*/
-#define WT_STAT_DSRC_CACHE_STATE_ROOT_ENTRIES 2068
+#define WT_STAT_DSRC_CACHE_STATE_ROOT_ENTRIES 2083
/*!
* cache_walk: Internal pages currently in cache, only reported if
* cache_walk or all statistics are enabled
*/
-#define WT_STAT_DSRC_CACHE_STATE_PAGES_INTERNAL 2069
+#define WT_STAT_DSRC_CACHE_STATE_PAGES_INTERNAL 2084
/*!
* cache_walk: Leaf pages currently in cache, only reported if cache_walk
* or all statistics are enabled
*/
-#define WT_STAT_DSRC_CACHE_STATE_PAGES_LEAF 2070
+#define WT_STAT_DSRC_CACHE_STATE_PAGES_LEAF 2085
/*!
* cache_walk: Maximum difference between current eviction generation
* when the page was last considered, only reported if cache_walk or all
* statistics are enabled
*/
-#define WT_STAT_DSRC_CACHE_STATE_GEN_MAX_GAP 2071
+#define WT_STAT_DSRC_CACHE_STATE_GEN_MAX_GAP 2086
/*!
* cache_walk: Maximum page size seen, only reported if cache_walk or all
* statistics are enabled
*/
-#define WT_STAT_DSRC_CACHE_STATE_MAX_PAGESIZE 2072
+#define WT_STAT_DSRC_CACHE_STATE_MAX_PAGESIZE 2087
/*!
* cache_walk: Minimum on-disk page image size seen, only reported if
* cache_walk or all statistics are enabled
*/
-#define WT_STAT_DSRC_CACHE_STATE_MIN_WRITTEN_SIZE 2073
+#define WT_STAT_DSRC_CACHE_STATE_MIN_WRITTEN_SIZE 2088
+/*!
+ * cache_walk: Number of pages never visited by eviction server, only
+ * reported if cache_walk or all statistics are enabled
+ */
+#define WT_STAT_DSRC_CACHE_STATE_UNVISITED_COUNT 2089
/*!
* cache_walk: On-disk page image sizes smaller than a single allocation
* unit, only reported if cache_walk or all statistics are enabled
*/
-#define WT_STAT_DSRC_CACHE_STATE_SMALLER_ALLOC_SIZE 2074
+#define WT_STAT_DSRC_CACHE_STATE_SMALLER_ALLOC_SIZE 2090
/*!
* cache_walk: Pages created in memory and never written, only reported
* if cache_walk or all statistics are enabled
*/
-#define WT_STAT_DSRC_CACHE_STATE_MEMORY 2075
+#define WT_STAT_DSRC_CACHE_STATE_MEMORY 2091
/*!
* cache_walk: Pages currently queued for eviction, only reported if
* cache_walk or all statistics are enabled
*/
-#define WT_STAT_DSRC_CACHE_STATE_QUEUED 2076
+#define WT_STAT_DSRC_CACHE_STATE_QUEUED 2092
/*!
* cache_walk: Pages that could not be queued for eviction, only reported
* if cache_walk or all statistics are enabled
*/
-#define WT_STAT_DSRC_CACHE_STATE_NOT_QUEUEABLE 2077
+#define WT_STAT_DSRC_CACHE_STATE_NOT_QUEUEABLE 2093
/*!
* cache_walk: Refs skipped during cache traversal, only reported if
* cache_walk or all statistics are enabled
*/
-#define WT_STAT_DSRC_CACHE_STATE_REFS_SKIPPED 2078
+#define WT_STAT_DSRC_CACHE_STATE_REFS_SKIPPED 2094
/*!
* cache_walk: Size of the root page, only reported if cache_walk or all
* statistics are enabled
*/
-#define WT_STAT_DSRC_CACHE_STATE_ROOT_SIZE 2079
+#define WT_STAT_DSRC_CACHE_STATE_ROOT_SIZE 2095
/*!
* cache_walk: Total number of pages currently in cache, only reported if
* cache_walk or all statistics are enabled
*/
-#define WT_STAT_DSRC_CACHE_STATE_PAGES 2080
+#define WT_STAT_DSRC_CACHE_STATE_PAGES 2096
/*! compression: compressed pages read */
-#define WT_STAT_DSRC_COMPRESS_READ 2081
+#define WT_STAT_DSRC_COMPRESS_READ 2097
/*! compression: compressed pages written */
-#define WT_STAT_DSRC_COMPRESS_WRITE 2082
+#define WT_STAT_DSRC_COMPRESS_WRITE 2098
/*! compression: page written failed to compress */
-#define WT_STAT_DSRC_COMPRESS_WRITE_FAIL 2083
+#define WT_STAT_DSRC_COMPRESS_WRITE_FAIL 2099
/*! compression: page written was too small to compress */
-#define WT_STAT_DSRC_COMPRESS_WRITE_TOO_SMALL 2084
+#define WT_STAT_DSRC_COMPRESS_WRITE_TOO_SMALL 2100
/*! compression: raw compression call failed, additional data available */
-#define WT_STAT_DSRC_COMPRESS_RAW_FAIL_TEMPORARY 2085
+#define WT_STAT_DSRC_COMPRESS_RAW_FAIL_TEMPORARY 2101
/*! compression: raw compression call failed, no additional data available */
-#define WT_STAT_DSRC_COMPRESS_RAW_FAIL 2086
+#define WT_STAT_DSRC_COMPRESS_RAW_FAIL 2102
/*! compression: raw compression call succeeded */
-#define WT_STAT_DSRC_COMPRESS_RAW_OK 2087
+#define WT_STAT_DSRC_COMPRESS_RAW_OK 2103
/*! cursor: bulk-loaded cursor-insert calls */
-#define WT_STAT_DSRC_CURSOR_INSERT_BULK 2088
+#define WT_STAT_DSRC_CURSOR_INSERT_BULK 2104
/*! cursor: create calls */
-#define WT_STAT_DSRC_CURSOR_CREATE 2089
+#define WT_STAT_DSRC_CURSOR_CREATE 2105
/*! cursor: cursor-insert key and value bytes inserted */
-#define WT_STAT_DSRC_CURSOR_INSERT_BYTES 2090
+#define WT_STAT_DSRC_CURSOR_INSERT_BYTES 2106
/*! cursor: cursor-remove key bytes removed */
-#define WT_STAT_DSRC_CURSOR_REMOVE_BYTES 2091
+#define WT_STAT_DSRC_CURSOR_REMOVE_BYTES 2107
/*! cursor: cursor-update value bytes updated */
-#define WT_STAT_DSRC_CURSOR_UPDATE_BYTES 2092
+#define WT_STAT_DSRC_CURSOR_UPDATE_BYTES 2108
/*! cursor: insert calls */
-#define WT_STAT_DSRC_CURSOR_INSERT 2093
+#define WT_STAT_DSRC_CURSOR_INSERT 2109
/*! cursor: modify calls */
-#define WT_STAT_DSRC_CURSOR_MODIFY 2094
+#define WT_STAT_DSRC_CURSOR_MODIFY 2110
/*! cursor: next calls */
-#define WT_STAT_DSRC_CURSOR_NEXT 2095
+#define WT_STAT_DSRC_CURSOR_NEXT 2111
/*! cursor: prev calls */
-#define WT_STAT_DSRC_CURSOR_PREV 2096
+#define WT_STAT_DSRC_CURSOR_PREV 2112
/*! cursor: remove calls */
-#define WT_STAT_DSRC_CURSOR_REMOVE 2097
+#define WT_STAT_DSRC_CURSOR_REMOVE 2113
/*! cursor: reserve calls */
-#define WT_STAT_DSRC_CURSOR_RESERVE 2098
+#define WT_STAT_DSRC_CURSOR_RESERVE 2114
/*! cursor: reset calls */
-#define WT_STAT_DSRC_CURSOR_RESET 2099
+#define WT_STAT_DSRC_CURSOR_RESET 2115
/*! cursor: restarted searches */
-#define WT_STAT_DSRC_CURSOR_RESTART 2100
+#define WT_STAT_DSRC_CURSOR_RESTART 2116
/*! cursor: search calls */
-#define WT_STAT_DSRC_CURSOR_SEARCH 2101
+#define WT_STAT_DSRC_CURSOR_SEARCH 2117
/*! cursor: search near calls */
-#define WT_STAT_DSRC_CURSOR_SEARCH_NEAR 2102
+#define WT_STAT_DSRC_CURSOR_SEARCH_NEAR 2118
/*! cursor: truncate calls */
-#define WT_STAT_DSRC_CURSOR_TRUNCATE 2103
+#define WT_STAT_DSRC_CURSOR_TRUNCATE 2119
/*! cursor: update calls */
-#define WT_STAT_DSRC_CURSOR_UPDATE 2104
+#define WT_STAT_DSRC_CURSOR_UPDATE 2120
/*! reconciliation: dictionary matches */
-#define WT_STAT_DSRC_REC_DICTIONARY 2105
+#define WT_STAT_DSRC_REC_DICTIONARY 2121
/*! reconciliation: fast-path pages deleted */
-#define WT_STAT_DSRC_REC_PAGE_DELETE_FAST 2106
+#define WT_STAT_DSRC_REC_PAGE_DELETE_FAST 2122
/*!
* reconciliation: internal page key bytes discarded using suffix
* compression
*/
-#define WT_STAT_DSRC_REC_SUFFIX_COMPRESSION 2107
+#define WT_STAT_DSRC_REC_SUFFIX_COMPRESSION 2123
/*! reconciliation: internal page multi-block writes */
-#define WT_STAT_DSRC_REC_MULTIBLOCK_INTERNAL 2108
+#define WT_STAT_DSRC_REC_MULTIBLOCK_INTERNAL 2124
/*! reconciliation: internal-page overflow keys */
-#define WT_STAT_DSRC_REC_OVERFLOW_KEY_INTERNAL 2109
+#define WT_STAT_DSRC_REC_OVERFLOW_KEY_INTERNAL 2125
/*! reconciliation: leaf page key bytes discarded using prefix compression */
-#define WT_STAT_DSRC_REC_PREFIX_COMPRESSION 2110
+#define WT_STAT_DSRC_REC_PREFIX_COMPRESSION 2126
/*! reconciliation: leaf page multi-block writes */
-#define WT_STAT_DSRC_REC_MULTIBLOCK_LEAF 2111
+#define WT_STAT_DSRC_REC_MULTIBLOCK_LEAF 2127
/*! reconciliation: leaf-page overflow keys */
-#define WT_STAT_DSRC_REC_OVERFLOW_KEY_LEAF 2112
+#define WT_STAT_DSRC_REC_OVERFLOW_KEY_LEAF 2128
/*! reconciliation: maximum blocks required for a page */
-#define WT_STAT_DSRC_REC_MULTIBLOCK_MAX 2113
+#define WT_STAT_DSRC_REC_MULTIBLOCK_MAX 2129
/*! reconciliation: overflow values written */
-#define WT_STAT_DSRC_REC_OVERFLOW_VALUE 2114
+#define WT_STAT_DSRC_REC_OVERFLOW_VALUE 2130
/*! reconciliation: page checksum matches */
-#define WT_STAT_DSRC_REC_PAGE_MATCH 2115
+#define WT_STAT_DSRC_REC_PAGE_MATCH 2131
/*! reconciliation: page reconciliation calls */
-#define WT_STAT_DSRC_REC_PAGES 2116
+#define WT_STAT_DSRC_REC_PAGES 2132
/*! reconciliation: page reconciliation calls for eviction */
-#define WT_STAT_DSRC_REC_PAGES_EVICTION 2117
+#define WT_STAT_DSRC_REC_PAGES_EVICTION 2133
/*! reconciliation: pages deleted */
-#define WT_STAT_DSRC_REC_PAGE_DELETE 2118
+#define WT_STAT_DSRC_REC_PAGE_DELETE 2134
/*! session: object compaction */
-#define WT_STAT_DSRC_SESSION_COMPACT 2119
+#define WT_STAT_DSRC_SESSION_COMPACT 2135
/*! session: open cursor count */
-#define WT_STAT_DSRC_SESSION_CURSOR_OPEN 2120
+#define WT_STAT_DSRC_SESSION_CURSOR_OPEN 2136
/*! transaction: update conflicts */
-#define WT_STAT_DSRC_TXN_UPDATE_CONFLICT 2121
+#define WT_STAT_DSRC_TXN_UPDATE_CONFLICT 2137
/*!
* @}
diff --git a/src/third_party/wiredtiger/src/include/wt_internal.h b/src/third_party/wiredtiger/src/include/wt_internal.h
index 1c9600dd27f..74fdc4c3925 100644
--- a/src/third_party/wiredtiger/src/include/wt_internal.h
+++ b/src/third_party/wiredtiger/src/include/wt_internal.h
@@ -250,8 +250,6 @@ struct __wt_ovfl_reuse;
typedef struct __wt_ovfl_reuse WT_OVFL_REUSE;
struct __wt_ovfl_track;
typedef struct __wt_ovfl_track WT_OVFL_TRACK;
-struct __wt_ovfl_txnc;
- typedef struct __wt_ovfl_txnc WT_OVFL_TXNC;
struct __wt_page;
typedef struct __wt_page WT_PAGE;
struct __wt_page_deleted;
diff --git a/src/third_party/wiredtiger/src/log/log.c b/src/third_party/wiredtiger/src/log/log.c
index 868f5d0eaf4..2a912e6568f 100644
--- a/src/third_party/wiredtiger/src/log/log.c
+++ b/src/third_party/wiredtiger/src/log/log.c
@@ -9,8 +9,7 @@
#include "wt_internal.h"
static int __log_newfile(WT_SESSION_IMPL *, bool, bool *);
-static int __log_openfile(
- WT_SESSION_IMPL *, WT_FH **, const char *, uint32_t, uint32_t);
+static int __log_openfile(WT_SESSION_IMPL *, uint32_t, uint32_t, WT_FH **);
static int __log_write_internal(
WT_SESSION_IMPL *, WT_ITEM *, WT_LSN *, uint32_t);
@@ -19,7 +18,109 @@ static int __log_write_internal(
/* Flags to __log_openfile */
#define WT_LOG_OPEN_CREATE_OK 0x01
-#define WT_LOG_OPEN_VERIFY 0x02
+
+/*
+ * __log_printf_internal --
+ * Internal call to write a log message.
+ */
+static int
+__log_printf_internal(WT_SESSION_IMPL *session, const char *fmt, ...)
+{
+ WT_DECL_RET;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = __wt_log_vprintf(session, fmt, ap);
+ va_end(ap);
+ return (ret);
+}
+
+/*
+ * __log_checksum_match --
+ * Given a log record, return whether the checksum matches.
+ */
+static bool
+__log_checksum_match(WT_SESSION_IMPL *session, WT_ITEM *buf, uint32_t reclen)
+{
+ WT_LOG_RECORD *logrec;
+ uint32_t checksum_calculate, checksum_tmp;
+
+ WT_UNUSED(session);
+ logrec = (WT_LOG_RECORD *)buf->mem;
+ checksum_tmp = logrec->checksum;
+ logrec->checksum = 0;
+ checksum_calculate = __wt_checksum(logrec, reclen);
+#ifdef WORDS_BIGENDIAN
+ checksum_calculate = __wt_bswap32(checksum_calculate);
+#endif
+ logrec->checksum = checksum_tmp;
+ if (logrec->checksum != checksum_calculate)
+ return (false);
+ else
+ return (true);
+}
+
+/*
+ * __log_get_files --
+ * Retrieve the list of all log-related files of the given prefix type.
+ */
+static int
+__log_get_files(WT_SESSION_IMPL *session,
+ const char *file_prefix, char ***filesp, u_int *countp)
+{
+ WT_CONNECTION_IMPL *conn;
+ const char *log_path;
+
+ *countp = 0;
+ *filesp = NULL;
+
+ conn = S2C(session);
+ log_path = conn->log_path;
+ if (log_path == NULL)
+ log_path = "";
+ return (__wt_fs_directory_list(
+ session, log_path, file_prefix, filesp, countp));
+}
+
+/*
+ * __log_prealloc_remove --
+ * Remove all previously created pre-allocated files.
+ */
+static int
+__log_prealloc_remove(WT_SESSION_IMPL *session)
+{
+ WT_DECL_RET;
+ WT_LOG *log;
+ uint32_t lognum;
+ u_int i, logcount;
+ char **logfiles;
+
+ logfiles = NULL;
+ logcount = 0;
+ log = S2C(session)->log;
+ __wt_spin_lock(session, &log->log_fs_lock);
+ /*
+ * Clean up any old interim pre-allocated files. We clean
+ * up these files because settings may have changed upon reboot
+ * and we want those settings to take effect right away.
+ */
+ WT_ERR(__log_get_files(session,
+ WT_LOG_TMPNAME, &logfiles, &logcount));
+ for (i = 0; i < logcount; i++) {
+ WT_ERR(__wt_log_extract_lognum(session, logfiles[i], &lognum));
+ WT_ERR(__wt_log_remove(session, WT_LOG_TMPNAME, lognum));
+ }
+ WT_ERR(__wt_fs_directory_list_free(session, &logfiles, logcount));
+ WT_ERR(__log_get_files(session,
+ WT_LOG_PREPNAME, &logfiles, &logcount));
+ for (i = 0; i < logcount; i++) {
+ WT_ERR(__wt_log_extract_lognum(session, logfiles[i], &lognum));
+ WT_ERR(__wt_log_remove(session, WT_LOG_PREPNAME, lognum));
+ }
+err: WT_TRET(__wt_fs_directory_list_free(session, &logfiles, logcount));
+ __wt_spin_unlock(session, &log->log_fs_lock);
+ return (ret);
+}
/*
* __log_wait_for_earlier_slot --
@@ -66,11 +167,13 @@ __log_fs_write(WT_SESSION_IMPL *session,
WT_DECL_RET;
/*
- * If we're writing into a new log file, we have to wait for all
+ * If we're writing into a new log file and we're running in
+ * compatibility mode to an older release, we have to wait for all
* writes to the previous log file to complete otherwise there could
* be a hole at the end of the previous log file that we cannot detect.
*/
- if (slot->slot_release_lsn.l.file < slot->slot_start_lsn.l.file) {
+ if (S2C(session)->log->log_version != WT_LOG_VERSION &&
+ slot->slot_release_lsn.l.file < slot->slot_start_lsn.l.file) {
__log_wait_for_earlier_slot(session, slot);
WT_RET(__wt_log_force_sync(session, &slot->slot_release_lsn));
}
@@ -208,8 +311,7 @@ __wt_log_force_sync(WT_SESSION_IMPL *session, WT_LSN *min_lsn)
* from under us and either be NULL or point to a different
* file than we want.
*/
- WT_ERR(__log_openfile(session,
- &log_fh, WT_LOG_FILENAME, min_lsn->l.file, 0));
+ WT_ERR(__log_openfile(session, min_lsn->l.file, 0, &log_fh));
__wt_verbose(session, WT_VERB_LOG,
"log_force_sync: sync %s to LSN %" PRIu32 "/%" PRIu32,
log_fh->name, min_lsn->l.file, min_lsn->l.offset);
@@ -314,28 +416,6 @@ __wt_log_written_reset(WT_SESSION_IMPL *session)
}
/*
- * __log_get_files --
- * Retrieve the list of all log-related files of the given prefix type.
- */
-static int
-__log_get_files(WT_SESSION_IMPL *session,
- const char *file_prefix, char ***filesp, u_int *countp)
-{
- WT_CONNECTION_IMPL *conn;
- const char *log_path;
-
- *countp = 0;
- *filesp = NULL;
-
- conn = S2C(session);
- log_path = conn->log_path;
- if (log_path == NULL)
- log_path = "";
- return (__wt_fs_directory_list(
- session, log_path, file_prefix, filesp, countp));
-}
-
-/*
* __wt_log_get_all_files --
* Retrieve the list of log files, either all of them or only the active
* ones (those that are not candidates for archiving). The caller is
@@ -571,7 +651,7 @@ __log_prealloc(WT_SESSION_IMPL *session, WT_FH *fh)
*/
if (FLD_ISSET(conn->log_flags, WT_CONN_LOG_ZERO_FILL))
return (__log_zero(session, fh,
- WT_LOG_FIRST_RECORD, conn->log_file_max));
+ WT_LOG_END_HEADER, conn->log_file_max));
/*
* We have exclusive access to the log file and there are no other
@@ -593,7 +673,7 @@ __log_size_fit(WT_SESSION_IMPL *session, WT_LSN *lsn, uint64_t recsize)
conn = S2C(session);
log = conn->log;
- return (lsn->l.offset == WT_LOG_FIRST_RECORD ||
+ return (lsn->l.offset == log->first_record ||
lsn->l.offset + (wt_off_t)recsize < conn->log_file_max);
}
@@ -662,17 +742,17 @@ __log_decrypt(WT_SESSION_IMPL *session, WT_ITEM *in, WT_ITEM *out)
}
/*
- * __log_fill --
+ * __wt_log_fill --
* Copy a thread's log records into the assigned slot.
*/
-static int
-__log_fill(WT_SESSION_IMPL *session,
+int
+__wt_log_fill(WT_SESSION_IMPL *session,
WT_MYSLOT *myslot, bool force, WT_ITEM *record, WT_LSN *lsnp)
{
WT_DECL_RET;
/*
- * Call __wt_write or copy into the buffer. For now the offset is the
+ * Call write or copy into the buffer. For now the offset is the
* real byte offset. If the offset becomes a unit of WT_LOG_ALIGN this
* is where we would multiply by WT_LOG_ALIGN to get the real file byte
* offset for write().
@@ -733,8 +813,7 @@ __log_file_header(
logrec = (WT_LOG_RECORD *)buf->mem;
desc = (WT_LOG_DESC *)logrec->record;
desc->log_magic = WT_LOG_MAGIC;
- desc->majorv = WT_LOG_MAJOR_VERSION;
- desc->minorv = WT_LOG_MINOR_VERSION;
+ desc->version = log->log_version;
desc->log_size = (uint64_t)conn->log_file_max;
__wt_log_desc_byteswap(desc);
@@ -759,7 +838,7 @@ __log_file_header(
/*
* We may recursively call __wt_log_acquire to allocate log space for
- * the log descriptor record. Call __log_fill to write it, but we
+ * the log descriptor record. Call __wt_log_fill to write it, but we
* do not need to call __wt_log_release because we're not waiting for
* any earlier operations to complete.
*/
@@ -770,7 +849,7 @@ __log_file_header(
WT_ASSERT(session, fh == NULL);
WT_ERR(__wt_log_acquire(session, log->allocsize, &tmp));
}
- WT_ERR(__log_fill(session, &myslot, true, buf, NULL));
+ WT_ERR(__wt_log_fill(session, &myslot, true, buf, NULL));
/*
* Make sure the header gets to disk.
*/
@@ -787,63 +866,143 @@ err: __wt_scr_free(session, &buf);
* Open a log file with the given log file number and return the WT_FH.
*/
static int
-__log_openfile(WT_SESSION_IMPL *session,
- WT_FH **fhp, const char *file_prefix, uint32_t id, uint32_t flags)
+__log_openfile(
+ WT_SESSION_IMPL *session, uint32_t id, uint32_t flags, WT_FH **fhp)
{
WT_CONNECTION_IMPL *conn;
WT_DECL_ITEM(buf);
WT_DECL_RET;
- WT_LOG *log;
- WT_LOG_DESC *desc;
- WT_LOG_RECORD *logrec;
- uint32_t allocsize;
u_int wtopen_flags;
conn = S2C(session);
- log = conn->log;
- if (log == NULL)
- allocsize = WT_LOG_ALIGN;
- else
- allocsize = log->allocsize;
WT_RET(__wt_scr_alloc(session, 0, &buf));
- WT_ERR(__log_filename(session, id, file_prefix, buf));
+ /*
+ * If we are creating the file then we use a temporary file name.
+ * Otherwise it is a log file name.
+ */
+ if (LF_ISSET(WT_LOG_OPEN_CREATE_OK)) {
+ wtopen_flags = WT_FS_OPEN_CREATE;
+ WT_ERR(__log_filename(session, id, WT_LOG_TMPNAME, buf));
+ } else {
+ wtopen_flags = 0;
+ WT_ERR(__log_filename(session, id, WT_LOG_FILENAME, buf));
+ }
__wt_verbose(session, WT_VERB_LOG,
"opening log %s", (const char *)buf->data);
- wtopen_flags = 0;
- if (LF_ISSET(WT_LOG_OPEN_CREATE_OK))
- FLD_SET(wtopen_flags, WT_FS_OPEN_CREATE);
if (FLD_ISSET(conn->direct_io, WT_DIRECT_IO_LOG))
FLD_SET(wtopen_flags, WT_FS_OPEN_DIRECTIO);
WT_ERR(__wt_open(
session, buf->data, WT_FS_OPEN_FILE_TYPE_LOG, wtopen_flags, fhp));
+err: __wt_scr_free(session, &buf);
+ return (ret);
+}
+
+/*
+ * __log_open_verify --
+ * Open a log file with the given log file number, verify its
+ * header and return various pieces of system information about
+ * this log file.
+ */
+static int
+__log_open_verify(WT_SESSION_IMPL *session, uint32_t id, WT_FH **fhp,
+ WT_LSN *lsnp, uint16_t *versionp)
+{
+ WT_CONNECTION_IMPL *conn;
+ WT_DECL_ITEM(buf);
+ WT_DECL_RET;
+ WT_FH *fh;
+ WT_LOG *log;
+ WT_LOG_DESC *desc;
+ WT_LOG_RECORD *logrec;
+ uint32_t allocsize, rectype;
+ const uint8_t *end, *p;
+
+ conn = S2C(session);
+ log = conn->log;
+ WT_RET(__wt_scr_alloc(session, 0, &buf));
+ WT_ERR(__log_openfile(session, id, 0, &fh));
+
+ if (log == NULL)
+ allocsize = WT_LOG_ALIGN;
+ else
+ allocsize = log->allocsize;
+ if (lsnp != NULL)
+ WT_ZERO_LSN(lsnp);
+ WT_ERR(__wt_buf_grow(session, buf, allocsize));
+ memset(buf->mem, 0, allocsize);
/*
- * If we are not creating the log file but opening it for reading,
- * check that the magic number and versions are correct.
+ * Read in the log file header and verify it.
*/
- if (LF_ISSET(WT_LOG_OPEN_VERIFY)) {
- WT_ERR(__wt_buf_grow(session, buf, allocsize));
- memset(buf->mem, 0, allocsize);
- WT_ERR(__wt_read(session, *fhp, 0, allocsize, buf->mem));
- logrec = (WT_LOG_RECORD *)buf->mem;
- __wt_log_record_byteswap(logrec);
- desc = (WT_LOG_DESC *)logrec->record;
- __wt_log_desc_byteswap(desc);
- if (desc->log_magic != WT_LOG_MAGIC)
- WT_PANIC_RET(session, WT_ERROR,
- "log file %s corrupted: Bad magic number %" PRIu32,
- (*fhp)->name, desc->log_magic);
- if (desc->majorv > WT_LOG_MAJOR_VERSION ||
- (desc->majorv == WT_LOG_MAJOR_VERSION &&
- desc->minorv > WT_LOG_MINOR_VERSION))
- WT_ERR_MSG(session, WT_ERROR,
- "unsupported WiredTiger file version: this build "
- " only supports major/minor versions up to %d/%d, "
- " and the file is version %" PRIu16 "/%" PRIu16,
- WT_LOG_MAJOR_VERSION, WT_LOG_MINOR_VERSION,
- desc->majorv, desc->minorv);
+ WT_ERR(__wt_read(session, fh, 0, allocsize, buf->mem));
+ logrec = (WT_LOG_RECORD *)buf->mem;
+ __wt_log_record_byteswap(logrec);
+ desc = (WT_LOG_DESC *)logrec->record;
+ __wt_log_desc_byteswap(desc);
+ if (desc->log_magic != WT_LOG_MAGIC)
+ WT_PANIC_RET(session, WT_ERROR,
+ "log file %s corrupted: Bad magic number %" PRIu32,
+ fh->name, desc->log_magic);
+ /*
+ * We cannot read future log file formats.
+ */
+ if (desc->version > WT_LOG_VERSION)
+ WT_ERR_MSG(session, WT_ERROR,
+ "unsupported WiredTiger file version: this build "
+ " only supports versions up to %d,"
+ " and the file is version %" PRIu16,
+ WT_LOG_VERSION, desc->version);
+
+ /*
+ * Set up the return values if the magic number is valid.
+ */
+ if (versionp != NULL)
+ *versionp = desc->version;
+
+ /*
+ * Skip reading in the previous LSN if log file is an old version
+ * or if the caller doesn't care about the LSN. Otherwise read that
+ * record in and set up the LSN. We already have a buffer that is
+ * the correct size. Reuse it.
+ */
+ if (lsnp == NULL ||
+ (desc->version < WT_LOG_VERSION_SYSTEM))
+ goto err;
+
+ memset(buf->mem, 0, allocsize);
+ WT_ERR(__wt_read(session, fh, allocsize, allocsize, buf->mem));
+ logrec = (WT_LOG_RECORD *)buf->mem;
+ /*
+ * We have a valid header but the system record is not there.
+ * The log ends here. Return without setting the LSN.
+ */
+ if (logrec->len == 0) {
+ __wt_verbose(session, WT_VERB_LOG,
+ "Log %s found empty log after header", fh->name);
+ goto err;
}
+
+ if (!__log_checksum_match(session, buf, allocsize))
+ WT_ERR_MSG(session, WT_ERROR,
+ "%s: System log record checksum mismatch", fh->name);
+ __wt_log_record_byteswap(logrec);
+ p = WT_LOG_SKIP_HEADER(buf->data);
+ end = (const uint8_t *)buf->data + allocsize;
+ WT_ERR(__wt_logrec_read(session, &p, end, &rectype));
+ if (rectype != WT_LOGREC_SYSTEM)
+ WT_ERR_MSG(session, WT_ERROR, "System log record missing");
+ WT_ERR(__wt_log_recover_system(session, &p, end, lsnp));
+
err: __wt_scr_free(session, &buf);
+
+ /*
+ * Return the file handle if needed, otherwise close it.
+ */
+ if (fhp != NULL && ret == 0)
+ *fhp = fh;
+ else
+ WT_TRET(__wt_close(session, &fh));
+
return (ret);
}
@@ -858,6 +1017,7 @@ __log_alloc_prealloc(WT_SESSION_IMPL *session, uint32_t to_num)
WT_DECL_ITEM(from_path);
WT_DECL_ITEM(to_path);
WT_DECL_RET;
+ WT_LOG *log;
uint32_t from_num;
u_int logcount;
char **logfiles;
@@ -865,6 +1025,7 @@ __log_alloc_prealloc(WT_SESSION_IMPL *session, uint32_t to_num)
/*
* If there are no pre-allocated files, return WT_NOTFOUND.
*/
+ log = S2C(session)->log;
logfiles = NULL;
WT_ERR(__log_get_files(session, WT_LOG_PREPNAME, &logfiles, &logcount));
if (logcount == 0)
@@ -879,6 +1040,7 @@ __log_alloc_prealloc(WT_SESSION_IMPL *session, uint32_t to_num)
WT_ERR(__wt_scr_alloc(session, 0, &to_path));
WT_ERR(__log_filename(session, from_num, WT_LOG_PREPNAME, from_path));
WT_ERR(__log_filename(session, to_num, WT_LOG_FILENAME, to_path));
+ __wt_spin_lock(session, &log->log_fs_lock);
__wt_verbose(session, WT_VERB_LOG,
"log_alloc_prealloc: rename log %s to %s",
(const char *)from_path->data, (const char *)to_path->data);
@@ -891,6 +1053,7 @@ __log_alloc_prealloc(WT_SESSION_IMPL *session, uint32_t to_num)
err: __wt_scr_free(session, &from_path);
__wt_scr_free(session, &to_path);
+ __wt_spin_unlock(session, &log->log_fs_lock);
WT_TRET(__wt_fs_directory_list_free(session, &logfiles, logcount));
return (ret);
}
@@ -906,7 +1069,7 @@ __log_newfile(WT_SESSION_IMPL *session, bool conn_open, bool *created)
WT_DECL_RET;
WT_FH *log_fh;
WT_LOG *log;
- WT_LSN end_lsn;
+ WT_LSN end_lsn, logrec_lsn;
u_int yield_cnt;
bool create_log;
@@ -941,7 +1104,7 @@ __log_newfile(WT_SESSION_IMPL *session, bool conn_open, bool *created)
/*
* If pre-allocating log files look for one; otherwise, or if we don't
- * find one create a log file. We can't use pre-allocated log files in
+ * find one, create a log file. We can't use pre-allocated log files
* while a hot backup is in progress: applications can copy the files
* in any way they choose, and a log file rename might confuse things.
*/
@@ -986,15 +1149,31 @@ __log_newfile(WT_SESSION_IMPL *session, bool conn_open, bool *created)
* we must pass in a local file handle. Otherwise there is a wide
* window where another thread could see a NULL log file handle.
*/
- WT_RET(__log_openfile(session,
- &log_fh, WT_LOG_FILENAME, log->fileid, 0));
- WT_PUBLISH(log->log_fh, log_fh);
+ WT_RET(__log_open_verify(session, log->fileid, &log_fh, NULL, NULL));
+ /*
+ * Write the LSN at the end of the last record in the previous log file
+ * as the first record in this log file.
+ */
+ if (log->fileid == 1)
+ WT_INIT_LSN(&logrec_lsn);
+ else
+ logrec_lsn = log->alloc_lsn;
/*
* We need to setup the LSNs. Set the end LSN and alloc LSN to
* the end of the header.
*/
- WT_SET_LSN(&log->alloc_lsn, log->fileid, WT_LOG_FIRST_RECORD);
+ WT_SET_LSN(&log->alloc_lsn, log->fileid, WT_LOG_END_HEADER);
+ /*
+ * If we're running the version where we write a system record
+ * do so now and update the alloc_lsn.
+ */
+ if (log->log_version == WT_LOG_VERSION) {
+ WT_RET(__wt_log_system_record(session,
+ log_fh, &logrec_lsn));
+ WT_SET_LSN(&log->alloc_lsn, log->fileid, log->first_record);
+ }
end_lsn = log->alloc_lsn;
+ WT_PUBLISH(log->log_fh, log_fh);
/*
* If we're called from connection creation code, we need to update
@@ -1012,6 +1191,83 @@ __log_newfile(WT_SESSION_IMPL *session, bool conn_open, bool *created)
}
/*
+ * __log_set_version --
+ * Set version related information under lock.
+ */
+static int
+__log_set_version(WT_SESSION_IMPL *session, uint16_t version,
+ uint32_t first_rec, bool live_chg, bool downgrade)
+{
+ WT_CONNECTION_IMPL *conn;
+ WT_LOG *log;
+
+ conn = S2C(session);
+ log = conn->log;
+
+ log->log_version = version;
+ log->first_record = first_rec;
+ if (downgrade)
+ FLD_SET(conn->log_flags, WT_CONN_LOG_DOWNGRADED);
+ else
+ FLD_CLR(conn->log_flags, WT_CONN_LOG_DOWNGRADED);
+ if (live_chg)
+ F_SET(log, WT_LOG_FORCE_NEWFILE);
+ if (!F_ISSET(conn, WT_CONN_READONLY))
+ return (__log_prealloc_remove(session));
+ else
+ return (0);
+}
+
+/*
+ * __wt_log_set_version --
+ * Change the version number in logging. Will be done with locking.
+ * We need to force the log file to advance and remove all old
+ * pre-allocated files.
+ */
+int
+__wt_log_set_version(WT_SESSION_IMPL *session, uint16_t version,
+ uint32_t first_rec, bool downgrade, bool live_chg, uint32_t *lognump)
+{
+ WT_CONNECTION_IMPL *conn;
+ WT_DECL_RET;
+ WT_LOG *log;
+
+ conn = S2C(session);
+ log = conn->log;
+
+ /*
+ * The steps are:
+ * - Set up versions and remove files under lock.
+ * - Set a flag so that the next slot change forces a file change.
+ * - Force out the slot that is currently active in the current log.
+ * - Write a log record to force a record into the new log file.
+ */
+ WT_WITH_SLOT_LOCK(session, log,
+ ret = __log_set_version(session,
+ version, first_rec, live_chg, downgrade));
+ if (!live_chg)
+ return (ret);
+ WT_ERR(ret);
+ /*
+ * A new log file will be used when we force out the earlier slot.
+ */
+ WT_ERR(__wt_log_force_write(session, 1, NULL));
+
+ /*
+ * We need to write a record to the new version log file so that
+ * a potential checkpoint finds LSNs in that new log file and
+ * an archive correctly removes all earlier logs.
+ * Write an internal printf record.
+ */
+ WT_ERR(__log_printf_internal(session,
+ "COMPATIBILITY: Version now %" PRIu16, log->log_version));
+ if (lognump != NULL)
+ *lognump = log->alloc_lsn.l.file;
+err:
+ return (ret);
+}
+
+/*
* __wt_log_acquire --
* Called serially when switching slots. Can be called recursively
* from __log_newfile when we change log files.
@@ -1043,8 +1299,10 @@ __wt_log_acquire(WT_SESSION_IMPL *session, uint64_t recsize, WT_LOGSLOT *slot)
* that exceed the maximum file size. We want to minimize the risk
* of an error due to no space.
*/
- if (!__log_size_fit(session, &log->alloc_lsn, recsize)) {
+ if (F_ISSET(log, WT_LOG_FORCE_NEWFILE) ||
+ !__log_size_fit(session, &log->alloc_lsn, recsize)) {
WT_RET(__log_newfile(session, false, &created_log));
+ F_CLR(log, WT_LOG_FORCE_NEWFILE);
if (log->log_close_fh != NULL)
F_SET(slot, WT_SLOT_CLOSEFH);
}
@@ -1053,7 +1311,7 @@ __wt_log_acquire(WT_SESSION_IMPL *session, uint64_t recsize, WT_LOGSLOT *slot)
* Pre-allocate on the first real write into the log file, if it
* was just created (i.e. not pre-allocated).
*/
- if (log->alloc_lsn.l.offset == WT_LOG_FIRST_RECORD && created_log)
+ if (log->alloc_lsn.l.offset == log->first_record && created_log)
WT_RET(__log_prealloc(session, log->log_fh));
/*
* Initialize the slot for activation.
@@ -1107,8 +1365,7 @@ __log_truncate_file(WT_SESSION_IMPL *session, WT_FH *log_fh, wt_off_t offset)
* we are in recovery or other dedicated time and not during live running.
*/
static int
-__log_truncate(WT_SESSION_IMPL *session,
- WT_LSN *lsn, const char *file_prefix, uint32_t this_log)
+__log_truncate(WT_SESSION_IMPL *session, WT_LSN *lsn, bool this_log)
{
WT_CONNECTION_IMPL *conn;
WT_DECL_RET;
@@ -1133,7 +1390,7 @@ __log_truncate(WT_SESSION_IMPL *session,
* before doing work, and if there's a not-supported error, turn off
* future truncates.
*/
- WT_ERR(__log_openfile(session, &log_fh, file_prefix, lsn->l.file, 0));
+ WT_ERR(__log_openfile(session, lsn->l.file, 0, &log_fh));
WT_ERR(__log_truncate_file(session, log_fh, lsn->l.offset));
WT_ERR(__wt_fsync(session, log_fh, true));
WT_ERR(__wt_close(session, &log_fh));
@@ -1148,14 +1405,13 @@ __log_truncate(WT_SESSION_IMPL *session,
for (i = 0; i < logcount; i++) {
WT_ERR(__wt_log_extract_lognum(session, logfiles[i], &lognum));
if (lognum > lsn->l.file && lognum < log->trunc_lsn.l.file) {
- WT_ERR(__log_openfile(session,
- &log_fh, file_prefix, lognum, 0));
+ WT_ERR(__log_openfile(session, lognum, 0, &log_fh));
/*
* If there are intervening files pre-allocated,
* truncate them to the end of the log file header.
*/
WT_ERR(__log_truncate_file(
- session, log_fh, WT_LOG_FIRST_RECORD));
+ session, log_fh, log->first_record));
WT_ERR(__wt_fsync(session, log_fh, true));
WT_ERR(__wt_close(session, &log_fh));
}
@@ -1198,17 +1454,17 @@ __wt_log_allocfile(
tmp_id = __wt_atomic_add32(&log->tmp_fileid, 1);
WT_ERR(__log_filename(session, tmp_id, WT_LOG_TMPNAME, from_path));
WT_ERR(__log_filename(session, lognum, dest, to_path));
+ __wt_spin_lock(session, &log->log_fs_lock);
/*
* Set up the temporary file.
*/
- WT_ERR(__log_openfile(session,
- &log_fh, WT_LOG_TMPNAME, tmp_id, WT_LOG_OPEN_CREATE_OK));
+ WT_ERR(__log_openfile(session, tmp_id, WT_LOG_OPEN_CREATE_OK, &log_fh));
WT_ERR(__log_file_header(session, log_fh, NULL, true));
WT_ERR(__log_prealloc(session, log_fh));
WT_ERR(__wt_fsync(session, log_fh, true));
WT_ERR(__wt_close(session, &log_fh));
__wt_verbose(session, WT_VERB_LOG,
- "log_prealloc: rename %s to %s",
+ "log_allocfile: rename %s to %s",
(const char *)from_path->data, (const char *)to_path->data);
/*
* Rename it into place and make it available.
@@ -1217,6 +1473,7 @@ __wt_log_allocfile(
err: __wt_scr_free(session, &from_path);
__wt_scr_free(session, &to_path);
+ __wt_spin_unlock(session, &log->log_fs_lock);
WT_TRET(__wt_close(session, &log_fh));
return (ret);
}
@@ -1255,6 +1512,7 @@ __wt_log_open(WT_SESSION_IMPL *session)
WT_DECL_RET;
WT_LOG *log;
uint32_t firstlog, lastlog, lognum;
+ uint16_t version;
u_int i, logcount;
char **logfiles;
@@ -1275,33 +1533,8 @@ __wt_log_open(WT_SESSION_IMPL *session)
WT_FS_OPEN_FILE_TYPE_DIRECTORY, 0, &log->log_dir_fh));
}
- if (!F_ISSET(conn, WT_CONN_READONLY)) {
- /*
- * Clean up any old interim pre-allocated files. We clean
- * up these files because settings have changed upon reboot
- * and we want those settings to take effect right away.
- */
- WT_ERR(__log_get_files(session,
- WT_LOG_TMPNAME, &logfiles, &logcount));
- for (i = 0; i < logcount; i++) {
- WT_ERR(__wt_log_extract_lognum(
- session, logfiles[i], &lognum));
- WT_ERR(__wt_log_remove(
- session, WT_LOG_TMPNAME, lognum));
- }
- WT_ERR(
- __wt_fs_directory_list_free(session, &logfiles, logcount));
- WT_ERR(__log_get_files(session,
- WT_LOG_PREPNAME, &logfiles, &logcount));
- for (i = 0; i < logcount; i++) {
- WT_ERR(__wt_log_extract_lognum(
- session, logfiles[i], &lognum));
- WT_ERR(__wt_log_remove(
- session, WT_LOG_PREPNAME, lognum));
- }
- WT_ERR(
- __wt_fs_directory_list_free(session, &logfiles, logcount));
- }
+ if (!F_ISSET(conn, WT_CONN_READONLY))
+ WT_ERR(__log_prealloc_remove(session));
/*
* Now look at the log files and set our LSNs.
@@ -1334,6 +1567,33 @@ __wt_log_open(WT_SESSION_IMPL *session)
/* If we found log files, save the new state. */
if (logcount > 0) {
+ /*
+ * If we're running in a downgraded mode and there are earlier
+ * logs detect if they're at a higher version. If so, we need
+ * to force recovery (to write a full checkpoint) and force
+ * archiving to remove all higher version logs.
+ */
+ if (FLD_ISSET(conn->log_flags, WT_CONN_LOG_DOWNGRADED)) {
+ for (i = 0; i < logcount; ++i) {
+ WT_ERR(__wt_log_extract_lognum(
+ session, logfiles[i], &lognum));
+ /*
+ * By sending in a NULL file handle, we don't
+ * have to close the file.
+ */
+ WT_ERR(__log_open_verify(session,
+ lognum, NULL, NULL, &version));
+ /*
+ * If we find any log file at the wrong version
+ * set the flag and we're done.
+ */
+ if (log->log_version != version) {
+ FLD_SET(conn->log_flags,
+ WT_CONN_LOG_FORCE_DOWNGRADE);
+ break;
+ }
+ }
+ }
log->trunc_lsn = log->alloc_lsn;
FLD_SET(conn->log_flags, WT_CONN_LOG_EXISTED);
}
@@ -1631,12 +1891,12 @@ __wt_log_scan(WT_SESSION_IMPL *session, WT_LSN *lsnp, uint32_t flags,
WT_ITEM *cbbuf;
WT_LOG *log;
WT_LOG_RECORD *logrec;
- WT_LSN end_lsn, next_lsn, rd_lsn, start_lsn;
+ WT_LSN end_lsn, next_lsn, prev_eof, prev_lsn, rd_lsn, start_lsn;
wt_off_t log_size;
uint32_t allocsize, firstlog, lastlog, lognum, rdup_len, reclen;
- uint32_t checksum_calculate, checksum_tmp;
u_int i, logcount;
int firstrecord;
+ uint16_t version;
bool eol, partial_record;
char **logfiles;
@@ -1660,66 +1920,26 @@ __wt_log_scan(WT_SESSION_IMPL *session, WT_LSN *lsnp, uint32_t flags,
"__wt_log_scan truncating to %" PRIu32 "/%" PRIu32,
log->trunc_lsn.l.file, log->trunc_lsn.l.offset);
+ if (lsnp != NULL &&
+ LF_ISSET(WT_LOGSCAN_FIRST|WT_LOGSCAN_FROM_CKP))
+ WT_RET_MSG(session, WT_ERROR,
+ "choose either a start LSN or a start flag");
+ /*
+ * Set up the allocation size, starting and ending LSNs. The values
+ * for those depend on whether logging is currently enabled or not.
+ */
+ lastlog = 0;
if (log != NULL) {
allocsize = log->allocsize;
-
+ end_lsn = log->alloc_lsn;
+ start_lsn = log->first_lsn;
if (lsnp == NULL) {
- if (LF_ISSET(WT_LOGSCAN_FIRST))
- start_lsn = log->first_lsn;
- else if (LF_ISSET(WT_LOGSCAN_FROM_CKP))
+ if (LF_ISSET(WT_LOGSCAN_FROM_CKP))
start_lsn = log->ckpt_lsn;
- else
+ else if (!LF_ISSET(WT_LOGSCAN_FIRST))
return (WT_ERROR); /* Illegal usage */
- } else {
- if (LF_ISSET(WT_LOGSCAN_FIRST|WT_LOGSCAN_FROM_CKP))
- WT_RET_MSG(session, WT_ERROR,
- "choose either a start LSN or a start flag");
-
- /*
- * Offsets must be on allocation boundaries.
- * An invalid LSN from a user should just return
- * WT_NOTFOUND. It is not an error. But if it is
- * from recovery, we expect valid LSNs so give more
- * information about that.
- */
- if (lsnp->l.offset % allocsize != 0) {
- if (LF_ISSET(WT_LOGSCAN_RECOVER))
- WT_RET_MSG(session, WT_NOTFOUND,
- "__wt_log_scan unaligned LSN %"
- PRIu32 "/%" PRIu32,
- lsnp->l.file, lsnp->l.offset);
- else
- return (WT_NOTFOUND);
- }
- /*
- * If the file is in the future it doesn't exist.
- * An invalid LSN from a user should just return
- * WT_NOTFOUND. It is not an error. But if it is
- * from recovery, we expect valid LSNs so give more
- * information about that.
- */
- if (lsnp->l.file > log->fileid) {
- if (LF_ISSET(WT_LOGSCAN_RECOVER))
- WT_RET_MSG(session, WT_NOTFOUND,
- "__wt_log_scan LSN %" PRIu32 "/%"
- PRIu32
- " larger than biggest log file %"
- PRIu32, lsnp->l.file,
- lsnp->l.offset, log->fileid);
- else
- return (WT_NOTFOUND);
- }
-
- /*
- * Log cursors may not know the starting LSN. If an
- * LSN is passed in that it is equal to the smallest
- * LSN, start from the beginning of the log.
- */
- start_lsn = *lsnp;
- if (WT_IS_INIT_LSN(&start_lsn))
- start_lsn = log->first_lsn;
}
- end_lsn = log->alloc_lsn;
+ lastlog = log->fileid;
} else {
/*
* If logging is not configured, we can still print out the log
@@ -1732,7 +1952,6 @@ __wt_log_scan(WT_SESSION_IMPL *session, WT_LSN *lsnp, uint32_t flags,
* a multiple of this.
*/
allocsize = WT_LOG_ALIGN;
- lastlog = 0;
firstlog = UINT32_MAX;
WT_RET(__log_get_files(session,
WT_LOG_FILENAME, &logfiles, &logcount));
@@ -1749,8 +1968,49 @@ __wt_log_scan(WT_SESSION_IMPL *session, WT_LSN *lsnp, uint32_t flags,
WT_ERR(
__wt_fs_directory_list_free(session, &logfiles, logcount));
}
- WT_ERR(__log_openfile(session,
- &log_fh, WT_LOG_FILENAME, start_lsn.l.file, WT_LOG_OPEN_VERIFY));
+ if (lsnp != NULL) {
+ /*
+ * Offsets must be on allocation boundaries.
+ * An invalid LSN from a user should just return
+ * WT_NOTFOUND. It is not an error. But if it is
+ * from recovery, we expect valid LSNs so give more
+ * information about that.
+ */
+ if (lsnp->l.offset % allocsize != 0) {
+ if (LF_ISSET(WT_LOGSCAN_RECOVER))
+ WT_ERR_MSG(session, WT_NOTFOUND,
+ "__wt_log_scan unaligned LSN %"
+ PRIu32 "/%" PRIu32,
+ lsnp->l.file, lsnp->l.offset);
+ else
+ return (WT_NOTFOUND);
+ }
+ /*
+ * If the file is in the future it doesn't exist.
+ * An invalid LSN from a user should just return
+ * WT_NOTFOUND. It is not an error. But if it is
+ * from recovery, we expect valid LSNs so give more
+ * information about that.
+ */
+ if (lsnp->l.file > lastlog) {
+ if (LF_ISSET(WT_LOGSCAN_RECOVER))
+ WT_ERR_MSG(session, WT_NOTFOUND,
+ "__wt_log_scan LSN %" PRIu32 "/%" PRIu32
+ " larger than biggest log file %" PRIu32,
+ lsnp->l.file, lsnp->l.offset, lastlog);
+ else
+ return (WT_NOTFOUND);
+ }
+ /*
+ * Log cursors may not know the starting LSN. If an
+ * LSN is passed in that it is equal to the smallest
+ * LSN, start from the beginning of the log.
+ */
+ if (!WT_IS_INIT_LSN(lsnp))
+ start_lsn = *lsnp;
+ }
+ WT_ERR(__log_open_verify(session,
+ start_lsn.l.file, &log_fh, &prev_lsn, NULL));
WT_ERR(__wt_filesize(session, log_fh, &log_size));
rd_lsn = start_lsn;
if (LF_ISSET(WT_LOGSCAN_RECOVER))
@@ -1784,8 +2044,7 @@ advance:
* Truncate this log file before we move to the next.
*/
if (LF_ISSET(WT_LOGSCAN_RECOVER))
- WT_ERR(__log_truncate(session,
- &rd_lsn, WT_LOG_FILENAME, 1));
+ WT_ERR(__log_truncate(session, &rd_lsn, true));
/*
* If we had a partial record, we'll want to break
* now after closing and truncating. Although for now
@@ -1795,21 +2054,47 @@ advance:
*/
if (partial_record)
break;
- WT_SET_LSN(&rd_lsn, rd_lsn.l.file + 1, 0);
/*
* Avoid an error message when we reach end of log
* by checking here.
*/
+ prev_eof = rd_lsn;
+ WT_SET_LSN(&rd_lsn, rd_lsn.l.file + 1, 0);
if (rd_lsn.l.file > end_lsn.l.file)
break;
- WT_ERR(__log_openfile(session,
- &log_fh, WT_LOG_FILENAME,
- rd_lsn.l.file, WT_LOG_OPEN_VERIFY));
if (LF_ISSET(WT_LOGSCAN_RECOVER))
__wt_verbose(session, WT_VERB_RECOVERY_PROGRESS,
"Recovering log %" PRIu32
" through %" PRIu32,
rd_lsn.l.file, end_lsn.l.file);
+ WT_ERR(__log_open_verify(session,
+ rd_lsn.l.file, &log_fh, &prev_lsn, &version));
+ /*
+ * Opening the log file reads with verify sets up the
+ * previous LSN from the first record. This detects
+ * a "hole" at the end of the previous log file.
+ */
+ if (LF_ISSET(WT_LOGSCAN_RECOVER) &&
+ !WT_IS_INIT_LSN(&prev_lsn) &&
+ !WT_IS_ZERO_LSN(&prev_lsn) &&
+ prev_lsn.l.offset != prev_eof.l.offset) {
+ WT_ASSERT(session,
+ prev_eof.l.file == prev_lsn.l.file);
+ break;
+ }
+ /*
+ * If we read a current version log file without a
+ * previous LSN record the log ended after writing
+ * that header. We're done.
+ */
+ if (LF_ISSET(WT_LOGSCAN_RECOVER) &&
+ version == WT_LOG_VERSION_SYSTEM &&
+ WT_IS_ZERO_LSN(&prev_lsn)) {
+ __wt_verbose(session, WT_VERB_LOG,
+ "log_scan: Stopping, no system "
+ "record detected in %s.", log_fh->name);
+ break;
+ }
WT_ERR(__wt_filesize(session, log_fh, &log_size));
eol = false;
continue;
@@ -1881,12 +2166,7 @@ advance:
*/
buf->size = reclen;
logrec = (WT_LOG_RECORD *)buf->mem;
- checksum_tmp = logrec->checksum;
- logrec->checksum = 0;
- checksum_calculate = __wt_checksum(logrec, reclen);
- logrec->checksum = checksum_tmp;
- __wt_log_record_byteswap(logrec);
- if (logrec->checksum != checksum_calculate) {
+ if (!__log_checksum_match(session, buf, reclen)) {
/*
* A checksum mismatch means we have reached the end of
* the useful part of the log. This should be found on
@@ -1904,6 +2184,7 @@ advance:
ret = WT_NOTFOUND;
break;
}
+ __wt_log_record_byteswap(logrec);
/*
* We have a valid log record. If it is not the log file
@@ -1946,8 +2227,12 @@ advance:
/* Truncate if we're in recovery. */
if (LF_ISSET(WT_LOGSCAN_RECOVER) &&
- __wt_log_cmp(&rd_lsn, &log->trunc_lsn) < 0)
- WT_ERR(__log_truncate(session, &rd_lsn, WT_LOG_FILENAME, 0));
+ __wt_log_cmp(&rd_lsn, &log->trunc_lsn) < 0) {
+ __wt_verbose(session, WT_VERB_LOG,
+ "__wt_log_scan truncating to %" PRIu32 "/%" PRIu32,
+ rd_lsn.l.file, rd_lsn.l.offset);
+ WT_ERR(__log_truncate(session, &rd_lsn, false));
+ }
err: WT_STAT_CONN_INCR(session, log_scans);
/*
@@ -2212,7 +2497,7 @@ __log_write_internal(WT_SESSION_IMPL *session, WT_ITEM *record, WT_LSN *lsnp,
F_ISSET(&myslot, WT_MYSLOT_UNBUFFERED) || force)
ret = __wt_log_slot_switch(session, &myslot, true, false, NULL);
if (ret == 0)
- ret = __log_fill(session, &myslot, false, record, &lsn);
+ ret = __wt_log_fill(session, &myslot, false, record, &lsn);
release_size = __wt_log_slot_release(&myslot, (int64_t)rdup_len);
/*
* If we get an error we still need to do proper accounting in
@@ -2365,7 +2650,7 @@ __wt_log_flush(WT_SESSION_IMPL *session, uint32_t flags)
* is single-threaded we could wait here forever because the write LSN
* doesn't switch into the new file until it contains a record.
*/
- if (last_lsn.l.offset == WT_LOG_FIRST_RECORD)
+ if (last_lsn.l.offset == log->first_record)
last_lsn = log->log_close_lsn;
/*
diff --git a/src/third_party/wiredtiger/src/log/log_slot.c b/src/third_party/wiredtiger/src/log/log_slot.c
index 5bd3d53a973..e0b301398a3 100644
--- a/src/third_party/wiredtiger/src/log/log_slot.c
+++ b/src/third_party/wiredtiger/src/log/log_slot.c
@@ -31,7 +31,7 @@ __log_slot_dump(WT_SESSION_IMPL *session)
earliest = i;
__wt_errx(session, "Slot %d:", i);
__wt_errx(session, " State: %" PRIx64 " Flags: %" PRIx32,
- slot->slot_state, slot->flags);
+ (uint64_t)slot->slot_state, slot->flags);
__wt_errx(session, " Start LSN: %" PRIu32 "/%" PRIu32,
slot->slot_start_lsn.l.file, slot->slot_start_lsn.l.offset);
__wt_errx(session, " End LSN: %" PRIu32 "/%" PRIu32,
@@ -173,9 +173,9 @@ retry:
if (WT_TIMEDIFF_SEC(now, begin) > 10) {
__wt_errx(session, "SLOT_CLOSE: Slot %"
PRIu32 " Timeout unbuffered, state 0x%"
- PRIx64 " unbuffered %" PRIu64,
+ PRIx64 " unbuffered %" PRId64,
(uint32_t)(slot - &log->slot_pool[0]),
- slot->slot_state,
+ (uint64_t)slot->slot_state,
slot->slot_unbuffered);
__log_slot_dump(session);
__wt_abort(session);
@@ -238,6 +238,7 @@ __log_slot_new(WT_SESSION_IMPL *session)
/*
* Rotate among the slots to lessen collisions.
*/
+ WT_RET(WT_SESSION_CHECK_PANIC(session));
for (i = 0, pool_i = log->pool_index; i < WT_SLOT_POOL;
i++, pool_i++) {
if (pool_i >= WT_SLOT_POOL)
@@ -314,7 +315,7 @@ __log_slot_switch_internal(
* because the slot could be part of an unbuffered operation.
*/
joined = WT_LOG_SLOT_JOINED(slot->slot_state);
- if (joined == 0 && forced) {
+ if (joined == 0 && forced && !F_ISSET(log, WT_LOG_FORCE_NEWFILE)) {
WT_STAT_CONN_INCR(session, log_force_write_skip);
if (did_work != NULL)
*did_work = false;
@@ -393,6 +394,9 @@ __wt_log_slot_switch(WT_SESSION_IMPL *session,
WT_STAT_CONN_INCR(session, log_slot_switch_busy);
__wt_yield();
}
+ WT_RET(WT_SESSION_CHECK_PANIC(session));
+ if (F_ISSET(S2C(session), WT_CONN_CLOSING))
+ break;
} while (F_ISSET(myslot, WT_MYSLOT_CLOSE) || (retry && ret == EBUSY));
return (ret);
}
diff --git a/src/third_party/wiredtiger/src/log/log_sys.c b/src/third_party/wiredtiger/src/log/log_sys.c
new file mode 100644
index 00000000000..0f3cfdbc14b
--- /dev/null
+++ b/src/third_party/wiredtiger/src/log/log_sys.c
@@ -0,0 +1,97 @@
+/*-
+ * Copyright (c) 2014-2017 MongoDB, Inc.
+ * Copyright (c) 2008-2014 WiredTiger, Inc.
+ * All rights reserved.
+ *
+ * See the file LICENSE for redistribution information.
+ */
+
+#include "wt_internal.h"
+
+/*
+ * __wt_log_system_record --
+ * Write a system log record for the previous LSN.
+ */
+int
+__wt_log_system_record(
+ WT_SESSION_IMPL *session, WT_FH *log_fh, WT_LSN *lsn)
+{
+ WT_DECL_ITEM(logrec_buf);
+ WT_DECL_RET;
+ WT_ITEM *dummy, empty;
+ WT_LOG *log;
+ WT_LOG_RECORD *logrec;
+ WT_LOGSLOT tmp;
+ WT_MYSLOT myslot;
+ const char *fmt = WT_UNCHECKED_STRING(IIIU);
+ uint32_t rectype = WT_LOGREC_SYSTEM;
+ size_t recsize;
+
+ log = S2C(session)->log;
+ WT_RET(__wt_logrec_alloc(session, log->allocsize, &logrec_buf));
+ memset((uint8_t *)logrec_buf->mem, 0, log->allocsize);
+ WT_CLEAR(empty);
+ dummy = &empty;
+ /*
+ * There is currently an unused portion of the system record for
+ * future use. Send in a NULL entry.
+ */
+ WT_ERR(__wt_struct_size(session, &recsize, fmt, rectype,
+ lsn->l.file, lsn->l.offset, dummy));
+ WT_ASSERT(session, recsize <= log->allocsize);
+ WT_ERR(__wt_struct_pack(session,
+ (uint8_t *)logrec_buf->data + logrec_buf->size, recsize, fmt,
+ rectype, lsn->l.file, lsn->l.offset, dummy));
+ logrec = (WT_LOG_RECORD *)logrec_buf->mem;
+ /*
+ * We know system records are this size. And we have to adjust
+ * the size now because we're not going through the normal log
+ * write path and the packing functions needed the correct offset
+ * earlier.
+ */
+ logrec_buf->size = logrec->len = log->allocsize;
+ /*
+ * We do not compress nor encrypt this record.
+ */
+ logrec->checksum = 0;
+ logrec->flags = 0;
+ __wt_log_record_byteswap(logrec);
+ logrec->checksum = __wt_checksum(logrec, log->allocsize);
+#ifdef WORDS_BIGENDIAN
+ logrec->checksum = __wt_bswap32(logrec->checksum);
+#endif
+ WT_CLEAR(tmp);
+ memset(&myslot, 0, sizeof(myslot));
+ myslot.slot = &tmp;
+ __wt_log_slot_activate(session, &tmp);
+ /*
+ * Override the file handle to the one we're using.
+ */
+ tmp.slot_fh = log_fh;
+ WT_ERR(__wt_log_fill(session, &myslot, true, logrec_buf, NULL));
+err: __wt_logrec_free(session, &logrec_buf);
+ return (ret);
+}
+
+/*
+ * __wt_log_recover_system --
+ * Process a system log record for the previous LSN in recovery.
+ */
+int
+__wt_log_recover_system(WT_SESSION_IMPL *session,
+ const uint8_t **pp, const uint8_t *end, WT_LSN *lsnp)
+{
+ WT_DECL_RET;
+ WT_ITEM unused;
+ uint32_t prev_file, prev_offset;
+ const char *fmt = WT_UNCHECKED_STRING(IIU);
+
+ if ((ret = __wt_struct_unpack(session, *pp, WT_PTRDIFF(end, *pp), fmt,
+ &prev_file, &prev_offset, &unused)) != 0)
+ WT_RET_MSG(session, ret,
+ "log_recover_prevlsn: unpack failure");
+ if (lsnp != NULL)
+ WT_SET_LSN(lsnp, prev_file, prev_offset);
+ *pp = end;
+ return (0);
+}
diff --git a/src/third_party/wiredtiger/src/lsm/lsm_cursor.c b/src/third_party/wiredtiger/src/lsm/lsm_cursor.c
index 06dfec725bb..6a1709b03f2 100644
--- a/src/third_party/wiredtiger/src/lsm/lsm_cursor.c
+++ b/src/third_party/wiredtiger/src/lsm/lsm_cursor.c
@@ -1775,9 +1775,7 @@ __wt_clsm_open(WT_SESSION_IMPL *session,
if (!WT_PREFIX_MATCH(uri, "lsm:"))
return (__wt_unexpected_object_type(session, uri, "lsm:"));
- if (F_ISSET(S2C(session), WT_CONN_IN_MEMORY))
- WT_RET_MSG(session, EINVAL,
- "LSM trees not supported by in-memory configurations");
+ WT_RET(__wt_inmem_unsupported_op(session, "LSM trees"));
WT_RET(__wt_config_gets_def(session, cfg, "checkpoint", 0, &cval));
if (cval.len != 0)
diff --git a/src/third_party/wiredtiger/src/lsm/lsm_merge.c b/src/third_party/wiredtiger/src/lsm/lsm_merge.c
index 28e954c6f6a..f3990a72d95 100644
--- a/src/third_party/wiredtiger/src/lsm/lsm_merge.c
+++ b/src/third_party/wiredtiger/src/lsm/lsm_merge.c
@@ -621,7 +621,7 @@ err: if (locked)
if (ret == EINTR)
__wt_verbose(session, WT_VERB_LSM,
- "Merge aborted due to close");
+ "%s", "Merge aborted due to close");
else
__wt_verbose(session, WT_VERB_LSM,
"Merge failed with %s",
diff --git a/src/third_party/wiredtiger/src/lsm/lsm_tree.c b/src/third_party/wiredtiger/src/lsm/lsm_tree.c
index ebdd1e492cc..18e1f6d3115 100644
--- a/src/third_party/wiredtiger/src/lsm/lsm_tree.c
+++ b/src/third_party/wiredtiger/src/lsm/lsm_tree.c
@@ -15,6 +15,42 @@ static int __lsm_tree_open(
static int __lsm_tree_set_name(WT_SESSION_IMPL *, WT_LSM_TREE *, const char *);
/*
+ * __lsm_tree_discard_state --
+ * Free the metadata configuration state related LSM tree pointers.
+ */
+static void
+__lsm_tree_discard_state(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree)
+{
+ WT_LSM_CHUNK *chunk;
+ u_int i;
+
+ __wt_free(session, lsm_tree->config);
+ __wt_free(session, lsm_tree->key_format);
+ __wt_free(session, lsm_tree->value_format);
+ __wt_free(session, lsm_tree->collator_name);
+ __wt_free(session, lsm_tree->bloom_config);
+ __wt_free(session, lsm_tree->file_config);
+
+ for (i = 0; i < lsm_tree->nchunks; i++) {
+ if ((chunk = lsm_tree->chunk[i]) == NULL)
+ continue;
+
+ __wt_free(session, chunk->bloom_uri);
+ __wt_free(session, chunk->uri);
+ __wt_free(session, chunk);
+ }
+
+ for (i = 0; i < lsm_tree->nold_chunks; i++) {
+ chunk = lsm_tree->old_chunks[i];
+ WT_ASSERT(session, chunk != NULL);
+
+ __wt_free(session, chunk->bloom_uri);
+ __wt_free(session, chunk->uri);
+ __wt_free(session, chunk);
+ }
+}
+
+/*
* __lsm_tree_discard --
* Free an LSM tree structure.
*/
@@ -22,8 +58,6 @@ static int
__lsm_tree_discard(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree, bool final)
{
WT_DECL_RET;
- WT_LSM_CHUNK *chunk;
- u_int i;
WT_UNUSED(final); /* Only used in diagnostic builds */
@@ -48,34 +82,12 @@ __lsm_tree_discard(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree, bool final)
lsm_tree->collator, &session->iface));
__wt_free(session, lsm_tree->name);
- __wt_free(session, lsm_tree->config);
- __wt_free(session, lsm_tree->key_format);
- __wt_free(session, lsm_tree->value_format);
- __wt_free(session, lsm_tree->collator_name);
- __wt_free(session, lsm_tree->bloom_config);
- __wt_free(session, lsm_tree->file_config);
-
- __wt_rwlock_destroy(session, &lsm_tree->rwlock);
-
- for (i = 0; i < lsm_tree->nchunks; i++) {
- if ((chunk = lsm_tree->chunk[i]) == NULL)
- continue;
-
- __wt_free(session, chunk->bloom_uri);
- __wt_free(session, chunk->uri);
- __wt_free(session, chunk);
- }
+ __lsm_tree_discard_state(session, lsm_tree);
__wt_free(session, lsm_tree->chunk);
+ __wt_free(session, lsm_tree->old_chunks);
- for (i = 0; i < lsm_tree->nold_chunks; i++) {
- chunk = lsm_tree->old_chunks[i];
- WT_ASSERT(session, chunk != NULL);
+ __wt_rwlock_destroy(session, &lsm_tree->rwlock);
- __wt_free(session, chunk->bloom_uri);
- __wt_free(session, chunk->uri);
- __wt_free(session, chunk);
- }
- __wt_free(session, lsm_tree->old_chunks);
__wt_free(session, lsm_tree);
return (ret);
@@ -851,45 +863,6 @@ __wt_lsm_tree_retire_chunks(WT_SESSION_IMPL *session,
}
/*
- * __wt_lsm_tree_alter --
- * Alter an LSM tree.
- */
-int
-__wt_lsm_tree_alter(
- WT_SESSION_IMPL *session, const char *uri, const char *cfg[])
-{
- WT_DECL_RET;
- WT_LSM_CHUNK *chunk;
- WT_LSM_TREE *lsm_tree;
- u_int i;
- bool locked;
-
- locked = false;
-
- /* Get the LSM tree. */
- WT_RET(__wt_lsm_tree_get(session, uri, false, &lsm_tree));
-
- /* Prevent any new opens. */
- __wt_lsm_tree_writelock(session, lsm_tree);
- locked = true;
-
- /* Alter the chunks. */
- for (i = 0; i < lsm_tree->nchunks; i++) {
- chunk = lsm_tree->chunk[i];
- WT_ERR(__wt_schema_alter(session, chunk->uri, cfg));
- if (F_ISSET(chunk, WT_LSM_CHUNK_BLOOM))
- WT_ERR(
- __wt_schema_alter(session, chunk->bloom_uri, cfg));
- }
- WT_ERR(__wt_lsm_meta_write(session, lsm_tree, cfg[0]));
-
-err: if (locked)
- __wt_lsm_tree_writeunlock(session, lsm_tree);
- __wt_lsm_tree_release(session, lsm_tree);
- return (ret);
-}
-
-/*
* __wt_lsm_tree_drop --
* Drop an LSM tree.
*/
@@ -1385,6 +1358,24 @@ __wt_lsm_tree_worker(WT_SESSION_IMPL *session,
WT_ERR(__wt_schema_worker(session, chunk->bloom_uri,
file_func, name_func, cfg, open_flags));
}
+ /*
+ * If this was an alter operation, we need to alter the configuration
+ * for the overall tree and then reread it so it isn't out of date.
+ * Reread it here so that we update the configuration of the
+ * current tree's structure to any new, altered values.
+ */
+ if (FLD_ISSET(open_flags, WT_BTREE_ALTER)) {
+ WT_ERR(__wt_lsm_meta_write(session, lsm_tree, cfg[0]));
+ /*
+ * We're about to read in the new configuration that
+ * we just wrote. Free the old ones.
+ */
+ __lsm_tree_discard_state(session, lsm_tree);
+ if ((ret = __wt_lsm_meta_read(session, lsm_tree)) != 0)
+ WT_PANIC_ERR(session, ret,
+ "Failed to read updated LSM configuration");
+ }
+
err: if (locked) {
if (exclusive)
__wt_lsm_tree_writeunlock(session, lsm_tree);
diff --git a/src/third_party/wiredtiger/src/meta/meta_ckpt.c b/src/third_party/wiredtiger/src/meta/meta_ckpt.c
index 0e96c4ee6ca..24f991cf549 100644
--- a/src/third_party/wiredtiger/src/meta/meta_ckpt.c
+++ b/src/third_party/wiredtiger/src/meta/meta_ckpt.c
@@ -429,7 +429,7 @@ __wt_meta_ckptlist_set(WT_SESSION_IMPL *session,
}
if (strcmp(ckpt->name, WT_CHECKPOINT) == 0)
WT_ERR(__wt_buf_catfmt(session, buf,
- "%s%s.%" PRId64 "=(addr=\"%.*s\",order=%" PRIu64
+ "%s%s.%" PRId64 "=(addr=\"%.*s\",order=%" PRId64
",time=%" PRIuMAX ",size=%" PRIu64
",write_gen=%" PRIu64 ")",
sep, ckpt->name, ckpt->order,
@@ -438,7 +438,7 @@ __wt_meta_ckptlist_set(WT_SESSION_IMPL *session,
ckpt->write_gen));
else
WT_ERR(__wt_buf_catfmt(session, buf,
- "%s%s=(addr=\"%.*s\",order=%" PRIu64
+ "%s%s=(addr=\"%.*s\",order=%" PRId64
",time=%" PRIuMAX ",size=%" PRIu64
",write_gen=%" PRIu64 ")",
sep, ckpt->name,
diff --git a/src/third_party/wiredtiger/src/os_win/os_map.c b/src/third_party/wiredtiger/src/os_win/os_map.c
index c0aa6dac28f..25835d2615d 100644
--- a/src/third_party/wiredtiger/src/os_win/os_map.c
+++ b/src/third_party/wiredtiger/src/os_win/os_map.c
@@ -82,6 +82,8 @@ __wt_win_unmap(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session,
WT_FILE_HANDLE_WIN *win_fh;
WT_SESSION_IMPL *session;
+ WT_UNUSED(length); /* !HAVE_VERBOSE */
+
win_fh = (WT_FILE_HANDLE_WIN *)file_handle;
session = (WT_SESSION_IMPL *)wt_session;
diff --git a/src/third_party/wiredtiger/src/reconcile/rec_track.c b/src/third_party/wiredtiger/src/reconcile/rec_track.c
index a431465661f..ee97d684529 100644
--- a/src/third_party/wiredtiger/src/reconcile/rec_track.c
+++ b/src/third_party/wiredtiger/src/reconcile/rec_track.c
@@ -16,11 +16,11 @@
(sizeof(s) + 2 * sizeof(void *) + (p)->addr_size + (p)->value_size)
/*
- * __ovfl_track_init --
+ * __wt_ovfl_track_init --
* Initialize the overflow tracking structure.
*/
-static int
-__ovfl_track_init(WT_SESSION_IMPL *session, WT_PAGE *page)
+int
+__wt_ovfl_track_init(WT_SESSION_IMPL *session, WT_PAGE *page)
{
return (__wt_calloc_one(session, &page->modify->ovfl_track));
}
@@ -36,6 +36,9 @@ __ovfl_discard_verbose(
WT_CELL_UNPACK *unpack, _unpack;
WT_DECL_ITEM(tmp);
+ WT_UNUSED(page); /* !HAVE_VERBOSE */
+ WT_UNUSED(tag); /* !HAVE_VERBOSE */
+
WT_RET(__wt_scr_alloc(session, 512, &tmp));
unpack = &_unpack;
@@ -128,7 +131,7 @@ __wt_ovfl_discard_add(WT_SESSION_IMPL *session, WT_PAGE *page, WT_CELL *cell)
WT_OVFL_TRACK *track;
if (page->modify->ovfl_track == NULL)
- WT_RET(__ovfl_track_init(session, page));
+ WT_RET(__wt_ovfl_track_init(session, page));
track = page->modify->ovfl_track;
WT_RET(__wt_realloc_def(session, &track->discard_allocated,
@@ -169,6 +172,10 @@ __ovfl_reuse_verbose(WT_SESSION_IMPL *session,
{
WT_DECL_ITEM(tmp);
+ WT_UNUSED(page); /* !HAVE_VERBOSE */
+ WT_UNUSED(reuse); /* !HAVE_VERBOSE */
+ WT_UNUSED(tag); /* !HAVE_VERBOSE */
+
WT_RET(__wt_scr_alloc(session, 64, &tmp));
__wt_verbose(session, WT_VERB_OVERFLOW,
@@ -182,7 +189,8 @@ __ovfl_reuse_verbose(WT_SESSION_IMPL *session,
F_ISSET(reuse, WT_OVFL_REUSE_INUSE) &&
F_ISSET(reuse, WT_OVFL_REUSE_JUST_ADDED) ? ", " : "",
F_ISSET(reuse, WT_OVFL_REUSE_JUST_ADDED) ? "just-added" : "",
- WT_MIN(reuse->value_size, 40), (char *)WT_OVFL_REUSE_VALUE(reuse));
+ (int)WT_MIN(reuse->value_size, 40),
+ (char *)WT_OVFL_REUSE_VALUE(reuse));
__wt_scr_free(session, &tmp);
return (0);
@@ -487,7 +495,7 @@ __wt_ovfl_reuse_add(WT_SESSION_IMPL *session, WT_PAGE *page,
uint8_t *p;
if (page->modify->ovfl_track == NULL)
- WT_RET(__ovfl_track_init(session, page));
+ WT_RET(__wt_ovfl_track_init(session, page));
head = page->modify->ovfl_track->ovfl_reuse;
@@ -557,311 +565,12 @@ __wt_ovfl_reuse_free(WT_SESSION_IMPL *session, WT_PAGE *page)
}
/*
- * __ovfl_txnc_verbose --
- * Dump information about a transaction-cached overflow record.
- */
-static int
-__ovfl_txnc_verbose(WT_SESSION_IMPL *session,
- WT_PAGE *page, WT_OVFL_TXNC *txnc, const char *tag)
-{
- WT_DECL_ITEM(tmp);
-
- WT_RET(__wt_scr_alloc(session, 64, &tmp));
-
- __wt_verbose(session, WT_VERB_OVERFLOW,
- "txn-cache: %s%s%p %s %" PRIu64 " {%.*s}",
- tag == NULL ? "" : tag,
- tag == NULL ? "" : ": ",
- (void *)page,
- __wt_addr_string(
- session, WT_OVFL_TXNC_ADDR(txnc), txnc->addr_size, tmp),
- txnc->current,
- WT_MIN(txnc->value_size, 40), (char *)WT_OVFL_TXNC_VALUE(txnc));
-
- __wt_scr_free(session, &tmp);
- return (0);
-}
-
-#if 0
-/*
- * __ovfl_txnc_dump --
- * Debugging information.
- */
-static void
-__ovfl_txnc_dump(WT_SESSION_IMPL *session, WT_PAGE *page)
-{
- WT_OVFL_TXNC **head, *txnc;
-
- if (page->modify == NULL || page->modify->ovfl_track == NULL)
- return;
- head = page->modify->ovfl_track->ovfl_txnc;
-
- for (txnc = head[0]; txnc != NULL; txnc = txnc->next[0])
- (void)__ovfl_txnc_verbose(session, page, txnc, "dump");
-}
-#endif
-
-/*
- * __ovfl_txnc_skip_search --
- * Return the first matching addr in the overflow transaction-cache list.
- */
-static WT_OVFL_TXNC *
-__ovfl_txnc_skip_search(WT_OVFL_TXNC **head, const void *addr, size_t addr_size)
-{
- WT_OVFL_TXNC **e;
- size_t len;
- int cmp, i;
-
- /*
- * Start at the highest skip level, then go as far as possible at each
- * level before stepping down to the next.
- */
- for (i = WT_SKIP_MAXDEPTH - 1, e = &head[i]; i >= 0;) {
- if (*e == NULL) { /* Empty levels */
- --i;
- --e;
- continue;
- }
-
- /*
- * Return any exact matches: we don't care in what search level
- * we found a match.
- */
- len = WT_MIN((*e)->addr_size, addr_size);
- cmp = memcmp(WT_OVFL_TXNC_ADDR(*e), addr, len);
- if (cmp == 0 && (*e)->addr_size == addr_size)
- return (*e);
-
- /*
- * If the skiplist address is larger than the search address, or
- * they compare equally and the skiplist address is longer than
- * the search address, drop down a level, otherwise continue on
- * this level.
- */
- if (cmp > 0 || (cmp == 0 && (*e)->addr_size > addr_size)) {
- --i; /* Drop down a level */
- --e;
- } else /* Keep going at this level */
- e = &(*e)->next[i];
- }
- return (NULL);
-}
-
-/*
- * __ovfl_txnc_skip_search_stack --
- * Search an overflow transaction-cache skiplist, returning an
- * insert/remove stack.
- */
-static void
-__ovfl_txnc_skip_search_stack(WT_OVFL_TXNC **head,
- WT_OVFL_TXNC ***stack, const void *addr, size_t addr_size)
-{
- WT_OVFL_TXNC **e;
- size_t len;
- int cmp, i;
-
- /*
- * Start at the highest skip level, then go as far as possible at each
- * level before stepping down to the next.
- */
- for (i = WT_SKIP_MAXDEPTH - 1, e = &head[i]; i >= 0;) {
- if (*e == NULL) { /* Empty levels */
- stack[i--] = e--;
- continue;
- }
-
- /*
- * If the skiplist addr is larger than the search addr, or
- * they compare equally and the skiplist addr is longer than
- * the search addr, drop down a level, otherwise continue on
- * this level.
- */
- len = WT_MIN((*e)->addr_size, addr_size);
- cmp = memcmp(WT_OVFL_TXNC_ADDR(*e), addr, len);
- if (cmp > 0 || (cmp == 0 && (*e)->addr_size > addr_size))
- stack[i--] = e--; /* Drop down a level */
- else
- e = &(*e)->next[i]; /* Keep going at this level */
- }
-}
-
-/*
- * __ovfl_txnc_wrapup --
- * Resolve the page's transaction-cache list.
- */
-static int
-__ovfl_txnc_wrapup(WT_SESSION_IMPL *session, WT_PAGE *page)
-{
- WT_OVFL_TXNC **e, **head, *txnc;
- uint64_t oldest_txn;
- size_t decr;
- int i;
-
- head = page->modify->ovfl_track->ovfl_txnc;
-
- /*
- * Take a snapshot of the oldest transaction ID we need to keep alive.
- * Since we do two passes through entries in the structure, the normal
- * visibility check could give different results as the global ID moves
- * forward.
- */
- oldest_txn = __wt_txn_oldest_id(session);
-
- /*
- * Discard any transaction-cache records with transaction IDs earlier
- * than any in the system.
- *
- * First, walk the overflow transaction-cache skip lists (except for
- * the lowest level), fixing up links.
- */
- for (i = WT_SKIP_MAXDEPTH - 1; i > 0; --i)
- for (e = &head[i]; (txnc = *e) != NULL;) {
- if (WT_TXNID_LE(oldest_txn, txnc->current)) {
- e = &txnc->next[i];
- continue;
- }
- *e = txnc->next[i];
- }
-
- /* Second, discard any no longer needed transaction-cache records. */
- decr = 0;
- for (e = &head[0]; (txnc = *e) != NULL;) {
- if (WT_TXNID_LE(oldest_txn, txnc->current)) {
- e = &txnc->next[0];
- continue;
- }
- *e = txnc->next[0];
-
- if (WT_VERBOSE_ISSET(session, WT_VERB_OVERFLOW))
- WT_RET(
- __ovfl_txnc_verbose(session, page, txnc, "free"));
-
- decr += WT_OVFL_SIZE(txnc, WT_OVFL_TXNC);
- __wt_free(session, txnc);
- }
-
- if (decr != 0)
- __wt_cache_page_inmem_decr(session, page, decr);
- return (0);
-}
-
-/*
- * __wt_ovfl_txnc_search --
- * Search the page's list of transaction-cache overflow records for a
- * match.
- */
-int
-__wt_ovfl_txnc_search(
- WT_PAGE *page, const uint8_t *addr, size_t addr_size, WT_ITEM *store)
-{
- WT_OVFL_TXNC **head, *txnc;
-
- if (page->modify->ovfl_track == NULL)
- return (WT_NOTFOUND);
-
- head = page->modify->ovfl_track->ovfl_txnc;
-
- if ((txnc = __ovfl_txnc_skip_search(head, addr, addr_size)) == NULL)
- return (WT_NOTFOUND);
-
- store->data = WT_OVFL_TXNC_VALUE(txnc);
- store->size = txnc->value_size;
- return (0);
-}
-
-/*
- * __wt_ovfl_txnc_add --
- * Add a new entry to the page's list of transaction-cached overflow
- * records.
- */
-int
-__wt_ovfl_txnc_add(WT_SESSION_IMPL *session, WT_PAGE *page,
- const uint8_t *addr, size_t addr_size,
- const void *value, size_t value_size)
-{
- WT_OVFL_TXNC **head, **stack[WT_SKIP_MAXDEPTH], *txnc;
- size_t size;
- u_int i, skipdepth;
- uint8_t *p;
-
- if (page->modify->ovfl_track == NULL)
- WT_RET(__ovfl_track_init(session, page));
-
- head = page->modify->ovfl_track->ovfl_txnc;
-
- /* Choose a skiplist depth for this insert. */
- skipdepth = __wt_skip_choose_depth(session);
-
- /*
- * Allocate the WT_OVFL_TXNC structure, next pointers for the skip
- * list, room for the address and value, then copy everything into
- * place.
- *
- * To minimize the WT_OVFL_TXNC structure size, the address offset
- * and size are single bytes: that's safe because the address follows
- * the structure (which can't be more than about 100B), and address
- * cookies are limited to 255B.
- */
- size = sizeof(WT_OVFL_TXNC) +
- skipdepth * sizeof(WT_OVFL_TXNC *) + addr_size + value_size;
- WT_RET(__wt_calloc(session, 1, size, &txnc));
- p = (uint8_t *)txnc +
- sizeof(WT_OVFL_TXNC) + skipdepth * sizeof(WT_OVFL_TXNC *);
- txnc->addr_offset = (uint8_t)WT_PTRDIFF(p, txnc);
- txnc->addr_size = (uint8_t)addr_size;
- memcpy(p, addr, addr_size);
- p += addr_size;
- txnc->value_offset = WT_PTRDIFF32(p, txnc);
- txnc->value_size = WT_STORE_SIZE(value_size);
- memcpy(p, value, value_size);
- txnc->current = __wt_txn_id_alloc(session, false);
-
- __wt_cache_page_inmem_incr(
- session, page, WT_OVFL_SIZE(txnc, WT_OVFL_TXNC));
-
- /* Insert the new entry into the skiplist. */
- __ovfl_txnc_skip_search_stack(head, stack, addr, addr_size);
- for (i = 0; i < skipdepth; ++i) {
- txnc->next[i] = *stack[i];
- *stack[i] = txnc;
- }
-
- if (WT_VERBOSE_ISSET(session, WT_VERB_OVERFLOW))
- WT_RET(__ovfl_txnc_verbose(session, page, txnc, "add"));
-
- return (0);
-}
-
-/*
- * __wt_ovfl_txnc_free --
- * Free the page's list of transaction-cached overflow records.
- */
-void
-__wt_ovfl_txnc_free(WT_SESSION_IMPL *session, WT_PAGE *page)
-{
- WT_OVFL_TXNC *txnc;
- WT_PAGE_MODIFY *mod;
- void *next;
-
- mod = page->modify;
- if (mod == NULL || mod->ovfl_track == NULL)
- return;
-
- for (txnc = mod->ovfl_track->ovfl_txnc[0];
- txnc != NULL; txnc = next) {
- next = txnc->next[0];
- __wt_free(session, txnc);
- }
-}
-
-/*
* __wt_ovfl_track_wrapup --
* Resolve the page's overflow tracking on reconciliation success.
*/
int
__wt_ovfl_track_wrapup(WT_SESSION_IMPL *session, WT_PAGE *page)
{
- WT_DECL_RET;
WT_OVFL_TRACK *track;
if (page->modify == NULL || page->modify->ovfl_track == NULL)
@@ -874,12 +583,7 @@ __wt_ovfl_track_wrapup(WT_SESSION_IMPL *session, WT_PAGE *page)
if (track->ovfl_reuse[0] != NULL)
WT_RET(__ovfl_reuse_wrapup(session, page));
- if (track->ovfl_txnc[0] != NULL) {
- __wt_writelock(session, &S2BT(session)->ovfl_lock);
- ret = __ovfl_txnc_wrapup(session, page);
- __wt_writeunlock(session, &S2BT(session)->ovfl_lock);
- }
- return (ret);
+ return (0);
}
/*
@@ -889,7 +593,6 @@ __wt_ovfl_track_wrapup(WT_SESSION_IMPL *session, WT_PAGE *page)
int
__wt_ovfl_track_wrapup_err(WT_SESSION_IMPL *session, WT_PAGE *page)
{
- WT_DECL_RET;
WT_OVFL_TRACK *track;
if (page->modify == NULL || page->modify->ovfl_track == NULL)
@@ -902,10 +605,5 @@ __wt_ovfl_track_wrapup_err(WT_SESSION_IMPL *session, WT_PAGE *page)
if (track->ovfl_reuse[0] != NULL)
WT_RET(__ovfl_reuse_wrapup_err(session, page));
- if (track->ovfl_txnc[0] != NULL) {
- __wt_writelock(session, &S2BT(session)->ovfl_lock);
- ret = __ovfl_txnc_wrapup(session, page);
- __wt_writeunlock(session, &S2BT(session)->ovfl_lock);
- }
- return (ret);
+ return (0);
}
diff --git a/src/third_party/wiredtiger/src/reconcile/rec_write.c b/src/third_party/wiredtiger/src/reconcile/rec_write.c
index a304dc54340..970f760f4ca 100644
--- a/src/third_party/wiredtiger/src/reconcile/rec_write.c
+++ b/src/third_party/wiredtiger/src/reconcile/rec_write.c
@@ -1179,7 +1179,7 @@ __rec_txn_read(WT_SESSION_IMPL *session, WT_RECONCILE *r,
WT_DECL_TIMESTAMP(max_timestamp)
WT_PAGE *page;
WT_UPDATE *append, *upd, *upd_list;
- size_t notused, update_mem;
+ size_t size, update_mem;
uint64_t max_txn, min_txn, txnid;
bool append_origv, skipped;
@@ -1204,8 +1204,8 @@ __rec_txn_read(WT_SESSION_IMPL *session, WT_RECONCILE *r,
update_mem = 0;
max_txn = WT_TXN_NONE;
#ifdef HAVE_TIMESTAMPS
- __wt_timestamp_set(max_timestamp, zero_timestamp);
- memset(min_timestamp, 0xff, WT_TIMESTAMP_SIZE);
+ __wt_timestamp_set_zero(max_timestamp);
+ __wt_timestamp_set_inf(min_timestamp);
#endif
min_txn = UINT64_MAX;
@@ -1419,45 +1419,6 @@ __rec_txn_read(WT_SESSION_IMPL *session, WT_RECONCILE *r,
/* The page can't be marked clean. */
r->leave_dirty = true;
-
- /*
- * A special-case for overflow values, where we can't write the
- * original on-page value item to disk because it's been updated
- * or removed.
- *
- * What happens is that an overflow value is updated or removed
- * and its backing blocks freed. If any reader in the system
- * might still want the value, a copy was cached in the page
- * reconciliation tracking memory, and the page cell set to
- * WT_CELL_VALUE_OVFL_RM. Eviction then chose the page and
- * we're splitting it up in order to push parts of it out of
- * memory.
- *
- * We could write the original on-page value item to disk... if
- * we had a copy. The cache may not have a copy (a globally
- * visible update would have kept a value from being cached), or
- * an update that subsequently became globally visible could
- * cause a cached value to be discarded. Either way, once there
- * is a globally visible update, we may not have the original
- * value.
- *
- * Fortunately, if there's a globally visible update we don't
- * care about the original version, so we simply ignore it, no
- * transaction can ever try and read it. If there isn't a
- * globally visible update, there had better be a cached value.
- *
- * In the latter case, we could write the value out to disk, but
- * (1) we are planning on re-instantiating this page in memory,
- * it isn't going to disk, and (2) the value item is eventually
- * going to be discarded, that seems like a waste of a write.
- * Instead, find the cached value and append it to the update
- * list we're saving for later restoration.
- */
- if (vpack != NULL &&
- vpack->raw == WT_CELL_VALUE_OVFL_RM &&
- !__wt_txn_visible_all(
- session, min_txn, WT_TIMESTAMP(min_timestamp)))
- append_origv = true;
} else {
/*
* The lookaside table eviction path.
@@ -1482,22 +1443,23 @@ __rec_txn_read(WT_SESSION_IMPL *session, WT_RECONCILE *r,
* key/value pair which simply doesn't exist for some reader;
* place a deleted record at the end of the update list.
*/
+ size = 0; /* -Wconditional-uninitialized */
if (vpack == NULL || vpack->type == WT_CELL_DEL)
WT_RET(__wt_update_alloc(session,
- NULL, &append, &notused, WT_UPDATE_DELETED));
+ NULL, &append, &size, WT_UPDATE_DELETED));
else {
WT_RET(__wt_scr_alloc(session, 0, &tmp));
if ((ret = __wt_page_cell_data_ref(
session, page, vpack, tmp)) == 0)
ret = __wt_update_alloc(session,
- tmp, &append, &notused, WT_UPDATE_STANDARD);
+ tmp, &append, &size, WT_UPDATE_STANDARD);
__wt_scr_free(session, &tmp);
WT_RET(ret);
}
/*
- * Give the entry an impossibly low transaction ID to ensure its
- * global visibility, append it to the update list.
+ * Give the entry no transaction ID to ensure global visibility,
+ * append it to the update list.
*
* Note the change to the actual reader-accessible update list:
* from now on, the original on-page value appears at the end
@@ -1508,8 +1470,7 @@ __rec_txn_read(WT_SESSION_IMPL *session, WT_RECONCILE *r,
for (upd = upd_list; upd->next != NULL; upd = upd->next)
;
WT_PUBLISH(upd->next, append);
- __wt_cache_page_inmem_incr(
- session, page, WT_UPDATE_MEMSIZE(append));
+ __wt_cache_page_inmem_incr(session, page, size);
}
/*
@@ -4752,29 +4713,25 @@ record_loop: /*
deleted = false;
/*
- * If doing update save and restore, there's an
- * update that's not globally visible, and the
+ * If doing an update save and restore, and the
* underlying value is a removed overflow value,
* we end up here.
*
- * When the update save/restore code noticed the
- * removed overflow value, it appended a copy of
- * the cached, original overflow value to the
- * update list being saved (ensuring the on-page
- * item will never be accessed after the page is
- * re-instantiated), then returned a NULL update
- * to us.
+ * If necessary, when the overflow value was
+ * originally removed, reconciliation appended
+ * a globally visible copy of the value to the
+ * key's update list, meaning the on-page item
+ * isn't accessed after page re-instantiation.
*
- * Assert the case: if we remove an underlying
- * overflow object, checkpoint reconciliation
- * should never see it again, there should be a
- * visible update in the way.
- *
- * Write a placeholder.
+ * Assert the case.
*/
WT_ASSERT(session,
F_ISSET(r, WT_EVICT_UPDATE_RESTORE));
+ /*
+ * The on-page value will never be accessed,
+ * write a placeholder record.
+ */
data = "@";
size = 1;
} else {
@@ -4905,16 +4862,12 @@ compare: /*
}
/*
- * If we had a reference to an overflow record we never used,
+ * The first time we find an overflow record we never used,
* discard the underlying blocks, they're no longer useful.
- *
- * One complication: we must cache a copy before discarding the
- * on-disk version if there's a transaction in the system that
- * might read the original value.
*/
if (ovfl_state == OVFL_UNUSED &&
vpack->raw != WT_CELL_VALUE_OVFL_RM)
- WT_ERR(__wt_ovfl_cache(session, page, upd, vpack));
+ WT_ERR(__wt_ovfl_remove(session, page, upd, vpack));
}
/* Walk any append list. */
@@ -5079,7 +5032,7 @@ __rec_row_int(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_PAGE *page)
cell = NULL;
key_onpage_ovfl = false;
- WT_RET(__rec_split_init(session, r, page, 0ULL, btree->maxintlpage));
+ WT_RET(__rec_split_init(session, r, page, 0, btree->maxintlpage));
/*
* Ideally, we'd never store the 0th key on row-store internal pages
@@ -5361,7 +5314,7 @@ __rec_row_leaf(WT_SESSION_IMPL *session,
key = &r->k;
val = &r->v;
- WT_RET(__rec_split_init(session, r, page, 0ULL, btree->maxleafpage));
+ WT_RET(__rec_split_init(session, r, page, 0, btree->maxleafpage));
/*
* Write any K/V pairs inserted into the page before the first from-disk
@@ -5451,18 +5404,15 @@ __rec_row_leaf(WT_SESSION_IMPL *session,
dictionary = true;
} else if (vpack->raw == WT_CELL_VALUE_OVFL_RM) {
/*
- * If doing update save and restore in service
- * of eviction, there's an update that's not
- * globally visible, and the underlying value
- * is a removed overflow value, we end up here.
+ * If doing an update save and restore, and the
+ * underlying value is a removed overflow value,
+ * we end up here.
*
- * When the update save/restore code noticed the
- * removed overflow value, it appended a copy of
- * the cached, original overflow value to the
- * update list being saved (ensuring any on-page
- * item will never be accessed after the page is
- * re-instantiated), then returned a NULL update
- * to us.
+ * If necessary, when the overflow value was
+ * originally removed, reconciliation appended
+ * a globally visible copy of the value to the
+ * key's update list, meaning the on-page item
+ * isn't accessed after page re-instantiation.
*
* Assert the case.
*/
@@ -5508,16 +5458,13 @@ __rec_row_leaf(WT_SESSION_IMPL *session,
}
} else {
/*
- * If the original value was an overflow and we've not
- * already done so, discard it. One complication: we
- * must cache a copy before discarding the on-disk
- * version if there's a transaction in the system that
- * might read the original value.
+ * The first time we find an overflow record we're not
+ * going to use, discard the underlying blocks.
*/
if (vpack != NULL &&
vpack->ovfl && vpack->raw != WT_CELL_VALUE_OVFL_RM)
- WT_ERR(
- __wt_ovfl_cache(session, page, rip, vpack));
+ WT_ERR(__wt_ovfl_remove(
+ session, page, upd, vpack));
/* If this key/value pair was deleted, we're done. */
if (upd->type == WT_UPDATE_DELETED) {
diff --git a/src/third_party/wiredtiger/src/schema/schema_alter.c b/src/third_party/wiredtiger/src/schema/schema_alter.c
index 346f09a1a64..7af4b86bc85 100644
--- a/src/third_party/wiredtiger/src/schema/schema_alter.c
+++ b/src/third_party/wiredtiger/src/schema/schema_alter.c
@@ -9,16 +9,24 @@
#include "wt_internal.h"
/*
- * __alter_file --
+ * __wt_alter --
* Alter a file.
*/
-static int
-__alter_file(WT_SESSION_IMPL *session, const char *uri, const char *newcfg[])
+int
+__wt_alter(WT_SESSION_IMPL *session, const char *newcfg[])
{
WT_DECL_RET;
- const char *cfg[4], *filename;
+ const char *cfg[4], *filename, *uri;
char *config, *newconfig;
+ uri = session->dhandle->name;
+ WT_RET(__wt_meta_track_on(session));
+
+ /*
+ * We know that we have exclusive access to the file. So it will be
+ * closed after we're done with it and the next open will see the
+ * updated metadata.
+ */
filename = uri;
newconfig = NULL;
if (!WT_PREFIX_SKIP(filename, "file:"))
@@ -48,122 +56,6 @@ __alter_file(WT_SESSION_IMPL *session, const char *uri, const char *newcfg[])
err: __wt_free(session, config);
__wt_free(session, newconfig);
- return (ret);
-}
-
-/*
- * __alter_colgroup --
- * WT_SESSION::alter for a colgroup.
- */
-static int
-__alter_colgroup(
- WT_SESSION_IMPL *session, const char *uri, const char *cfg[])
-{
- WT_COLGROUP *colgroup;
- WT_DECL_RET;
-
- WT_ASSERT(session, F_ISSET(session, WT_SESSION_LOCKED_TABLE));
-
- /* If we can get the colgroup, perform any potential alterations. */
- if ((ret = __wt_schema_get_colgroup(
- session, uri, false, NULL, &colgroup)) == 0)
- WT_TRET(__wt_schema_alter(session, colgroup->source, cfg));
-
- return (ret);
-}
-
-/*
- * __alter_index --
- * WT_SESSION::alter for an index.
- */
-static int
-__alter_index(
- WT_SESSION_IMPL *session, const char *uri, const char *cfg[])
-{
- WT_INDEX *idx;
- WT_DECL_RET;
-
- /* If we can get the index, perform any potential alterations. */
- if ((ret = __wt_schema_get_index(
- session, uri, false, NULL, &idx)) == 0)
- WT_TRET(__wt_schema_alter(session, idx->source, cfg));
-
- return (ret);
-}
-
-/*
- * __alter_table --
- * WT_SESSION::alter for a table.
- */
-static int
-__alter_table(WT_SESSION_IMPL *session, const char *uri, const char *cfg[])
-{
- WT_COLGROUP *colgroup;
- WT_DECL_RET;
- WT_TABLE *table;
- const char *name;
- u_int i;
-
- name = uri;
- (void)WT_PREFIX_SKIP(name, "table:");
-
- WT_RET(__wt_schema_get_table(
- session, name, strlen(name), true, &table));
-
- /*
- * Alter the column groups only if we are using the default
- * column group. Otherwise the user should alter each
- * index or column group explicitly.
- */
- if (table->ncolgroups == 0)
- for (i = 0; i < WT_COLGROUPS(table); i++) {
- if ((colgroup = table->cgroups[i]) == NULL)
- continue;
- /*
- * Alter the column group before updating the metadata
- * to avoid the metadata for the table becoming
- * inconsistent if we can't get exclusive access.
- */
- WT_ERR(__wt_schema_alter(
- session, colgroup->source, cfg));
- }
-err: __wt_schema_release_table(session, table);
- return (ret);
-}
-
-/*
- * __wt_schema_alter --
- * Process a WT_SESSION::alter operation for all supported types.
- */
-int
-__wt_schema_alter(WT_SESSION_IMPL *session, const char *uri, const char *cfg[])
-{
- WT_DATA_SOURCE *dsrc;
- WT_DECL_RET;
-
- WT_RET(__wt_meta_track_on(session));
-
- /* Paranoia: clear any handle from our caller. */
- session->dhandle = NULL;
-
- if (WT_PREFIX_MATCH(uri, "colgroup:"))
- ret = __alter_colgroup(session, uri, cfg);
- else if (WT_PREFIX_MATCH(uri, "file:"))
- ret = __alter_file(session, uri, cfg);
- else if (WT_PREFIX_MATCH(uri, "index:"))
- ret = __alter_index(session, uri, cfg);
- else if (WT_PREFIX_MATCH(uri, "lsm:"))
- ret = __wt_lsm_tree_alter(session, uri, cfg);
- else if (WT_PREFIX_MATCH(uri, "table:"))
- ret = __alter_table(session, uri, cfg);
- else if ((dsrc = __wt_schema_get_source(session, uri)) != NULL)
- ret = dsrc->alter == NULL ?
- __wt_object_unsupported(session, uri) :
- dsrc->alter(dsrc,
- &session->iface, uri, (WT_CONFIG_ARG *)cfg);
- else
- ret = __wt_bad_object_type(session, uri);
-
/*
* Map WT_NOTFOUND to ENOENT, based on the assumption WT_NOTFOUND means
* there was no metadata entry.
diff --git a/src/third_party/wiredtiger/src/session/session_api.c b/src/third_party/wiredtiger/src/session/session_api.c
index 882de30f12b..2ad2380dc2c 100644
--- a/src/third_party/wiredtiger/src/session/session_api.c
+++ b/src/third_party/wiredtiger/src/session/session_api.c
@@ -149,6 +149,10 @@ __session_alter(WT_SESSION *wt_session, const char *uri, const char *config)
SESSION_API_CALL(session, alter, config, cfg);
+ /* In-memory ignores alter operations. */
+ if (F_ISSET(S2C(session), WT_CONN_IN_MEMORY))
+ goto err;
+
/* Disallow objects in the WiredTiger name space. */
WT_ERR(__wt_str_name_check(session, uri));
@@ -161,8 +165,9 @@ __session_alter(WT_SESSION *wt_session, const char *uri, const char *config)
cfg[1] = NULL;
WT_WITH_CHECKPOINT_LOCK(session,
WT_WITH_SCHEMA_LOCK(session,
- WT_WITH_TABLE_WRITE_LOCK(session,
- ret = __wt_schema_alter(session, uri, cfg))));
+ ret = __wt_schema_worker(session, uri, __wt_alter, NULL, cfg,
+ WT_BTREE_ALTER |
+ WT_DHANDLE_DISCARD_FORCE | WT_DHANDLE_EXCLUSIVE)));
err: if (ret != 0)
WT_STAT_CONN_INCR(session, session_table_alter_fail);
@@ -700,6 +705,10 @@ __session_rebalance(WT_SESSION *wt_session, const char *uri, const char *config)
SESSION_API_CALL(session, rebalance, config, cfg);
+ /* In-memory ignores rebalance operations. */
+ if (F_ISSET(S2C(session), WT_CONN_IN_MEMORY))
+ goto err;
+
/* Block out checkpoints to avoid spurious EBUSY errors. */
WT_WITH_CHECKPOINT_LOCK(session,
WT_WITH_SCHEMA_LOCK(session,
@@ -709,8 +718,7 @@ __session_rebalance(WT_SESSION *wt_session, const char *uri, const char *config)
err: if (ret != 0)
WT_STAT_CONN_INCR(session, session_table_rebalance_fail);
else
- WT_STAT_CONN_INCR(session,
- session_table_rebalance_success);
+ WT_STAT_CONN_INCR(session, session_table_rebalance_success);
API_END_RET_NOTFOUND_MAP(session, ret);
}
@@ -1046,10 +1054,7 @@ __session_salvage(WT_SESSION *wt_session, const char *uri, const char *config)
SESSION_API_CALL(session, salvage, config, cfg);
- if (F_ISSET(S2C(session), WT_CONN_IN_MEMORY))
- WT_ERR_MSG(session, ENOTSUP,
- "WT_SESSION.salvage not supported for in-memory "
- "configurations");
+ WT_ERR(__wt_inmem_unsupported_op(session, NULL));
/* Block out checkpoints to avoid spurious EBUSY errors. */
WT_WITH_CHECKPOINT_LOCK(session,
@@ -1258,7 +1263,7 @@ __session_truncate(WT_SESSION *wt_session,
WT_ERR_MSG(session, EINVAL,
"the truncate method should not specify any"
"target after the log: URI prefix");
- WT_ERR(__wt_log_truncate_files(session, start, cfg));
+ WT_ERR(__wt_log_truncate_files(session, start, false));
} else if (WT_PREFIX_MATCH(uri, "file:"))
WT_ERR(__wt_session_range_truncate(
session, uri, start, stop));
@@ -1319,6 +1324,9 @@ __session_upgrade(WT_SESSION *wt_session, const char *uri, const char *config)
session = (WT_SESSION_IMPL *)wt_session;
SESSION_API_CALL(session, upgrade, config, cfg);
+
+ WT_ERR(__wt_inmem_unsupported_op(session, NULL));
+
/* Block out checkpoints to avoid spurious EBUSY errors. */
WT_WITH_CHECKPOINT_LOCK(session,
WT_WITH_SCHEMA_LOCK(session,
@@ -1363,10 +1371,7 @@ __session_verify(WT_SESSION *wt_session, const char *uri, const char *config)
SESSION_API_CALL(session, verify, config, cfg);
- if (F_ISSET(S2C(session), WT_CONN_IN_MEMORY))
- WT_ERR_MSG(session, ENOTSUP,
- "WT_SESSION.verify not supported for in-memory "
- "configurations");
+ WT_ERR(__wt_inmem_unsupported_op(session, NULL));
/* Block out checkpoints to avoid spurious EBUSY errors. */
WT_WITH_CHECKPOINT_LOCK(session,
@@ -1632,10 +1637,7 @@ __session_checkpoint(WT_SESSION *wt_session, const char *config)
WT_STAT_CONN_INCR(session, txn_checkpoint);
SESSION_API_CALL(session, checkpoint, config, cfg);
- if (F_ISSET(S2C(session), WT_CONN_IN_MEMORY))
- WT_ERR_MSG(session, ENOTSUP,
- "WT_SESSION.checkpoint not supported for in-memory "
- "configurations");
+ WT_ERR(__wt_inmem_unsupported_op(session, NULL));
/*
* Checkpoints require a snapshot to write a transactionally consistent
@@ -1826,7 +1828,7 @@ __open_session(WT_CONNECTION_IMPL *conn,
if (i == conn->session_size)
WT_ERR_MSG(session, ENOMEM,
"only configured to support %" PRIu32 " sessions"
- " (including %" PRIu32 " additional internal sessions)",
+ " (including %d additional internal sessions)",
conn->session_size, WT_EXTRA_INTERNAL_SESSIONS);
/*
diff --git a/src/third_party/wiredtiger/src/session/session_compact.c b/src/third_party/wiredtiger/src/session/session_compact.c
index c4710dbb1a5..10328e0db5b 100644
--- a/src/third_party/wiredtiger/src/session/session_compact.c
+++ b/src/third_party/wiredtiger/src/session/session_compact.c
@@ -324,7 +324,7 @@ __wt_session_compact(
session = (WT_SESSION_IMPL *)wt_session;
SESSION_API_CALL(session, compact, config, cfg);
- /* In-memory is already as compact as it's going to get. */
+ /* In-memory ignores compaction operations. */
if (F_ISSET(S2C(session), WT_CONN_IN_MEMORY))
goto err;
diff --git a/src/third_party/wiredtiger/src/support/err.c b/src/third_party/wiredtiger/src/support/err.c
index 5ec995d8f65..94ae27628c2 100644
--- a/src/third_party/wiredtiger/src/support/err.c
+++ b/src/third_party/wiredtiger/src/support/err.c
@@ -361,6 +361,22 @@ __wt_ext_err_printf(
}
/*
+ * __wt_verbose_worker --
+ * Verbose message.
+ */
+void
+__wt_verbose_worker(WT_SESSION_IMPL *session, const char *fmt, ...)
+ WT_GCC_FUNC_ATTRIBUTE((format (printf, 2, 3)))
+ WT_GCC_FUNC_ATTRIBUTE((cold))
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ WT_IGNORE_RET(__wt_eventv(session, true, 0, NULL, 0, fmt, ap));
+ va_end(ap);
+}
+
+/*
* info_msg --
* Informational message.
*/
@@ -533,6 +549,22 @@ __wt_illegal_value(WT_SESSION_IMPL *session, const char *name)
}
/*
+ * __wt_inmem_unsupported_op --
+ * Print a standard error message for an operation that's not supported
+ * for in-memory configurations.
+ */
+int
+__wt_inmem_unsupported_op(WT_SESSION_IMPL *session, const char *tag)
+ WT_GCC_FUNC_ATTRIBUTE((cold))
+{
+ if (F_ISSET(S2C(session), WT_CONN_IN_MEMORY))
+ WT_RET_MSG(session, ENOTSUP,
+ "%s%snot supported for in-memory configurations",
+ tag == NULL ? "" : tag, tag == NULL ? "" : ": ");
+ return (0);
+}
+
+/*
* __wt_object_unsupported --
* Print a standard error message for an object that doesn't support a
* particular operation.
diff --git a/src/third_party/wiredtiger/src/support/generation.c b/src/third_party/wiredtiger/src/support/generation.c
index 6e16d7e57fe..182fb2de095 100644
--- a/src/third_party/wiredtiger/src/support/generation.c
+++ b/src/third_party/wiredtiger/src/support/generation.c
@@ -116,6 +116,12 @@ __wt_gen_drain(WT_SESSION_IMPL *session, int which, uint64_t generation)
if (v == 0 || v >= generation)
break;
+ /* If we're waiting on ourselves, we're deadlocked. */
+ if (session == s) {
+ WT_ASSERT(session, session != s);
+ WT_IGNORE_RET(__wt_panic(session));
+ }
+
/*
* The pause count is cumulative, quit spinning if it's
* not doing us any good, that can happen in generations
diff --git a/src/third_party/wiredtiger/src/support/rand.c b/src/third_party/wiredtiger/src/support/rand.c
index 8083b8801c1..64ed2341eeb 100644
--- a/src/third_party/wiredtiger/src/support/rand.c
+++ b/src/third_party/wiredtiger/src/support/rand.c
@@ -120,15 +120,3 @@ __wt_random(WT_RAND_STATE volatile * rnd_state)
return ((z << 16) + (w & 65535));
}
-
-/*
- * __wt_random64 --
- * Return a 64-bit pseudo-random number.
- */
-uint64_t
-__wt_random64(WT_RAND_STATE volatile * rnd_state)
- WT_GCC_FUNC_ATTRIBUTE((visibility("default")))
-{
- return (((uint64_t)__wt_random(rnd_state) << 32) +
- __wt_random(rnd_state));
-}
diff --git a/src/third_party/wiredtiger/src/support/stat.c b/src/third_party/wiredtiger/src/support/stat.c
index 2dc006da827..14a1d2a3b86 100644
--- a/src/third_party/wiredtiger/src/support/stat.c
+++ b/src/third_party/wiredtiger/src/support/stat.c
@@ -48,6 +48,19 @@ static const char * const __stats_dsrc_desc[] = {
"cache: bytes written from cache",
"cache: checkpoint blocked page eviction",
"cache: data source pages selected for eviction unable to be evicted",
+ "cache: eviction walk passes of a file",
+ "cache: eviction walk target pages histogram - 0-9",
+ "cache: eviction walk target pages histogram - 10-31",
+ "cache: eviction walk target pages histogram - 128 and higher",
+ "cache: eviction walk target pages histogram - 32-63",
+ "cache: eviction walk target pages histogram - 64-128",
+ "cache: eviction walks abandoned",
+ "cache: eviction walks gave up because they restarted their walk twice",
+ "cache: eviction walks gave up because they saw too many pages and found no candidates",
+ "cache: eviction walks gave up because they saw too many pages and found too few candidates",
+ "cache: eviction walks reached end of tree",
+ "cache: eviction walks started from root of tree",
+ "cache: eviction walks started from saved location in tree",
"cache: hazard pointer blocked page eviction",
"cache: in-memory page passed criteria to be split",
"cache: in-memory page splits",
@@ -56,18 +69,20 @@ static const char * const __stats_dsrc_desc[] = {
"cache: leaf pages split during eviction",
"cache: modified pages evicted",
"cache: overflow pages read into cache",
- "cache: overflow values cached in memory",
"cache: page split during eviction deepened the tree",
"cache: page written requiring lookaside records",
"cache: pages read into cache",
"cache: pages read into cache requiring lookaside entries",
"cache: pages requested from the cache",
+ "cache: pages seen by eviction walk",
"cache: pages written from cache",
"cache: pages written requiring in-memory restoration",
"cache: tracked dirty bytes in the cache",
"cache: unmodified pages evicted",
"cache_walk: Average difference between current eviction generation when the page was last considered",
"cache_walk: Average on-disk page image size seen",
+ "cache_walk: Average time in cache for pages that have been visited by the eviction server",
+ "cache_walk: Average time in cache for pages that have not been visited by the eviction server",
"cache_walk: Clean pages currently in cache",
"cache_walk: Current eviction generation",
"cache_walk: Dirty pages currently in cache",
@@ -77,6 +92,7 @@ static const char * const __stats_dsrc_desc[] = {
"cache_walk: Maximum difference between current eviction generation when the page was last considered",
"cache_walk: Maximum page size seen",
"cache_walk: Minimum on-disk page image size seen",
+ "cache_walk: Number of pages never visited by eviction server",
"cache_walk: On-disk page image sizes smaller than a single allocation unit",
"cache_walk: Pages created in memory and never written",
"cache_walk: Pages currently queued for eviction",
@@ -212,6 +228,19 @@ __wt_stat_dsrc_clear_single(WT_DSRC_STATS *stats)
stats->cache_bytes_write = 0;
stats->cache_eviction_checkpoint = 0;
stats->cache_eviction_fail = 0;
+ stats->cache_eviction_walk_passes = 0;
+ stats->cache_eviction_target_page_lt10 = 0;
+ stats->cache_eviction_target_page_lt32 = 0;
+ stats->cache_eviction_target_page_ge128 = 0;
+ stats->cache_eviction_target_page_lt64 = 0;
+ stats->cache_eviction_target_page_lt128 = 0;
+ stats->cache_eviction_walks_abandoned = 0;
+ stats->cache_eviction_walks_stopped = 0;
+ stats->cache_eviction_walks_gave_up_no_targets = 0;
+ stats->cache_eviction_walks_gave_up_ratio = 0;
+ stats->cache_eviction_walks_ended = 0;
+ stats->cache_eviction_walk_from_root = 0;
+ stats->cache_eviction_walk_saved_pos = 0;
stats->cache_eviction_hazard = 0;
stats->cache_inmem_splittable = 0;
stats->cache_inmem_split = 0;
@@ -220,18 +249,20 @@ __wt_stat_dsrc_clear_single(WT_DSRC_STATS *stats)
stats->cache_eviction_split_leaf = 0;
stats->cache_eviction_dirty = 0;
stats->cache_read_overflow = 0;
- stats->cache_overflow_value = 0;
stats->cache_eviction_deepen = 0;
stats->cache_write_lookaside = 0;
stats->cache_read = 0;
stats->cache_read_lookaside = 0;
stats->cache_pages_requested = 0;
+ stats->cache_eviction_pages_seen = 0;
stats->cache_write = 0;
stats->cache_write_restore = 0;
/* not clearing cache_bytes_dirty */
stats->cache_eviction_clean = 0;
/* not clearing cache_state_gen_avg_gap */
/* not clearing cache_state_avg_written_size */
+ /* not clearing cache_state_avg_visited_age */
+ /* not clearing cache_state_avg_unvisited_age */
/* not clearing cache_state_pages_clean */
/* not clearing cache_state_gen_current */
/* not clearing cache_state_pages_dirty */
@@ -241,6 +272,7 @@ __wt_stat_dsrc_clear_single(WT_DSRC_STATS *stats)
/* not clearing cache_state_gen_max_gap */
/* not clearing cache_state_max_pagesize */
/* not clearing cache_state_min_written_size */
+ /* not clearing cache_state_unvisited_count */
/* not clearing cache_state_smaller_alloc_size */
/* not clearing cache_state_memory */
/* not clearing cache_state_queued */
@@ -361,6 +393,30 @@ __wt_stat_dsrc_aggregate_single(
to->cache_bytes_write += from->cache_bytes_write;
to->cache_eviction_checkpoint += from->cache_eviction_checkpoint;
to->cache_eviction_fail += from->cache_eviction_fail;
+ to->cache_eviction_walk_passes += from->cache_eviction_walk_passes;
+ to->cache_eviction_target_page_lt10 +=
+ from->cache_eviction_target_page_lt10;
+ to->cache_eviction_target_page_lt32 +=
+ from->cache_eviction_target_page_lt32;
+ to->cache_eviction_target_page_ge128 +=
+ from->cache_eviction_target_page_ge128;
+ to->cache_eviction_target_page_lt64 +=
+ from->cache_eviction_target_page_lt64;
+ to->cache_eviction_target_page_lt128 +=
+ from->cache_eviction_target_page_lt128;
+ to->cache_eviction_walks_abandoned +=
+ from->cache_eviction_walks_abandoned;
+ to->cache_eviction_walks_stopped +=
+ from->cache_eviction_walks_stopped;
+ to->cache_eviction_walks_gave_up_no_targets +=
+ from->cache_eviction_walks_gave_up_no_targets;
+ to->cache_eviction_walks_gave_up_ratio +=
+ from->cache_eviction_walks_gave_up_ratio;
+ to->cache_eviction_walks_ended += from->cache_eviction_walks_ended;
+ to->cache_eviction_walk_from_root +=
+ from->cache_eviction_walk_from_root;
+ to->cache_eviction_walk_saved_pos +=
+ from->cache_eviction_walk_saved_pos;
to->cache_eviction_hazard += from->cache_eviction_hazard;
to->cache_inmem_splittable += from->cache_inmem_splittable;
to->cache_inmem_split += from->cache_inmem_split;
@@ -370,12 +426,12 @@ __wt_stat_dsrc_aggregate_single(
to->cache_eviction_split_leaf += from->cache_eviction_split_leaf;
to->cache_eviction_dirty += from->cache_eviction_dirty;
to->cache_read_overflow += from->cache_read_overflow;
- to->cache_overflow_value += from->cache_overflow_value;
to->cache_eviction_deepen += from->cache_eviction_deepen;
to->cache_write_lookaside += from->cache_write_lookaside;
to->cache_read += from->cache_read;
to->cache_read_lookaside += from->cache_read_lookaside;
to->cache_pages_requested += from->cache_pages_requested;
+ to->cache_eviction_pages_seen += from->cache_eviction_pages_seen;
to->cache_write += from->cache_write;
to->cache_write_restore += from->cache_write_restore;
to->cache_bytes_dirty += from->cache_bytes_dirty;
@@ -383,6 +439,9 @@ __wt_stat_dsrc_aggregate_single(
to->cache_state_gen_avg_gap += from->cache_state_gen_avg_gap;
to->cache_state_avg_written_size +=
from->cache_state_avg_written_size;
+ to->cache_state_avg_visited_age += from->cache_state_avg_visited_age;
+ to->cache_state_avg_unvisited_age +=
+ from->cache_state_avg_unvisited_age;
to->cache_state_pages_clean += from->cache_state_pages_clean;
to->cache_state_gen_current += from->cache_state_gen_current;
to->cache_state_pages_dirty += from->cache_state_pages_dirty;
@@ -393,6 +452,7 @@ __wt_stat_dsrc_aggregate_single(
to->cache_state_max_pagesize += from->cache_state_max_pagesize;
to->cache_state_min_written_size +=
from->cache_state_min_written_size;
+ to->cache_state_unvisited_count += from->cache_state_unvisited_count;
to->cache_state_smaller_alloc_size +=
from->cache_state_smaller_alloc_size;
to->cache_state_memory += from->cache_state_memory;
@@ -520,6 +580,32 @@ __wt_stat_dsrc_aggregate(
to->cache_eviction_checkpoint +=
WT_STAT_READ(from, cache_eviction_checkpoint);
to->cache_eviction_fail += WT_STAT_READ(from, cache_eviction_fail);
+ to->cache_eviction_walk_passes +=
+ WT_STAT_READ(from, cache_eviction_walk_passes);
+ to->cache_eviction_target_page_lt10 +=
+ WT_STAT_READ(from, cache_eviction_target_page_lt10);
+ to->cache_eviction_target_page_lt32 +=
+ WT_STAT_READ(from, cache_eviction_target_page_lt32);
+ to->cache_eviction_target_page_ge128 +=
+ WT_STAT_READ(from, cache_eviction_target_page_ge128);
+ to->cache_eviction_target_page_lt64 +=
+ WT_STAT_READ(from, cache_eviction_target_page_lt64);
+ to->cache_eviction_target_page_lt128 +=
+ WT_STAT_READ(from, cache_eviction_target_page_lt128);
+ to->cache_eviction_walks_abandoned +=
+ WT_STAT_READ(from, cache_eviction_walks_abandoned);
+ to->cache_eviction_walks_stopped +=
+ WT_STAT_READ(from, cache_eviction_walks_stopped);
+ to->cache_eviction_walks_gave_up_no_targets +=
+ WT_STAT_READ(from, cache_eviction_walks_gave_up_no_targets);
+ to->cache_eviction_walks_gave_up_ratio +=
+ WT_STAT_READ(from, cache_eviction_walks_gave_up_ratio);
+ to->cache_eviction_walks_ended +=
+ WT_STAT_READ(from, cache_eviction_walks_ended);
+ to->cache_eviction_walk_from_root +=
+ WT_STAT_READ(from, cache_eviction_walk_from_root);
+ to->cache_eviction_walk_saved_pos +=
+ WT_STAT_READ(from, cache_eviction_walk_saved_pos);
to->cache_eviction_hazard +=
WT_STAT_READ(from, cache_eviction_hazard);
to->cache_inmem_splittable +=
@@ -533,7 +619,6 @@ __wt_stat_dsrc_aggregate(
WT_STAT_READ(from, cache_eviction_split_leaf);
to->cache_eviction_dirty += WT_STAT_READ(from, cache_eviction_dirty);
to->cache_read_overflow += WT_STAT_READ(from, cache_read_overflow);
- to->cache_overflow_value += WT_STAT_READ(from, cache_overflow_value);
to->cache_eviction_deepen +=
WT_STAT_READ(from, cache_eviction_deepen);
to->cache_write_lookaside +=
@@ -542,6 +627,8 @@ __wt_stat_dsrc_aggregate(
to->cache_read_lookaside += WT_STAT_READ(from, cache_read_lookaside);
to->cache_pages_requested +=
WT_STAT_READ(from, cache_pages_requested);
+ to->cache_eviction_pages_seen +=
+ WT_STAT_READ(from, cache_eviction_pages_seen);
to->cache_write += WT_STAT_READ(from, cache_write);
to->cache_write_restore += WT_STAT_READ(from, cache_write_restore);
to->cache_bytes_dirty += WT_STAT_READ(from, cache_bytes_dirty);
@@ -550,6 +637,10 @@ __wt_stat_dsrc_aggregate(
WT_STAT_READ(from, cache_state_gen_avg_gap);
to->cache_state_avg_written_size +=
WT_STAT_READ(from, cache_state_avg_written_size);
+ to->cache_state_avg_visited_age +=
+ WT_STAT_READ(from, cache_state_avg_visited_age);
+ to->cache_state_avg_unvisited_age +=
+ WT_STAT_READ(from, cache_state_avg_unvisited_age);
to->cache_state_pages_clean +=
WT_STAT_READ(from, cache_state_pages_clean);
to->cache_state_gen_current +=
@@ -568,6 +659,8 @@ __wt_stat_dsrc_aggregate(
WT_STAT_READ(from, cache_state_max_pagesize);
to->cache_state_min_written_size +=
WT_STAT_READ(from, cache_state_min_written_size);
+ to->cache_state_unvisited_count +=
+ WT_STAT_READ(from, cache_state_unvisited_count);
to->cache_state_smaller_alloc_size +=
WT_STAT_READ(from, cache_state_smaller_alloc_size);
to->cache_state_memory += WT_STAT_READ(from, cache_state_memory);
@@ -678,13 +771,25 @@ static const char * const __stats_connection_desc[] = {
"cache: eviction calls to get a page found queue empty after locking",
"cache: eviction currently operating in aggressive mode",
"cache: eviction empty score",
+ "cache: eviction passes of a file",
"cache: eviction server candidate queue empty when topping up",
"cache: eviction server candidate queue not empty when topping up",
"cache: eviction server evicting pages",
"cache: eviction server slept, because we did not make progress with eviction",
"cache: eviction server unable to reach eviction goal",
"cache: eviction state",
+ "cache: eviction walk target pages histogram - 0-9",
+ "cache: eviction walk target pages histogram - 10-31",
+ "cache: eviction walk target pages histogram - 128 and higher",
+ "cache: eviction walk target pages histogram - 32-63",
+ "cache: eviction walk target pages histogram - 64-128",
"cache: eviction walks abandoned",
+ "cache: eviction walks gave up because they restarted their walk twice",
+ "cache: eviction walks gave up because they saw too many pages and found no candidates",
+ "cache: eviction walks gave up because they saw too many pages and found too few candidates",
+ "cache: eviction walks reached end of tree",
+ "cache: eviction walks started from root of tree",
+ "cache: eviction walks started from saved location in tree",
"cache: eviction worker thread active",
"cache: eviction worker thread created",
"cache: eviction worker thread evicting pages",
@@ -711,7 +816,6 @@ static const char * const __stats_connection_desc[] = {
"cache: modified pages evicted",
"cache: modified pages evicted by application threads",
"cache: overflow pages read into cache",
- "cache: overflow values cached in memory",
"cache: page split during eviction deepened the tree",
"cache: page written requiring lookaside records",
"cache: pages currently held in the cache",
@@ -789,6 +893,7 @@ static const char * const __stats_connection_desc[] = {
"lock: table read lock acquisitions",
"lock: table write lock acquisitions",
"log: busy returns attempting to switch slots",
+ "log: force checkpoint calls slept",
"log: log bytes of payload data",
"log: log bytes written",
"log: log files manually zero-filled",
@@ -981,13 +1086,25 @@ __wt_stat_connection_clear_single(WT_CONNECTION_STATS *stats)
stats->cache_eviction_get_ref_empty2 = 0;
/* not clearing cache_eviction_aggressive_set */
/* not clearing cache_eviction_empty_score */
+ stats->cache_eviction_walk_passes = 0;
stats->cache_eviction_queue_empty = 0;
stats->cache_eviction_queue_not_empty = 0;
stats->cache_eviction_server_evicting = 0;
stats->cache_eviction_server_slept = 0;
stats->cache_eviction_slow = 0;
/* not clearing cache_eviction_state */
+ stats->cache_eviction_target_page_lt10 = 0;
+ stats->cache_eviction_target_page_lt32 = 0;
+ stats->cache_eviction_target_page_ge128 = 0;
+ stats->cache_eviction_target_page_lt64 = 0;
+ stats->cache_eviction_target_page_lt128 = 0;
stats->cache_eviction_walks_abandoned = 0;
+ stats->cache_eviction_walks_stopped = 0;
+ stats->cache_eviction_walks_gave_up_no_targets = 0;
+ stats->cache_eviction_walks_gave_up_ratio = 0;
+ stats->cache_eviction_walks_ended = 0;
+ stats->cache_eviction_walk_from_root = 0;
+ stats->cache_eviction_walk_saved_pos = 0;
/* not clearing cache_eviction_active_workers */
stats->cache_eviction_worker_created = 0;
stats->cache_eviction_worker_evicting = 0;
@@ -1014,7 +1131,6 @@ __wt_stat_connection_clear_single(WT_CONNECTION_STATS *stats)
stats->cache_eviction_dirty = 0;
stats->cache_eviction_app_dirty = 0;
stats->cache_read_overflow = 0;
- stats->cache_overflow_value = 0;
stats->cache_eviction_deepen = 0;
stats->cache_write_lookaside = 0;
/* not clearing cache_pages_inuse */
@@ -1092,6 +1208,7 @@ __wt_stat_connection_clear_single(WT_CONNECTION_STATS *stats)
stats->lock_table_read_count = 0;
stats->lock_table_write_count = 0;
stats->log_slot_switch_busy = 0;
+ stats->log_force_ckpt_sleep = 0;
stats->log_bytes_payload = 0;
stats->log_bytes_written = 0;
stats->log_zero_fills = 0;
@@ -1272,6 +1389,8 @@ __wt_stat_connection_aggregate(
WT_STAT_READ(from, cache_eviction_aggressive_set);
to->cache_eviction_empty_score +=
WT_STAT_READ(from, cache_eviction_empty_score);
+ to->cache_eviction_walk_passes +=
+ WT_STAT_READ(from, cache_eviction_walk_passes);
to->cache_eviction_queue_empty +=
WT_STAT_READ(from, cache_eviction_queue_empty);
to->cache_eviction_queue_not_empty +=
@@ -1282,8 +1401,30 @@ __wt_stat_connection_aggregate(
WT_STAT_READ(from, cache_eviction_server_slept);
to->cache_eviction_slow += WT_STAT_READ(from, cache_eviction_slow);
to->cache_eviction_state += WT_STAT_READ(from, cache_eviction_state);
+ to->cache_eviction_target_page_lt10 +=
+ WT_STAT_READ(from, cache_eviction_target_page_lt10);
+ to->cache_eviction_target_page_lt32 +=
+ WT_STAT_READ(from, cache_eviction_target_page_lt32);
+ to->cache_eviction_target_page_ge128 +=
+ WT_STAT_READ(from, cache_eviction_target_page_ge128);
+ to->cache_eviction_target_page_lt64 +=
+ WT_STAT_READ(from, cache_eviction_target_page_lt64);
+ to->cache_eviction_target_page_lt128 +=
+ WT_STAT_READ(from, cache_eviction_target_page_lt128);
to->cache_eviction_walks_abandoned +=
WT_STAT_READ(from, cache_eviction_walks_abandoned);
+ to->cache_eviction_walks_stopped +=
+ WT_STAT_READ(from, cache_eviction_walks_stopped);
+ to->cache_eviction_walks_gave_up_no_targets +=
+ WT_STAT_READ(from, cache_eviction_walks_gave_up_no_targets);
+ to->cache_eviction_walks_gave_up_ratio +=
+ WT_STAT_READ(from, cache_eviction_walks_gave_up_ratio);
+ to->cache_eviction_walks_ended +=
+ WT_STAT_READ(from, cache_eviction_walks_ended);
+ to->cache_eviction_walk_from_root +=
+ WT_STAT_READ(from, cache_eviction_walk_from_root);
+ to->cache_eviction_walk_saved_pos +=
+ WT_STAT_READ(from, cache_eviction_walk_saved_pos);
to->cache_eviction_active_workers +=
WT_STAT_READ(from, cache_eviction_active_workers);
to->cache_eviction_worker_created +=
@@ -1330,7 +1471,6 @@ __wt_stat_connection_aggregate(
to->cache_eviction_app_dirty +=
WT_STAT_READ(from, cache_eviction_app_dirty);
to->cache_read_overflow += WT_STAT_READ(from, cache_read_overflow);
- to->cache_overflow_value += WT_STAT_READ(from, cache_overflow_value);
to->cache_eviction_deepen +=
WT_STAT_READ(from, cache_eviction_deepen);
to->cache_write_lookaside +=
@@ -1433,6 +1573,7 @@ __wt_stat_connection_aggregate(
to->lock_table_write_count +=
WT_STAT_READ(from, lock_table_write_count);
to->log_slot_switch_busy += WT_STAT_READ(from, log_slot_switch_busy);
+ to->log_force_ckpt_sleep += WT_STAT_READ(from, log_force_ckpt_sleep);
to->log_bytes_payload += WT_STAT_READ(from, log_bytes_payload);
to->log_bytes_written += WT_STAT_READ(from, log_bytes_written);
to->log_zero_fills += WT_STAT_READ(from, log_zero_fills);
diff --git a/src/third_party/wiredtiger/src/txn/txn.c b/src/third_party/wiredtiger/src/txn/txn.c
index 02adad65ba5..18a3c0021f0 100644
--- a/src/third_party/wiredtiger/src/txn/txn.c
+++ b/src/third_party/wiredtiger/src/txn/txn.c
@@ -441,7 +441,6 @@ __wt_txn_config(WT_SESSION_IMPL *session, const char *cfg[])
if (cval.len > 0) {
#ifdef HAVE_TIMESTAMPS
WT_TXN_GLOBAL *txn_global = &S2C(session)->txn_global;
- WT_TXN_STATE *txn_state = WT_SESSION_TXN_STATE(session);
wt_timestamp_t oldest_timestamp;
WT_RET(__wt_txn_parse_timestamp(
@@ -455,9 +454,8 @@ __wt_txn_config(WT_SESSION_IMPL *session, const char *cfg[])
WT_RET_MSG(session, EINVAL,
"read timestamp %.*s older than oldest timestamp",
(int)cval.len, cval.str);
- __wt_timestamp_set(
- txn_state->read_timestamp, txn->read_timestamp);
- F_SET(txn, WT_TXN_HAS_TS_READ);
+
+ __wt_txn_set_read_timestamp(session);
txn->isolation = WT_ISO_SNAPSHOT;
#else
WT_RET_MSG(session, EINVAL, "read_timestamp requires a "
@@ -531,22 +529,15 @@ __wt_txn_release(WT_SESSION_IMPL *session)
WT_ASSERT(session, txn_state->id != WT_TXN_NONE &&
txn->id != WT_TXN_NONE);
WT_PUBLISH(txn_state->id, WT_TXN_NONE);
-#ifdef HAVE_TIMESTAMPS
- if (F_ISSET(txn, WT_TXN_HAS_TS_COMMIT)) {
- /*
- * We rely on a non-zero ID to protect our published
- * commit timestamp. Otherwise we would need a lock
- * here.
- */
- WT_WRITE_BARRIER();
- __wt_timestamp_set(
- txn_state->commit_timestamp, zero_timestamp);
- }
-#endif
txn->id = WT_TXN_NONE;
}
+#ifdef HAVE_TIMESTAMPS
+ __wt_txn_clear_commit_timestamp(session);
+ __wt_txn_clear_read_timestamp(session);
+#endif
+
/* Free the scratch buffer allocated for logging. */
__wt_logrec_free(session, &txn->logrec);
@@ -578,7 +569,6 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[])
WT_TXN_OP *op;
#ifdef HAVE_TIMESTAMPS
WT_TXN_GLOBAL *txn_global = &S2C(session)->txn_global;
- WT_TXN_STATE *txn_state = WT_SESSION_TXN_STATE(session);
wt_timestamp_t prev_commit_timestamp;
bool update_timestamp;
#endif
@@ -601,13 +591,7 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[])
#ifdef HAVE_TIMESTAMPS
WT_ERR(__wt_txn_parse_timestamp(
session, "commit", txn->commit_timestamp, &cval));
- if (!F_ISSET(txn, WT_TXN_HAS_TS_COMMIT)) {
- __wt_writelock(session, &txn_global->rwlock);
- __wt_timestamp_set(txn_state->commit_timestamp,
- txn->commit_timestamp);
- __wt_writeunlock(session, &txn_global->rwlock);
- F_SET(txn, WT_TXN_HAS_TS_COMMIT);
- }
+ __wt_txn_set_commit_timestamp(session);
#else
WT_ERR_MSG(session, EINVAL, "commit_timestamp requires a "
"version of WiredTiger built with timestamp support");
@@ -944,8 +928,14 @@ __wt_txn_global_init(WT_SESSION_IMPL *session, const char *cfg[])
WT_RET(__wt_spin_init(
session, &txn_global->id_lock, "transaction id lock"));
WT_RET(__wt_rwlock_init(session, &txn_global->rwlock));
- WT_RET(__wt_rwlock_init(session, &txn_global->nsnap_rwlock));
+ WT_RET(__wt_rwlock_init(session, &txn_global->commit_timestamp_rwlock));
+ TAILQ_INIT(&txn_global->commit_timestamph);
+
+ WT_RET(__wt_rwlock_init(session, &txn_global->read_timestamp_rwlock));
+ TAILQ_INIT(&txn_global->read_timestamph);
+
+ WT_RET(__wt_rwlock_init(session, &txn_global->nsnap_rwlock));
txn_global->nsnap_oldest_id = WT_TXN_NONE;
TAILQ_INIT(&txn_global->nsnaph);
@@ -976,6 +966,8 @@ __wt_txn_global_destroy(WT_SESSION_IMPL *session)
__wt_spin_destroy(session, &txn_global->id_lock);
__wt_rwlock_destroy(session, &txn_global->rwlock);
+ __wt_rwlock_destroy(session, &txn_global->commit_timestamp_rwlock);
+ __wt_rwlock_destroy(session, &txn_global->read_timestamp_rwlock);
__wt_rwlock_destroy(session, &txn_global->nsnap_rwlock);
__wt_free(session, txn_global->states);
}
diff --git a/src/third_party/wiredtiger/src/txn/txn_ckpt.c b/src/third_party/wiredtiger/src/txn/txn_ckpt.c
index 73ad96b5518..519d3469865 100644
--- a/src/third_party/wiredtiger/src/txn/txn_ckpt.c
+++ b/src/third_party/wiredtiger/src/txn/txn_ckpt.c
@@ -625,6 +625,7 @@ __checkpoint_prepare(WT_SESSION_IMPL *session, const char *cfg[])
*/
__wt_writelock(session, &txn_global->rwlock);
txn_global->checkpoint_state = *txn_state;
+ txn_global->checkpoint_txn = txn;
txn_global->checkpoint_state.pinned_id = WT_MIN(txn->id, txn->snap_min);
/*
@@ -646,6 +647,15 @@ __checkpoint_prepare(WT_SESSION_IMPL *session, const char *cfg[])
txn_state->metadata_pinned = WT_TXN_NONE;
__wt_writeunlock(session, &txn_global->rwlock);
+#ifdef HAVE_TIMESTAMPS
+ /*
+ * Now that the checkpoint transaction is published, clear it from the
+ * regular lists.
+ */
+ __wt_txn_clear_commit_timestamp(session);
+ __wt_txn_clear_read_timestamp(session);
+#endif
+
/*
* Get a list of handles we want to flush; for named checkpoints this
* may pull closed objects into the session cache.
diff --git a/src/third_party/wiredtiger/src/txn/txn_log.c b/src/third_party/wiredtiger/src/txn/txn_log.c
index 3d218aea94f..d291139284a 100644
--- a/src/third_party/wiredtiger/src/txn/txn_log.c
+++ b/src/third_party/wiredtiger/src/txn/txn_log.c
@@ -425,7 +425,8 @@ __wt_txn_checkpoint_log(
* metadata LSN and we do not want to archive in that case.
*/
if (!conn->hot_backup &&
- !FLD_ISSET(conn->log_flags, WT_CONN_LOG_RECOVER_DIRTY) &&
+ (!FLD_ISSET(conn->log_flags, WT_CONN_LOG_RECOVER_DIRTY) ||
+ FLD_ISSET(conn->log_flags, WT_CONN_LOG_FORCE_DOWNGRADE)) &&
txn->full_ckpt)
__wt_log_ckpt(session, ckpt_lsn);
@@ -589,6 +590,16 @@ __txn_printlog(WT_SESSION_IMPL *session,
WT_RET(__wt_fprintf(session, WT_STDOUT(session),
" \"message\" : \"%s\"\n", msg));
break;
+
+ case WT_LOGREC_SYSTEM:
+ WT_RET(__wt_struct_unpack(session, p, WT_PTRDIFF(end, p),
+ WT_UNCHECKED_STRING(II), &lsnfile, &lsnoffset));
+ WT_RET(__wt_fprintf(session, WT_STDOUT(session),
+ " \"type\" : \"system\",\n"));
+ WT_RET(__wt_fprintf(session, WT_STDOUT(session),
+ " \"prev_lsn\" : [%" PRIu32 ",%" PRIu32 "]\n",
+ lsnfile, lsnoffset));
+ break;
}
WT_RET(__wt_fprintf(session, WT_STDOUT(session), " }"));
diff --git a/src/third_party/wiredtiger/src/txn/txn_recover.c b/src/third_party/wiredtiger/src/txn/txn_recover.c
index 58f4f0750d7..d08c2717f7a 100644
--- a/src/third_party/wiredtiger/src/txn/txn_recover.c
+++ b/src/third_party/wiredtiger/src/txn/txn_recover.c
@@ -235,8 +235,8 @@ __txn_op_apply(
return (0);
err: __wt_err(session, ret,
- "operation apply failed during recovery: operation type %d "
- "at LSN %" PRIu32 "/%" PRIu32,
+ "operation apply failed during recovery: operation type %"
+ PRIu32 " at LSN %" PRIu32 "/%" PRIu32,
optype, lsnp->l.file, lsnp->l.offset);
return (ret);
}
@@ -588,7 +588,6 @@ __wt_txn_recover(WT_SESSION_IMPL *session)
* LSN and archiving.
*/
ckpt: WT_ERR(session->iface.checkpoint(&session->iface, "force=1"));
-
done: FLD_SET(conn->log_flags, WT_CONN_LOG_RECOVER_DONE);
err: WT_TRET(__recovery_free(&r));
__wt_free(session, config);
diff --git a/src/third_party/wiredtiger/src/txn/txn_timestamp.c b/src/third_party/wiredtiger/src/txn/txn_timestamp.c
index ebef0320d4f..a975341c189 100644
--- a/src/third_party/wiredtiger/src/txn/txn_timestamp.c
+++ b/src/third_party/wiredtiger/src/txn/txn_timestamp.c
@@ -24,7 +24,7 @@ __wt_txn_parse_timestamp(WT_SESSION_IMPL *session,
const char *hexts;
char padbuf[2 * WT_TIMESTAMP_SIZE + 1];
- __wt_timestamp_set(timestamp, zero_timestamp);
+ __wt_timestamp_set_zero(timestamp);
if (cval->len == 0)
return (0);
@@ -80,9 +80,8 @@ __txn_global_query_timestamp(
{
WT_CONNECTION_IMPL *conn;
WT_CONFIG_ITEM cval;
+ WT_TXN *txn;
WT_TXN_GLOBAL *txn_global;
- WT_TXN_STATE *s;
- uint32_t i, session_cnt;
conn = S2C(session);
txn_global = &conn->txn_global;
@@ -93,35 +92,36 @@ __txn_global_query_timestamp(
return (WT_NOTFOUND);
__wt_readlock(session, &txn_global->rwlock);
__wt_timestamp_set(ts, txn_global->commit_timestamp);
- WT_ORDERED_READ(session_cnt, conn->session_cnt);
- for (i = 0, s = txn_global->states; i < session_cnt; i++, s++) {
- if (s->id == WT_TXN_NONE ||
- __wt_timestamp_iszero(s->commit_timestamp))
- continue;
- if (__wt_timestamp_cmp(s->commit_timestamp, ts) < 0)
- __wt_timestamp_set(ts, s->commit_timestamp);
- }
__wt_readunlock(session, &txn_global->rwlock);
+
+ /* Compare with the oldest running transaction. */
+ __wt_readlock(session, &txn_global->commit_timestamp_rwlock);
+ txn = TAILQ_FIRST(&txn_global->commit_timestamph);
+ if (txn != NULL &&
+ __wt_timestamp_cmp(txn->commit_timestamp, ts) < 0)
+ __wt_timestamp_set(ts, txn->commit_timestamp);
+ __wt_readunlock(session, &txn_global->commit_timestamp_rwlock);
} else if (WT_STRING_MATCH("oldest_reader", cval.str, cval.len)) {
if (!txn_global->has_oldest_timestamp)
return (WT_NOTFOUND);
__wt_readlock(session, &txn_global->rwlock);
__wt_timestamp_set(ts, txn_global->oldest_timestamp);
- /* Look at running checkpoints. */
- s = &txn_global->checkpoint_state;
- if (s->pinned_id != WT_TXN_NONE &&
- !__wt_timestamp_iszero(s->read_timestamp) &&
- __wt_timestamp_cmp(s->read_timestamp, ts) < 0)
- __wt_timestamp_set(ts, s->read_timestamp);
- WT_ORDERED_READ(session_cnt, conn->session_cnt);
- for (i = 0, s = txn_global->states; i < session_cnt; i++, s++) {
- if (s->pinned_id == WT_TXN_NONE ||
- __wt_timestamp_iszero(s->read_timestamp))
- continue;
- if (__wt_timestamp_cmp(s->read_timestamp, ts) < 0)
- __wt_timestamp_set(ts, s->read_timestamp);
- }
+
+ /* Check for a running checkpoint */
+ txn = txn_global->checkpoint_txn;
+ if (txn_global->checkpoint_state.pinned_id != WT_TXN_NONE &&
+ !__wt_timestamp_iszero(txn->read_timestamp) &&
+ __wt_timestamp_cmp(txn->read_timestamp, ts) < 0)
+ __wt_timestamp_set(ts, txn->read_timestamp);
__wt_readunlock(session, &txn_global->rwlock);
+
+ /* Look for the oldest ordinary reader. */
+ __wt_readlock(session, &txn_global->read_timestamp_rwlock);
+ txn = TAILQ_FIRST(&txn_global->read_timestamph);
+ if (txn != NULL &&
+ __wt_timestamp_cmp(txn->read_timestamp, ts) < 0)
+ __wt_timestamp_set(ts, txn->read_timestamp);
+ __wt_readunlock(session, &txn_global->read_timestamp_rwlock);
} else
return (__wt_illegal_value(session, NULL));
@@ -143,6 +143,11 @@ __wt_txn_global_query_timestamp(
size_t len;
uint8_t *tsp;
+ /*
+ * Keep clang-analyzer happy: it can't tell that ts will be set
+ * whenever the call below succeeds.
+ */
+ WT_CLEAR(ts);
WT_RET(__txn_global_query_timestamp(session, ts, cfg));
/* Avoid memory allocation: set up an item guaranteed large enough. */
@@ -279,18 +284,10 @@ __wt_txn_set_timestamp(WT_SESSION_IMPL *session, const char *cfg[])
if (ret == 0 && cval.len != 0) {
#ifdef HAVE_TIMESTAMPS
WT_TXN *txn = &session->txn;
- WT_TXN_GLOBAL *txn_global = &S2C(session)->txn_global;
- WT_TXN_STATE *txn_state = WT_SESSION_TXN_STATE(session);
WT_RET(__wt_txn_parse_timestamp(
session, "commit", txn->commit_timestamp, &cval));
- if (!F_ISSET(txn, WT_TXN_HAS_TS_COMMIT)) {
- __wt_writelock(session, &txn_global->rwlock);
- __wt_timestamp_set(txn_state->commit_timestamp,
- txn->commit_timestamp);
- __wt_writeunlock(session, &txn_global->rwlock);
- F_SET(txn, WT_TXN_HAS_TS_COMMIT);
- }
+ __wt_txn_set_commit_timestamp(session);
#else
WT_RET_MSG(session, EINVAL, "commit_timestamp requires a "
"version of WiredTiger built with timestamp support");
@@ -300,3 +297,110 @@ __wt_txn_set_timestamp(WT_SESSION_IMPL *session, const char *cfg[])
return (0);
}
+
+/*
+ * __wt_txn_set_commit_timestamp --
+ * Publish a transaction's commit timestamp.
+ */
+void
+__wt_txn_set_commit_timestamp(WT_SESSION_IMPL *session)
+{
+ WT_TXN *prev, *txn;
+ WT_TXN_GLOBAL *txn_global;
+
+ txn = &session->txn;
+ txn_global = &S2C(session)->txn_global;
+
+ if (F_ISSET(txn, WT_TXN_HAS_TS_COMMIT))
+ return;
+
+ __wt_writelock(session, &txn_global->commit_timestamp_rwlock);
+ for (prev = TAILQ_LAST(&txn_global->commit_timestamph, __wt_txn_cts_qh);
+ prev != NULL && __wt_timestamp_cmp(
+ prev->commit_timestamp, txn->commit_timestamp) > 0;
+ prev = TAILQ_PREV(prev, __wt_txn_cts_qh, commit_timestampq))
+ ;
+ if (prev == NULL)
+ TAILQ_INSERT_HEAD(
+ &txn_global->commit_timestamph, txn, commit_timestampq);
+ else
+ TAILQ_INSERT_AFTER(&txn_global->commit_timestamph,
+ prev, txn, commit_timestampq);
+ __wt_writeunlock(session, &txn_global->commit_timestamp_rwlock);
+ F_SET(txn, WT_TXN_HAS_TS_COMMIT);
+}
+
+/*
+ * __wt_txn_clear_commit_timestamp --
+ * Clear a transaction's published commit timestamp.
+ */
+void
+__wt_txn_clear_commit_timestamp(WT_SESSION_IMPL *session)
+{
+ WT_TXN *txn;
+ WT_TXN_GLOBAL *txn_global;
+
+ txn = &session->txn;
+ txn_global = &S2C(session)->txn_global;
+
+ if (!F_ISSET(txn, WT_TXN_HAS_TS_COMMIT))
+ return;
+
+ __wt_writelock(session, &txn_global->commit_timestamp_rwlock);
+ TAILQ_REMOVE(&txn_global->commit_timestamph, txn, commit_timestampq);
+ __wt_writeunlock(session, &txn_global->commit_timestamp_rwlock);
+}
+
+/*
+ * __wt_txn_set_read_timestamp --
+ * Publish a transaction's read timestamp.
+ */
+void
+__wt_txn_set_read_timestamp(WT_SESSION_IMPL *session)
+{
+ WT_TXN *prev, *txn;
+ WT_TXN_GLOBAL *txn_global;
+
+ txn = &session->txn;
+ txn_global = &S2C(session)->txn_global;
+
+ if (F_ISSET(txn, WT_TXN_HAS_TS_READ))
+ return;
+
+ __wt_writelock(session, &txn_global->read_timestamp_rwlock);
+ for (prev = TAILQ_LAST(&txn_global->read_timestamph, __wt_txn_rts_qh);
+ prev != NULL && __wt_timestamp_cmp(
+ prev->read_timestamp, txn->read_timestamp) > 0;
+ prev = TAILQ_PREV(prev, __wt_txn_rts_qh, read_timestampq))
+ ;
+ if (prev == NULL)
+ TAILQ_INSERT_HEAD(
+ &txn_global->read_timestamph, txn, read_timestampq);
+ else
+ TAILQ_INSERT_AFTER(
+ &txn_global->read_timestamph, prev, txn, read_timestampq);
+ __wt_writeunlock(session, &txn_global->read_timestamp_rwlock);
+ F_SET(txn, WT_TXN_HAS_TS_READ);
+}
+
+/*
+ * __wt_txn_clear_read_timestamp --
+ * Clear a transaction's published read timestamp.
+ */
+void
+__wt_txn_clear_read_timestamp(WT_SESSION_IMPL *session)
+{
+ WT_TXN *txn;
+ WT_TXN_GLOBAL *txn_global;
+
+ txn = &session->txn;
+ txn_global = &S2C(session)->txn_global;
+
+ if (!F_ISSET(txn, WT_TXN_HAS_TS_READ))
+ return;
+
+ __wt_writelock(session, &txn_global->read_timestamp_rwlock);
+ TAILQ_REMOVE(&txn_global->read_timestamph, txn, read_timestampq);
+ __wt_writeunlock(session, &txn_global->read_timestamp_rwlock);
+ F_CLR(txn, WT_TXN_HAS_TS_READ);
+}
diff --git a/src/third_party/wiredtiger/src/utilities/util.h b/src/third_party/wiredtiger/src/utilities/util.h
index 0238915df07..adf3f844295 100644
--- a/src/third_party/wiredtiger/src/utilities/util.h
+++ b/src/third_party/wiredtiger/src/utilities/util.h
@@ -32,6 +32,7 @@ int util_cerr(WT_CURSOR *, const char *, int);
int util_compact(WT_SESSION *, int, char *[]);
void util_copyright(void);
int util_create(WT_SESSION *, int, char *[]);
+int util_downgrade(WT_SESSION *, WT_CONNECTION *, int, char *[]);
int util_drop(WT_SESSION *, int, char *[]);
int util_dump(WT_SESSION *, int, char *[]);
int util_err(WT_SESSION *, int, const char *, ...)
diff --git a/src/third_party/wiredtiger/src/utilities/util_downgrade.c b/src/third_party/wiredtiger/src/utilities/util_downgrade.c
new file mode 100644
index 00000000000..4263727242c
--- /dev/null
+++ b/src/third_party/wiredtiger/src/utilities/util_downgrade.c
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2014-2017 MongoDB, Inc.
+ * Copyright (c) 2008-2014 WiredTiger, Inc.
+ * All rights reserved.
+ *
+ * See the file LICENSE for redistribution information.
+ */
+
+#include "util.h"
+
+static int usage(void);
+
+int
+util_downgrade(WT_SESSION *session, WT_CONNECTION *conn, int argc, char *argv[])
+{
+ WT_DECL_RET;
+ int ch;
+ char config_str[128], *release;
+
+ release = NULL;
+ while ((ch = __wt_getopt(progname, argc, argv, "V:")) != EOF)
+ switch (ch) {
+ case 'V':
+ release = __wt_optarg;
+ break;
+ case '?':
+ default:
+ return (usage());
+ }
+ argc -= __wt_optind;
+ argv += __wt_optind;
+
+ /*
+ * The release argument is required.
+ * There should not be any more arguments.
+ */
+ if (argc != 0 || release == NULL)
+ return (usage());
+
+ if ((ret = __wt_snprintf(config_str, sizeof(config_str),
+ "compatibility=(release=%s)", release)) != 0)
+ return (util_err(session, ret, NULL));
+ if ((ret = conn->reconfigure(conn, config_str)) != 0)
+ return (util_err(session, ret, "conn.downgrade"));
+
+ return (0);
+}
+
+static int
+usage(void)
+{
+ (void)fprintf(stderr,
+ "usage: %s %s "
+ "downgrade -V release\n",
+ progname, usage_prefix);
+ return (1);
+}
diff --git a/src/third_party/wiredtiger/src/utilities/util_list.c b/src/third_party/wiredtiger/src/utilities/util_list.c
index 72888e03183..dcb1c97b529 100644
--- a/src/third_party/wiredtiger/src/utilities/util_list.c
+++ b/src/third_party/wiredtiger/src/utilities/util_list.c
@@ -231,7 +231,8 @@ list_print_checkpoint(WT_SESSION *session, const char *key)
if (ci.root_size != 0) {
printf("\t\t" "root offset: %" PRIuMAX
" (0x%" PRIxMAX ")\n",
- (intmax_t)ci.root_offset, (intmax_t)ci.root_offset);
+ (uintmax_t)ci.root_offset,
+ (uintmax_t)ci.root_offset);
printf("\t\t" "root size: %" PRIu32
" (0x%" PRIx32 ")\n",
ci.root_size, ci.root_size);
diff --git a/src/third_party/wiredtiger/src/utilities/util_main.c b/src/third_party/wiredtiger/src/utilities/util_main.c
index 010af63ea30..a068bfb320d 100644
--- a/src/third_party/wiredtiger/src/utilities/util_main.c
+++ b/src/third_party/wiredtiger/src/utilities/util_main.c
@@ -41,6 +41,7 @@ usage(void)
"\t" "compact\t compact an object\n"
"\t" "copyright copyright information\n"
"\t" "create\t create an object\n"
+ "\t" "downgrade\t downgrade an database\n"
"\t" "drop\t drop an object\n"
"\t" "dump\t dump an object\n"
"\t" "list\t list database objects\n"
@@ -66,7 +67,8 @@ main(int argc, char *argv[])
WT_SESSION *session;
size_t len;
int ch, major_v, minor_v, tret, (*func)(WT_SESSION *, int, char *[]);
- bool logoff, recover;
+ int (*cfunc)(WT_SESSION *, WT_CONNECTION *, int, char *[]);
+ bool logoff, needconn, recover;
char *p, *secretkey;
const char *cmd_config, *config, *p1, *p2, *p3, *rec_config;
@@ -80,6 +82,8 @@ main(int argc, char *argv[])
++progname;
command = "";
+ needconn = false;
+
/* Check the version against the library build. */
(void)wiredtiger_version(&major_v, & minor_v, NULL);
if (major_v != WIREDTIGER_VERSION_MAJOR ||
@@ -156,6 +160,7 @@ main(int argc, char *argv[])
__wt_optreset = __wt_optind = 1;
func = NULL;
+ cfunc = NULL;
switch (command[0]) {
case 'a':
if (strcmp(command, "alter") == 0)
@@ -177,7 +182,10 @@ main(int argc, char *argv[])
}
break;
case 'd':
- if (strcmp(command, "drop") == 0)
+ if (strcmp(command, "downgrade") == 0) {
+ cfunc = util_downgrade;
+ needconn = true;
+ } else if (strcmp(command, "drop") == 0)
func = util_drop;
else if (strcmp(command, "dump") == 0)
func = util_dump;
@@ -234,7 +242,7 @@ main(int argc, char *argv[])
default:
break;
}
- if (func == NULL) {
+ if (func == NULL && cfunc == NULL) {
usage();
goto err;
}
@@ -278,7 +286,10 @@ main(int argc, char *argv[])
}
/* Call the function. */
- ret = func(session, argc, argv);
+ if (needconn)
+ ret = cfunc(session, conn, argc, argv);
+ else
+ ret = func(session, argc, argv);
if (0) {
err: ret = 1;
diff --git a/src/third_party/wiredtiger/test/csuite/rwlock/main.c b/src/third_party/wiredtiger/test/csuite/rwlock/main.c
index 3610953a7eb..f1bad3f538f 100644
--- a/src/third_party/wiredtiger/test/csuite/rwlock/main.c
+++ b/src/third_party/wiredtiger/test/csuite/rwlock/main.c
@@ -73,13 +73,12 @@ main(int argc, char *argv[])
testutil_check(__wt_rwlock_init(NULL, &rwlock));
testutil_check(pthread_rwlock_init(&p_rwlock, NULL));
- testutil_check(pthread_create(
- &dump_id, NULL, thread_dump, (void *)opts));
+ testutil_check(pthread_create(&dump_id, NULL, thread_dump, opts));
__wt_epoch(NULL, &ts);
for (i = 0; i < (int)opts->nthreads; ++i)
- testutil_check(pthread_create(
- &id[i], NULL, thread_rwlock, (void *)opts));
+ testutil_check(
+ pthread_create(&id[i], NULL, thread_rwlock, opts));
while (--i >= 0)
testutil_check(pthread_join(id[i], NULL));
diff --git a/src/third_party/wiredtiger/test/csuite/wt1965_col_efficiency/main.c b/src/third_party/wiredtiger/test/csuite/wt1965_col_efficiency/main.c
index e6801d8d37e..265fef8e76f 100644
--- a/src/third_party/wiredtiger/test/csuite/wt1965_col_efficiency/main.c
+++ b/src/third_party/wiredtiger/test/csuite/wt1965_col_efficiency/main.c
@@ -147,8 +147,8 @@ main(int argc, char *argv[])
testutil_check(session->close(session, NULL));
for (t = 0; t < NR_THREADS; ++t)
- testutil_check(pthread_create(
- &thr[t], NULL, thread_func, (void *)opts));
+ testutil_check(
+ pthread_create(&thr[t], NULL, thread_func, opts));
for (t = 0; t < NR_THREADS; ++t)
(void)pthread_join(thr[t], NULL);
diff --git a/src/third_party/wiredtiger/test/csuite/wt2246_col_append/main.c b/src/third_party/wiredtiger/test/csuite/wt2246_col_append/main.c
index c71edf6a0a9..bf2d4b8ffc4 100644
--- a/src/third_party/wiredtiger/test/csuite/wt2246_col_append/main.c
+++ b/src/third_party/wiredtiger/test/csuite/wt2246_col_append/main.c
@@ -141,8 +141,8 @@ main(int argc, char *argv[])
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));
+ testutil_check(
+ pthread_create(&idlist[id], NULL, thread_append, opts));
}
for (i = 0; i < id; ++i)
diff --git a/src/third_party/wiredtiger/test/csuite/wt2323_join_visibility/main.c b/src/third_party/wiredtiger/test/csuite/wt2323_join_visibility/main.c
index 89f9eeefb69..3f313a5bfde 100644
--- a/src/third_party/wiredtiger/test/csuite/wt2323_join_visibility/main.c
+++ b/src/third_party/wiredtiger/test/csuite/wt2323_join_visibility/main.c
@@ -186,8 +186,8 @@ test_join(TEST_OPTS *opts, SHARED_OPTS *sharedopts, bool bloom,
insert_args[i].nthread = N_INSERT_THREAD;
insert_args[i].testopts = opts;
insert_args[i].sharedopts = sharedopts;
- testutil_check(pthread_create(&insert_tid[i], NULL,
- thread_insert, (void *)&insert_args[i]));
+ testutil_check(pthread_create(
+ &insert_tid[i], NULL, thread_insert, &insert_args[i]));
}
for (i = 0; i < N_JOIN_THREAD; ++i) {
@@ -195,8 +195,8 @@ test_join(TEST_OPTS *opts, SHARED_OPTS *sharedopts, bool bloom,
join_args[i].nthread = N_JOIN_THREAD;
join_args[i].testopts = opts;
join_args[i].sharedopts = sharedopts;
- testutil_check(pthread_create(&join_tid[i], NULL,
- thread_join, (void *)&join_args[i]));
+ testutil_check(pthread_create(
+ &join_tid[i], NULL, thread_join, &join_args[i]));
}
/*
diff --git a/src/third_party/wiredtiger/test/csuite/wt2535_insert_race/main.c b/src/third_party/wiredtiger/test/csuite/wt2535_insert_race/main.c
index 92e69c5920c..f5848203f37 100644
--- a/src/third_party/wiredtiger/test/csuite/wt2535_insert_race/main.c
+++ b/src/third_party/wiredtiger/test/csuite/wt2535_insert_race/main.c
@@ -81,8 +81,8 @@ main(int argc, char *argv[])
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));
+ testutil_check(
+ pthread_create(&id[i], NULL, thread_insert_race, opts));
}
while (--i >= 0)
testutil_check(pthread_join(id[i], NULL));
diff --git a/src/third_party/wiredtiger/test/csuite/wt2853_perf/main.c b/src/third_party/wiredtiger/test/csuite/wt2853_perf/main.c
index 69e6b871dae..a671464d7e2 100644
--- a/src/third_party/wiredtiger/test/csuite/wt2853_perf/main.c
+++ b/src/third_party/wiredtiger/test/csuite/wt2853_perf/main.c
@@ -149,8 +149,8 @@ main(int argc, char *argv[])
insert_args[i].nthread = N_INSERT_THREAD;
insert_args[i].testopts = opts;
insert_args[i].sharedopts = sharedopts;
- testutil_check(pthread_create(&insert_tid[i], NULL,
- thread_insert, (void *)&insert_args[i]));
+ testutil_check(pthread_create(
+ &insert_tid[i], NULL, thread_insert, &insert_args[i]));
}
for (i = 0; i < N_GET_THREAD; ++i) {
@@ -158,8 +158,8 @@ main(int argc, char *argv[])
get_args[i].nthread = N_GET_THREAD;
get_args[i].testopts = opts;
get_args[i].sharedopts = sharedopts;
- testutil_check(pthread_create(&get_tid[i], NULL,
- thread_get, (void *)&get_args[i]));
+ testutil_check(pthread_create(
+ &get_tid[i], NULL, thread_get, &get_args[i]));
}
/*
diff --git a/src/third_party/wiredtiger/test/csuite/wt3363_checkpoint_op_races/main.c b/src/third_party/wiredtiger/test/csuite/wt3363_checkpoint_op_races/main.c
index 5c9c3d96454..ffef7f5fa9f 100644
--- a/src/third_party/wiredtiger/test/csuite/wt3363_checkpoint_op_races/main.c
+++ b/src/third_party/wiredtiger/test/csuite/wt3363_checkpoint_op_races/main.c
@@ -41,9 +41,9 @@
* any operation taking longer than 1/2 the delay time, we abort dumping a core
* file which can be used to determine what operation was blocked.
*/
-void* do_checkpoints(void *);
-void* do_ops(void *);
-void* monitor(void *);
+static WT_THREAD_RET do_checkpoints(void *);
+static WT_THREAD_RET do_ops(void *);
+static WT_THREAD_RET monitor(void *);
/*
* Time delay to introduce into checkpoints in seconds. Should be at-least
@@ -51,8 +51,8 @@ void* monitor(void *);
* this is set to 10 seconds and we expect no single operation to take longer
* than 5 seconds.
*/
-#define MAX_EXECUTION_TIME 10
-#define N_THREADS 10
+#define MAX_EXECUTION_TIME 10
+#define N_THREADS 10
/*
* Number of seconds to execute for. Initially set to 15 minutes, as we need to
@@ -60,7 +60,7 @@ void* monitor(void *);
* testing 5 minutes was enough to reproduce the issue, so we run for 3x that
* here to ensure we reproduce before declaring success.
*/
-#define RUNTIME 900.0
+#define RUNTIME 900.0
static WT_EVENT_HANDLER event_handler = {
handle_op_error,
@@ -72,17 +72,10 @@ static WT_EVENT_HANDLER event_handler = {
int
main(int argc, char *argv[])
{
- TEST_PER_THREAD_OPTS thread_args[N_THREADS];
TEST_OPTS *opts, _opts;
+ TEST_PER_THREAD_OPTS thread_args[N_THREADS];
pthread_t ckpt_thread, mon_thread, threads[N_THREADS];
int i;
- bool diagnostic;
-
-#ifdef HAVE_DIAGNOSTIC
- diagnostic = true;
-#else
- diagnostic = false;
-#endif
/*
* This test should not run unless we have compiled with diagnostic
@@ -90,7 +83,15 @@ main(int argc, char *argv[])
* attempting to set the option to add the delays to checkpoints if
* diagnostic mode is not enable and runs for 15 minutes.
*/
- if (!testutil_is_flag_set("WT3363_CHECKPOINT_OP_RACES") || !diagnostic)
+#if !defined(HAVE_DIAGNOSTIC)
+ /*
+ * Put the return in a conditional, otherwise some compilers will
+ * complain that code beyond the return is unreachable.
+ */
+ if (true)
+ return (EXIT_SUCCESS);
+#endif
+ if (!testutil_is_flag_set("WT3363_CHECKPOINT_OP_RACES"))
return (EXIT_SUCCESS);
opts = &_opts;
@@ -105,14 +106,14 @@ main(int argc, char *argv[])
&opts->conn));
testutil_check(pthread_create(
- &ckpt_thread, NULL, do_checkpoints, (void *)opts));
+ &ckpt_thread, NULL, do_checkpoints, opts));
for (i = 0; i < N_THREADS; ++i) {
thread_args[i].testopts = opts;
thread_args[i].thread_counter = 0;
thread_args[i].threadnum = i;
testutil_check(pthread_create(
- &threads[i], NULL, do_ops, (void *)&thread_args[i]));
+ &threads[i], NULL, do_ops, &thread_args[i]));
}
/*
@@ -120,8 +121,7 @@ main(int argc, char *argv[])
* This thread will need to monitor each threads counter to track if it
* is stuck.
*/
- testutil_check(
- pthread_create(&mon_thread, NULL, monitor, &thread_args));
+ testutil_check(pthread_create(&mon_thread, NULL, monitor, thread_args));
for (i = 0; i < N_THREADS; ++i)
testutil_check(pthread_join(threads[i], NULL));
@@ -139,7 +139,7 @@ main(int argc, char *argv[])
/*
* Function for repeatedly running checkpoint operations.
*/
-void *
+static WT_THREAD_RET
do_checkpoints(void *_opts)
{
TEST_OPTS *opts;
@@ -159,7 +159,7 @@ do_checkpoints(void *_opts)
if (ret != EBUSY && ret != ENOENT)
testutil_die(ret, "session.checkpoint");
- testutil_check(session->close(session, NULL));
+ testutil_check(session->close(session, NULL));
/*
* A short sleep to let operations process and avoid back to
@@ -169,21 +169,21 @@ do_checkpoints(void *_opts)
(void)time(&now);
}
- return (NULL);
+ return (WT_THREAD_RET_VALUE);
}
/*
* Function to monitor running operations and abort to dump core in the event
* that we catch an operation running long.
*/
-void *
+static WT_THREAD_RET
monitor(void *args)
{
TEST_PER_THREAD_OPTS *thread_args;
time_t now, start;
int ctr, i, last_ops[N_THREADS];
- thread_args = (TEST_PER_THREAD_OPTS*)args;
+ thread_args = (TEST_PER_THREAD_OPTS *)args;
(void)time(&start);
(void)time(&now);
@@ -191,13 +191,12 @@ monitor(void *args)
memset(last_ops, 0, sizeof(int) + N_THREADS);
while (difftime(now, start) < RUNTIME) {
-
/*
* Checkpoints will run for slightly over MAX_EXECUTION_TIME.
* MAX_EXECUTION_TIME should always be long enough that we can
* complete any single operation in 1/2 that time.
*/
- sleep(MAX_EXECUTION_TIME/2);
+ sleep(MAX_EXECUTION_TIME / 2);
for (i = 0; i < N_THREADS; i++) {
ctr = thread_args[i].thread_counter;
@@ -217,20 +216,20 @@ monitor(void *args)
else {
printf("Thread %d had a task running"
" for more than %d seconds\n",
- i, MAX_EXECUTION_TIME/2);
+ i, MAX_EXECUTION_TIME / 2);
abort();
}
}
(void)time(&now);
}
- return (NULL);
+ return (WT_THREAD_RET_VALUE);
}
/*
* Worker thread. Executes random operations from the set of 6.
*/
-void *
+static WT_THREAD_RET
do_ops(void *args)
{
WT_RAND_STATE rnd;
@@ -242,27 +241,27 @@ do_ops(void *args)
while (difftime(now, start) < RUNTIME) {
switch (__wt_random(&rnd) % 6) {
- case 0:
- op_bulk(args);
- break;
- case 1:
- op_create(args);
- break;
- case 2:
- op_cursor(args);
- break;
- case 3:
- op_drop(args);
- break;
- case 4:
- op_bulk_unique(args);
- break;
- case 5:
- op_create_unique(args);
- break;
+ case 0:
+ op_bulk(args);
+ break;
+ case 1:
+ op_create(args);
+ break;
+ case 2:
+ op_cursor(args);
+ break;
+ case 3:
+ op_drop(args);
+ break;
+ case 4:
+ op_bulk_unique(args);
+ break;
+ case 5:
+ op_create_unique(args);
+ break;
}
(void)time(&now);
}
- return (NULL);
+ return (WT_THREAD_RET_VALUE);
}
diff --git a/src/third_party/wiredtiger/test/fops/fops.c b/src/third_party/wiredtiger/test/fops/fops.c
index 911bfba55ad..cf182d757e2 100644
--- a/src/third_party/wiredtiger/test/fops/fops.c
+++ b/src/third_party/wiredtiger/test/fops/fops.c
@@ -161,7 +161,7 @@ print_stats(u_int nthreads)
s = run_stats;
for (id = 0; id < nthreads; ++id, ++s)
printf(
- "%2d:"
+ "%2u:"
"\t" "bulk %3d, checkpoint %3d, create %3d, cursor %3d,\n"
"\t" "drop %3d, rebalance %3d, upgrade %3d, verify %3d\n",
id, s->bulk + s->bulk_unique, s->ckpt,
diff --git a/src/third_party/wiredtiger/test/format/bulk.c b/src/third_party/wiredtiger/test/format/bulk.c
index 0e7c54516e6..5d236ec5b42 100644
--- a/src/third_party/wiredtiger/test/format/bulk.c
+++ b/src/third_party/wiredtiger/test/format/bulk.c
@@ -58,8 +58,14 @@ wts_load(void)
if (g.c_reverse)
is_bulk = false;
- testutil_check(session->open_cursor(session, g.uri, NULL,
- is_bulk ? "bulk,append" : NULL, &cursor));
+ /*
+ * open_cursor can return EBUSY if concurrent with a metadata
+ * operation, retry in that case.
+ */
+ while ((ret = session->open_cursor(session, g.uri, NULL,
+ is_bulk ? "bulk,append" : NULL, &cursor)) == EBUSY)
+ __wt_yield();
+ testutil_check(ret);
/* Set up the key/value buffers. */
key_gen_setup(&key);
diff --git a/src/third_party/wiredtiger/test/format/compact.c b/src/third_party/wiredtiger/test/format/compact.c
index f2fa7521946..ba5efa5e53d 100644
--- a/src/third_party/wiredtiger/test/format/compact.c
+++ b/src/third_party/wiredtiger/test/format/compact.c
@@ -63,8 +63,12 @@ compact(void *arg)
if (g.workers_finished)
break;
- if ((ret = session->compact(
- session, g.uri, NULL)) != 0 && ret != WT_ROLLBACK)
+ /*
+ * Compact can return EBUSY if concurrent with alter.
+ */
+ while ((ret = session->compact(session, g.uri, NULL)) == EBUSY)
+ __wt_yield();
+ if (ret != 0 && ret != WT_ROLLBACK)
testutil_die(ret, "session.compact");
}
diff --git a/src/third_party/wiredtiger/test/format/config.c b/src/third_party/wiredtiger/test/format/config.c
index 2685438af00..f7aad2ae0a7 100644
--- a/src/third_party/wiredtiger/test/format/config.c
+++ b/src/third_party/wiredtiger/test/format/config.c
@@ -30,6 +30,7 @@
#include "config.h"
static void config_checksum(void);
+static void config_compatibility(void);
static void config_compression(const char *);
static void config_encryption(void);
static const char *config_file_type(u_int);
@@ -40,6 +41,7 @@ static int config_is_perm(const char *);
static void config_isolation(void);
static void config_lrt(void);
static void config_map_checksum(const char *, u_int *);
+static void config_map_compatibility(const char *, u_int *);
static void config_map_compression(const char *, u_int *);
static void config_map_encryption(const char *, u_int *);
static void config_map_file_type(const char *, u_int *);
@@ -158,6 +160,7 @@ config_setup(void)
g.c_threads = 1;
config_checksum();
+ config_compatibility();
config_compression("compression");
config_compression("logging_compression");
config_encryption();
@@ -308,6 +311,36 @@ config_compression(const char *conf_name)
}
/*
+ * config_compatibility --
+ * Compatibility configuration.
+ */
+static void
+config_compatibility(void)
+{
+ /*
+ * Compatibility is only relevant if logging is enabled.
+ * Skip it no matter what if we're not logging.
+ */
+ if (g.c_logging == 0) {
+ config_single("compatibility=none", 0);
+ return;
+ }
+ /* Choose a compatibility mode if nothing was specified. */
+ if (!config_is_perm("compatibility"))
+ switch (mmrand(NULL, 1, 10)) {
+ case 1: /* 10% */
+ config_single("compatibility=v1", 0);
+ break;
+ case 2: /* 10% */
+ config_single("compatibility=v2", 0);
+ break;
+ default: /* 80% */
+ config_single("compatibility=none", 0);
+ break;
+ }
+}
+
+/*
* config_encryption --
* Encryption configuration.
*/
@@ -381,10 +414,14 @@ config_in_memory_check(void)
return;
/* Turn off a lot of stuff. */
+ if (!config_is_perm("alter"))
+ config_single("alter=off", 0);
if (!config_is_perm("backups"))
config_single("backups=off", 0);
if (!config_is_perm("checkpoints"))
config_single("checkpoints=off", 0);
+ if (!config_is_perm("compatibility"))
+ config_single("compatibility=none", 0);
if (!config_is_perm("compression"))
config_single("compression=none", 0);
if (!config_is_perm("logging"))
@@ -732,6 +769,10 @@ config_single(const char *s, int perm)
config_map_checksum(ep, &g.c_checksum_flag);
*cp->vstr = dstrdup(ep);
} else if (strncmp(
+ s, "compatibility", strlen("compatibility")) == 0) {
+ config_map_compatibility(ep, &g.c_compat_flag);
+ *cp->vstr = dstrdup(ep);
+ } else if (strncmp(
s, "compression", strlen("compression")) == 0) {
config_map_compression(ep, &g.c_compression_flag);
*cp->vstr = dstrdup(ep);
@@ -827,6 +868,24 @@ config_map_checksum(const char *s, u_int *vp)
}
/*
+ * config_map_compatibility --
+ * Map a compatibility configuration to a flag.
+ */
+static void
+config_map_compatibility(const char *s, u_int *vp)
+{
+ if (strcmp(s, "none") == 0)
+ *vp = COMPAT_NONE;
+ else if (strcmp(s, "v1") == 0)
+ *vp = COMPAT_V1;
+ else if (strcmp(s, "v2") == 0)
+ *vp = COMPAT_V2;
+ else
+ testutil_die(EINVAL,
+ "illegal compatibility configuration: %s", s);
+}
+
+/*
* config_map_compression --
* Map a compression configuration to a flag.
*/
diff --git a/src/third_party/wiredtiger/test/format/config.h b/src/third_party/wiredtiger/test/format/config.h
index ea30986f453..ef3fcf8c028 100644
--- a/src/third_party/wiredtiger/test/format/config.h
+++ b/src/third_party/wiredtiger/test/format/config.h
@@ -117,6 +117,10 @@ static CONFIG c[] = {
"if compaction is running", /* 10% */
C_BOOL, 10, 0, 0, &g.c_compact, NULL },
+ { "compatibility",
+ "log file compatibility (none | v1 | v2 )",
+ C_IGNORE|C_STRING, 0, 0, 0, NULL, &g.c_compat },
+
{ "compression",
"type of compression " COMPRESSION_LIST,
C_IGNORE|C_STRING, 0, 0, 0, NULL, &g.c_compression },
diff --git a/src/third_party/wiredtiger/test/format/format.h b/src/third_party/wiredtiger/test/format/format.h
index 7860bb539ed..30246ce69a1 100644
--- a/src/third_party/wiredtiger/test/format/format.h
+++ b/src/third_party/wiredtiger/test/format/format.h
@@ -155,6 +155,7 @@ typedef struct {
char *c_checksum;
uint32_t c_chunk_size;
uint32_t c_compact;
+ char *c_compat;
char *c_compression;
char *c_config_open;
uint32_t c_data_extend;
@@ -220,6 +221,11 @@ typedef struct {
#define CHECKSUM_UNCOMPRESSED 3
u_int c_checksum_flag; /* Checksum flag value */
+#define COMPAT_NONE 1
+#define COMPAT_V1 2
+#define COMPAT_V2 3
+ u_int c_compat_flag; /* Compatibility flag value */
+
#define COMPRESS_NONE 1
#define COMPRESS_LZ4 2
#define COMPRESS_LZ4_NO_RAW 3
@@ -285,6 +291,7 @@ void bdb_update(const void *, size_t, const void *, size_t);
WT_THREAD_RET alter(void *);
WT_THREAD_RET backup(void *);
WT_THREAD_RET compact(void *);
+WT_THREAD_RET compat(void *);
void config_clear(void);
void config_error(void);
void config_file(const char *);
diff --git a/src/third_party/wiredtiger/test/format/lrt.c b/src/third_party/wiredtiger/test/format/lrt.c
index b9622cdb635..5073d5aad03 100644
--- a/src/third_party/wiredtiger/test/format/lrt.c
+++ b/src/third_party/wiredtiger/test/format/lrt.c
@@ -59,8 +59,14 @@ lrt(void *arg)
/* Open a session and cursor. */
conn = g.wts_conn;
testutil_check(conn->open_session(conn, NULL, NULL, &session));
- testutil_check(session->open_cursor(
- session, g.uri, NULL, NULL, &cursor));
+ /*
+ * open_cursor can return EBUSY if concurrent with a metadata
+ * operation, retry in that case.
+ */
+ while ((ret = session->open_cursor(
+ session, g.uri, NULL, NULL, &cursor)) == EBUSY)
+ __wt_yield();
+ testutil_check(ret);
for (pinned = 0;;) {
if (pinned) {
diff --git a/src/third_party/wiredtiger/test/format/ops.c b/src/third_party/wiredtiger/test/format/ops.c
index 76b1261e9ab..f8c275bb67d 100644
--- a/src/third_party/wiredtiger/test/format/ops.c
+++ b/src/third_party/wiredtiger/test/format/ops.c
@@ -62,7 +62,7 @@ wts_ops(int lastrun)
TINFO **tinfo_list, *tinfo, total;
WT_CONNECTION *conn;
WT_SESSION *session;
- wt_thread_t alter_tid, backup_tid, compact_tid, lrt_tid;
+ wt_thread_t alter_tid, backup_tid, compact_tid, compat_tid, lrt_tid;
int64_t fourths, thread_ops;
uint32_t i;
int running;
@@ -73,6 +73,7 @@ wts_ops(int lastrun)
memset(&alter_tid, 0, sizeof(alter_tid));
memset(&backup_tid, 0, sizeof(backup_tid));
memset(&compact_tid, 0, sizeof(compact_tid));
+ memset(&compat_tid, 0, sizeof(compat_tid));
memset(&lrt_tid, 0, sizeof(lrt_tid));
/*
@@ -138,6 +139,9 @@ wts_ops(int lastrun)
if (g.c_compact)
testutil_check(
__wt_thread_create(NULL, &compact_tid, compact, NULL));
+ if (g.c_compat_flag != COMPAT_NONE)
+ testutil_check(
+ __wt_thread_create(NULL, &compat_tid, compat, NULL));
if (!SINGLETHREADED && g.c_long_running_txn)
testutil_check(__wt_thread_create(NULL, &lrt_tid, lrt, NULL));
@@ -197,7 +201,7 @@ wts_ops(int lastrun)
free(tinfo_list[i]);
free(tinfo_list);
- /* Wait for the backup, compaction, long-running reader threads. */
+ /* Wait for the other threads. */
g.workers_finished = 1;
if (g.c_alter)
testutil_check(__wt_thread_join(NULL, alter_tid));
@@ -205,6 +209,8 @@ wts_ops(int lastrun)
testutil_check(__wt_thread_join(NULL, backup_tid));
if (g.c_compact)
testutil_check(__wt_thread_join(NULL, compact_tid));
+ if (g.c_compat_flag != COMPAT_NONE)
+ testutil_check(__wt_thread_join(NULL, compat_tid));
if (!SINGLETHREADED && g.c_long_running_txn)
testutil_check(__wt_thread_join(NULL, lrt_tid));
g.workers_finished = 0;
@@ -525,8 +531,14 @@ ops(void *arg)
*/
if (!SINGLETHREADED && !DATASOURCE("lsm") &&
ckpt_available && mmrand(&tinfo->rnd, 1, 10) == 1) {
- testutil_check(session->open_cursor(session,
- g.uri, NULL, ckpt_name, &cursor));
+ /*
+ * open_cursor can return EBUSY if concurrent
+ * with a metadata operation, retry.
+ */
+ while ((ret = session->open_cursor(session,
+ g.uri, NULL, ckpt_name, &cursor)) == EBUSY)
+ __wt_yield();
+ testutil_check(ret);
/* Pick the next session/cursor close/open. */
session_op += 250;
@@ -537,9 +549,13 @@ ops(void *arg)
/*
* Configure "append", in the case of column
* stores, we append when inserting new rows.
+ * open_cursor can return EBUSY if concurrent
+ * with a metadata operation, retry.
*/
- testutil_check(session->open_cursor(
- session, g.uri, NULL, "append", &cursor));
+ while ((ret = session->open_cursor(session,
+ g.uri, NULL, "append", &cursor)) == EBUSY)
+ __wt_yield();
+ testutil_check(ret);
/* Pick the next session/cursor close/open. */
session_op += mmrand(&tinfo->rnd, 100, 5000);
@@ -924,8 +940,14 @@ wts_read_scan(void)
/* Open a session and cursor pair. */
testutil_check(conn->open_session(conn, NULL, NULL, &session));
- testutil_check(
- session->open_cursor(session, g.uri, NULL, NULL, &cursor));
+ /*
+ * open_cursor can return EBUSY if concurrent with a metadata
+ * operation, retry in that case.
+ */
+ while ((ret = session->open_cursor(
+ session, g.uri, NULL, NULL, &cursor)) == EBUSY)
+ __wt_yield();
+ testutil_check(ret);
/* Check a random subset of the records using the key. */
for (last_keyno = keyno = 0; keyno < g.key_cnt;) {
diff --git a/src/third_party/wiredtiger/test/format/t.c b/src/third_party/wiredtiger/test/format/t.c
index 0cfe4e40421..c70f6facfc5 100644
--- a/src/third_party/wiredtiger/test/format/t.c
+++ b/src/third_party/wiredtiger/test/format/t.c
@@ -250,7 +250,7 @@ main(int argc, char *argv[])
/* Overwrite the progress line with a completion line. */
if (!g.c_quiet)
printf("\r%78s\r", " ");
- printf("%4d: %s, %s (%.0f seconds)\n",
+ printf("%4" PRIu32 ": %s, %s (%.0f seconds)\n",
g.run_cnt, g.c_data_source,
g.c_file_type, difftime(time(NULL), start));
fflush(stdout);
diff --git a/src/third_party/wiredtiger/test/format/util.c b/src/third_party/wiredtiger/test/format/util.c
index f09bb160893..6d24073da1a 100644
--- a/src/third_party/wiredtiger/test/format/util.c
+++ b/src/third_party/wiredtiger/test/format/util.c
@@ -134,7 +134,7 @@ key_gen_insert(WT_RAND_STATE *rnd, WT_ITEM *key, uint64_t keyno)
"11", "12", "13", "14", "15"
};
- key_gen_common(key, keyno, suffix[mmrand(rnd, 1, 15) - 1]);
+ key_gen_common(key, keyno, suffix[mmrand(rnd, 0, 14)]);
}
static uint32_t val_dup_data_len; /* Length of duplicate data items */
@@ -408,8 +408,9 @@ path_setup(const char *home)
uint32_t
rng(WT_RAND_STATE *rnd)
{
- char buf[64];
- uint32_t r;
+ u_long ulv;
+ uint32_t v;
+ char *endptr, buf[64];
/*
* Threaded operations have their own RNG information, otherwise we
@@ -439,16 +440,19 @@ rng(WT_RAND_STATE *rnd)
testutil_die(errno, "random number log");
}
- return ((uint32_t)strtoul(buf, NULL, 10));
+ errno = 0;
+ ulv = strtoul(buf, &endptr, 10);
+ testutil_assert(errno == 0 && endptr[0] == '\n');
+ return ((uint32_t)ulv);
}
- r = __wt_random(rnd);
+ v = __wt_random(rnd);
/* Save and flush the random number so we're up-to-date on error. */
- (void)fprintf(g.randfp, "%" PRIu32 "\n", r);
+ (void)fprintf(g.randfp, "%" PRIu32 "\n", v);
(void)fflush(g.randfp);
- return (r);
+ return (v);
}
/*
@@ -476,6 +480,7 @@ WT_THREAD_RET
alter(void *arg)
{
WT_CONNECTION *conn;
+ WT_DECL_RET;
WT_SESSION *session;
u_int period;
bool access_value;
@@ -501,8 +506,12 @@ alter(void *arg)
"access_pattern_hint=%s",
access_value ? "random" : "none"));
access_value = !access_value;
- if (session->alter(session, g.uri, buf) != 0)
- break;
+ /*
+ * Alter can return EBUSY if concurrent with other operations.
+ */
+ while ((ret = session->alter(session, g.uri, buf)) != 0 &&
+ ret != EBUSY)
+ testutil_die(ret, "session.alter");
while (period > 0 && !g.workers_finished) {
--period;
sleep(1);
@@ -512,3 +521,45 @@ alter(void *arg)
testutil_check(session->close(session, NULL));
return (WT_THREAD_RET_VALUE);
}
+
+#define COMPATSTR_V1 "compatibility=(release=2.6)"
+#define COMPATSTR_V2 "compatibility=(release=3.0)"
+
+/*
+ * compat --
+ * Periodically reconfigure the compatibility option.
+ */
+WT_THREAD_RET
+compat(void *arg)
+{
+ WT_CONNECTION *conn;
+ WT_DECL_RET;
+ u_int count, period;
+ const char *str;
+
+ (void)(arg);
+
+ conn = g.wts_conn;
+ str = NULL;
+ /*
+ * Perform compatibility swaps at somewhere under 10 seconds (so we
+ * get at least one done), and then at 7 second intervals.
+ */
+ for (period = mmrand(NULL, 1, 10), count = 0;; ++count, period = 7) {
+ if (count % 2 == 0)
+ str = COMPATSTR_V1;
+ else
+ str = COMPATSTR_V2;
+ if ((ret = conn->reconfigure(conn, str)) != 0)
+ testutil_die(ret, "conn.reconfigure");
+
+ /* Sleep for short periods so we don't make the run wait. */
+ while (period > 0 && !g.workers_finished) {
+ --period;
+ sleep(1);
+ }
+ if (g.workers_finished)
+ break;
+ }
+ return (WT_THREAD_RET_VALUE);
+}
diff --git a/src/third_party/wiredtiger/test/format/wts.c b/src/third_party/wiredtiger/test/format/wts.c
index 6bfec79436c..6a58cad5403 100644
--- a/src/third_party/wiredtiger/test/format/wts.c
+++ b/src/third_party/wiredtiger/test/format/wts.c
@@ -72,6 +72,34 @@ compressor(uint32_t compress_flag)
}
/*
+ * compatibility --
+ * Configure compatibility.
+ */
+static const char *
+compatibility(uint32_t compat_flag)
+{
+ const char *p;
+
+ p = "unrecognized compatibility flag";
+ switch (compat_flag) {
+ case COMPAT_NONE:
+ p = "";
+ break;
+ case COMPAT_V1:
+ p = "2.6";
+ break;
+ case COMPAT_V2:
+ p = "3.0";
+ break;
+ default:
+ testutil_die(EINVAL,
+ "illegal compatibility flag: %#" PRIx32, compat_flag);
+ /* NOTREACHED */
+ }
+ return (p);
+}
+
+/*
* encryptor --
* Configure encryption.
*/
@@ -191,13 +219,17 @@ wts_open(const char *home, bool set_api, WT_CONNECTION **connp)
",eviction=(threads_max=%" PRIu32 ")", g.c_evict_max);
/* Logging configuration. */
- if (g.c_logging)
+ if (g.c_logging) {
CONFIG_APPEND(p,
",log=(enabled=true,archive=%d,prealloc=%d"
",compressor=\"%s\")",
g.c_logging_archive ? 1 : 0,
g.c_logging_prealloc ? 1 : 0,
compressor(g.c_logging_compression_flag));
+ CONFIG_APPEND(p,
+ ",compatibility=(release=%s)",
+ compatibility(g.c_compat_flag));
+ }
if (g.c_encryption)
CONFIG_APPEND(p,
diff --git a/src/third_party/wiredtiger/test/packing/intpack-test.c b/src/third_party/wiredtiger/test/packing/intpack-test.c
index e7822015091..172575c3d3d 100644
--- a/src/third_party/wiredtiger/test/packing/intpack-test.c
+++ b/src/third_party/wiredtiger/test/packing/intpack-test.c
@@ -31,14 +31,14 @@
int
main(void)
{
- const uint8_t *cp;
- uint8_t buf[10], *p;
uint64_t ncalls, r, r2, s;
+ uint8_t buf[WT_INTPACK64_MAXSIZE], *p;
+ const uint8_t *cp;
int i;
- ncalls = 0;
+ memset(buf, 0xff, sizeof(buf)); /* -Werror=maybe-uninitialized */
- for (i = 0; i < 10000000; i++) {
+ for (ncalls = 0, i = 0; i < 10000000; i++) {
for (s = 0; s < 50; s += 5) {
++ncalls;
r = 1ULL << s;
@@ -60,14 +60,11 @@ main(void)
cp = buf;
memmove(&r2, cp, sizeof(r2));
#endif
- if (r != r2) {
- fprintf(stderr, "mismatch!\n");
- break;
- }
+ testutil_assert(r == r2);
}
}
- printf("Number of calls: %llu\n", (unsigned long long)ncalls);
+ printf("Number of calls: %" PRIu64 "\n", ncalls);
return (0);
}
diff --git a/src/third_party/wiredtiger/test/packing/intpack-test2.c b/src/third_party/wiredtiger/test/packing/intpack-test2.c
index e216899cebb..13f9ab0d2d7 100644
--- a/src/third_party/wiredtiger/test/packing/intpack-test2.c
+++ b/src/third_party/wiredtiger/test/packing/intpack-test2.c
@@ -31,7 +31,7 @@
int
main(void)
{
- uint8_t buf[10], *p, *end;
+ uint8_t buf[WT_INTPACK64_MAXSIZE], *p, *end;
int64_t i;
for (i = 1; i < 1LL << 60; i <<= 1) {
diff --git a/src/third_party/wiredtiger/test/packing/intpack-test3.c b/src/third_party/wiredtiger/test/packing/intpack-test3.c
index 00fc80e24a2..dad31fd7f7d 100644
--- a/src/third_party/wiredtiger/test/packing/intpack-test3.c
+++ b/src/third_party/wiredtiger/test/packing/intpack-test3.c
@@ -35,7 +35,7 @@ void
test_value(int64_t val)
{
const uint8_t *cp;
- uint8_t buf[10], *p;
+ uint8_t buf[WT_INTPACK64_MAXSIZE], *p;
int64_t sinput, soutput;
uint64_t uinput, uoutput;
size_t used_len;
@@ -50,8 +50,8 @@ test_value(int64_t val)
testutil_check(__wt_vunpack_int(&cp, used_len, &soutput));
/* Ensure we got the correct value back */
if (sinput != soutput) {
- fprintf(stderr, "mismatch %" PRIu64 ", %" PRIu64 "\n",
- sinput, soutput);
+ fprintf(stderr,
+ "mismatch %" PRId64 ", %" PRId64 "\n", sinput, soutput);
abort();
}
/* Ensure that decoding used the correct amount of buffer */
@@ -74,8 +74,8 @@ test_value(int64_t val)
testutil_check(__wt_vunpack_uint(&cp, sizeof(buf), &uoutput));
/* Ensure we got the correct value back */
if (sinput != soutput) {
- fprintf(stderr, "mismatch %" PRIu64 ", %" PRIu64 "\n",
- sinput, soutput);
+ fprintf(stderr,
+ "mismatch %" PRId64 ", %" PRId64 "\n", sinput, soutput);
abort();
}
/* Ensure that decoding used the correct amount of buffer */
diff --git a/src/third_party/wiredtiger/test/packing/packing-test.c b/src/third_party/wiredtiger/test/packing/packing-test.c
index bd48ac7125c..684cdec554a 100644
--- a/src/third_party/wiredtiger/test/packing/packing-test.c
+++ b/src/third_party/wiredtiger/test/packing/packing-test.c
@@ -51,7 +51,7 @@ check(const char *fmt, ...)
printf("%s ", fmt);
for (p = buf, end = p + len; p < end; p++)
- printf("%02x", *p & 0xff);
+ printf("%02x", (u_char)*p & 0xff);
printf("\n");
}
diff --git a/src/third_party/wiredtiger/test/recovery/random-abort.c b/src/third_party/wiredtiger/test/recovery/random-abort.c
index 7e76f61bd12..5588da00bd9 100644
--- a/src/third_party/wiredtiger/test/recovery/random-abort.c
+++ b/src/third_party/wiredtiger/test/recovery/random-abort.c
@@ -38,6 +38,7 @@ static char home[1024]; /* Program working dir */
*/
static const char * const uri = "table:main";
static const char * const fs_main = "main.wt";
+static bool compat;
static bool inmem;
#define MAX_TH 12
@@ -46,6 +47,7 @@ static bool inmem;
#define MIN_TIME 10
#define RECORDS_FILE "records-%" PRIu32
+#define ENV_CONFIG_COMPAT ",compatibility=(release=\"2.9\")"
#define ENV_CONFIG_DEF \
"create,log=(file_max=10M,enabled)"
#define ENV_CONFIG_TXNSYNC \
@@ -167,16 +169,19 @@ fill_db(uint32_t nth)
wt_thread_t *thr;
uint32_t i;
int ret;
- const char *envconf;
+ char envconf[512];
thr = dcalloc(nth, sizeof(*thr));
td = dcalloc(nth, sizeof(WT_THREAD_DATA));
if (chdir(home) != 0)
testutil_die(errno, "Child chdir: %s", home);
if (inmem)
- envconf = ENV_CONFIG_DEF;
+ strcpy(envconf, ENV_CONFIG_DEF);
else
- envconf = ENV_CONFIG_TXNSYNC;
+ strcpy(envconf, ENV_CONFIG_TXNSYNC);
+ if (compat)
+ strcat(envconf, ENV_CONFIG_COMPAT);
+
if ((ret = wiredtiger_open(NULL, NULL, envconf, &conn)) != 0)
testutil_die(ret, "wiredtiger_open");
if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0)
@@ -221,27 +226,30 @@ main(int argc, char *argv[])
FILE *fp;
WT_CONNECTION *conn;
WT_CURSOR *cursor;
- WT_SESSION *session;
WT_RAND_STATE rnd;
+ WT_SESSION *session;
+ pid_t pid;
uint64_t absent, count, key, last_key, middle;
uint32_t i, nth, timeout;
int ch, status, ret;
- pid_t pid;
- bool fatal, rand_th, rand_time, verify_only;
const char *working_dir;
char fname[64], kname[64], statname[1024];
+ bool fatal, rand_th, rand_time, verify_only;
(void)testutil_set_progname(argv);
- inmem = false;
+ compat = inmem = false;
nth = MIN_TH;
rand_th = rand_time = true;
timeout = MIN_TIME;
verify_only = false;
working_dir = "WT_TEST.random-abort";
- while ((ch = __wt_getopt(progname, argc, argv, "h:mT:t:v")) != EOF)
+ while ((ch = __wt_getopt(progname, argc, argv, "Ch:mT:t:v")) != EOF)
switch (ch) {
+ case 'C':
+ compat = true;
+ break;
case 'h':
working_dir = __wt_optarg;
break;
@@ -291,6 +299,8 @@ main(int argc, char *argv[])
if (nth < MIN_TH)
nth = MIN_TH;
}
+ printf("Parent: Compatibility %s in-mem log %s\n",
+ compat ? "true" : "false", inmem ? "true" : "false");
printf("Parent: Create %" PRIu32
" threads; sleep %" PRIu32 " seconds\n", nth, timeout);
/*
diff --git a/src/third_party/wiredtiger/test/recovery/smoke.sh b/src/third_party/wiredtiger/test/recovery/smoke.sh
index ce0662d3b2b..ba4d77c642b 100755
--- a/src/third_party/wiredtiger/test/recovery/smoke.sh
+++ b/src/third_party/wiredtiger/test/recovery/smoke.sh
@@ -6,4 +6,6 @@ set -e
$TEST_WRAPPER ./random-abort -t 10 -T 5
$TEST_WRAPPER ./random-abort -m -t 10 -T 5
+$TEST_WRAPPER ./random-abort -C -t 10 -T 5
+$TEST_WRAPPER ./random-abort -C -m -t 10 -T 5
$TEST_WRAPPER ./truncated-log
diff --git a/src/third_party/wiredtiger/test/recovery/truncated-log.c b/src/third_party/wiredtiger/test/recovery/truncated-log.c
index c9d73e0cf48..73ebe7dfae7 100644
--- a/src/third_party/wiredtiger/test/recovery/truncated-log.c
+++ b/src/third_party/wiredtiger/test/recovery/truncated-log.c
@@ -90,14 +90,17 @@ write_and_read_new(WT_SESSION *session)
&optype, &fileid, &logrec_key, &logrec_value)) != 0)
testutil_die(errno, "get_value");
/*
- * We should never see a record from log file 2. We wrote
+ * We should never see a record from us in log file 2. We wrote
* a record there, but then the record in log file 1 was
* truncated to be a partial record, ending the log there.
* So everything after that, including everything in log
* file 2, is invalid until we get to log file 3 which is where
* the post-recovery records will be written.
+ * The one exception in log file two is the system record for
+ * the previous log file's LSN. Although it is written by the
+ * system, we do walk it when using a cursor.
*/
- if (log_file == 2)
+ if (log_file == 2 && rectype != WT_LOGREC_SYSTEM)
testutil_die(EINVAL, "Found LSN in Log 2");
#if 0
printf("LSN [%" PRIu32 "][%" PRIu32 "].%" PRIu32
@@ -348,9 +351,10 @@ main(int argc, char *argv[])
/*
* The max key in the saved file is the key we truncated, but the
* key space starts at 0 and we're counting the records here, so we
- * expect the max key number of records.
+ * expect the max key number of records. Add one for the system
+ * record for the previous LSN that the cursor will see too.
*/
- if (count > max_key) {
+ if (count > (max_key + 1)) {
printf("expected %" PRIu32 " records found %" PRIu32 "\n",
max_key, count);
return (EXIT_FAILURE);
diff --git a/src/third_party/wiredtiger/test/suite/suite_subprocess.py b/src/third_party/wiredtiger/test/suite/suite_subprocess.py
index 86134db5f88..626a6b5efd3 100644
--- a/src/third_party/wiredtiger/test/suite/suite_subprocess.py
+++ b/src/third_party/wiredtiger/test/suite/suite_subprocess.py
@@ -119,11 +119,13 @@ class suite_subprocess:
# Run the wt utility.
def runWt(self, args, infilename=None,
- outfilename=None, errfilename=None, reopensession=True, failure=False):
+ outfilename=None, errfilename=None, closeconn=True,
+ reopensession=True, failure=False):
# Close the connection to guarantee everything is flushed, and that
# we can open it from another process.
- self.close_conn()
+ if closeconn:
+ self.close_conn()
wtoutname = outfilename or "wt.out"
wterrname = errfilename or "wt.err"
@@ -166,5 +168,5 @@ class suite_subprocess:
self.check_empty_file(wtoutname)
# Reestablish the connection if needed
- if reopensession:
+ if reopensession and closeconn:
self.open_conn()
diff --git a/src/third_party/wiredtiger/test/suite/test_alter02.py b/src/third_party/wiredtiger/test/suite/test_alter02.py
new file mode 100644
index 00000000000..3c5b67aeba5
--- /dev/null
+++ b/src/third_party/wiredtiger/test/suite/test_alter02.py
@@ -0,0 +1,234 @@
+#!/usr/bin/env python
+#
+# Public Domain 2014-2017 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.
+
+import sys, wiredtiger, wttest
+from wtscenario import make_scenarios
+
+# test_alter02.py
+# Smoke-test the session alter operations.
+class test_alter02(wttest.WiredTigerTestCase):
+ entries = 500
+ # Binary values.
+ value = u'\u0001\u0002abcd\u0003\u0004'
+ value2 = u'\u0001\u0002dcba\u0003\u0004'
+
+ conn_log = [
+ ('conn-always-logged', dict(conncreate=True, connreopen=True)),
+ ('conn-create-logged', dict(conncreate=True, connreopen=False)),
+ ('conn-reopen-logged', dict(conncreate=False, connreopen=True)),
+ ('conn-never-logged', dict(conncreate=False, connreopen=False)),
+ ]
+
+ types = [
+ ('file', dict(uri='file:', use_cg=False, use_index=False)),
+ ('lsm', dict(uri='lsm:', use_cg=False, use_index=False)),
+ ('table-cg', dict(uri='table:', use_cg=True, use_index=False)),
+ ('table-index', dict(uri='table:', use_cg=False, use_index=True)),
+ ('table-simple', dict(uri='table:', use_cg=False, use_index=False)),
+ ]
+
+ tables = [
+ ('always-logged', dict(name='table0', logcreate=True, logalter=True)),
+ ('create-logged', dict(name='table1', logcreate=True, logalter=False)),
+ ('alter-logged', dict(name='table2', logcreate=False, logalter=True)),
+ ('never-logged', dict(name='table3', logcreate=False, logalter=False)),
+ ]
+
+ reopen = [
+ ('no-reopen', dict(reopen=False)),
+ ('reopen', dict(reopen=True)),
+ ]
+ scenarios = make_scenarios(conn_log, types, tables, reopen)
+
+ # This test varies the log setting. Override the standard methods.
+ def setUpConnectionOpen(self, dir):
+ return None
+ def setUpSessionOpen(self, conn):
+ return None
+ def ConnectionOpen(self):
+ self.home = '.'
+
+ conn_params = 'create,log=(archive=false,file_max=100K,%s)' % self.uselog
+
+ try:
+ self.conn = wiredtiger.wiredtiger_open(self.home, conn_params)
+ except wiredtiger.WiredTigerError as e:
+ print "Failed conn at '%s' with config '%s'" % (dir, conn_params)
+ self.session = self.conn.open_session()
+
+ # Verify the metadata string for this URI and that its setting in the
+ # metdata file is correct.
+ def verify_metadata(self, metastr):
+ if metastr == '':
+ return
+ cursor = self.session.open_cursor('metadata:', None, None)
+ #
+ # Walk through all the metadata looking for the entries that are
+ # the file URIs for components of the table.
+ #
+ found = False
+ while True:
+ ret = cursor.next()
+ if ret != 0:
+ break
+ key = cursor.get_key()
+ check_meta = ((key.find("lsm:") != -1 or key.find("file:") != -1) \
+ and key.find(self.name) != -1)
+ if check_meta:
+ value = cursor[key]
+ found = True
+ self.assertTrue(value.find(metastr) != -1)
+ cursor.close()
+ self.assertTrue(found == True)
+
+ # Verify the data in the log. If the data should be logged we write one
+ # value. If it should not be logged, we write a different value.
+ def verify_logrecs(self, expected_keys):
+ c = self.session.open_cursor('log:', None, None)
+ count = 0
+ while c.next() == 0:
+ # lsn.file, lsn.offset, opcount
+ keys = c.get_key()
+ # txnid, rectype, optype, fileid, logrec_key, logrec_value
+ values = c.get_value()
+ try:
+ if self.value in str(values[5]): # logrec_value
+ count += 1
+ self.assertFalse(value2 in str(values[5]))
+ except:
+ pass
+ c.close()
+ self.assertEqual(count, expected_keys)
+
+ # Alter: Change the log setting after creation
+ def test_alter02_log(self):
+ uri = self.uri + self.name
+ create_params = 'key_format=i,value_format=S,'
+ complex_params = ''
+
+ # Set up logging for the connection.
+ if self.conncreate:
+ self.uselog = 'enabled=true'
+ conn_logged = 1
+ else:
+ self.uselog = 'enabled=false'
+ conn_logged = 0
+ self.ConnectionOpen()
+
+ # Set up logging for the table.
+ if self.logcreate:
+ log_param = 'log=(enabled=true)'
+ table_logged = 1
+ else:
+ log_param = 'log=(enabled=false)'
+ table_logged = 0
+ create_params += '%s,' % log_param
+ complex_params += '%s,' % log_param
+
+ cgparam = ''
+ if self.use_cg or self.use_index:
+ cgparam = 'columns=(k,v),'
+ if self.use_cg:
+ cgparam += 'colgroups=(g0),'
+
+ self.session.create(uri, create_params + cgparam)
+ # Add in column group or index settings.
+ if self.use_cg:
+ cgparam = 'columns=(v),'
+ suburi = 'colgroup:' + self.name + ':g0'
+ self.session.create(suburi, complex_params + cgparam)
+ if self.use_index:
+ suburi = 'index:' + self.name + ':i0'
+ self.session.create(suburi, complex_params + cgparam)
+
+ # Put some data in table.
+ c = self.session.open_cursor(uri, None)
+ if self.logcreate:
+ myvalue = self.value
+ else:
+ myvalue = self.value2
+ for k in range(self.entries):
+ c[k] = myvalue
+ c.close()
+
+ # Verify the logging string in the metadata.
+ self.verify_metadata(log_param)
+
+ # Verify the logged operations only if logging is enabled.
+ expected_keys = conn_logged * table_logged * self.entries
+ if conn_logged != 0:
+ self.pr("EXPECTED KEYS 1: " + str(expected_keys))
+ self.verify_logrecs(expected_keys)
+
+ # Set the alter setting for the table.
+ if self.logalter:
+ log_str = 'log=(enabled=true)'
+ table_logged = 1
+ else:
+ log_str = 'log=(enabled=false)'
+ table_logged = 0
+ alter_param = '%s' % log_str
+ special = self.use_cg or self.use_index
+
+ # Set the log setting on the new connection.
+ if self.reopen:
+ if self.connreopen:
+ self.uselog = 'enabled=true'
+ conn_logged = 1
+ else:
+ self.uselog = 'enabled=false'
+ conn_logged = 0
+ self.conn.close()
+ self.ConnectionOpen()
+
+ self.session.alter(uri, alter_param)
+ if special:
+ self.session.alter(suburi, alter_param)
+ self.verify_metadata(log_str)
+ # Put some more data in table.
+ c = self.session.open_cursor(uri, None)
+ if self.logalter:
+ myvalue = self.value
+ else:
+ myvalue = self.value2
+ for k in range(self.entries):
+ c[k + self.entries] = myvalue
+ c.close()
+ # If we logged the new connection and the table, add in the
+ # number of keys we expect.
+ expected_keys += conn_logged * table_logged * self.entries
+ # if self.logalter and self.connreopen == self.reopen:
+ # expected_keys += self.entries
+ # If we logged the connection at any time then check
+ # the log records.
+ if self.conncreate or (self.connreopen and self.reopen):
+ self.pr("EXPECTED KEYS 2: " + str(expected_keys))
+ self.verify_logrecs(expected_keys)
+
+if __name__ == '__main__':
+ wttest.run()
diff --git a/src/third_party/wiredtiger/test/suite/test_compat01.py b/src/third_party/wiredtiger/test/suite/test_compat01.py
new file mode 100644
index 00000000000..460d38d5e08
--- /dev/null
+++ b/src/third_party/wiredtiger/test/suite/test_compat01.py
@@ -0,0 +1,182 @@
+#!/usr/bin/env python
+#
+# Public Domain 2014-2017 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.
+#
+# test_compat01.py
+# Check compatibility API
+
+import fnmatch, os, shutil, sys, time
+from suite_subprocess import suite_subprocess
+from wtscenario import make_scenarios
+import wttest
+
+class test_compat01(wttest.WiredTigerTestCase, suite_subprocess):
+ # Add enough entries and use a small log size to generate more than
+ # one log file.
+ entries = 2000
+ logmax = "100K"
+ tablename = 'test_compat01'
+ uri = 'table:' + tablename
+ sync_list = [
+ '(method=fsync,enabled)',
+ '(method=none,enabled)',
+ ]
+
+ # The API uses only the major and minor numbers but accepts with
+ # and without the patch number. Test both.
+ start_compat = [
+ ('def', dict(compat1='none', current1=True)),
+ ('current', dict(compat1="3.0", current1=True)),
+ ('current_patch', dict(compat1="3.0.0", current1=True)),
+ ('minor_only', dict(compat1="2.6", current1=False)),
+ ('minor_patch', dict(compat1="2.6.1", current1=False)),
+ ('old', dict(compat1="1.8", current1=False)),
+ ('old_patch', dict(compat1="1.8.1", current1=False)),
+ ]
+ restart_compat = [
+ ('def2', dict(compat2='none', current2=True)),
+ ('current2', dict(compat2="3.0", current2=True)),
+ ('current_patch2', dict(compat2="3.0.0", current2=True)),
+ ('minor_only2', dict(compat2="2.6", current2=False)),
+ ('minor_patch2', dict(compat2="2.6.1", current2=False)),
+ ('old2', dict(compat2="1.8", current2=False)),
+ ('old_patch2', dict(compat2="1.8.1", current2=False)),
+ ]
+ scenarios = make_scenarios(restart_compat, start_compat)
+
+ def make_compat_str(self, create):
+ compat_str = ''
+ if (create == True and self.compat1 != 'none'):
+ #compat_str = 'verbose=(temporary),compatibility=(release="%s"),' % self.compat1
+ compat_str = 'compatibility=(release="%s"),' % self.compat1
+ elif (create == False and self.compat2 != 'none'):
+ #compat_str = 'verbose=(temporary),compatibility=(release="%s"),' % self.compat2
+ compat_str = 'compatibility=(release="%s"),' % self.compat2
+ return compat_str
+
+ def conn_config(self):
+ # Cycle through the different transaction_sync values in a
+ # deterministic manner.
+ txn_sync = self.sync_list[
+ self.scenario_number % len(self.sync_list)]
+ # Set archive false on the home directory.
+ log_str = 'log=(archive=false,enabled,file_max=%s),' % self.logmax + \
+ 'transaction_sync="%s",' % txn_sync
+ compat_str = self.make_compat_str(True)
+ self.pr("Conn config:" + log_str + compat_str)
+ return log_str + compat_str
+
+ def check_prev_lsn(self, conn_close, prev_lsn_count):
+ #
+ # Run printlog and look for the prev_lsn log record. Verify its
+ # existence with the passed in expected result. We don't use
+ # check_file_contains because that only looks in the first 100K and
+ # we don't know how big our text-based log output is. Look through
+ # the entire file if needed and set a boolean for comparison.
+ #
+ self.runWt(['printlog'], outfilename='printlog.out', closeconn=conn_close)
+ contains = 0
+ with open('printlog.out') as logfile:
+ for line in logfile:
+ if 'prev_lsn' in line:
+ contains += 1
+ self.assertEqual(prev_lsn_count, contains)
+
+ def check_log(self, reconfig):
+ orig_logs = fnmatch.filter(os.listdir('.'), "*gerLog*")
+ compat_str = self.make_compat_str(False)
+ if self.current1:
+ prev_lsn_logs = len(orig_logs)
+ else:
+ prev_lsn_logs = 0
+
+ if not reconfig:
+ #
+ # Close and open the connection to force recovery and reset the
+ # compatibility string on startup.
+ #
+ self.conn.close()
+ log_str = 'log=(enabled,file_max=%s,archive=false),' % self.logmax
+ restart_config = log_str + compat_str
+ self.pr("Restart conn " + restart_config)
+ #
+ # Open a connection to force it to run recovery.
+ #
+ conn = self.wiredtiger_open('.', restart_config)
+ conn.close()
+ check_close = False
+ #
+ # If the version was upgraded we'll see a new log file containing
+ # the new log record no matter what the original setting was.
+ #
+ if self.current2:
+ prev_lsn_logs += 1
+ else:
+ self.pr("Reconfigure: " + compat_str)
+ self.conn.reconfigure(compat_str)
+ check_close = True
+ #
+ # If we're reconfiguring, we'll only see another new log file
+ # when upgrading. Staying at the same version has no effect.
+ #
+ if self.current2 and not self.current1:
+ prev_lsn_logs += 1
+
+ # Run printlog and verify the new record does or does not exist.
+ # Need to check count of log files that should and should not have
+ # the prev_lsn record based on the count of log files that exist
+ # before and after. Pass that into this function and check the
+ # number of prev_lsn records we see.
+ self.check_prev_lsn(check_close, prev_lsn_logs)
+
+ def run_test(self, reconfig):
+ # If reconfiguring with the empty string there is nothing to do.
+ if reconfig == True and self.compat2 == 'none':
+ return
+ self.session.create(self.uri, 'key_format=i,value_format=i')
+ c = self.session.open_cursor(self.uri, None)
+ #
+ # Add some entries to generate log files.
+ #
+ for i in range(self.entries):
+ c[i] = i + 1
+ c.close()
+
+ # Check the log state after the entire op completes
+ # and run recovery with the restart compatibility mode.
+ self.check_log(reconfig)
+
+ # Run the same test but reset the compatibility via
+ # reconfigure or changing it when reopening the connection.
+ def test_reconfig(self):
+ self.run_test(True)
+
+ def test_restart(self):
+ self.run_test(False)
+
+if __name__ == '__main__':
+ wttest.run()
diff --git a/src/third_party/wiredtiger/test/suite/test_cursor07.py b/src/third_party/wiredtiger/test/suite/test_cursor07.py
index a31d0d401e0..94989dd68a2 100644
--- a/src/third_party/wiredtiger/test/suite/test_cursor07.py
+++ b/src/third_party/wiredtiger/test/suite/test_cursor07.py
@@ -38,8 +38,12 @@ import wttest
class test_cursor07(wttest.WiredTigerTestCase, suite_subprocess):
logmax = "100K"
- tablename = 'test_cursor07'
- uri = 'table:' + tablename
+ tablename1 = 'test_cursor07_log'
+ tablename2 = 'test_cursor07_nolog'
+ tablename3 = 'test_cursor07_nologtxn'
+ uri1 = 'table:' + tablename1
+ uri2 = 'table:' + tablename2
+ uri3 = 'table:' + tablename3
# A large number of keys will force a log file change which will
# test that scenario for log cursors.
nkeys = 7000
@@ -56,17 +60,34 @@ class test_cursor07(wttest.WiredTigerTestCase, suite_subprocess):
def test_log_cursor(self):
# print "Creating %s with config '%s'" % (self.uri, self.create_params)
create_params = 'key_format=i,value_format=S'
- self.session.create(self.uri, create_params)
- c = self.session.open_cursor(self.uri, None)
+ create_nolog_params = 'key_format=i,value_format=S,log=(enabled=false)'
+ self.session.create(self.uri1, create_params)
+ c1 = self.session.open_cursor(self.uri1, None)
+ self.session.create(self.uri2, create_nolog_params)
+ c2 = self.session.open_cursor(self.uri2, None)
+ self.session.create(self.uri3, create_nolog_params)
+ c3 = self.session.open_cursor(self.uri3, None)
# A binary value.
value = u'\u0001\u0002abcd\u0003\u0004'
+ value_nolog = u'\u0001\u0002dcba\u0003\u0004'
+ # We want to test both adding data to a table that is not logged
+ # that is part of the same transaction as a table that is logged
+ # as well as in its own transaction.
self.session.begin_transaction()
for k in range(self.nkeys):
- c[k] = value
+ c1[k] = value
+ c3[k] = value_nolog
self.session.commit_transaction()
- c.close()
+ c1.close()
+ c3.close()
+
+ self.session.begin_transaction()
+ for k in range(self.nkeys):
+ c2[k] = value_nolog
+ self.session.commit_transaction()
+ c2.close()
if self.reopen:
self.reopen_conn()
@@ -82,6 +103,7 @@ class test_cursor07(wttest.WiredTigerTestCase, suite_subprocess):
try:
if value in str(values[5]): # logrec_value
count += 1
+ self.assertFalse(value2 in str(values[5]))
except:
pass
c.close()
diff --git a/src/third_party/wiredtiger/test/suite/test_reconfig02.py b/src/third_party/wiredtiger/test/suite/test_reconfig02.py
index 3bdc19fb2f8..bba224d1bb5 100644
--- a/src/third_party/wiredtiger/test/suite/test_reconfig02.py
+++ b/src/third_party/wiredtiger/test/suite/test_reconfig02.py
@@ -100,9 +100,9 @@ class test_reconfig02(wttest.WiredTigerTestCase):
c.close()
# Close and reopen connection to write a checkpoint, move to the
# next log file and verify that archive did not run.
- orig_logs = fnmatch.filter(os.listdir('.'), "*Log*")
+ orig_logs = fnmatch.filter(os.listdir('.'), "*gerLog*")
self.reopen_conn()
- cur_logs = fnmatch.filter(os.listdir('.'), "*Log*")
+ cur_logs = fnmatch.filter(os.listdir('.'), "*gerLog*")
for o in orig_logs:
self.assertEqual(True, o in cur_logs)
@@ -111,7 +111,7 @@ class test_reconfig02(wttest.WiredTigerTestCase):
self.conn.reconfigure("log=(archive=true)")
self.session.checkpoint("force")
time.sleep(2)
- cur_logs = fnmatch.filter(os.listdir('.'), "*Log*")
+ cur_logs = fnmatch.filter(os.listdir('.'), "*gerLog*")
for o in orig_logs:
self.assertEqual(False, o in cur_logs)
diff --git a/src/third_party/wiredtiger/test/suite/test_stat_log02.py b/src/third_party/wiredtiger/test/suite/test_stat_log02.py
new file mode 100644
index 00000000000..322092c8190
--- /dev/null
+++ b/src/third_party/wiredtiger/test/suite/test_stat_log02.py
@@ -0,0 +1,111 @@
+#!/usr/bin/env python
+#
+# Public Domain 2014-2017 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.
+
+import glob
+import json
+import os.path
+import time
+import helper, wiredtiger, wttest
+from wiredtiger import stat
+
+# test_stat_log02.py
+# Statistics log JSON testing
+class test_stat_log02(wttest.WiredTigerTestCase):
+ """
+ Test statistics log JSON outputs
+ """
+
+ # Tests need to setup the connection in their own way.
+ def setUpConnectionOpen(self, dir):
+ return None
+
+ def setUpSessionOpen(self, conn):
+ return None
+
+ def test_stats_log_json(self):
+ self.conn = self.wiredtiger_open(
+ None, "create,statistics=(fast),statistics_log=(wait=1,json)")
+
+ self.wait_for_stats_file(".")
+ self.check_stats_file(".")
+
+ def test_stats_log_on_json_with_tables(self):
+ self.conn = self.wiredtiger_open(None,
+ "create,statistics=(fast),statistics_log=(wait=1,json,sources=[file:])")
+
+ # Create a session and table to give us some stats
+ session = self.conn.open_session()
+ session.create("table:foo")
+ c = session.open_cursor("table:foo")
+ c["foo"] = "foo"
+ c.close()
+ session.close()
+
+ self.wait_for_stats_file(".")
+ self.close_conn()
+ self.check_stats_file(".")
+ self.check_file_contains_tables(".")
+
+ def wait_for_stats_file(self, dir):
+ # We wait for 30 sleeps then fail
+ number_sleeps = 0
+ while True:
+ time.sleep(1)
+ files = glob.glob(dir + '/' + 'WiredTigerStat.[0-9]*')
+ for f in files:
+ if os.stat(f).st_size != 0:
+ return
+
+ number_sleeps += 1
+ self.assertLess(number_sleeps, 30)
+
+ def check_stats_file(self, dir):
+ files = glob.glob(dir + '/' + 'WiredTigerStat.[0-9]*')
+ self.assertTrue(files)
+ self.check_file_is_json(files[0])
+
+ def check_file_is_json(self, file_name):
+ f = open(file_name, 'r')
+ for line in f:
+ # This will throw assertions if we don't have correctly formed JSON
+ json.loads(line)
+
+ def check_file_contains_tables(self, dir):
+ files = glob.glob(dir + '/' + 'WiredTigerStat.[0-9]*')
+ f = open(files[0], 'r')
+ has_tables = False
+ for line in f:
+ data = json.loads(line)
+ if "wiredTigerTables" in data:
+ if "file:foo.wt" in data["wiredTigerTables"]:
+ has_tables = True
+
+ self.assertTrue(has_tables)
+
+if __name__ == '__main__':
+ wttest.run()
diff --git a/src/third_party/wiredtiger/test/suite/test_txn02.py b/src/third_party/wiredtiger/test/suite/test_txn02.py
index b61a9ed9f99..6e54270d3ad 100644
--- a/src/third_party/wiredtiger/test/suite/test_txn02.py
+++ b/src/third_party/wiredtiger/test/suite/test_txn02.py
@@ -163,7 +163,7 @@ class test_txn02(wttest.WiredTigerTestCase, suite_subprocess):
self.scenario_number % len(self.archive_list)]
backup_conn_params = \
'log=(enabled,file_max=%s,archive=%s)' % (self.logmax, self.archive)
- orig_logs = fnmatch.filter(os.listdir(self.backup_dir), "*Log*")
+ orig_logs = fnmatch.filter(os.listdir(self.backup_dir), "*gerLog*")
endcount = 2
count = 0
while count < endcount:
@@ -183,7 +183,7 @@ class test_txn02(wttest.WiredTigerTestCase, suite_subprocess):
# have been archived if configured. Subsequent openings would not
# archive because no checkpoint is written due to no modifications.
#
- cur_logs = fnmatch.filter(os.listdir(self.backup_dir), "*Log*")
+ cur_logs = fnmatch.filter(os.listdir(self.backup_dir), "*gerLog*")
for o in orig_logs:
if self.archive == 'true':
self.assertEqual(False, o in cur_logs)
@@ -195,7 +195,7 @@ class test_txn02(wttest.WiredTigerTestCase, suite_subprocess):
# it does not.
#
self.runWt(['-h', self.backup_dir, 'printlog'], outfilename='printlog.out')
- pr_logs = fnmatch.filter(os.listdir(self.backup_dir), "*Log*")
+ pr_logs = fnmatch.filter(os.listdir(self.backup_dir), "*gerLog*")
self.assertEqual(cur_logs, pr_logs)
def test_ops(self):
diff --git a/src/third_party/wiredtiger/test/suite/test_txn05.py b/src/third_party/wiredtiger/test/suite/test_txn05.py
index 6a5be0a5df4..045cd570d8a 100644
--- a/src/third_party/wiredtiger/test/suite/test_txn05.py
+++ b/src/third_party/wiredtiger/test/suite/test_txn05.py
@@ -127,7 +127,7 @@ class test_txn05(wttest.WiredTigerTestCase, suite_subprocess):
self.scenario_number % len(self.archive_list)]
backup_conn_params = \
'log=(enabled,file_max=%s,archive=%s)' % (self.logmax, self.archive)
- orig_logs = fnmatch.filter(os.listdir(self.backup_dir), "*Log*")
+ orig_logs = fnmatch.filter(os.listdir(self.backup_dir), "*gerLog*")
endcount = 2
count = 0
while count < endcount:
@@ -142,7 +142,7 @@ class test_txn05(wttest.WiredTigerTestCase, suite_subprocess):
time.sleep(1.0)
if count == 0:
first_logs = \
- fnmatch.filter(os.listdir(self.backup_dir), "*Log*")
+ fnmatch.filter(os.listdir(self.backup_dir), "*gerLog*")
backup_conn.close()
count += 1
#
@@ -150,7 +150,7 @@ class test_txn05(wttest.WiredTigerTestCase, suite_subprocess):
# have been archived if configured. Subsequent openings would not
# archive because no checkpoint is written due to no modifications.
#
- cur_logs = fnmatch.filter(os.listdir(self.backup_dir), "*Log*")
+ cur_logs = fnmatch.filter(os.listdir(self.backup_dir), "*gerLog*")
for o in orig_logs:
# Creating the backup was effectively an unclean shutdown so
# even after sleeping, we should never archive log files
diff --git a/src/third_party/wiredtiger/test/suite/test_txn11.py b/src/third_party/wiredtiger/test/suite/test_txn11.py
index 4b4db9ce315..0cb2dfd615a 100644
--- a/src/third_party/wiredtiger/test/suite/test_txn11.py
+++ b/src/third_party/wiredtiger/test/suite/test_txn11.py
@@ -50,12 +50,12 @@ class test_txn11(wttest.WiredTigerTestCase, suite_subprocess):
'transaction_sync=(enabled=false),'
def run_checkpoints(self):
- orig_logs = fnmatch.filter(os.listdir(self.home), "*Log*")
+ orig_logs = fnmatch.filter(os.listdir(self.home), "*gerLog*")
checkpoints = 0
sorig = set(orig_logs)
while checkpoints < 500:
self.session.checkpoint()
- cur_logs = fnmatch.filter(os.listdir(self.home), "*Log*")
+ cur_logs = fnmatch.filter(os.listdir(self.home), "*gerLog*")
scur = set(cur_logs)
if scur.isdisjoint(sorig):
break
diff --git a/src/third_party/wiredtiger/test/suite/test_txn16.py b/src/third_party/wiredtiger/test/suite/test_txn16.py
index 929da2291c7..921b67e3f6b 100644
--- a/src/third_party/wiredtiger/test/suite/test_txn16.py
+++ b/src/third_party/wiredtiger/test/suite/test_txn16.py
@@ -82,14 +82,14 @@ class test_txn16(wttest.WiredTigerTestCase, suite_subprocess):
loop = 0
# Record original log files. There should never be overlap
# with these even after they're removed.
- orig_logs = fnmatch.filter(os.listdir(homedir), "*Log*")
+ orig_logs = fnmatch.filter(os.listdir(homedir), "*gerLog*")
while loop < 3:
# Reopen with logging on to run recovery first time
on_conn = self.wiredtiger_open(homedir, self.conn_on)
on_conn.close()
if loop > 0:
# Get current log files.
- cur_logs = fnmatch.filter(os.listdir(homedir), "*Log*")
+ cur_logs = fnmatch.filter(os.listdir(homedir), "*gerLog*")
scur = set(cur_logs)
sorig = set(orig_logs)
# There should never be overlap with the log files that
@@ -106,7 +106,7 @@ class test_txn16(wttest.WiredTigerTestCase, suite_subprocess):
last_logs = cur_logs
loop += 1
# Remove all log files before opening without logging.
- cur_logs = fnmatch.filter(os.listdir(homedir), "*Log*")
+ cur_logs = fnmatch.filter(os.listdir(homedir), "*gerLog*")
for l in cur_logs:
path=homedir + "/" + l
os.remove(path)
diff --git a/src/third_party/wiredtiger/test/thread/rw.c b/src/third_party/wiredtiger/test/thread/rw.c
index 3283f780b32..66f706d0d34 100644
--- a/src/third_party/wiredtiger/test/thread/rw.c
+++ b/src/third_party/wiredtiger/test/thread/rw.c
@@ -347,6 +347,6 @@ print_stats(u_int nthreads)
s = run_info;
for (id = 0; id < nthreads; ++id, ++s)
- printf("%3d: read %6d, remove %6d, update %6d\n",
+ printf("%3u: read %6d, remove %6d, update %6d\n",
id, s->reads, s->remove, s->update);
}
diff --git a/src/third_party/wiredtiger/test/utility/test_util.h b/src/third_party/wiredtiger/test/utility/test_util.h
index f07fec98bfe..e53018ad4ea 100644
--- a/src/third_party/wiredtiger/test/utility/test_util.h
+++ b/src/third_party/wiredtiger/test/utility/test_util.h
@@ -217,21 +217,19 @@ const char *example_setup(int, char * const *);
*/
int handle_op_error(WT_EVENT_HANDLER *, WT_SESSION *, int, const char *);
int handle_op_message(WT_EVENT_HANDLER *, WT_SESSION *, const char *);
-void *op_bulk(void *);
-void *op_bulk_unique(void *);
-void *op_cursor(void *);
-void *op_create(void *);
-void *op_create_unique(void *);
-void *op_drop(void *);
-void testutil_clean_work_dir(const char *);
-void testutil_cleanup(TEST_OPTS *);
-bool testutil_is_flag_set(const char *);
-void testutil_make_work_dir(const 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 *);
+void op_bulk(void *);
+void op_bulk_unique(void *);
+void op_create(void *);
+void op_create_unique(void *);
+void op_cursor(void *);
+void op_drop(void *);
+void testutil_clean_work_dir(const char *);
+void testutil_cleanup(TEST_OPTS *);
+bool testutil_is_flag_set(const char *);
+void testutil_make_work_dir(const char *);
+int testutil_parse_opts(int, char * const *, TEST_OPTS *);
+void testutil_work_dir_from_path(char *, size_t, const char *);
+WT_THREAD_RET thread_append(void *);
extern const char *progname;
const char *testutil_set_progname(char * const *);
diff --git a/src/third_party/wiredtiger/test/utility/thread.c b/src/third_party/wiredtiger/test/utility/thread.c
index 4c5202016a5..ed8c7e5ae73 100644
--- a/src/third_party/wiredtiger/test/utility/thread.c
+++ b/src/third_party/wiredtiger/test/utility/thread.c
@@ -34,7 +34,7 @@
* One thread (the first thread created by an application) checks for a
* terminating condition after each insert.
*/
-void *
+WT_THREAD_RET
thread_append(void *arg)
{
TEST_OPTS *opts;
@@ -70,75 +70,7 @@ thread_append(void *arg)
}
}
- 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) {
- testutil_check(__wt_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);
+ return (WT_THREAD_RET_VALUE);
}
/*
@@ -198,7 +130,7 @@ handle_op_message(WT_EVENT_HANDLER *handler,
/*
* Create a table and open a bulk cursor on it.
*/
-void *
+void
op_bulk(void *arg)
{
TEST_OPTS *opts;
@@ -228,14 +160,12 @@ op_bulk(void *arg)
testutil_check(session->close(session, NULL));
args->thread_counter++;
-
- return (NULL);
}
/*
* Create a guaranteed unique table and open and close a bulk cursor on it.
*/
-void *
+void
op_bulk_unique(void *arg)
{
TEST_OPTS *opts;
@@ -286,14 +216,12 @@ op_bulk_unique(void *arg)
testutil_check(session->close(session, NULL));
args->thread_counter++;
-
- return (NULL);
}
/*
* Open and close cursor on a table.
*/
-void *
+void
op_cursor(void *arg)
{
TEST_OPTS *opts;
@@ -317,14 +245,12 @@ op_cursor(void *arg)
testutil_check(session->close(session, NULL));
args->thread_counter++;
-
- return (NULL);
}
/*
* Create a table.
*/
-void *
+void
op_create(void *arg)
{
TEST_OPTS *opts;
@@ -344,14 +270,12 @@ op_create(void *arg)
testutil_check(session->close(session, NULL));
args->thread_counter++;
-
- return (NULL);
}
/*
* Create and drop a unique guaranteed table.
*/
-void *
+void
op_create_unique(void *arg)
{
TEST_OPTS *opts;
@@ -389,14 +313,12 @@ op_create_unique(void *arg)
testutil_check(session->close(session, NULL));
args->thread_counter++;
-
- return (NULL);
}
/*
* Drop a table.
*/
-void *
+void
op_drop(void *arg)
{
TEST_PER_THREAD_OPTS *args;
@@ -419,6 +341,4 @@ op_drop(void *arg)
testutil_check(session->close(session, NULL));
args->thread_counter++;
-
- return (NULL);
}
diff --git a/src/third_party/wiredtiger/tools/wtstats/stat_data.py b/src/third_party/wiredtiger/tools/wtstats/stat_data.py
index 09fca2b9525..41bc26abbaf 100644
--- a/src/third_party/wiredtiger/tools/wtstats/stat_data.py
+++ b/src/third_party/wiredtiger/tools/wtstats/stat_data.py
@@ -13,7 +13,6 @@ no_scale_per_second_list = [
'cache: hazard pointer maximum array length',
'cache: maximum bytes configured',
'cache: maximum page size at eviction',
- 'cache: overflow values cached in memory',
'cache: pages currently held in the cache',
'cache: percentage overhead',
'cache: tracked bytes belonging to internal pages in the cache',
@@ -94,10 +93,11 @@ no_scale_per_second_list = [
'btree: row-store internal pages',
'btree: row-store leaf pages',
'cache: bytes currently in the cache',
- 'cache: overflow values cached in memory',
'cache: tracked dirty bytes in the cache',
'cache_walk: Average difference between current eviction generation when the page was last considered',
'cache_walk: Average on-disk page image size seen',
+ 'cache_walk: Average time in cache for pages that have been visited by the eviction server',
+ 'cache_walk: Average time in cache for pages that have not been visited by the eviction server',
'cache_walk: Clean pages currently in cache',
'cache_walk: Current eviction generation',
'cache_walk: Dirty pages currently in cache',
@@ -107,6 +107,7 @@ no_scale_per_second_list = [
'cache_walk: Maximum difference between current eviction generation when the page was last considered',
'cache_walk: Maximum page size seen',
'cache_walk: Minimum on-disk page image size seen',
+ 'cache_walk: Number of pages never visited by eviction server',
'cache_walk: On-disk page image sizes smaller than a single allocation unit',
'cache_walk: Pages created in memory and never written',
'cache_walk: Pages currently queued for eviction',
@@ -194,6 +195,8 @@ no_clear_list = [
'cache: tracked dirty bytes in the cache',
'cache_walk: Average difference between current eviction generation when the page was last considered',
'cache_walk: Average on-disk page image size seen',
+ 'cache_walk: Average time in cache for pages that have been visited by the eviction server',
+ 'cache_walk: Average time in cache for pages that have not been visited by the eviction server',
'cache_walk: Clean pages currently in cache',
'cache_walk: Current eviction generation',
'cache_walk: Dirty pages currently in cache',
@@ -203,6 +206,7 @@ no_clear_list = [
'cache_walk: Maximum difference between current eviction generation when the page was last considered',
'cache_walk: Maximum page size seen',
'cache_walk: Minimum on-disk page image size seen',
+ 'cache_walk: Number of pages never visited by eviction server',
'cache_walk: On-disk page image sizes smaller than a single allocation unit',
'cache_walk: Pages created in memory and never written',
'cache_walk: Pages currently queued for eviction',