summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Chen <luke.chen@mongodb.com>2019-07-05 14:06:01 +1000
committerLuke Chen <luke.chen@mongodb.com>2019-07-05 14:06:01 +1000
commit55062d72da95ff15d0524778dd72922988a33faa (patch)
treecca11532a005e9401d95e1bba7a1585ff8236b5e
parent6296d2f907565ec44410a43868ee41cf46fbdd16 (diff)
downloadmongo-55062d72da95ff15d0524778dd72922988a33faa.tar.gz
Import wiredtiger: 298609418d45b9821c06d588d28b710b7b36c195 from branch mongodb-3.6
ref: dc91a569c8..298609418d for: 3.6.14 WT-4352 Resolve birthmarks during eviction in more cases WT-4421 Add a way to calculate modify operations WT-4693 WT_CONNECTION::reconfigure should not require quiescence when downgraded WT-4706 Add a statistic to track the lookaside table size WT-4750 Sweep can remove active lookaside records when files are closed and re-opened WT-4759 Save a copy when an old overflow value is discarded WT-4768 Inconsistent data with lookaside eviction followed by sweep WT-4769 Don't discard active history for empty pages WT-4776 Modify operations should be equivalent to updates WT-4794 Mark lookaside history resolved in all paths WT-4803 Implement file_max configuration for Cache Overflow mechanism WT-4823 Add check for uninitialised lookaside resources WT-4848 Fix perf regression when calculating differences
-rw-r--r--src/third_party/wiredtiger/build_win/wiredtiger.def1
-rw-r--r--src/third_party/wiredtiger/dist/api_data.py12
-rw-r--r--src/third_party/wiredtiger/dist/filelist1
-rw-r--r--src/third_party/wiredtiger/dist/s_export.list1
-rw-r--r--src/third_party/wiredtiger/dist/s_funcs.list1
-rw-r--r--src/third_party/wiredtiger/dist/s_string.ok6
-rwxr-xr-xsrc/third_party/wiredtiger/dist/s_void1
-rw-r--r--src/third_party/wiredtiger/dist/stat_data.py2
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_all.c20
-rw-r--r--src/third_party/wiredtiger/import.data2
-rw-r--r--src/third_party/wiredtiger/lang/java/wiredtiger.i1
-rw-r--r--src/third_party/wiredtiger/lang/python/wiredtiger.i41
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_cursor.c9
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_delete.c5
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_handle.c16
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_read.c12
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_ret.c7
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_split.c3
-rw-r--r--src/third_party/wiredtiger/src/cache/cache_las.c108
-rw-r--r--src/third_party/wiredtiger/src/config/config_def.c143
-rw-r--r--src/third_party/wiredtiger/src/conn/api_calc_modify.c208
-rw-r--r--src/third_party/wiredtiger/src/conn/conn_open.c2
-rw-r--r--src/third_party/wiredtiger/src/conn/conn_reconfig.c36
-rw-r--r--src/third_party/wiredtiger/src/docs/Doxyfile2
-rw-r--r--src/third_party/wiredtiger/src/evict/evict_file.c22
-rw-r--r--src/third_party/wiredtiger/src/include/btmem.h5
-rw-r--r--src/third_party/wiredtiger/src/include/btree.h6
-rw-r--r--src/third_party/wiredtiger/src/include/btree.i2
-rw-r--r--src/third_party/wiredtiger/src/include/cache.h2
-rw-r--r--src/third_party/wiredtiger/src/include/extern.h4
-rw-r--r--src/third_party/wiredtiger/src/include/meta.h1
-rw-r--r--src/third_party/wiredtiger/src/include/stat.h2
-rw-r--r--src/third_party/wiredtiger/src/include/wiredtiger.in694
-rw-r--r--src/third_party/wiredtiger/src/reconcile/rec_write.c26
-rw-r--r--src/third_party/wiredtiger/src/support/stat.c8
-rw-r--r--src/third_party/wiredtiger/src/txn/txn_rollback_to_stable.c48
-rw-r--r--src/third_party/wiredtiger/test/csuite/Makefile.am4
-rw-r--r--src/third_party/wiredtiger/test/csuite/wt3338_partial_update/main.c137
-rw-r--r--src/third_party/wiredtiger/test/csuite/wt4803_cache_overflow_abort/main.c239
-rw-r--r--src/third_party/wiredtiger/test/suite/test_calc_modify.py118
-rw-r--r--src/third_party/wiredtiger/test/suite/test_compat01.py8
-rw-r--r--src/third_party/wiredtiger/test/suite/test_las04.py110
42 files changed, 1569 insertions, 507 deletions
diff --git a/src/third_party/wiredtiger/build_win/wiredtiger.def b/src/third_party/wiredtiger/build_win/wiredtiger.def
index 79fa84a11e0..71c52bd81af 100644
--- a/src/third_party/wiredtiger/build_win/wiredtiger.def
+++ b/src/third_party/wiredtiger/build_win/wiredtiger.def
@@ -1,5 +1,6 @@
LIBRARY WIREDTIGER
EXPORTS
+ wiredtiger_calc_modify
wiredtiger_config_parser_open
wiredtiger_config_validate
wiredtiger_crc32c_func
diff --git a/src/third_party/wiredtiger/dist/api_data.py b/src/third_party/wiredtiger/dist/api_data.py
index 08a322a66e7..9db4799026d 100644
--- a/src/third_party/wiredtiger/dist/api_data.py
+++ b/src/third_party/wiredtiger/dist/api_data.py
@@ -430,6 +430,18 @@ connection_runtime_config = [
for space to be available in cache before giving up. Default will
wait forever''',
min=0),
+ Config('cache_overflow', '', r'''
+ cache overflow configuration options''',
+ type='category', subconfig=[
+ Config('file_max', '0', r'''
+ The maximum number of bytes that WiredTiger is allowed to use for
+ its cache overflow mechanism. If the cache overflow file exceeds
+ this size, a panic will be triggered. The default value means that
+ the cache overflow file is unbounded and may use as much space as
+ the filesystem will accommodate. The minimum non-zero setting is
+ 100MB.''', # !!! Must match WT_LAS_FILE_MIN
+ min='0')
+ ]),
Config('cache_overhead', '8', r'''
assume the heap allocator overhead is the specified percentage, and
adjust the cache usage by that amount (for example, if there is 10GB
diff --git a/src/third_party/wiredtiger/dist/filelist b/src/third_party/wiredtiger/dist/filelist
index 79590313b89..1bbeeb3c7a3 100644
--- a/src/third_party/wiredtiger/dist/filelist
+++ b/src/third_party/wiredtiger/dist/filelist
@@ -62,6 +62,7 @@ src/config/config_collapse.c
src/config/config_def.c
src/config/config_ext.c
src/config/config_upgrade.c
+src/conn/api_calc_modify.c
src/conn/api_strerror.c
src/conn/api_version.c
src/conn/conn_api.c
diff --git a/src/third_party/wiredtiger/dist/s_export.list b/src/third_party/wiredtiger/dist/s_export.list
index e49fa113d96..e85bf62517d 100644
--- a/src/third_party/wiredtiger/dist/s_export.list
+++ b/src/third_party/wiredtiger/dist/s_export.list
@@ -1,4 +1,5 @@
# List of OK external symbols.
+wiredtiger_calc_modify
wiredtiger_config_parser_open
wiredtiger_config_validate
wiredtiger_crc32c_func
diff --git a/src/third_party/wiredtiger/dist/s_funcs.list b/src/third_party/wiredtiger/dist/s_funcs.list
index 95c568a19ff..bcedc19a459 100644
--- a/src/third_party/wiredtiger/dist/s_funcs.list
+++ b/src/third_party/wiredtiger/dist/s_funcs.list
@@ -33,6 +33,7 @@ __wt_stat_join_aggregate
__wt_stat_join_clear_all
__wt_stream_set_no_buffer
__wt_try_readlock
+wiredtiger_calc_modify
wiredtiger_config_parser_open
wiredtiger_config_validate
wiredtiger_pack_int
diff --git a/src/third_party/wiredtiger/dist/s_string.ok b/src/third_party/wiredtiger/dist/s_string.ok
index ed5f27cdf11..8b3110e87c8 100644
--- a/src/third_party/wiredtiger/dist/s_string.ok
+++ b/src/third_party/wiredtiger/dist/s_string.ok
@@ -527,6 +527,7 @@ bzDecompressInit
bzalloc
bzfree
bzip
+calc
call's
calloc
cas
@@ -951,6 +952,7 @@ marshalled
maxCLevel
maxcpu
maxdbs
+maxdiff
mbll
mbss
mem
@@ -998,9 +1000,11 @@ needkey
needvalue
negint
nentries
+nentriesp
newbar
newfile
newuri
+newv
nextprev
nfilename
nhex
@@ -1029,6 +1033,7 @@ numSymbols
numbare
offpage
ok
+oldv
ondisk
onint
online
@@ -1216,6 +1221,7 @@ subgets
subinit
sublicense
subone
+suboptimal
subtest
subtree
sunique
diff --git a/src/third_party/wiredtiger/dist/s_void b/src/third_party/wiredtiger/dist/s_void
index 8798893597d..aa20270ad27 100755
--- a/src/third_party/wiredtiger/dist/s_void
+++ b/src/third_party/wiredtiger/dist/s_void
@@ -118,6 +118,7 @@ func_ok()
-e '/int snappy_pre_size$/d' \
-e '/int snappy_terminate$/d' \
-e '/int subtest_error_handler$/d' \
+ -e '/int test_las_workload$/d' \
-e '/int uri2name$/d' \
-e '/int usage$/d' \
-e '/int util_err$/d' \
diff --git a/src/third_party/wiredtiger/dist/stat_data.py b/src/third_party/wiredtiger/dist/stat_data.py
index 2bf788085b1..cad3735a8d1 100644
--- a/src/third_party/wiredtiger/dist/stat_data.py
+++ b/src/third_party/wiredtiger/dist/stat_data.py
@@ -264,6 +264,8 @@ connection_stats = [
CacheStat('cache_lookaside_cursor_wait_internal', 'cache overflow cursor internal thread wait time (usecs)'),
CacheStat('cache_lookaside_entries', 'cache overflow table entries', 'no_clear,no_scale'),
CacheStat('cache_lookaside_insert', 'cache overflow table insert calls'),
+ CacheStat('cache_lookaside_ondisk', 'cache overflow table on-disk size', 'no_clear,no_scale,size'),
+ CacheStat('cache_lookaside_ondisk_max', 'cache overflow table max on-disk size', 'no_clear,no_scale,size'),
CacheStat('cache_lookaside_remove', 'cache overflow table remove calls'),
CacheStat('cache_lookaside_score', 'cache overflow score', 'no_clear,no_scale'),
CacheStat('cache_overhead', 'percentage overhead', 'no_clear,no_scale'),
diff --git a/src/third_party/wiredtiger/examples/c/ex_all.c b/src/third_party/wiredtiger/examples/c/ex_all.c
index 190c2c421d3..cc9df3f03c3 100644
--- a/src/third_party/wiredtiger/examples/c/ex_all.c
+++ b/src/third_party/wiredtiger/examples/c/ex_all.c
@@ -1353,6 +1353,26 @@ main(int argc, char *argv[])
}
{
+ /*! [Calculate a modify operation] */
+ WT_MODIFY mod[3];
+ int nmod = 3;
+ WT_ITEM prev, newv;
+ prev.data = "the quick brown fox jumped over the lazy dog. " \
+ "THE QUICK BROWN FOX JUMPED OVER THE LAZY DOG. " \
+ "the quick brown fox jumped over the lazy dog. " \
+ "THE QUICK BROWN FOX JUMPED OVER THE LAZY DOG. ";
+ prev.size = strlen(prev.data);
+ newv.data = "A quick brown fox jumped over the lazy dog. " \
+ "THE QUICK BROWN FOX JUMPED OVER THE LAZY DOG. " \
+ "then a quick brown fox jumped over the lazy dog. " \
+ "THE QUICK BROWN FOX JUMPED OVER THE LAZY DOG. " \
+ "then what?";
+ newv.size = strlen(newv.data);
+ error_check(wiredtiger_calc_modify(NULL, &prev, &newv, 20, mod, &nmod));
+ /*! [Calculate a modify operation] */
+ }
+
+ {
const char *buffer = "some string";
size_t len = strlen(buffer);
/*! [Checksum a buffer] */
diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data
index 0aaf4175e25..d0379dd479e 100644
--- a/src/third_party/wiredtiger/import.data
+++ b/src/third_party/wiredtiger/import.data
@@ -1,5 +1,5 @@
{
- "commit": "dc91a569c824b133fde67be22f0e5a20dbb9db74",
+ "commit": "298609418d45b9821c06d588d28b710b7b36c195",
"github": "wiredtiger/wiredtiger.git",
"vendor": "wiredtiger",
"branch": "mongodb-3.6"
diff --git a/src/third_party/wiredtiger/lang/java/wiredtiger.i b/src/third_party/wiredtiger/lang/java/wiredtiger.i
index dfac0e9ec8d..5ef1658a322 100644
--- a/src/third_party/wiredtiger/lang/java/wiredtiger.i
+++ b/src/third_party/wiredtiger/lang/java/wiredtiger.i
@@ -357,6 +357,7 @@ WT_CLASS(struct __wt_async_op, WT_ASYNC_OP, op)
%ignore __wt_modify::position;
%ignore __wt_modify::size;
%ignore __wt_cursor::modify;
+%ignore wiredtiger_calc_modify;
%ignore __wt_cursor::compare(WT_CURSOR *, WT_CURSOR *, int *);
%rename (compare_wrap) __wt_cursor::compare;
diff --git a/src/third_party/wiredtiger/lang/python/wiredtiger.i b/src/third_party/wiredtiger/lang/python/wiredtiger.i
index 0c95be87c1b..d3eb79cfd63 100644
--- a/src/third_party/wiredtiger/lang/python/wiredtiger.i
+++ b/src/third_party/wiredtiger/lang/python/wiredtiger.i
@@ -151,6 +151,41 @@ from packing import pack, unpack
}
}
+%typemap(in,numinputs=1) (WT_MODIFY *entries, int *nentriesp) (WT_MODIFY *mod, int nentries) {
+ nentries = (int) PyLong_AsLong($input);
+ if (__wt_calloc_def(NULL, (size_t)nentries, &mod) != 0)
+ SWIG_exception_fail(SWIG_MemoryError, "WT calloc failed");
+ $1 = mod;
+ $2 = &nentries;
+}
+
+%typemap(argout) (WT_MODIFY *entries, int *nentriesp) {
+ int i;
+ $result = PyList_New(*$2);
+ for (i = 0; i < *$2; i++) {
+ PyObject *o = SWIG_NewPointerObj(Py_None, SWIGTYPE_p___wt_modify, 0);
+ PyObject_SetAttrString(o, "data", PyString_FromStringAndSize(
+ $1[i].data.data, $1[i].data.size));
+ PyObject_SetAttrString(o, "offset",
+ PyInt_FromLong($1[i].offset));
+ PyObject_SetAttrString(o, "size",
+ PyInt_FromLong($1[i].size));
+ PyList_SetItem($result, i, o);
+ }
+}
+
+%typemap(in) const WT_ITEM * (WT_ITEM val, long sz) {
+ if (PyString_AsStringAndSize($input, &val.data, &sz) < 0)
+ SWIG_exception_fail(SWIG_AttributeError,
+ "bad string value for WT_ITEM");
+ val.size = (size_t)sz;
+ $1 = &val;
+}
+
+%typemap(freearg) (WT_MODIFY *entries, int *nentriesp) {
+ __wt_free(NULL, $1);
+}
+
%typemap(in) WT_MODIFY * (int len, WT_MODIFY *modarray, int i) {
len = PyList_Size($input);
/*
@@ -209,7 +244,7 @@ from packing import pack, unpack
}
%typemap(freearg) WT_MODIFY * {
- /* The WT_MODIFY arg is in position 2. Is there a better way? */
+ /* The WT_MODIFY arg is in position 2. Is there a better way? */
WT_MODIFY *modarray = modarray2;
size_t i, len;
@@ -981,6 +1016,9 @@ typedef int int_void;
self.data = data
self.offset = offset
self.size = size
+
+ def __repr__(self):
+ return 'Modify(\'%s\', %d, %d)' % (self.data, self.offset, self.size)
%}
};
@@ -1013,6 +1051,7 @@ int timestamp_build() {
return WT_TIMESTAMP_SIZE > 0;
}
%}
+
int diagnostic_build();
int timestamp_build();
diff --git a/src/third_party/wiredtiger/src/btree/bt_cursor.c b/src/third_party/wiredtiger/src/btree/bt_cursor.c
index 199c57972d7..8f4f7982e3d 100644
--- a/src/third_party/wiredtiger/src/btree/bt_cursor.c
+++ b/src/third_party/wiredtiger/src/btree/bt_cursor.c
@@ -1393,12 +1393,13 @@ __cursor_chain_exceeded(WT_CURSOR_BTREE *cbt)
upd != NULL && upd->type == WT_UPDATE_MODIFY;
++i, upd = upd->next) {
upd_size += WT_UPDATE_MEMSIZE(upd);
- if (upd_size >= WT_MODIFY_MEM_FACTOR * cursor->value.size)
+ if (i >= WT_MAX_MODIFY_UPDATE &&
+ upd_size * WT_MODIFY_MEM_FRACTION >= cursor->value.size)
return (true);
}
- if (upd != NULL && upd->type == WT_UPDATE_STANDARD &&
- __wt_txn_upd_visible_all(session, upd) &&
- i >= WT_MAX_MODIFY_UPDATE)
+ if (i >= WT_MAX_MODIFY_UPDATE && upd != NULL &&
+ upd->type == WT_UPDATE_STANDARD &&
+ __wt_txn_upd_visible_all(session, upd))
return (true);
return (false);
}
diff --git a/src/third_party/wiredtiger/src/btree/bt_delete.c b/src/third_party/wiredtiger/src/btree/bt_delete.c
index 6f2b28d296a..8e9d937991a 100644
--- a/src/third_party/wiredtiger/src/btree/bt_delete.c
+++ b/src/third_party/wiredtiger/src/btree/bt_delete.c
@@ -279,13 +279,14 @@ __wt_delete_page_skip(WT_SESSION_IMPL *session, WT_REF *ref, bool visible_all)
* the page could switch to an in-memory state at any time. Lock down
* the structure, just to be safe.
*/
- if (ref->page_del == NULL)
+ if (ref->page_del == NULL && ref->page_las == NULL)
return (true);
if (!__wt_atomic_casv32(&ref->state, WT_REF_DELETED, WT_REF_LOCKED))
return (false);
- skip = !__wt_page_del_active(session, ref, visible_all);
+ skip = !__wt_page_del_active(session, ref, visible_all) &&
+ !__wt_page_las_active(session, ref);
/*
* The page_del structure can be freed as soon as the delete is stable:
diff --git a/src/third_party/wiredtiger/src/btree/bt_handle.c b/src/third_party/wiredtiger/src/btree/bt_handle.c
index 5d9609c3a52..610dd971e34 100644
--- a/src/third_party/wiredtiger/src/btree/bt_handle.c
+++ b/src/third_party/wiredtiger/src/btree/bt_handle.c
@@ -115,6 +115,12 @@ __wt_btree_open(WT_SESSION_IMPL *session, const char *op_cfg[])
/* Initialize and configure the WT_BTREE structure. */
WT_ERR(__btree_conf(session, &ckpt));
+ /*
+ * We could be a re-open of a table that was put in the lookaside
+ * dropped list. Remove our id from that list.
+ */
+ __wt_las_remove_dropped(session);
+
/* Connect to the underlying block manager. */
filename = dhandle->name;
if (!WT_PREFIX_SKIP(filename, "file:"))
@@ -236,6 +242,16 @@ __wt_btree_close(WT_SESSION_IMPL *session)
F_SET(btree, WT_BTREE_CLOSED);
/*
+ * If closing a tree let sweep drop lookaside entries for it.
+ */
+ if (F_ISSET(S2C(session), WT_CONN_LOOKASIDE_OPEN) &&
+ btree->lookaside_entries) {
+ WT_ASSERT(session, !WT_IS_METADATA(btree->dhandle) &&
+ !F_ISSET(btree, WT_BTREE_LOOKASIDE));
+ WT_TRET(__wt_las_save_dropped(session));
+ }
+
+ /*
* If we turned eviction off and never turned it back on, do that now,
* otherwise the counter will be off.
*/
diff --git a/src/third_party/wiredtiger/src/btree/bt_read.c b/src/third_party/wiredtiger/src/btree/bt_read.c
index 1254b86c6ea..bbf60aabc20 100644
--- a/src/third_party/wiredtiger/src/btree/bt_read.c
+++ b/src/third_party/wiredtiger/src/btree/bt_read.c
@@ -291,6 +291,13 @@ __las_page_instantiate(WT_SESSION_IMPL *session, WT_REF *ref)
}
}
+ /*
+ * Now the lookaside history has been read into cache there is no
+ * further need to maintain a reference to it.
+ */
+ ref->page_las->eviction_to_lookaside = false;
+ ref->page_las->resolved = true;
+
err: if (locked)
__wt_readunlock(session, &cache->las_sweepwalk_lock);
WT_TRET(__wt_las_cursor_close(session, &cursor, session_flags));
@@ -414,7 +421,6 @@ __page_read_lookaside(WT_SESSION_IMPL *session,
}
WT_RET(__las_page_instantiate(session, ref));
- ref->page_las->eviction_to_lookaside = false;
return (0);
}
@@ -538,10 +544,8 @@ skip_read:
* information), first update based on the lookaside table and
* then apply the delete.
*/
- if (ref->page_las != NULL) {
+ if (ref->page_las != NULL)
WT_ERR(__las_page_instantiate(session, ref));
- ref->page_las->eviction_to_lookaside = false;
- }
/* Move all records to a deleted state. */
WT_ERR(__wt_delete_page_instantiate(session, ref));
diff --git a/src/third_party/wiredtiger/src/btree/bt_ret.c b/src/third_party/wiredtiger/src/btree/bt_ret.c
index 95ba4114345..60cb3d53699 100644
--- a/src/third_party/wiredtiger/src/btree/bt_ret.c
+++ b/src/third_party/wiredtiger/src/btree/bt_ret.c
@@ -201,6 +201,13 @@ __wt_value_return_upd(WT_SESSION_IMPL *session,
memcpy(listp, list, sizeof(list));
}
listp[i++] = upd;
+
+ /*
+ * Once a modify is found, all previously committed
+ * modifications should be applied regardless of
+ * visibility.
+ */
+ ignore_visibility = true;
}
}
diff --git a/src/third_party/wiredtiger/src/btree/bt_split.c b/src/third_party/wiredtiger/src/btree/bt_split.c
index 42d232fc7b4..0ea367fa360 100644
--- a/src/third_party/wiredtiger/src/btree/bt_split.c
+++ b/src/third_party/wiredtiger/src/btree/bt_split.c
@@ -855,6 +855,9 @@ __split_parent(WT_SESSION_IMPL *session, WT_REF *ref, WT_REF **ref_new,
}
}
+ /* Check that we are not discarding active history. */
+ WT_ASSERT(session, !__wt_page_las_active(session, next_ref));
+
/*
* The page-delete and lookaside memory weren't added to the
* parent's footprint, ignore it here.
diff --git a/src/third_party/wiredtiger/src/cache/cache_las.c b/src/third_party/wiredtiger/src/cache/cache_las.c
index cf28027d8b7..b38da22fc4a 100644
--- a/src/third_party/wiredtiger/src/cache/cache_las.c
+++ b/src/third_party/wiredtiger/src/cache/cache_las.c
@@ -57,6 +57,46 @@ __las_entry_count(WT_CACHE *cache)
}
/*
+ * __wt_las_config --
+ * Configure the lookaside table.
+ */
+int
+__wt_las_config(WT_SESSION_IMPL *session, const char **cfg)
+{
+ WT_CONFIG_ITEM cval;
+ WT_CURSOR_BTREE *las_cursor;
+ WT_SESSION_IMPL *las_session;
+
+ WT_RET(__wt_config_gets(
+ session, cfg, "cache_overflow.file_max", &cval));
+
+ if (cval.val != 0 && cval.val < WT_LAS_FILE_MIN)
+ WT_RET_MSG(session, EINVAL,
+ "max cache overflow size %" PRId64 " below minimum %d",
+ cval.val, WT_LAS_FILE_MIN);
+
+ /* This is expected for in-memory configurations. */
+ las_session = S2C(session)->cache->las_session[0];
+ WT_ASSERT(session,
+ las_session != NULL || F_ISSET(S2C(session), WT_CONN_IN_MEMORY));
+
+ if (las_session == NULL)
+ return (0);
+
+ /*
+ * We need to set file_max on the btree associated with one of the
+ * lookaside sessions.
+ */
+ las_cursor = (WT_CURSOR_BTREE *)las_session->las_cursor;
+ las_cursor->btree->file_max = (uint64_t)cval.val;
+
+ WT_STAT_CONN_SET(
+ session, cache_lookaside_ondisk_max, las_cursor->btree->file_max);
+
+ return (0);
+}
+
+/*
* __wt_las_empty --
* Return when there are entries in the lookaside table.
*/
@@ -126,7 +166,7 @@ __wt_las_stats_update(WT_SESSION_IMPL *session)
* Initialize the database's lookaside store.
*/
int
-__wt_las_create(WT_SESSION_IMPL *session)
+__wt_las_create(WT_SESSION_IMPL *session, const char **cfg)
{
WT_CACHE *cache;
WT_CONNECTION_IMPL *conn;
@@ -166,6 +206,8 @@ __wt_las_create(WT_SESSION_IMPL *session)
WT_RET(__wt_las_cursor_open(cache->las_session[i]));
}
+ WT_RET(__wt_las_config(session, cfg));
+
/* The statistics server is already running, make sure we don't race. */
WT_WRITE_BARRIER();
F_SET(conn, WT_CONN_LOOKASIDE_OPEN);
@@ -622,8 +664,9 @@ __wt_las_insert_block(WT_CURSOR *cursor,
WT_SESSION_IMPL *session;
WT_TXN_ISOLATION saved_isolation;
WT_UPDATE *upd;
+ wt_off_t las_size;
uint64_t insert_cnt;
- uint64_t las_counter, las_pageid;
+ uint64_t las_counter, las_pageid, max_las_size;
uint32_t btree_id, i, slot;
uint8_t *p;
bool local_txn;
@@ -766,6 +809,14 @@ __wt_las_insert_block(WT_CURSOR *cursor,
} while ((upd = upd->next) != NULL);
}
+ WT_ERR(__wt_block_manager_named_size(session, WT_LAS_FILE, &las_size));
+ WT_STAT_CONN_SET(session, cache_lookaside_ondisk, las_size);
+ max_las_size = ((WT_CURSOR_BTREE *)cursor)->btree->file_max;
+ if (max_las_size != 0 && (uint64_t)las_size > max_las_size)
+ WT_PANIC_MSG(session, WT_PANIC,
+ "WiredTigerLAS: file size of %" PRIu64 " exceeds maximum "
+ "size %" PRIu64, (uint64_t)las_size, max_las_size);
+
err: /* Resolve the transaction. */
if (local_txn) {
if (ret == 0)
@@ -882,6 +933,33 @@ __wt_las_remove_block(
}
/*
+ * __wt_las_remove_dropped --
+ * Remove an opened btree ID if it is in the dropped table.
+ */
+void
+__wt_las_remove_dropped(WT_SESSION_IMPL *session)
+{
+ WT_BTREE *btree;
+ WT_CACHE *cache;
+ u_int i, j;
+
+ btree = S2BT(session);
+ cache = S2C(session)->cache;
+
+ __wt_spin_lock(session, &cache->las_sweep_lock);
+ for (i = 0; i < cache->las_dropped_next &&
+ cache->las_dropped[i] != btree->id; i++)
+ ;
+
+ if (i < cache->las_dropped_next) {
+ cache->las_dropped_next--;
+ for (j = i; j < cache->las_dropped_next; j++)
+ cache->las_dropped[j] = cache->las_dropped[j + 1];
+ }
+ __wt_spin_unlock(session, &cache->las_sweep_lock);
+}
+
+/*
* __wt_las_save_dropped --
* Save a dropped btree ID to be swept from the lookaside table.
*/
@@ -958,6 +1036,19 @@ __las_sweep_init(WT_SESSION_IMPL *session)
goto err;
}
+ /*
+ * Record the current page ID: sweep will stop after this point.
+ *
+ * Since the btree IDs we're scanning are closed, any eviction must
+ * have already completed, so we won't miss anything with this
+ * approach.
+ *
+ * Also, if a tree is reopened and there is lookaside activity before
+ * this sweep completes, it will have a higher page ID and should not
+ * be removed.
+ */
+ cache->las_sweep_max_pageid = cache->las_pageid;
+
/* Scan the btree IDs to find min/max. */
cache->las_sweep_dropmin = UINT32_MAX;
cache->las_sweep_dropmax = 0;
@@ -1058,7 +1149,7 @@ __wt_las_sweep(WT_SESSION_IMPL *session)
* table. Searching for the same key could leave us stuck at
* the end of the table, repeatedly checking the same rows.
*/
- sweep_key->size = 0;
+ __wt_buf_free(session, sweep_key);
} else
ret = __las_sweep_init(session);
if (ret != 0)
@@ -1088,6 +1179,17 @@ __wt_las_sweep(WT_SESSION_IMPL *session)
cnt = 0;
/*
+ * Don't go past the end of lookaside from when sweep started.
+ * If a file is reopened, its ID may be reused past this point
+ * so the bitmap we're using is not valid.
+ */
+ if (las_pageid > cache->las_sweep_max_pageid) {
+ __wt_buf_free(session, sweep_key);
+ ret = WT_NOTFOUND;
+ break;
+ }
+
+ /*
* We only want to break between key blocks. Stop if we've
* processed enough entries either all we wanted or enough
* and there is a reader waiting and we're on a key boundary.
diff --git a/src/third_party/wiredtiger/src/config/config_def.c b/src/third_party/wiredtiger/src/config/config_def.c
index 1bda9a62e25..1e6c6775ba5 100644
--- a/src/third_party/wiredtiger/src/config/config_def.c
+++ b/src/third_party/wiredtiger/src/config/config_def.c
@@ -61,6 +61,12 @@ static const WT_CONFIG_CHECK
};
static const WT_CONFIG_CHECK
+ confchk_wiredtiger_open_cache_overflow_subconfigs[] = {
+ { "file_max", "int", NULL, "min=0", NULL, 0 },
+ { NULL, NULL, NULL, NULL, NULL, 0 }
+};
+
+static const WT_CONFIG_CHECK
confchk_wiredtiger_open_checkpoint_subconfigs[] = {
{ "log_size", "int", NULL, "min=0,max=2GB", NULL, 0 },
{ "wait", "int", NULL, "min=0,max=100000", NULL, 0 },
@@ -139,6 +145,9 @@ static const WT_CONFIG_CHECK confchk_WT_CONNECTION_reconfigure[] = {
NULL, NULL,
confchk_wiredtiger_open_async_subconfigs, 3 },
{ "cache_max_wait_ms", "int", NULL, "min=0", NULL, 0 },
+ { "cache_overflow", "category",
+ NULL, NULL,
+ confchk_wiredtiger_open_cache_overflow_subconfigs, 1 },
{ "cache_overhead", "int", NULL, "min=0,max=30", NULL, 0 },
{ "cache_size", "int", NULL, "min=1MB,max=10TB", NULL, 0 },
{ "checkpoint", "category",
@@ -822,6 +831,9 @@ static const WT_CONFIG_CHECK confchk_wiredtiger_open[] = {
{ "builtin_extension_config", "string", NULL, NULL, NULL, 0 },
{ "cache_cursors", "boolean", NULL, NULL, NULL, 0 },
{ "cache_max_wait_ms", "int", NULL, "min=0", NULL, 0 },
+ { "cache_overflow", "category",
+ NULL, NULL,
+ confchk_wiredtiger_open_cache_overflow_subconfigs, 1 },
{ "cache_overhead", "int", NULL, "min=0,max=30", NULL, 0 },
{ "cache_size", "int", NULL, "min=1MB,max=10TB", NULL, 0 },
{ "checkpoint", "category",
@@ -928,6 +940,9 @@ static const WT_CONFIG_CHECK confchk_wiredtiger_open_all[] = {
{ "builtin_extension_config", "string", NULL, NULL, NULL, 0 },
{ "cache_cursors", "boolean", NULL, NULL, NULL, 0 },
{ "cache_max_wait_ms", "int", NULL, "min=0", NULL, 0 },
+ { "cache_overflow", "category",
+ NULL, NULL,
+ confchk_wiredtiger_open_cache_overflow_subconfigs, 1 },
{ "cache_overhead", "int", NULL, "min=0,max=30", NULL, 0 },
{ "cache_size", "int", NULL, "min=1MB,max=10TB", NULL, 0 },
{ "checkpoint", "category",
@@ -1035,6 +1050,9 @@ static const WT_CONFIG_CHECK confchk_wiredtiger_open_basecfg[] = {
{ "builtin_extension_config", "string", NULL, NULL, NULL, 0 },
{ "cache_cursors", "boolean", NULL, NULL, NULL, 0 },
{ "cache_max_wait_ms", "int", NULL, "min=0", NULL, 0 },
+ { "cache_overflow", "category",
+ NULL, NULL,
+ confchk_wiredtiger_open_cache_overflow_subconfigs, 1 },
{ "cache_overhead", "int", NULL, "min=0,max=30", NULL, 0 },
{ "cache_size", "int", NULL, "min=1MB,max=10TB", NULL, 0 },
{ "checkpoint", "category",
@@ -1136,6 +1154,9 @@ static const WT_CONFIG_CHECK confchk_wiredtiger_open_usercfg[] = {
{ "builtin_extension_config", "string", NULL, NULL, NULL, 0 },
{ "cache_cursors", "boolean", NULL, NULL, NULL, 0 },
{ "cache_max_wait_ms", "int", NULL, "min=0", NULL, 0 },
+ { "cache_overflow", "category",
+ NULL, NULL,
+ confchk_wiredtiger_open_cache_overflow_subconfigs, 1 },
{ "cache_overhead", "int", NULL, "min=0,max=30", NULL, 0 },
{ "cache_size", "int", NULL, "min=1MB,max=10TB", NULL, 0 },
{ "checkpoint", "category",
@@ -1278,9 +1299,9 @@ static const WT_CONFIG_ENTRY config_entries[] = {
},
{ "WT_CONNECTION.reconfigure",
"async=(enabled=false,ops_max=1024,threads=2),cache_max_wait_ms=0"
- ",cache_overhead=8,cache_size=100MB,checkpoint=(log_size=0,"
- "wait=0),compatibility=(release=),error_prefix=,"
- "eviction=(threads_max=8,threads_min=1),"
+ ",cache_overflow=(file_max=0),cache_overhead=8,cache_size=100MB,"
+ "checkpoint=(log_size=0,wait=0),compatibility=(release=),"
+ "error_prefix=,eviction=(threads_max=8,threads_min=1),"
"eviction_checkpoint_target=1,eviction_dirty_target=5,"
"eviction_dirty_trigger=20,eviction_target=80,eviction_trigger=95"
",file_manager=(close_handle_minimum=250,close_idle_time=30,"
@@ -1291,7 +1312,7 @@ static const WT_CONFIG_ENTRY config_entries[] = {
"statistics=none,statistics_log=(json=false,on_close=false,"
"sources=,timestamp=\"%b %d %H:%M:%S\",wait=0),"
"timing_stress_for_test=,verbose=",
- confchk_WT_CONNECTION_reconfigure, 23
+ confchk_WT_CONNECTION_reconfigure, 24
},
{ "WT_CONNECTION.rollback_to_stable",
"",
@@ -1525,65 +1546,67 @@ static const WT_CONFIG_ENTRY config_entries[] = {
{ "wiredtiger_open",
"async=(enabled=false,ops_max=1024,threads=2),buffer_alignment=-1"
",builtin_extension_config=,cache_cursors=true,"
- "cache_max_wait_ms=0,cache_overhead=8,cache_size=100MB,"
- "checkpoint=(log_size=0,wait=0),checkpoint_sync=true,"
- "compatibility=(release=,require_max=,require_min=),"
- "config_base=true,create=false,direct_io=,encryption=(keyid=,"
- "name=,secretkey=),error_prefix=,eviction=(threads_max=8,"
- "threads_min=1),eviction_checkpoint_target=1,"
- "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,close_scan_interval=10),hazard_max=1000,"
- "in_memory=false,log=(archive=true,compressor=,enabled=false,"
- "file_max=100MB,path=\".\",prealloc=true,recover=on,"
- "zero_fill=false),lsm_manager=(merge=true,worker_thread_max=4),"
- "lsm_merge=true,mmap=true,multiprocess=false,"
- "operation_tracking=(enabled=false,path=\".\"),readonly=false,"
- "salvage=false,session_max=100,session_scratch_max=2MB,"
- "session_table_cache=true,shared_cache=(chunk=10MB,name=,quota=0,"
- "reserve=0,size=500MB),statistics=none,statistics_log=(json=false"
- ",on_close=false,path=\".\",sources=,timestamp=\"%b %d %H:%M:%S\""
- ",wait=0),timing_stress_for_test=,transaction_sync=(enabled=false"
- ",method=fsync),use_environment=true,use_environment_priv=false,"
+ "cache_max_wait_ms=0,cache_overflow=(file_max=0),cache_overhead=8"
+ ",cache_size=100MB,checkpoint=(log_size=0,wait=0),"
+ "checkpoint_sync=true,compatibility=(release=,require_max=,"
+ "require_min=),config_base=true,create=false,direct_io=,"
+ "encryption=(keyid=,name=,secretkey=),error_prefix=,"
+ "eviction=(threads_max=8,threads_min=1),"
+ "eviction_checkpoint_target=1,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,"
+ "close_scan_interval=10),hazard_max=1000,in_memory=false,"
+ "log=(archive=true,compressor=,enabled=false,file_max=100MB,"
+ "path=\".\",prealloc=true,recover=on,zero_fill=false),"
+ "lsm_manager=(merge=true,worker_thread_max=4),lsm_merge=true,"
+ "mmap=true,multiprocess=false,operation_tracking=(enabled=false,"
+ "path=\".\"),readonly=false,salvage=false,session_max=100,"
+ "session_scratch_max=2MB,session_table_cache=true,"
+ "shared_cache=(chunk=10MB,name=,quota=0,reserve=0,size=500MB),"
+ "statistics=none,statistics_log=(json=false,on_close=false,"
+ "path=\".\",sources=,timestamp=\"%b %d %H:%M:%S\",wait=0),"
+ "timing_stress_for_test=,transaction_sync=(enabled=false,"
+ "method=fsync),use_environment=true,use_environment_priv=false,"
"verbose=,write_through=",
- confchk_wiredtiger_open, 47
+ confchk_wiredtiger_open, 48
},
{ "wiredtiger_open_all",
"async=(enabled=false,ops_max=1024,threads=2),buffer_alignment=-1"
",builtin_extension_config=,cache_cursors=true,"
- "cache_max_wait_ms=0,cache_overhead=8,cache_size=100MB,"
- "checkpoint=(log_size=0,wait=0),checkpoint_sync=true,"
- "compatibility=(release=,require_max=,require_min=),"
- "config_base=true,create=false,direct_io=,encryption=(keyid=,"
- "name=,secretkey=),error_prefix=,eviction=(threads_max=8,"
- "threads_min=1),eviction_checkpoint_target=1,"
- "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,close_scan_interval=10),hazard_max=1000,"
- "in_memory=false,log=(archive=true,compressor=,enabled=false,"
- "file_max=100MB,path=\".\",prealloc=true,recover=on,"
- "zero_fill=false),lsm_manager=(merge=true,worker_thread_max=4),"
- "lsm_merge=true,mmap=true,multiprocess=false,"
- "operation_tracking=(enabled=false,path=\".\"),readonly=false,"
- "salvage=false,session_max=100,session_scratch_max=2MB,"
- "session_table_cache=true,shared_cache=(chunk=10MB,name=,quota=0,"
- "reserve=0,size=500MB),statistics=none,statistics_log=(json=false"
- ",on_close=false,path=\".\",sources=,timestamp=\"%b %d %H:%M:%S\""
- ",wait=0),timing_stress_for_test=,transaction_sync=(enabled=false"
- ",method=fsync),use_environment=true,use_environment_priv=false,"
+ "cache_max_wait_ms=0,cache_overflow=(file_max=0),cache_overhead=8"
+ ",cache_size=100MB,checkpoint=(log_size=0,wait=0),"
+ "checkpoint_sync=true,compatibility=(release=,require_max=,"
+ "require_min=),config_base=true,create=false,direct_io=,"
+ "encryption=(keyid=,name=,secretkey=),error_prefix=,"
+ "eviction=(threads_max=8,threads_min=1),"
+ "eviction_checkpoint_target=1,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,"
+ "close_scan_interval=10),hazard_max=1000,in_memory=false,"
+ "log=(archive=true,compressor=,enabled=false,file_max=100MB,"
+ "path=\".\",prealloc=true,recover=on,zero_fill=false),"
+ "lsm_manager=(merge=true,worker_thread_max=4),lsm_merge=true,"
+ "mmap=true,multiprocess=false,operation_tracking=(enabled=false,"
+ "path=\".\"),readonly=false,salvage=false,session_max=100,"
+ "session_scratch_max=2MB,session_table_cache=true,"
+ "shared_cache=(chunk=10MB,name=,quota=0,reserve=0,size=500MB),"
+ "statistics=none,statistics_log=(json=false,on_close=false,"
+ "path=\".\",sources=,timestamp=\"%b %d %H:%M:%S\",wait=0),"
+ "timing_stress_for_test=,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, 48
+ confchk_wiredtiger_open_all, 49
},
{ "wiredtiger_open_basecfg",
"async=(enabled=false,ops_max=1024,threads=2),buffer_alignment=-1"
",builtin_extension_config=,cache_cursors=true,"
- "cache_max_wait_ms=0,cache_overhead=8,cache_size=100MB,"
- "checkpoint=(log_size=0,wait=0),checkpoint_sync=true,"
- "compatibility=(release=,require_max=,require_min=),direct_io=,"
- "encryption=(keyid=,name=,secretkey=),error_prefix=,"
- "eviction=(threads_max=8,threads_min=1),"
+ "cache_max_wait_ms=0,cache_overflow=(file_max=0),cache_overhead=8"
+ ",cache_size=100MB,checkpoint=(log_size=0,wait=0),"
+ "checkpoint_sync=true,compatibility=(release=,require_max=,"
+ "require_min=),direct_io=,encryption=(keyid=,name=,secretkey=),"
+ "error_prefix=,eviction=(threads_max=8,threads_min=1),"
"eviction_checkpoint_target=1,eviction_dirty_target=5,"
"eviction_dirty_trigger=20,eviction_target=80,eviction_trigger=95"
",extensions=,file_extend=,file_manager=(close_handle_minimum=250"
@@ -1599,16 +1622,16 @@ static const WT_CONFIG_ENTRY config_entries[] = {
"path=\".\",sources=,timestamp=\"%b %d %H:%M:%S\",wait=0),"
"timing_stress_for_test=,transaction_sync=(enabled=false,"
"method=fsync),verbose=,version=(major=0,minor=0),write_through=",
- confchk_wiredtiger_open_basecfg, 42
+ confchk_wiredtiger_open_basecfg, 43
},
{ "wiredtiger_open_usercfg",
"async=(enabled=false,ops_max=1024,threads=2),buffer_alignment=-1"
",builtin_extension_config=,cache_cursors=true,"
- "cache_max_wait_ms=0,cache_overhead=8,cache_size=100MB,"
- "checkpoint=(log_size=0,wait=0),checkpoint_sync=true,"
- "compatibility=(release=,require_max=,require_min=),direct_io=,"
- "encryption=(keyid=,name=,secretkey=),error_prefix=,"
- "eviction=(threads_max=8,threads_min=1),"
+ "cache_max_wait_ms=0,cache_overflow=(file_max=0),cache_overhead=8"
+ ",cache_size=100MB,checkpoint=(log_size=0,wait=0),"
+ "checkpoint_sync=true,compatibility=(release=,require_max=,"
+ "require_min=),direct_io=,encryption=(keyid=,name=,secretkey=),"
+ "error_prefix=,eviction=(threads_max=8,threads_min=1),"
"eviction_checkpoint_target=1,eviction_dirty_target=5,"
"eviction_dirty_trigger=20,eviction_target=80,eviction_trigger=95"
",extensions=,file_extend=,file_manager=(close_handle_minimum=250"
@@ -1624,7 +1647,7 @@ static const WT_CONFIG_ENTRY config_entries[] = {
"path=\".\",sources=,timestamp=\"%b %d %H:%M:%S\",wait=0),"
"timing_stress_for_test=,transaction_sync=(enabled=false,"
"method=fsync),verbose=,write_through=",
- confchk_wiredtiger_open_usercfg, 41
+ confchk_wiredtiger_open_usercfg, 42
},
{ NULL, NULL, NULL, 0 }
};
diff --git a/src/third_party/wiredtiger/src/conn/api_calc_modify.c b/src/third_party/wiredtiger/src/conn/api_calc_modify.c
new file mode 100644
index 00000000000..0888ce7b706
--- /dev/null
+++ b/src/third_party/wiredtiger/src/conn/api_calc_modify.c
@@ -0,0 +1,208 @@
+/*-
+ * Copyright (c) 2014-2018 MongoDB, Inc.
+ * Copyright (c) 2008-2014 WiredTiger, Inc.
+ * All rights reserved.
+ *
+ * See the file LICENSE for redistribution information.
+ */
+
+#include "wt_internal.h"
+
+#define WT_CM_BLOCKSIZE 8
+#define WT_CM_MINMATCH 64
+#define WT_CM_STARTGAP (WT_CM_BLOCKSIZE / 2)
+
+typedef struct {
+ WT_SESSION_IMPL *session;
+
+ const uint8_t *s1, *e1; /* Start / end of pre-image. */
+ const uint8_t *s2, *e2; /* Start / end of after-image. */
+
+ const uint8_t *used1, *used2; /* Used up to here. */
+
+ size_t maxdiff;
+ int maxentries;
+} WT_CM_STATE;
+
+typedef struct {
+ const uint8_t *m1, *m2;
+ size_t len;
+} WT_CM_MATCH;
+
+/*
+ * __cm_add_modify --
+ * Add a modify operation to the list of entries.
+ *
+ * Fails if all entries are used or the maximum bytes of difference is
+ * exceeded.
+ */
+static int
+__cm_add_modify(WT_CM_STATE *cms, const uint8_t *p2,
+ const uint8_t *m1, const uint8_t *m2, WT_MODIFY *entries, int *nentriesp)
+{
+ WT_MODIFY *mod;
+ size_t len1, len2;
+
+ WT_ASSERT(cms->session, m1 >= cms->used1 && m2 >= cms->used2);
+
+ len1 = (size_t)(m1 - cms->used1);
+ len2 = (size_t)(m2 - cms->used2);
+
+ if (*nentriesp >= cms->maxentries || len2 > cms->maxdiff)
+ return (WT_NOTFOUND);
+
+ mod = entries + (*nentriesp)++;
+ mod->offset = (size_t)(p2 - cms->s2);
+ mod->size = len1;
+ mod->data.data = p2;
+ mod->data.size = len2;
+ cms->maxdiff -= len2;
+
+ return (0);
+}
+
+/*
+ * __cm_extend --
+ * Given a potential match size, extend to find the complete match.
+ */
+static void
+__cm_extend(WT_CM_STATE *cms,
+ const uint8_t *m1, const uint8_t *m2, WT_CM_MATCH *match)
+{
+ ptrdiff_t n;
+ const uint8_t *p1, *p2;
+
+ p1 = m1;
+ p2 = m2;
+
+ /*
+ * Keep skipping half of the remaining bytes while they compare equal.
+ * This is significantly faster than our byte-at-a-time loop below.
+ */
+ for (p1 = m1, p2 = m2;
+ (n = WT_MIN(cms->e1 - p1, cms->e2 - p2) / 2) > 8 &&
+ memcmp(p1, p2, (size_t)n) == 0;
+ p1 += n, p2 += n)
+ ;
+
+ /* Step past the end and before the beginning of the matching block. */
+ for (n = WT_MIN(cms->e1 - p1, cms->e2 - p2);
+ n > 0 && *p1 == *p2;
+ n--, p1++, p2++)
+ ;
+
+ for (n = WT_MIN(m1 - cms->used1, m2 - cms->used2);
+ n > 0 && *m1 == *m2;
+ n--, m1--, m2--)
+ ;
+
+ match->m1 = m1 + 1;
+ match->m2 = m2 + 1;
+ match->len = p1 > m1 ? (size_t)((p1 - m1) - 1) : 0;
+}
+
+/*
+ * __cm_fingerprint --
+ * Calculate an integral "fingerprint" of a block of bytes.
+ */
+static inline uint64_t
+__cm_fingerprint(const uint8_t *p)
+{
+ uint64_t h;
+
+ WT_STATIC_ASSERT(sizeof(h) <= WT_CM_BLOCKSIZE);
+ memcpy(&h, p, WT_CM_BLOCKSIZE);
+ return (h);
+}
+
+/*
+ * wiredtiger_calc_modify --
+ * Calculate a set of WT_MODIFY operations to represent an update.
+ */
+int
+wiredtiger_calc_modify(WT_SESSION *wt_session,
+ const WT_ITEM *oldv, const WT_ITEM *newv,
+ size_t maxdiff, WT_MODIFY *entries, int *nentriesp)
+{
+ WT_CM_MATCH match;
+ WT_CM_STATE cms;
+ size_t gap, i;
+ uint64_t h, hend, hstart;
+ const uint8_t *p1, *p2;
+ bool start;
+
+ if (oldv->size < WT_CM_MINMATCH || newv->size < WT_CM_MINMATCH)
+ return (WT_NOTFOUND);
+
+ cms.session = (WT_SESSION_IMPL *)wt_session;
+
+ cms.s1 = cms.used1 = oldv->data;
+ cms.e1 = cms.s1 + oldv->size;
+ cms.s2 = cms.used2 = newv->data;
+ cms.e2 = cms.s2 + newv->size;
+ cms.maxdiff = maxdiff;
+ cms.maxentries = *nentriesp;
+ *nentriesp = 0;
+
+ /* Ignore matches at the beginning / end. */
+ __cm_extend(&cms, cms.s1, cms.s2, &match);
+ cms.used1 += match.len;
+ cms.used2 += match.len;
+ if (cms.used1 < cms.e1 && cms.used2 < cms.e2) {
+ __cm_extend(&cms, cms.e1 - 1, cms.e2 - 1, &match);
+ cms.e1 -= match.len;
+ cms.e2 -= match.len;
+ }
+
+ if (cms.used1 + WT_CM_BLOCKSIZE >= cms.e1 ||
+ cms.used2 + WT_CM_BLOCKSIZE >= cms.e2)
+ goto end;
+
+ /*
+ * Walk through the post-image, maintaining start / end markers
+ * separated by a gap in the pre-image. If the current point in the
+ * post-image matches either marker, try to extend the match to find a
+ * (large) range of matching bytes. If the end of the range is reached
+ * in the post-image without finding a good match, double the size of
+ * the gap, update the markers and keep trying.
+ */
+ h = hstart = hend = 0;
+ i = gap = 0;
+ for (p1 = cms.used1, p2 = cms.used2, start = true;
+ p1 + WT_CM_BLOCKSIZE <= cms.e1 && p2 + WT_CM_BLOCKSIZE <= cms.e2;
+ p2++, i++) {
+ if (start || i == gap) {
+ p1 += gap;
+ gap = start ? WT_CM_STARTGAP : gap * 2;
+ if (p1 + gap + WT_CM_BLOCKSIZE >= cms.e1)
+ break;
+ if (gap > maxdiff)
+ return (WT_NOTFOUND);
+ hstart = start ? __cm_fingerprint(p1) : hend;
+ hend = __cm_fingerprint(p1 + gap);
+ start = false;
+ i = 0;
+ }
+ h = __cm_fingerprint(p2);
+ match.len = 0;
+ if (h == hstart)
+ __cm_extend(&cms, p1, p2, &match);
+ else if (h == hend)
+ __cm_extend(&cms, p1 + gap, p2, &match);
+
+ if (match.len < WT_CM_MINMATCH)
+ continue;
+
+ WT_RET(__cm_add_modify(&cms, cms.used2, match.m1, match.m2,
+ entries, nentriesp));
+ cms.used1 = p1 = match.m1 + match.len;
+ cms.used2 = p2 = match.m2 + match.len;
+ start = true;
+ }
+
+end: if (cms.used1 < cms.e1 || cms.used2 < cms.e2)
+ WT_RET(__cm_add_modify(&cms, cms.used2, cms.e1, cms.e2,
+ entries, nentriesp));
+
+ return (0);
+}
diff --git a/src/third_party/wiredtiger/src/conn/conn_open.c b/src/third_party/wiredtiger/src/conn/conn_open.c
index 6fa87d47a91..446e8701250 100644
--- a/src/third_party/wiredtiger/src/conn/conn_open.c
+++ b/src/third_party/wiredtiger/src/conn/conn_open.c
@@ -237,7 +237,7 @@ __wt_connection_workers(WT_SESSION_IMPL *session, const char *cfg[])
WT_RET(__wt_meta_track_init(session));
/* Create the lookaside table. */
- WT_RET(__wt_las_create(session));
+ WT_RET(__wt_las_create(session, cfg));
/*
* Start eviction threads.
diff --git a/src/third_party/wiredtiger/src/conn/conn_reconfig.c b/src/third_party/wiredtiger/src/conn/conn_reconfig.c
index 8bf2a53e49b..e557d0d3472 100644
--- a/src/third_party/wiredtiger/src/conn/conn_reconfig.c
+++ b/src/third_party/wiredtiger/src/conn/conn_reconfig.c
@@ -55,7 +55,7 @@ __wt_conn_compat_config(
uint16_t max_major, max_minor, min_major, min_minor;
uint16_t rel_major, rel_minor;
char *value;
- bool txn_active;
+ bool txn_active, unchg;
conn = S2C(session);
value = NULL;
@@ -63,6 +63,7 @@ __wt_conn_compat_config(
max_minor = WT_CONN_COMPAT_NONE;
min_major = WT_CONN_COMPAT_NONE;
min_minor = WT_CONN_COMPAT_NONE;
+ unchg = false;
WT_RET(__wt_config_gets(session, cfg, "compatibility.release", &cval));
if (cval.len == 0) {
@@ -74,21 +75,31 @@ __wt_conn_compat_config(
session, &cval, &rel_major, &rel_minor));
/*
- * We're doing an upgrade or downgrade, check whether
- * transactions are active.
+ * If the user is running downgraded, then the compatibility
+ * string is part of the configuration string. Determine if
+ * the user is actually changing the compatibility.
*/
- WT_RET(__wt_txn_activity_check(session, &txn_active));
- if (txn_active)
- WT_RET_MSG(session, ENOTSUP,
- "system must be quiescent"
- " for upgrade or downgrade");
+ if (reconfig && rel_major == conn->compat_major &&
+ rel_minor == conn->compat_minor)
+ unchg = true;
+ else {
+ /*
+ * We're doing an upgrade or downgrade, check whether
+ * transactions are active.
+ */
+ WT_RET(__wt_txn_activity_check(session, &txn_active));
+ if (txn_active)
+ WT_RET_MSG(session, ENOTSUP,
+ "system must be quiescent"
+ " for upgrade or downgrade");
+ }
F_SET(conn, WT_CONN_COMPATIBILITY);
}
/*
- * If we're a reconfigure and the user did not set any compatibility,
- * we're done.
+ * If we're a reconfigure and the user did not set any compatibility
+ * or did not change the setting, we're done.
*/
- if (reconfig && !F_ISSET(conn, WT_CONN_COMPATIBILITY))
+ if (reconfig && (!F_ISSET(conn, WT_CONN_COMPATIBILITY) || unchg))
goto done;
/*
@@ -476,12 +487,13 @@ __wt_conn_reconfig(WT_SESSION_IMPL *session, const char **cfg)
WT_ERR(__wt_async_reconfig(session, cfg));
WT_ERR(__wt_cache_config(session, true, cfg));
WT_ERR(__wt_checkpoint_server_create(session, cfg));
+ WT_ERR(__wt_las_config(session, cfg));
WT_ERR(__wt_logmgr_reconfig(session, cfg));
WT_ERR(__wt_lsm_manager_reconfig(session, cfg));
WT_ERR(__wt_statlog_create(session, cfg));
WT_ERR(__wt_sweep_config(session, cfg));
- WT_ERR(__wt_verbose_config(session, cfg));
WT_ERR(__wt_timing_stress_config(session, cfg));
+ WT_ERR(__wt_verbose_config(session, cfg));
/* Third, merge everything together, creating a new connection state. */
WT_ERR(__wt_config_merge(session, cfg, NULL, &p));
diff --git a/src/third_party/wiredtiger/src/docs/Doxyfile b/src/third_party/wiredtiger/src/docs/Doxyfile
index 60b6c4690b0..567a8cb92fb 100644
--- a/src/third_party/wiredtiger/src/docs/Doxyfile
+++ b/src/third_party/wiredtiger/src/docs/Doxyfile
@@ -210,7 +210,7 @@ ALIASES = \
configempty{2}="@param config configuration string, see @ref config_strings. No values currently permitted." \
configend=" </table>" \
configstart{2}="@param config configuration string, see @ref config_strings. Permitted values:\n <table>@hrow{Name,Effect,Values}" \
-"ebusy_errors=@returns zero on success, EBUSY if the object is not available for exclusive access, and a non-zero error code on failure. See @ref error_handling \"Error handling\" for details." \
+ ebusy_errors="@returns zero on success, EBUSY if the object is not available for exclusive access, and a non-zero error code on failure. See @ref error_handling \"Error handling\" for details." \
errors="@returns zero on success and a non-zero error code on failure. See @ref error_handling \"Error handling\" for details." \
exclusive="This method requires exclusive access to the specified data source(s). If any cursors are open with the specified name(s) or a data source is otherwise in use, the call will fail and return \c EBUSY.\n\n" \
ex_ref{1}="@ref \1 \"\1\"" \
diff --git a/src/third_party/wiredtiger/src/evict/evict_file.c b/src/third_party/wiredtiger/src/evict/evict_file.c
index df88a64daa9..5c0b6462b56 100644
--- a/src/third_party/wiredtiger/src/evict/evict_file.c
+++ b/src/third_party/wiredtiger/src/evict/evict_file.c
@@ -16,7 +16,6 @@ int
__wt_evict_file(WT_SESSION_IMPL *session, WT_CACHE_OP syncop)
{
WT_BTREE *btree;
- WT_CONNECTION_IMPL *conn;
WT_DATA_HANDLE *dhandle;
WT_DECL_RET;
WT_PAGE *page;
@@ -25,7 +24,6 @@ __wt_evict_file(WT_SESSION_IMPL *session, WT_CACHE_OP syncop)
dhandle = session->dhandle;
btree = dhandle->handle;
- conn = S2C(session);
/*
* We need exclusive access to the file, we're about to discard the root
@@ -41,24 +39,6 @@ __wt_evict_file(WT_SESSION_IMPL *session, WT_CACHE_OP syncop)
if (btree->root.page == NULL)
return (0);
- /*
- * If discarding a dead tree, remove any lookaside entries. This deals
- * with the case where a tree is dropped with "force=true". It happens
- * that we also force-drop the lookaside table itself: it can never
- * participate in lookaside eviction, and we can't open a cursor on it
- * as we are discarding it.
- *
- * We use the special page ID zero so that all lookaside entries for
- * the tree are removed.
- */
- if (F_ISSET(dhandle, WT_DHANDLE_DEAD) &&
- F_ISSET(conn, WT_CONN_LOOKASIDE_OPEN) && btree->lookaside_entries) {
- WT_ASSERT(session, !WT_IS_METADATA(dhandle) &&
- !F_ISSET(btree, WT_BTREE_LOOKASIDE));
-
- WT_RET(__wt_las_save_dropped(session));
- }
-
/* Make sure the oldest transaction ID is up-to-date. */
WT_RET(__wt_txn_update_oldest(
session, WT_TXN_OLDEST_STRICT | WT_TXN_OLDEST_WAIT));
@@ -123,7 +103,7 @@ __wt_evict_file(WT_SESSION_IMPL *session, WT_CACHE_OP syncop)
*/
WT_ASSERT(session,
F_ISSET(dhandle, WT_DHANDLE_DEAD) ||
- F_ISSET(conn, WT_CONN_CLOSING) ||
+ F_ISSET(S2C(session), WT_CONN_CLOSING) ||
__wt_page_can_evict(session, ref, NULL));
__wt_ref_out(session, ref);
break;
diff --git a/src/third_party/wiredtiger/src/include/btmem.h b/src/third_party/wiredtiger/src/include/btmem.h
index f4a6871e9a6..dcfb59d2ce9 100644
--- a/src/third_party/wiredtiger/src/include/btmem.h
+++ b/src/third_party/wiredtiger/src/include/btmem.h
@@ -239,6 +239,7 @@ struct __wt_page_lookaside {
WT_DECL_TIMESTAMP(max_timestamp)/* Maximum timestamp */
WT_DECL_TIMESTAMP(unstable_timestamp)/* First timestamp not on page */
bool eviction_to_lookaside; /* Revert to lookaside on eviction */
+ bool resolved; /* History has been read into cache */
bool skew_newest; /* Page image has newest versions */
};
@@ -1083,9 +1084,9 @@ struct __wt_update {
/*
* WT_MODIFY_MEM_FACTOR --
- * Limit update chains to a factor of the base document size.
+ * Limit update chains to a fraction of the base document size.
*/
-#define WT_MODIFY_MEM_FACTOR 1
+#define WT_MODIFY_MEM_FRACTION 10
/*
* WT_INSERT --
diff --git a/src/third_party/wiredtiger/src/include/btree.h b/src/third_party/wiredtiger/src/include/btree.h
index 593745cc315..f4ed7c1a644 100644
--- a/src/third_party/wiredtiger/src/include/btree.h
+++ b/src/third_party/wiredtiger/src/include/btree.h
@@ -193,6 +193,12 @@ struct __wt_btree {
uint64_t bytes_dirty_leaf; /* Bytes in dirty leaf pages. */
/*
+ * The maximum bytes allowed to be used for the table on disk. This is
+ * currently only used for the lookaside table.
+ */
+ uint64_t file_max;
+
+ /*
* We flush pages from the tree (in order to make checkpoint faster),
* without a high-level lock. To avoid multiple threads flushing at
* the same time, lock the tree.
diff --git a/src/third_party/wiredtiger/src/include/btree.i b/src/third_party/wiredtiger/src/include/btree.i
index 41d843790e8..4ca82e1ee9e 100644
--- a/src/third_party/wiredtiger/src/include/btree.i
+++ b/src/third_party/wiredtiger/src/include/btree.i
@@ -1189,6 +1189,8 @@ __wt_page_las_active(WT_SESSION_IMPL *session, WT_REF *ref)
if ((page_las = ref->page_las) == NULL)
return (false);
+ if (page_las->resolved)
+ return (false);
if (!page_las->skew_newest)
return (true);
if (__wt_txn_visible_all(session, page_las->max_txn,
diff --git a/src/third_party/wiredtiger/src/include/cache.h b/src/third_party/wiredtiger/src/include/cache.h
index 8afedb30832..9e849bf4d7f 100644
--- a/src/third_party/wiredtiger/src/include/cache.h
+++ b/src/third_party/wiredtiger/src/include/cache.h
@@ -54,6 +54,7 @@ typedef enum __wt_cache_op {
WT_SYNC_WRITE_LEAVES
} WT_CACHE_OP;
+#define WT_LAS_FILE_MIN (100 * WT_MEGABYTE)
#define WT_LAS_NUM_SESSIONS 5
#define WT_LAS_SWEEP_ENTRIES (20 * WT_THOUSAND)
#define WT_LAS_SWEEP_SEC 2
@@ -210,6 +211,7 @@ struct __wt_cache {
uint32_t las_sweep_dropmin; /* Minimum btree ID in current set. */
uint8_t *las_sweep_dropmap; /* Bitmap of dropped btree IDs. */
uint32_t las_sweep_dropmax; /* Maximum btree ID in current set. */
+ uint64_t las_sweep_max_pageid; /* Maximum page ID for sweep. */
uint32_t *las_dropped; /* List of dropped btree IDs. */
size_t las_dropped_next; /* Next index into drop list. */
diff --git a/src/third_party/wiredtiger/src/include/extern.h b/src/third_party/wiredtiger/src/include/extern.h
index 0e3bc68fcc6..afc89795500 100644
--- a/src/third_party/wiredtiger/src/include/extern.h
+++ b/src/third_party/wiredtiger/src/include/extern.h
@@ -201,9 +201,10 @@ extern int __wt_update_alloc(WT_SESSION_IMPL *session, const WT_ITEM *value, WT_
extern WT_UPDATE *__wt_update_obsolete_check(WT_SESSION_IMPL *session, WT_PAGE *page, WT_UPDATE *upd);
extern int __wt_search_insert(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt, WT_INSERT_HEAD *ins_head, WT_ITEM *srch_key) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_row_search(WT_SESSION_IMPL *session, WT_ITEM *srch_key, WT_REF *leaf, WT_CURSOR_BTREE *cbt, bool insert, bool restore) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
+extern int __wt_las_config(WT_SESSION_IMPL *session, const char **cfg) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern bool __wt_las_empty(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern void __wt_las_stats_update(WT_SESSION_IMPL *session);
-extern int __wt_las_create(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
+extern int __wt_las_create(WT_SESSION_IMPL *session, const char **cfg) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_las_destroy(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_las_cursor_open(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern void __wt_las_cursor(WT_SESSION_IMPL *session, WT_CURSOR **cursorp, uint32_t *session_flags);
@@ -213,6 +214,7 @@ extern bool __wt_las_page_skip(WT_SESSION_IMPL *session, WT_REF *ref) WT_GCC_FUN
extern int __wt_las_insert_block(WT_CURSOR *cursor, WT_BTREE *btree, WT_PAGE *page, WT_MULTI *multi, WT_ITEM *key) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_las_cursor_position(WT_CURSOR *cursor, uint64_t pageid) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_las_remove_block(WT_SESSION_IMPL *session, uint64_t pageid, bool lock_wait) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
+extern void __wt_las_remove_dropped(WT_SESSION_IMPL *session);
extern int __wt_las_save_dropped(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_las_sweep(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern uint32_t __wt_checksum_sw(const void *chunk, size_t len);
diff --git a/src/third_party/wiredtiger/src/include/meta.h b/src/third_party/wiredtiger/src/include/meta.h
index 3c028d1484b..4ae083d2885 100644
--- a/src/third_party/wiredtiger/src/include/meta.h
+++ b/src/third_party/wiredtiger/src/include/meta.h
@@ -27,6 +27,7 @@
#define WT_METAFILE_SLVG "WiredTiger.wt.orig" /* Metadata copy */
#define WT_METAFILE_URI "file:WiredTiger.wt" /* Metadata table URI */
+#define WT_LAS_FILE "WiredTigerLAS.wt" /* Lookaside table */
#define WT_LAS_URI "file:WiredTigerLAS.wt" /* Lookaside table URI*/
#define WT_SYSTEM_PREFIX "system:" /* System URI prefix */
diff --git a/src/third_party/wiredtiger/src/include/stat.h b/src/third_party/wiredtiger/src/include/stat.h
index 38224cd2bc0..98064e547e1 100644
--- a/src/third_party/wiredtiger/src/include/stat.h
+++ b/src/third_party/wiredtiger/src/include/stat.h
@@ -359,6 +359,8 @@ struct __wt_connection_stats {
int64_t cache_lookaside_score;
int64_t cache_lookaside_entries;
int64_t cache_lookaside_insert;
+ int64_t cache_lookaside_ondisk_max;
+ int64_t cache_lookaside_ondisk;
int64_t cache_lookaside_remove;
int64_t cache_eviction_checkpoint;
int64_t cache_eviction_get_ref;
diff --git a/src/third_party/wiredtiger/src/include/wiredtiger.in b/src/third_party/wiredtiger/src/include/wiredtiger.in
index 73078f797b6..36f9ecff5c7 100644
--- a/src/third_party/wiredtiger/src/include/wiredtiger.in
+++ b/src/third_party/wiredtiger/src/include/wiredtiger.in
@@ -2187,6 +2187,16 @@ struct __wt_connection {
* application thread will wait for space to be available in cache
* before giving up. Default will wait forever., an integer greater
* than or equal to 0; default \c 0.}
+ * @config{cache_overflow = (, cache overflow configuration options., a
+ * set of related configuration options defined below.}
+ * @config{&nbsp;&nbsp;&nbsp;&nbsp;file_max, The maximum number of bytes
+ * that WiredTiger is allowed to use for its cache overflow mechanism.
+ * If the cache overflow file exceeds this size\, a panic will be
+ * triggered. The default value means that the cache overflow file is
+ * unbounded and may use as much space as the filesystem will
+ * accommodate. The minimum non-zero setting is 100MB., an integer
+ * greater than or equal to 0; default \c 0.}
+ * @config{ ),,}
* @config{cache_overhead, assume the heap allocator overhead is the
* specified percentage\, and adjust the cache usage by that amount (for
* example\, if there is 10GB of data in cache\, a percentage of 10
@@ -2772,6 +2782,15 @@ struct __wt_connection {
* thread will wait for space to be available in cache before giving up.
* Default will wait forever., an integer greater than or equal to 0; default \c
* 0.}
+ * @config{cache_overflow = (, cache overflow configuration options., a set of
+ * related configuration options defined below.}
+ * @config{&nbsp;&nbsp;&nbsp;&nbsp;file_max, The maximum number of bytes that
+ * WiredTiger is allowed to use for its cache overflow mechanism. If the cache
+ * overflow file exceeds this size\, a panic will be triggered. The default
+ * value means that the cache overflow file is unbounded and may use as much
+ * space as the filesystem will accommodate. The minimum non-zero setting is
+ * 100MB., an integer greater than or equal to 0; default \c 0.}
+ * @config{ ),,}
* @config{cache_overhead, assume the heap allocator overhead is the specified
* percentage\, and adjust the cache usage by that amount (for example\, if
* there is 10GB of data in cache\, a percentage of 10 means WiredTiger treats
@@ -3614,10 +3633,43 @@ struct __wt_config_parser {
uint32_t (*wiredtiger_crc32c_func(void))(const void *, size_t)
WT_ATTRIBUTE_LIBRARY_VISIBLE;
-/*! @} */
#endif /* !defined(SWIG) */
/*!
+ * Calculate a set of WT_MODIFY operations to represent an update.
+ * This call will calculate a set of modifications to an old value that produce
+ * the new value. If more modifications are required than fit in the array
+ * passed in by the caller, or if more bytes have changed than the \c maxdiff
+ * parameter, the call will fail. The matching algorithm is approximate, so it
+ * may fail and return WT_NOTFOUND if a matching set of WT_MODIFY operations
+ * is not found.
+ *
+ * The \c maxdiff parameter bounds how much work will be done searching for a
+ * match: to ensure a match is found, it may need to be set larger than actual
+ * number of bytes that differ between the old and new values. In particular,
+ * repeated patterns of bytes in the values can lead to suboptimal matching,
+ * and matching ranges less than 64 bytes long will not be detected.
+ *
+ * If the call succeeds, the WT_MODIFY operations will point into \c newv,
+ * which must remain valid until WT_CURSOR::modify is called.
+ *
+ * @snippet ex_all.c Calculate a modify operation
+ *
+ * @param session the current WiredTiger session (may be NULL)
+ * @param oldv old value
+ * @param newv new value
+ * @param maxdiff maximum bytes difference
+ * @param[out] entries array of modifications producing the new value
+ * @param[in,out] nentriesp size of \c entries array passed in,
+ * set to the number of entries used
+ * @errors
+ */
+int wiredtiger_calc_modify(WT_SESSION *session,
+ const WT_ITEM *oldv, const WT_ITEM *newv,
+ size_t maxdiff, WT_MODIFY *entries, int *nentriesp)
+ WT_ATTRIBUTE_LIBRARY_VISIBLE;
+
+/*!
* Get version information.
*
* @snippet ex_all.c Get the WiredTiger library version #1
@@ -3631,6 +3683,8 @@ uint32_t (*wiredtiger_crc32c_func(void))(const void *, size_t)
const char *wiredtiger_version(int *majorp, int *minorp, int *patchp)
WT_ATTRIBUTE_LIBRARY_VISIBLE;
+/*! @} */
+
/*******************************************
* Error returns
*******************************************/
@@ -5074,703 +5128,707 @@ extern int wiredtiger_extension_terminate(WT_CONNECTION *connection);
#define WT_STAT_CONN_CACHE_LOOKASIDE_ENTRIES 1044
/*! cache: cache overflow table insert calls */
#define WT_STAT_CONN_CACHE_LOOKASIDE_INSERT 1045
+/*! cache: cache overflow table max on-disk size */
+#define WT_STAT_CONN_CACHE_LOOKASIDE_ONDISK_MAX 1046
+/*! cache: cache overflow table on-disk size */
+#define WT_STAT_CONN_CACHE_LOOKASIDE_ONDISK 1047
/*! cache: cache overflow table remove calls */
-#define WT_STAT_CONN_CACHE_LOOKASIDE_REMOVE 1046
+#define WT_STAT_CONN_CACHE_LOOKASIDE_REMOVE 1048
/*! cache: checkpoint blocked page eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_CHECKPOINT 1047
+#define WT_STAT_CONN_CACHE_EVICTION_CHECKPOINT 1049
/*! cache: eviction calls to get a page */
-#define WT_STAT_CONN_CACHE_EVICTION_GET_REF 1048
+#define WT_STAT_CONN_CACHE_EVICTION_GET_REF 1050
/*! cache: eviction calls to get a page found queue empty */
-#define WT_STAT_CONN_CACHE_EVICTION_GET_REF_EMPTY 1049
+#define WT_STAT_CONN_CACHE_EVICTION_GET_REF_EMPTY 1051
/*! cache: eviction calls to get a page found queue empty after locking */
-#define WT_STAT_CONN_CACHE_EVICTION_GET_REF_EMPTY2 1050
+#define WT_STAT_CONN_CACHE_EVICTION_GET_REF_EMPTY2 1052
/*! cache: eviction currently operating in aggressive mode */
-#define WT_STAT_CONN_CACHE_EVICTION_AGGRESSIVE_SET 1051
+#define WT_STAT_CONN_CACHE_EVICTION_AGGRESSIVE_SET 1053
/*! cache: eviction empty score */
-#define WT_STAT_CONN_CACHE_EVICTION_EMPTY_SCORE 1052
+#define WT_STAT_CONN_CACHE_EVICTION_EMPTY_SCORE 1054
/*! cache: eviction passes of a file */
-#define WT_STAT_CONN_CACHE_EVICTION_WALK_PASSES 1053
+#define WT_STAT_CONN_CACHE_EVICTION_WALK_PASSES 1055
/*! cache: eviction server candidate queue empty when topping up */
-#define WT_STAT_CONN_CACHE_EVICTION_QUEUE_EMPTY 1054
+#define WT_STAT_CONN_CACHE_EVICTION_QUEUE_EMPTY 1056
/*! cache: eviction server candidate queue not empty when topping up */
-#define WT_STAT_CONN_CACHE_EVICTION_QUEUE_NOT_EMPTY 1055
+#define WT_STAT_CONN_CACHE_EVICTION_QUEUE_NOT_EMPTY 1057
/*! cache: eviction server evicting pages */
-#define WT_STAT_CONN_CACHE_EVICTION_SERVER_EVICTING 1056
+#define WT_STAT_CONN_CACHE_EVICTION_SERVER_EVICTING 1058
/*!
* cache: eviction server slept, because we did not make progress with
* eviction
*/
-#define WT_STAT_CONN_CACHE_EVICTION_SERVER_SLEPT 1057
+#define WT_STAT_CONN_CACHE_EVICTION_SERVER_SLEPT 1059
/*! cache: eviction server unable to reach eviction goal */
-#define WT_STAT_CONN_CACHE_EVICTION_SLOW 1058
+#define WT_STAT_CONN_CACHE_EVICTION_SLOW 1060
/*! cache: eviction state */
-#define WT_STAT_CONN_CACHE_EVICTION_STATE 1059
+#define WT_STAT_CONN_CACHE_EVICTION_STATE 1061
/*! cache: eviction walk target pages histogram - 0-9 */
-#define WT_STAT_CONN_CACHE_EVICTION_TARGET_PAGE_LT10 1060
+#define WT_STAT_CONN_CACHE_EVICTION_TARGET_PAGE_LT10 1062
/*! cache: eviction walk target pages histogram - 10-31 */
-#define WT_STAT_CONN_CACHE_EVICTION_TARGET_PAGE_LT32 1061
+#define WT_STAT_CONN_CACHE_EVICTION_TARGET_PAGE_LT32 1063
/*! cache: eviction walk target pages histogram - 128 and higher */
-#define WT_STAT_CONN_CACHE_EVICTION_TARGET_PAGE_GE128 1062
+#define WT_STAT_CONN_CACHE_EVICTION_TARGET_PAGE_GE128 1064
/*! cache: eviction walk target pages histogram - 32-63 */
-#define WT_STAT_CONN_CACHE_EVICTION_TARGET_PAGE_LT64 1063
+#define WT_STAT_CONN_CACHE_EVICTION_TARGET_PAGE_LT64 1065
/*! cache: eviction walk target pages histogram - 64-128 */
-#define WT_STAT_CONN_CACHE_EVICTION_TARGET_PAGE_LT128 1064
+#define WT_STAT_CONN_CACHE_EVICTION_TARGET_PAGE_LT128 1066
/*! cache: eviction walks abandoned */
-#define WT_STAT_CONN_CACHE_EVICTION_WALKS_ABANDONED 1065
+#define WT_STAT_CONN_CACHE_EVICTION_WALKS_ABANDONED 1067
/*! cache: eviction walks gave up because they restarted their walk twice */
-#define WT_STAT_CONN_CACHE_EVICTION_WALKS_STOPPED 1066
+#define WT_STAT_CONN_CACHE_EVICTION_WALKS_STOPPED 1068
/*!
* 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 1067
+#define WT_STAT_CONN_CACHE_EVICTION_WALKS_GAVE_UP_NO_TARGETS 1069
/*!
* 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 1068
+#define WT_STAT_CONN_CACHE_EVICTION_WALKS_GAVE_UP_RATIO 1070
/*! cache: eviction walks reached end of tree */
-#define WT_STAT_CONN_CACHE_EVICTION_WALKS_ENDED 1069
+#define WT_STAT_CONN_CACHE_EVICTION_WALKS_ENDED 1071
/*! cache: eviction walks started from root of tree */
-#define WT_STAT_CONN_CACHE_EVICTION_WALK_FROM_ROOT 1070
+#define WT_STAT_CONN_CACHE_EVICTION_WALK_FROM_ROOT 1072
/*! cache: eviction walks started from saved location in tree */
-#define WT_STAT_CONN_CACHE_EVICTION_WALK_SAVED_POS 1071
+#define WT_STAT_CONN_CACHE_EVICTION_WALK_SAVED_POS 1073
/*! cache: eviction worker thread active */
-#define WT_STAT_CONN_CACHE_EVICTION_ACTIVE_WORKERS 1072
+#define WT_STAT_CONN_CACHE_EVICTION_ACTIVE_WORKERS 1074
/*! cache: eviction worker thread created */
-#define WT_STAT_CONN_CACHE_EVICTION_WORKER_CREATED 1073
+#define WT_STAT_CONN_CACHE_EVICTION_WORKER_CREATED 1075
/*! cache: eviction worker thread evicting pages */
-#define WT_STAT_CONN_CACHE_EVICTION_WORKER_EVICTING 1074
+#define WT_STAT_CONN_CACHE_EVICTION_WORKER_EVICTING 1076
/*! cache: eviction worker thread removed */
-#define WT_STAT_CONN_CACHE_EVICTION_WORKER_REMOVED 1075
+#define WT_STAT_CONN_CACHE_EVICTION_WORKER_REMOVED 1077
/*! cache: eviction worker thread stable number */
-#define WT_STAT_CONN_CACHE_EVICTION_STABLE_STATE_WORKERS 1076
+#define WT_STAT_CONN_CACHE_EVICTION_STABLE_STATE_WORKERS 1078
/*!
* cache: failed eviction of pages that exceeded the in-memory maximum
* count
*/
-#define WT_STAT_CONN_CACHE_EVICTION_FORCE_FAIL 1077
+#define WT_STAT_CONN_CACHE_EVICTION_FORCE_FAIL 1079
/*!
* cache: failed eviction of pages that exceeded the in-memory maximum
* time (usecs)
*/
-#define WT_STAT_CONN_CACHE_EVICTION_FORCE_FAIL_TIME 1078
+#define WT_STAT_CONN_CACHE_EVICTION_FORCE_FAIL_TIME 1080
/*! cache: files with active eviction walks */
-#define WT_STAT_CONN_CACHE_EVICTION_WALKS_ACTIVE 1079
+#define WT_STAT_CONN_CACHE_EVICTION_WALKS_ACTIVE 1081
/*! cache: files with new eviction walks started */
-#define WT_STAT_CONN_CACHE_EVICTION_WALKS_STARTED 1080
+#define WT_STAT_CONN_CACHE_EVICTION_WALKS_STARTED 1082
/*! cache: force re-tuning of eviction workers once in a while */
-#define WT_STAT_CONN_CACHE_EVICTION_FORCE_RETUNE 1081
+#define WT_STAT_CONN_CACHE_EVICTION_FORCE_RETUNE 1083
/*! cache: hazard pointer blocked page eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_HAZARD 1082
+#define WT_STAT_CONN_CACHE_EVICTION_HAZARD 1084
/*! cache: hazard pointer check calls */
-#define WT_STAT_CONN_CACHE_HAZARD_CHECKS 1083
+#define WT_STAT_CONN_CACHE_HAZARD_CHECKS 1085
/*! cache: hazard pointer check entries walked */
-#define WT_STAT_CONN_CACHE_HAZARD_WALKS 1084
+#define WT_STAT_CONN_CACHE_HAZARD_WALKS 1086
/*! cache: hazard pointer maximum array length */
-#define WT_STAT_CONN_CACHE_HAZARD_MAX 1085
+#define WT_STAT_CONN_CACHE_HAZARD_MAX 1087
/*! cache: in-memory page passed criteria to be split */
-#define WT_STAT_CONN_CACHE_INMEM_SPLITTABLE 1086
+#define WT_STAT_CONN_CACHE_INMEM_SPLITTABLE 1088
/*! cache: in-memory page splits */
-#define WT_STAT_CONN_CACHE_INMEM_SPLIT 1087
+#define WT_STAT_CONN_CACHE_INMEM_SPLIT 1089
/*! cache: internal pages evicted */
-#define WT_STAT_CONN_CACHE_EVICTION_INTERNAL 1088
+#define WT_STAT_CONN_CACHE_EVICTION_INTERNAL 1090
/*! cache: internal pages split during eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_SPLIT_INTERNAL 1089
+#define WT_STAT_CONN_CACHE_EVICTION_SPLIT_INTERNAL 1091
/*! cache: leaf pages split during eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_SPLIT_LEAF 1090
+#define WT_STAT_CONN_CACHE_EVICTION_SPLIT_LEAF 1092
/*! cache: maximum bytes configured */
-#define WT_STAT_CONN_CACHE_BYTES_MAX 1091
+#define WT_STAT_CONN_CACHE_BYTES_MAX 1093
/*! cache: maximum page size at eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_MAXIMUM_PAGE_SIZE 1092
+#define WT_STAT_CONN_CACHE_EVICTION_MAXIMUM_PAGE_SIZE 1094
/*! cache: modified pages evicted */
-#define WT_STAT_CONN_CACHE_EVICTION_DIRTY 1093
+#define WT_STAT_CONN_CACHE_EVICTION_DIRTY 1095
/*! cache: modified pages evicted by application threads */
-#define WT_STAT_CONN_CACHE_EVICTION_APP_DIRTY 1094
+#define WT_STAT_CONN_CACHE_EVICTION_APP_DIRTY 1096
/*! cache: operations timed out waiting for space in cache */
-#define WT_STAT_CONN_CACHE_TIMED_OUT_OPS 1095
+#define WT_STAT_CONN_CACHE_TIMED_OUT_OPS 1097
/*! cache: overflow pages read into cache */
-#define WT_STAT_CONN_CACHE_READ_OVERFLOW 1096
+#define WT_STAT_CONN_CACHE_READ_OVERFLOW 1098
/*! cache: page split during eviction deepened the tree */
-#define WT_STAT_CONN_CACHE_EVICTION_DEEPEN 1097
+#define WT_STAT_CONN_CACHE_EVICTION_DEEPEN 1099
/*! cache: page written requiring cache overflow records */
-#define WT_STAT_CONN_CACHE_WRITE_LOOKASIDE 1098
+#define WT_STAT_CONN_CACHE_WRITE_LOOKASIDE 1100
/*! cache: pages currently held in the cache */
-#define WT_STAT_CONN_CACHE_PAGES_INUSE 1099
+#define WT_STAT_CONN_CACHE_PAGES_INUSE 1101
/*! cache: pages evicted because they exceeded the in-memory maximum count */
-#define WT_STAT_CONN_CACHE_EVICTION_FORCE 1100
+#define WT_STAT_CONN_CACHE_EVICTION_FORCE 1102
/*!
* cache: pages evicted because they exceeded the in-memory maximum time
* (usecs)
*/
-#define WT_STAT_CONN_CACHE_EVICTION_FORCE_TIME 1101
+#define WT_STAT_CONN_CACHE_EVICTION_FORCE_TIME 1103
/*! cache: pages evicted because they had chains of deleted items count */
-#define WT_STAT_CONN_CACHE_EVICTION_FORCE_DELETE 1102
+#define WT_STAT_CONN_CACHE_EVICTION_FORCE_DELETE 1104
/*!
* cache: pages evicted because they had chains of deleted items time
* (usecs)
*/
-#define WT_STAT_CONN_CACHE_EVICTION_FORCE_DELETE_TIME 1103
+#define WT_STAT_CONN_CACHE_EVICTION_FORCE_DELETE_TIME 1105
/*! cache: pages evicted by application threads */
-#define WT_STAT_CONN_CACHE_EVICTION_APP 1104
+#define WT_STAT_CONN_CACHE_EVICTION_APP 1106
/*! cache: pages queued for eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_PAGES_QUEUED 1105
+#define WT_STAT_CONN_CACHE_EVICTION_PAGES_QUEUED 1107
/*! cache: pages queued for urgent eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_PAGES_QUEUED_URGENT 1106
+#define WT_STAT_CONN_CACHE_EVICTION_PAGES_QUEUED_URGENT 1108
/*! cache: pages queued for urgent eviction during walk */
-#define WT_STAT_CONN_CACHE_EVICTION_PAGES_QUEUED_OLDEST 1107
+#define WT_STAT_CONN_CACHE_EVICTION_PAGES_QUEUED_OLDEST 1109
/*! cache: pages read into cache */
-#define WT_STAT_CONN_CACHE_READ 1108
+#define WT_STAT_CONN_CACHE_READ 1110
/*! cache: pages read into cache after truncate */
-#define WT_STAT_CONN_CACHE_READ_DELETED 1109
+#define WT_STAT_CONN_CACHE_READ_DELETED 1111
/*! cache: pages read into cache after truncate in prepare state */
-#define WT_STAT_CONN_CACHE_READ_DELETED_PREPARED 1110
+#define WT_STAT_CONN_CACHE_READ_DELETED_PREPARED 1112
/*! cache: pages read into cache requiring cache overflow entries */
-#define WT_STAT_CONN_CACHE_READ_LOOKASIDE 1111
+#define WT_STAT_CONN_CACHE_READ_LOOKASIDE 1113
/*! cache: pages read into cache requiring cache overflow for checkpoint */
-#define WT_STAT_CONN_CACHE_READ_LOOKASIDE_CHECKPOINT 1112
+#define WT_STAT_CONN_CACHE_READ_LOOKASIDE_CHECKPOINT 1114
/*! cache: pages read into cache skipping older cache overflow entries */
-#define WT_STAT_CONN_CACHE_READ_LOOKASIDE_SKIPPED 1113
+#define WT_STAT_CONN_CACHE_READ_LOOKASIDE_SKIPPED 1115
/*!
* cache: pages read into cache with skipped cache overflow entries
* needed later
*/
-#define WT_STAT_CONN_CACHE_READ_LOOKASIDE_DELAY 1114
+#define WT_STAT_CONN_CACHE_READ_LOOKASIDE_DELAY 1116
/*!
* cache: pages read into cache with skipped cache overflow entries
* needed later by checkpoint
*/
-#define WT_STAT_CONN_CACHE_READ_LOOKASIDE_DELAY_CHECKPOINT 1115
+#define WT_STAT_CONN_CACHE_READ_LOOKASIDE_DELAY_CHECKPOINT 1117
/*! cache: pages requested from the cache */
-#define WT_STAT_CONN_CACHE_PAGES_REQUESTED 1116
+#define WT_STAT_CONN_CACHE_PAGES_REQUESTED 1118
/*! cache: pages seen by eviction walk */
-#define WT_STAT_CONN_CACHE_EVICTION_PAGES_SEEN 1117
+#define WT_STAT_CONN_CACHE_EVICTION_PAGES_SEEN 1119
/*! cache: pages selected for eviction unable to be evicted */
-#define WT_STAT_CONN_CACHE_EVICTION_FAIL 1118
+#define WT_STAT_CONN_CACHE_EVICTION_FAIL 1120
/*! cache: pages walked for eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_WALK 1119
+#define WT_STAT_CONN_CACHE_EVICTION_WALK 1121
/*! cache: pages written from cache */
-#define WT_STAT_CONN_CACHE_WRITE 1120
+#define WT_STAT_CONN_CACHE_WRITE 1122
/*! cache: pages written requiring in-memory restoration */
-#define WT_STAT_CONN_CACHE_WRITE_RESTORE 1121
+#define WT_STAT_CONN_CACHE_WRITE_RESTORE 1123
/*! cache: percentage overhead */
-#define WT_STAT_CONN_CACHE_OVERHEAD 1122
+#define WT_STAT_CONN_CACHE_OVERHEAD 1124
/*! cache: tracked bytes belonging to internal pages in the cache */
-#define WT_STAT_CONN_CACHE_BYTES_INTERNAL 1123
+#define WT_STAT_CONN_CACHE_BYTES_INTERNAL 1125
/*! cache: tracked bytes belonging to leaf pages in the cache */
-#define WT_STAT_CONN_CACHE_BYTES_LEAF 1124
+#define WT_STAT_CONN_CACHE_BYTES_LEAF 1126
/*! cache: tracked dirty bytes in the cache */
-#define WT_STAT_CONN_CACHE_BYTES_DIRTY 1125
+#define WT_STAT_CONN_CACHE_BYTES_DIRTY 1127
/*! cache: tracked dirty pages in the cache */
-#define WT_STAT_CONN_CACHE_PAGES_DIRTY 1126
+#define WT_STAT_CONN_CACHE_PAGES_DIRTY 1128
/*! cache: unmodified pages evicted */
-#define WT_STAT_CONN_CACHE_EVICTION_CLEAN 1127
+#define WT_STAT_CONN_CACHE_EVICTION_CLEAN 1129
/*! connection: auto adjusting condition resets */
-#define WT_STAT_CONN_COND_AUTO_WAIT_RESET 1128
+#define WT_STAT_CONN_COND_AUTO_WAIT_RESET 1130
/*! connection: auto adjusting condition wait calls */
-#define WT_STAT_CONN_COND_AUTO_WAIT 1129
+#define WT_STAT_CONN_COND_AUTO_WAIT 1131
/*! connection: detected system time went backwards */
-#define WT_STAT_CONN_TIME_TRAVEL 1130
+#define WT_STAT_CONN_TIME_TRAVEL 1132
/*! connection: files currently open */
-#define WT_STAT_CONN_FILE_OPEN 1131
+#define WT_STAT_CONN_FILE_OPEN 1133
/*! connection: memory allocations */
-#define WT_STAT_CONN_MEMORY_ALLOCATION 1132
+#define WT_STAT_CONN_MEMORY_ALLOCATION 1134
/*! connection: memory frees */
-#define WT_STAT_CONN_MEMORY_FREE 1133
+#define WT_STAT_CONN_MEMORY_FREE 1135
/*! connection: memory re-allocations */
-#define WT_STAT_CONN_MEMORY_GROW 1134
+#define WT_STAT_CONN_MEMORY_GROW 1136
/*! connection: pthread mutex condition wait calls */
-#define WT_STAT_CONN_COND_WAIT 1135
+#define WT_STAT_CONN_COND_WAIT 1137
/*! connection: pthread mutex shared lock read-lock calls */
-#define WT_STAT_CONN_RWLOCK_READ 1136
+#define WT_STAT_CONN_RWLOCK_READ 1138
/*! connection: pthread mutex shared lock write-lock calls */
-#define WT_STAT_CONN_RWLOCK_WRITE 1137
+#define WT_STAT_CONN_RWLOCK_WRITE 1139
/*! connection: total fsync I/Os */
-#define WT_STAT_CONN_FSYNC_IO 1138
+#define WT_STAT_CONN_FSYNC_IO 1140
/*! connection: total read I/Os */
-#define WT_STAT_CONN_READ_IO 1139
+#define WT_STAT_CONN_READ_IO 1141
/*! connection: total write I/Os */
-#define WT_STAT_CONN_WRITE_IO 1140
+#define WT_STAT_CONN_WRITE_IO 1142
/*! cursor: cached cursor count */
-#define WT_STAT_CONN_CURSOR_CACHED_COUNT 1141
+#define WT_STAT_CONN_CURSOR_CACHED_COUNT 1143
/*! cursor: cursor close calls that result in cache */
-#define WT_STAT_CONN_CURSOR_CACHE 1142
+#define WT_STAT_CONN_CURSOR_CACHE 1144
/*! cursor: cursor create calls */
-#define WT_STAT_CONN_CURSOR_CREATE 1143
+#define WT_STAT_CONN_CURSOR_CREATE 1145
/*! cursor: cursor insert calls */
-#define WT_STAT_CONN_CURSOR_INSERT 1144
+#define WT_STAT_CONN_CURSOR_INSERT 1146
/*! cursor: cursor modify calls */
-#define WT_STAT_CONN_CURSOR_MODIFY 1145
+#define WT_STAT_CONN_CURSOR_MODIFY 1147
/*! cursor: cursor next calls */
-#define WT_STAT_CONN_CURSOR_NEXT 1146
+#define WT_STAT_CONN_CURSOR_NEXT 1148
/*! cursor: cursor operation restarted */
-#define WT_STAT_CONN_CURSOR_RESTART 1147
+#define WT_STAT_CONN_CURSOR_RESTART 1149
/*! cursor: cursor prev calls */
-#define WT_STAT_CONN_CURSOR_PREV 1148
+#define WT_STAT_CONN_CURSOR_PREV 1150
/*! cursor: cursor remove calls */
-#define WT_STAT_CONN_CURSOR_REMOVE 1149
+#define WT_STAT_CONN_CURSOR_REMOVE 1151
/*! cursor: cursor reserve calls */
-#define WT_STAT_CONN_CURSOR_RESERVE 1150
+#define WT_STAT_CONN_CURSOR_RESERVE 1152
/*! cursor: cursor reset calls */
-#define WT_STAT_CONN_CURSOR_RESET 1151
+#define WT_STAT_CONN_CURSOR_RESET 1153
/*! cursor: cursor search calls */
-#define WT_STAT_CONN_CURSOR_SEARCH 1152
+#define WT_STAT_CONN_CURSOR_SEARCH 1154
/*! cursor: cursor search near calls */
-#define WT_STAT_CONN_CURSOR_SEARCH_NEAR 1153
+#define WT_STAT_CONN_CURSOR_SEARCH_NEAR 1155
/*! cursor: cursor sweep buckets */
-#define WT_STAT_CONN_CURSOR_SWEEP_BUCKETS 1154
+#define WT_STAT_CONN_CURSOR_SWEEP_BUCKETS 1156
/*! cursor: cursor sweep cursors closed */
-#define WT_STAT_CONN_CURSOR_SWEEP_CLOSED 1155
+#define WT_STAT_CONN_CURSOR_SWEEP_CLOSED 1157
/*! cursor: cursor sweep cursors examined */
-#define WT_STAT_CONN_CURSOR_SWEEP_EXAMINED 1156
+#define WT_STAT_CONN_CURSOR_SWEEP_EXAMINED 1158
/*! cursor: cursor sweeps */
-#define WT_STAT_CONN_CURSOR_SWEEP 1157
+#define WT_STAT_CONN_CURSOR_SWEEP 1159
/*! cursor: cursor update calls */
-#define WT_STAT_CONN_CURSOR_UPDATE 1158
+#define WT_STAT_CONN_CURSOR_UPDATE 1160
/*! cursor: cursors reused from cache */
-#define WT_STAT_CONN_CURSOR_REOPEN 1159
+#define WT_STAT_CONN_CURSOR_REOPEN 1161
/*! cursor: open cursor count */
-#define WT_STAT_CONN_CURSOR_OPEN_COUNT 1160
+#define WT_STAT_CONN_CURSOR_OPEN_COUNT 1162
/*! cursor: truncate calls */
-#define WT_STAT_CONN_CURSOR_TRUNCATE 1161
+#define WT_STAT_CONN_CURSOR_TRUNCATE 1163
/*! data-handle: connection data handles currently active */
-#define WT_STAT_CONN_DH_CONN_HANDLE_COUNT 1162
+#define WT_STAT_CONN_DH_CONN_HANDLE_COUNT 1164
/*! data-handle: connection sweep candidate became referenced */
-#define WT_STAT_CONN_DH_SWEEP_REF 1163
+#define WT_STAT_CONN_DH_SWEEP_REF 1165
/*! data-handle: connection sweep dhandles closed */
-#define WT_STAT_CONN_DH_SWEEP_CLOSE 1164
+#define WT_STAT_CONN_DH_SWEEP_CLOSE 1166
/*! data-handle: connection sweep dhandles removed from hash list */
-#define WT_STAT_CONN_DH_SWEEP_REMOVE 1165
+#define WT_STAT_CONN_DH_SWEEP_REMOVE 1167
/*! data-handle: connection sweep time-of-death sets */
-#define WT_STAT_CONN_DH_SWEEP_TOD 1166
+#define WT_STAT_CONN_DH_SWEEP_TOD 1168
/*! data-handle: connection sweeps */
-#define WT_STAT_CONN_DH_SWEEPS 1167
+#define WT_STAT_CONN_DH_SWEEPS 1169
/*! data-handle: session dhandles swept */
-#define WT_STAT_CONN_DH_SESSION_HANDLES 1168
+#define WT_STAT_CONN_DH_SESSION_HANDLES 1170
/*! data-handle: session sweep attempts */
-#define WT_STAT_CONN_DH_SESSION_SWEEPS 1169
+#define WT_STAT_CONN_DH_SESSION_SWEEPS 1171
/*! lock: checkpoint lock acquisitions */
-#define WT_STAT_CONN_LOCK_CHECKPOINT_COUNT 1170
+#define WT_STAT_CONN_LOCK_CHECKPOINT_COUNT 1172
/*! lock: checkpoint lock application thread wait time (usecs) */
-#define WT_STAT_CONN_LOCK_CHECKPOINT_WAIT_APPLICATION 1171
+#define WT_STAT_CONN_LOCK_CHECKPOINT_WAIT_APPLICATION 1173
/*! lock: checkpoint lock internal thread wait time (usecs) */
-#define WT_STAT_CONN_LOCK_CHECKPOINT_WAIT_INTERNAL 1172
+#define WT_STAT_CONN_LOCK_CHECKPOINT_WAIT_INTERNAL 1174
/*!
* lock: commit timestamp queue lock application thread time waiting
* (usecs)
*/
-#define WT_STAT_CONN_LOCK_COMMIT_TIMESTAMP_WAIT_APPLICATION 1173
+#define WT_STAT_CONN_LOCK_COMMIT_TIMESTAMP_WAIT_APPLICATION 1175
/*! lock: commit timestamp queue lock internal thread time waiting (usecs) */
-#define WT_STAT_CONN_LOCK_COMMIT_TIMESTAMP_WAIT_INTERNAL 1174
+#define WT_STAT_CONN_LOCK_COMMIT_TIMESTAMP_WAIT_INTERNAL 1176
/*! lock: commit timestamp queue read lock acquisitions */
-#define WT_STAT_CONN_LOCK_COMMIT_TIMESTAMP_READ_COUNT 1175
+#define WT_STAT_CONN_LOCK_COMMIT_TIMESTAMP_READ_COUNT 1177
/*! lock: commit timestamp queue write lock acquisitions */
-#define WT_STAT_CONN_LOCK_COMMIT_TIMESTAMP_WRITE_COUNT 1176
+#define WT_STAT_CONN_LOCK_COMMIT_TIMESTAMP_WRITE_COUNT 1178
/*! lock: dhandle lock application thread time waiting (usecs) */
-#define WT_STAT_CONN_LOCK_DHANDLE_WAIT_APPLICATION 1177
+#define WT_STAT_CONN_LOCK_DHANDLE_WAIT_APPLICATION 1179
/*! lock: dhandle lock internal thread time waiting (usecs) */
-#define WT_STAT_CONN_LOCK_DHANDLE_WAIT_INTERNAL 1178
+#define WT_STAT_CONN_LOCK_DHANDLE_WAIT_INTERNAL 1180
/*! lock: dhandle read lock acquisitions */
-#define WT_STAT_CONN_LOCK_DHANDLE_READ_COUNT 1179
+#define WT_STAT_CONN_LOCK_DHANDLE_READ_COUNT 1181
/*! lock: dhandle write lock acquisitions */
-#define WT_STAT_CONN_LOCK_DHANDLE_WRITE_COUNT 1180
+#define WT_STAT_CONN_LOCK_DHANDLE_WRITE_COUNT 1182
/*! lock: metadata lock acquisitions */
-#define WT_STAT_CONN_LOCK_METADATA_COUNT 1181
+#define WT_STAT_CONN_LOCK_METADATA_COUNT 1183
/*! lock: metadata lock application thread wait time (usecs) */
-#define WT_STAT_CONN_LOCK_METADATA_WAIT_APPLICATION 1182
+#define WT_STAT_CONN_LOCK_METADATA_WAIT_APPLICATION 1184
/*! lock: metadata lock internal thread wait time (usecs) */
-#define WT_STAT_CONN_LOCK_METADATA_WAIT_INTERNAL 1183
+#define WT_STAT_CONN_LOCK_METADATA_WAIT_INTERNAL 1185
/*!
* lock: read timestamp queue lock application thread time waiting
* (usecs)
*/
-#define WT_STAT_CONN_LOCK_READ_TIMESTAMP_WAIT_APPLICATION 1184
+#define WT_STAT_CONN_LOCK_READ_TIMESTAMP_WAIT_APPLICATION 1186
/*! lock: read timestamp queue lock internal thread time waiting (usecs) */
-#define WT_STAT_CONN_LOCK_READ_TIMESTAMP_WAIT_INTERNAL 1185
+#define WT_STAT_CONN_LOCK_READ_TIMESTAMP_WAIT_INTERNAL 1187
/*! lock: read timestamp queue read lock acquisitions */
-#define WT_STAT_CONN_LOCK_READ_TIMESTAMP_READ_COUNT 1186
+#define WT_STAT_CONN_LOCK_READ_TIMESTAMP_READ_COUNT 1188
/*! lock: read timestamp queue write lock acquisitions */
-#define WT_STAT_CONN_LOCK_READ_TIMESTAMP_WRITE_COUNT 1187
+#define WT_STAT_CONN_LOCK_READ_TIMESTAMP_WRITE_COUNT 1189
/*! lock: schema lock acquisitions */
-#define WT_STAT_CONN_LOCK_SCHEMA_COUNT 1188
+#define WT_STAT_CONN_LOCK_SCHEMA_COUNT 1190
/*! lock: schema lock application thread wait time (usecs) */
-#define WT_STAT_CONN_LOCK_SCHEMA_WAIT_APPLICATION 1189
+#define WT_STAT_CONN_LOCK_SCHEMA_WAIT_APPLICATION 1191
/*! lock: schema lock internal thread wait time (usecs) */
-#define WT_STAT_CONN_LOCK_SCHEMA_WAIT_INTERNAL 1190
+#define WT_STAT_CONN_LOCK_SCHEMA_WAIT_INTERNAL 1192
/*!
* lock: table lock application thread time waiting for the table lock
* (usecs)
*/
-#define WT_STAT_CONN_LOCK_TABLE_WAIT_APPLICATION 1191
+#define WT_STAT_CONN_LOCK_TABLE_WAIT_APPLICATION 1193
/*!
* lock: table lock internal thread time waiting for the table lock
* (usecs)
*/
-#define WT_STAT_CONN_LOCK_TABLE_WAIT_INTERNAL 1192
+#define WT_STAT_CONN_LOCK_TABLE_WAIT_INTERNAL 1194
/*! lock: table read lock acquisitions */
-#define WT_STAT_CONN_LOCK_TABLE_READ_COUNT 1193
+#define WT_STAT_CONN_LOCK_TABLE_READ_COUNT 1195
/*! lock: table write lock acquisitions */
-#define WT_STAT_CONN_LOCK_TABLE_WRITE_COUNT 1194
+#define WT_STAT_CONN_LOCK_TABLE_WRITE_COUNT 1196
/*! lock: txn global lock application thread time waiting (usecs) */
-#define WT_STAT_CONN_LOCK_TXN_GLOBAL_WAIT_APPLICATION 1195
+#define WT_STAT_CONN_LOCK_TXN_GLOBAL_WAIT_APPLICATION 1197
/*! lock: txn global lock internal thread time waiting (usecs) */
-#define WT_STAT_CONN_LOCK_TXN_GLOBAL_WAIT_INTERNAL 1196
+#define WT_STAT_CONN_LOCK_TXN_GLOBAL_WAIT_INTERNAL 1198
/*! lock: txn global read lock acquisitions */
-#define WT_STAT_CONN_LOCK_TXN_GLOBAL_READ_COUNT 1197
+#define WT_STAT_CONN_LOCK_TXN_GLOBAL_READ_COUNT 1199
/*! lock: txn global write lock acquisitions */
-#define WT_STAT_CONN_LOCK_TXN_GLOBAL_WRITE_COUNT 1198
+#define WT_STAT_CONN_LOCK_TXN_GLOBAL_WRITE_COUNT 1200
/*! log: busy returns attempting to switch slots */
-#define WT_STAT_CONN_LOG_SLOT_SWITCH_BUSY 1199
+#define WT_STAT_CONN_LOG_SLOT_SWITCH_BUSY 1201
/*! log: force archive time sleeping (usecs) */
-#define WT_STAT_CONN_LOG_FORCE_ARCHIVE_SLEEP 1200
+#define WT_STAT_CONN_LOG_FORCE_ARCHIVE_SLEEP 1202
/*! log: log bytes of payload data */
-#define WT_STAT_CONN_LOG_BYTES_PAYLOAD 1201
+#define WT_STAT_CONN_LOG_BYTES_PAYLOAD 1203
/*! log: log bytes written */
-#define WT_STAT_CONN_LOG_BYTES_WRITTEN 1202
+#define WT_STAT_CONN_LOG_BYTES_WRITTEN 1204
/*! log: log files manually zero-filled */
-#define WT_STAT_CONN_LOG_ZERO_FILLS 1203
+#define WT_STAT_CONN_LOG_ZERO_FILLS 1205
/*! log: log flush operations */
-#define WT_STAT_CONN_LOG_FLUSH 1204
+#define WT_STAT_CONN_LOG_FLUSH 1206
/*! log: log force write operations */
-#define WT_STAT_CONN_LOG_FORCE_WRITE 1205
+#define WT_STAT_CONN_LOG_FORCE_WRITE 1207
/*! log: log force write operations skipped */
-#define WT_STAT_CONN_LOG_FORCE_WRITE_SKIP 1206
+#define WT_STAT_CONN_LOG_FORCE_WRITE_SKIP 1208
/*! log: log records compressed */
-#define WT_STAT_CONN_LOG_COMPRESS_WRITES 1207
+#define WT_STAT_CONN_LOG_COMPRESS_WRITES 1209
/*! log: log records not compressed */
-#define WT_STAT_CONN_LOG_COMPRESS_WRITE_FAILS 1208
+#define WT_STAT_CONN_LOG_COMPRESS_WRITE_FAILS 1210
/*! log: log records too small to compress */
-#define WT_STAT_CONN_LOG_COMPRESS_SMALL 1209
+#define WT_STAT_CONN_LOG_COMPRESS_SMALL 1211
/*! log: log release advances write LSN */
-#define WT_STAT_CONN_LOG_RELEASE_WRITE_LSN 1210
+#define WT_STAT_CONN_LOG_RELEASE_WRITE_LSN 1212
/*! log: log scan operations */
-#define WT_STAT_CONN_LOG_SCANS 1211
+#define WT_STAT_CONN_LOG_SCANS 1213
/*! log: log scan records requiring two reads */
-#define WT_STAT_CONN_LOG_SCAN_REREADS 1212
+#define WT_STAT_CONN_LOG_SCAN_REREADS 1214
/*! log: log server thread advances write LSN */
-#define WT_STAT_CONN_LOG_WRITE_LSN 1213
+#define WT_STAT_CONN_LOG_WRITE_LSN 1215
/*! log: log server thread write LSN walk skipped */
-#define WT_STAT_CONN_LOG_WRITE_LSN_SKIP 1214
+#define WT_STAT_CONN_LOG_WRITE_LSN_SKIP 1216
/*! log: log sync operations */
-#define WT_STAT_CONN_LOG_SYNC 1215
+#define WT_STAT_CONN_LOG_SYNC 1217
/*! log: log sync time duration (usecs) */
-#define WT_STAT_CONN_LOG_SYNC_DURATION 1216
+#define WT_STAT_CONN_LOG_SYNC_DURATION 1218
/*! log: log sync_dir operations */
-#define WT_STAT_CONN_LOG_SYNC_DIR 1217
+#define WT_STAT_CONN_LOG_SYNC_DIR 1219
/*! log: log sync_dir time duration (usecs) */
-#define WT_STAT_CONN_LOG_SYNC_DIR_DURATION 1218
+#define WT_STAT_CONN_LOG_SYNC_DIR_DURATION 1220
/*! log: log write operations */
-#define WT_STAT_CONN_LOG_WRITES 1219
+#define WT_STAT_CONN_LOG_WRITES 1221
/*! log: logging bytes consolidated */
-#define WT_STAT_CONN_LOG_SLOT_CONSOLIDATED 1220
+#define WT_STAT_CONN_LOG_SLOT_CONSOLIDATED 1222
/*! log: maximum log file size */
-#define WT_STAT_CONN_LOG_MAX_FILESIZE 1221
+#define WT_STAT_CONN_LOG_MAX_FILESIZE 1223
/*! log: number of pre-allocated log files to create */
-#define WT_STAT_CONN_LOG_PREALLOC_MAX 1222
+#define WT_STAT_CONN_LOG_PREALLOC_MAX 1224
/*! log: pre-allocated log files not ready and missed */
-#define WT_STAT_CONN_LOG_PREALLOC_MISSED 1223
+#define WT_STAT_CONN_LOG_PREALLOC_MISSED 1225
/*! log: pre-allocated log files prepared */
-#define WT_STAT_CONN_LOG_PREALLOC_FILES 1224
+#define WT_STAT_CONN_LOG_PREALLOC_FILES 1226
/*! log: pre-allocated log files used */
-#define WT_STAT_CONN_LOG_PREALLOC_USED 1225
+#define WT_STAT_CONN_LOG_PREALLOC_USED 1227
/*! log: records processed by log scan */
-#define WT_STAT_CONN_LOG_SCAN_RECORDS 1226
+#define WT_STAT_CONN_LOG_SCAN_RECORDS 1228
/*! log: slot close lost race */
-#define WT_STAT_CONN_LOG_SLOT_CLOSE_RACE 1227
+#define WT_STAT_CONN_LOG_SLOT_CLOSE_RACE 1229
/*! log: slot close unbuffered waits */
-#define WT_STAT_CONN_LOG_SLOT_CLOSE_UNBUF 1228
+#define WT_STAT_CONN_LOG_SLOT_CLOSE_UNBUF 1230
/*! log: slot closures */
-#define WT_STAT_CONN_LOG_SLOT_CLOSES 1229
+#define WT_STAT_CONN_LOG_SLOT_CLOSES 1231
/*! log: slot join atomic update races */
-#define WT_STAT_CONN_LOG_SLOT_RACES 1230
+#define WT_STAT_CONN_LOG_SLOT_RACES 1232
/*! log: slot join calls atomic updates raced */
-#define WT_STAT_CONN_LOG_SLOT_YIELD_RACE 1231
+#define WT_STAT_CONN_LOG_SLOT_YIELD_RACE 1233
/*! log: slot join calls did not yield */
-#define WT_STAT_CONN_LOG_SLOT_IMMEDIATE 1232
+#define WT_STAT_CONN_LOG_SLOT_IMMEDIATE 1234
/*! log: slot join calls found active slot closed */
-#define WT_STAT_CONN_LOG_SLOT_YIELD_CLOSE 1233
+#define WT_STAT_CONN_LOG_SLOT_YIELD_CLOSE 1235
/*! log: slot join calls slept */
-#define WT_STAT_CONN_LOG_SLOT_YIELD_SLEEP 1234
+#define WT_STAT_CONN_LOG_SLOT_YIELD_SLEEP 1236
/*! log: slot join calls yielded */
-#define WT_STAT_CONN_LOG_SLOT_YIELD 1235
+#define WT_STAT_CONN_LOG_SLOT_YIELD 1237
/*! log: slot join found active slot closed */
-#define WT_STAT_CONN_LOG_SLOT_ACTIVE_CLOSED 1236
+#define WT_STAT_CONN_LOG_SLOT_ACTIVE_CLOSED 1238
/*! log: slot joins yield time (usecs) */
-#define WT_STAT_CONN_LOG_SLOT_YIELD_DURATION 1237
+#define WT_STAT_CONN_LOG_SLOT_YIELD_DURATION 1239
/*! log: slot transitions unable to find free slot */
-#define WT_STAT_CONN_LOG_SLOT_NO_FREE_SLOTS 1238
+#define WT_STAT_CONN_LOG_SLOT_NO_FREE_SLOTS 1240
/*! log: slot unbuffered writes */
-#define WT_STAT_CONN_LOG_SLOT_UNBUFFERED 1239
+#define WT_STAT_CONN_LOG_SLOT_UNBUFFERED 1241
/*! log: total in-memory size of compressed records */
-#define WT_STAT_CONN_LOG_COMPRESS_MEM 1240
+#define WT_STAT_CONN_LOG_COMPRESS_MEM 1242
/*! log: total log buffer size */
-#define WT_STAT_CONN_LOG_BUFFER_SIZE 1241
+#define WT_STAT_CONN_LOG_BUFFER_SIZE 1243
/*! log: total size of compressed records */
-#define WT_STAT_CONN_LOG_COMPRESS_LEN 1242
+#define WT_STAT_CONN_LOG_COMPRESS_LEN 1244
/*! log: written slots coalesced */
-#define WT_STAT_CONN_LOG_SLOT_COALESCED 1243
+#define WT_STAT_CONN_LOG_SLOT_COALESCED 1245
/*! log: yields waiting for previous log file close */
-#define WT_STAT_CONN_LOG_CLOSE_YIELDS 1244
+#define WT_STAT_CONN_LOG_CLOSE_YIELDS 1246
/*! perf: file system read latency histogram (bucket 1) - 10-49ms */
-#define WT_STAT_CONN_PERF_HIST_FSREAD_LATENCY_LT50 1245
+#define WT_STAT_CONN_PERF_HIST_FSREAD_LATENCY_LT50 1247
/*! perf: file system read latency histogram (bucket 2) - 50-99ms */
-#define WT_STAT_CONN_PERF_HIST_FSREAD_LATENCY_LT100 1246
+#define WT_STAT_CONN_PERF_HIST_FSREAD_LATENCY_LT100 1248
/*! perf: file system read latency histogram (bucket 3) - 100-249ms */
-#define WT_STAT_CONN_PERF_HIST_FSREAD_LATENCY_LT250 1247
+#define WT_STAT_CONN_PERF_HIST_FSREAD_LATENCY_LT250 1249
/*! perf: file system read latency histogram (bucket 4) - 250-499ms */
-#define WT_STAT_CONN_PERF_HIST_FSREAD_LATENCY_LT500 1248
+#define WT_STAT_CONN_PERF_HIST_FSREAD_LATENCY_LT500 1250
/*! perf: file system read latency histogram (bucket 5) - 500-999ms */
-#define WT_STAT_CONN_PERF_HIST_FSREAD_LATENCY_LT1000 1249
+#define WT_STAT_CONN_PERF_HIST_FSREAD_LATENCY_LT1000 1251
/*! perf: file system read latency histogram (bucket 6) - 1000ms+ */
-#define WT_STAT_CONN_PERF_HIST_FSREAD_LATENCY_GT1000 1250
+#define WT_STAT_CONN_PERF_HIST_FSREAD_LATENCY_GT1000 1252
/*! perf: file system write latency histogram (bucket 1) - 10-49ms */
-#define WT_STAT_CONN_PERF_HIST_FSWRITE_LATENCY_LT50 1251
+#define WT_STAT_CONN_PERF_HIST_FSWRITE_LATENCY_LT50 1253
/*! perf: file system write latency histogram (bucket 2) - 50-99ms */
-#define WT_STAT_CONN_PERF_HIST_FSWRITE_LATENCY_LT100 1252
+#define WT_STAT_CONN_PERF_HIST_FSWRITE_LATENCY_LT100 1254
/*! perf: file system write latency histogram (bucket 3) - 100-249ms */
-#define WT_STAT_CONN_PERF_HIST_FSWRITE_LATENCY_LT250 1253
+#define WT_STAT_CONN_PERF_HIST_FSWRITE_LATENCY_LT250 1255
/*! perf: file system write latency histogram (bucket 4) - 250-499ms */
-#define WT_STAT_CONN_PERF_HIST_FSWRITE_LATENCY_LT500 1254
+#define WT_STAT_CONN_PERF_HIST_FSWRITE_LATENCY_LT500 1256
/*! perf: file system write latency histogram (bucket 5) - 500-999ms */
-#define WT_STAT_CONN_PERF_HIST_FSWRITE_LATENCY_LT1000 1255
+#define WT_STAT_CONN_PERF_HIST_FSWRITE_LATENCY_LT1000 1257
/*! perf: file system write latency histogram (bucket 6) - 1000ms+ */
-#define WT_STAT_CONN_PERF_HIST_FSWRITE_LATENCY_GT1000 1256
+#define WT_STAT_CONN_PERF_HIST_FSWRITE_LATENCY_GT1000 1258
/*! perf: operation read latency histogram (bucket 1) - 100-249us */
-#define WT_STAT_CONN_PERF_HIST_OPREAD_LATENCY_LT250 1257
+#define WT_STAT_CONN_PERF_HIST_OPREAD_LATENCY_LT250 1259
/*! perf: operation read latency histogram (bucket 2) - 250-499us */
-#define WT_STAT_CONN_PERF_HIST_OPREAD_LATENCY_LT500 1258
+#define WT_STAT_CONN_PERF_HIST_OPREAD_LATENCY_LT500 1260
/*! perf: operation read latency histogram (bucket 3) - 500-999us */
-#define WT_STAT_CONN_PERF_HIST_OPREAD_LATENCY_LT1000 1259
+#define WT_STAT_CONN_PERF_HIST_OPREAD_LATENCY_LT1000 1261
/*! perf: operation read latency histogram (bucket 4) - 1000-9999us */
-#define WT_STAT_CONN_PERF_HIST_OPREAD_LATENCY_LT10000 1260
+#define WT_STAT_CONN_PERF_HIST_OPREAD_LATENCY_LT10000 1262
/*! perf: operation read latency histogram (bucket 5) - 10000us+ */
-#define WT_STAT_CONN_PERF_HIST_OPREAD_LATENCY_GT10000 1261
+#define WT_STAT_CONN_PERF_HIST_OPREAD_LATENCY_GT10000 1263
/*! perf: operation write latency histogram (bucket 1) - 100-249us */
-#define WT_STAT_CONN_PERF_HIST_OPWRITE_LATENCY_LT250 1262
+#define WT_STAT_CONN_PERF_HIST_OPWRITE_LATENCY_LT250 1264
/*! perf: operation write latency histogram (bucket 2) - 250-499us */
-#define WT_STAT_CONN_PERF_HIST_OPWRITE_LATENCY_LT500 1263
+#define WT_STAT_CONN_PERF_HIST_OPWRITE_LATENCY_LT500 1265
/*! perf: operation write latency histogram (bucket 3) - 500-999us */
-#define WT_STAT_CONN_PERF_HIST_OPWRITE_LATENCY_LT1000 1264
+#define WT_STAT_CONN_PERF_HIST_OPWRITE_LATENCY_LT1000 1266
/*! perf: operation write latency histogram (bucket 4) - 1000-9999us */
-#define WT_STAT_CONN_PERF_HIST_OPWRITE_LATENCY_LT10000 1265
+#define WT_STAT_CONN_PERF_HIST_OPWRITE_LATENCY_LT10000 1267
/*! perf: operation write latency histogram (bucket 5) - 10000us+ */
-#define WT_STAT_CONN_PERF_HIST_OPWRITE_LATENCY_GT10000 1266
+#define WT_STAT_CONN_PERF_HIST_OPWRITE_LATENCY_GT10000 1268
/*! reconciliation: fast-path pages deleted */
-#define WT_STAT_CONN_REC_PAGE_DELETE_FAST 1267
+#define WT_STAT_CONN_REC_PAGE_DELETE_FAST 1269
/*! reconciliation: page reconciliation calls */
-#define WT_STAT_CONN_REC_PAGES 1268
+#define WT_STAT_CONN_REC_PAGES 1270
/*! reconciliation: page reconciliation calls for eviction */
-#define WT_STAT_CONN_REC_PAGES_EVICTION 1269
+#define WT_STAT_CONN_REC_PAGES_EVICTION 1271
/*! reconciliation: pages deleted */
-#define WT_STAT_CONN_REC_PAGE_DELETE 1270
+#define WT_STAT_CONN_REC_PAGE_DELETE 1272
/*! reconciliation: split bytes currently awaiting free */
-#define WT_STAT_CONN_REC_SPLIT_STASHED_BYTES 1271
+#define WT_STAT_CONN_REC_SPLIT_STASHED_BYTES 1273
/*! reconciliation: split objects currently awaiting free */
-#define WT_STAT_CONN_REC_SPLIT_STASHED_OBJECTS 1272
+#define WT_STAT_CONN_REC_SPLIT_STASHED_OBJECTS 1274
/*! session: open session count */
-#define WT_STAT_CONN_SESSION_OPEN 1273
+#define WT_STAT_CONN_SESSION_OPEN 1275
/*! session: session query timestamp calls */
-#define WT_STAT_CONN_SESSION_QUERY_TS 1274
+#define WT_STAT_CONN_SESSION_QUERY_TS 1276
/*! session: table alter failed calls */
-#define WT_STAT_CONN_SESSION_TABLE_ALTER_FAIL 1275
+#define WT_STAT_CONN_SESSION_TABLE_ALTER_FAIL 1277
/*! session: table alter successful calls */
-#define WT_STAT_CONN_SESSION_TABLE_ALTER_SUCCESS 1276
+#define WT_STAT_CONN_SESSION_TABLE_ALTER_SUCCESS 1278
/*! session: table alter unchanged and skipped */
-#define WT_STAT_CONN_SESSION_TABLE_ALTER_SKIP 1277
+#define WT_STAT_CONN_SESSION_TABLE_ALTER_SKIP 1279
/*! session: table compact failed calls */
-#define WT_STAT_CONN_SESSION_TABLE_COMPACT_FAIL 1278
+#define WT_STAT_CONN_SESSION_TABLE_COMPACT_FAIL 1280
/*! session: table compact successful calls */
-#define WT_STAT_CONN_SESSION_TABLE_COMPACT_SUCCESS 1279
+#define WT_STAT_CONN_SESSION_TABLE_COMPACT_SUCCESS 1281
/*! session: table create failed calls */
-#define WT_STAT_CONN_SESSION_TABLE_CREATE_FAIL 1280
+#define WT_STAT_CONN_SESSION_TABLE_CREATE_FAIL 1282
/*! session: table create successful calls */
-#define WT_STAT_CONN_SESSION_TABLE_CREATE_SUCCESS 1281
+#define WT_STAT_CONN_SESSION_TABLE_CREATE_SUCCESS 1283
/*! session: table drop failed calls */
-#define WT_STAT_CONN_SESSION_TABLE_DROP_FAIL 1282
+#define WT_STAT_CONN_SESSION_TABLE_DROP_FAIL 1284
/*! session: table drop successful calls */
-#define WT_STAT_CONN_SESSION_TABLE_DROP_SUCCESS 1283
+#define WT_STAT_CONN_SESSION_TABLE_DROP_SUCCESS 1285
/*! session: table rebalance failed calls */
-#define WT_STAT_CONN_SESSION_TABLE_REBALANCE_FAIL 1284
+#define WT_STAT_CONN_SESSION_TABLE_REBALANCE_FAIL 1286
/*! session: table rebalance successful calls */
-#define WT_STAT_CONN_SESSION_TABLE_REBALANCE_SUCCESS 1285
+#define WT_STAT_CONN_SESSION_TABLE_REBALANCE_SUCCESS 1287
/*! session: table rename failed calls */
-#define WT_STAT_CONN_SESSION_TABLE_RENAME_FAIL 1286
+#define WT_STAT_CONN_SESSION_TABLE_RENAME_FAIL 1288
/*! session: table rename successful calls */
-#define WT_STAT_CONN_SESSION_TABLE_RENAME_SUCCESS 1287
+#define WT_STAT_CONN_SESSION_TABLE_RENAME_SUCCESS 1289
/*! session: table salvage failed calls */
-#define WT_STAT_CONN_SESSION_TABLE_SALVAGE_FAIL 1288
+#define WT_STAT_CONN_SESSION_TABLE_SALVAGE_FAIL 1290
/*! session: table salvage successful calls */
-#define WT_STAT_CONN_SESSION_TABLE_SALVAGE_SUCCESS 1289
+#define WT_STAT_CONN_SESSION_TABLE_SALVAGE_SUCCESS 1291
/*! session: table truncate failed calls */
-#define WT_STAT_CONN_SESSION_TABLE_TRUNCATE_FAIL 1290
+#define WT_STAT_CONN_SESSION_TABLE_TRUNCATE_FAIL 1292
/*! session: table truncate successful calls */
-#define WT_STAT_CONN_SESSION_TABLE_TRUNCATE_SUCCESS 1291
+#define WT_STAT_CONN_SESSION_TABLE_TRUNCATE_SUCCESS 1293
/*! session: table verify failed calls */
-#define WT_STAT_CONN_SESSION_TABLE_VERIFY_FAIL 1292
+#define WT_STAT_CONN_SESSION_TABLE_VERIFY_FAIL 1294
/*! session: table verify successful calls */
-#define WT_STAT_CONN_SESSION_TABLE_VERIFY_SUCCESS 1293
+#define WT_STAT_CONN_SESSION_TABLE_VERIFY_SUCCESS 1295
/*! thread-state: active filesystem fsync calls */
-#define WT_STAT_CONN_THREAD_FSYNC_ACTIVE 1294
+#define WT_STAT_CONN_THREAD_FSYNC_ACTIVE 1296
/*! thread-state: active filesystem read calls */
-#define WT_STAT_CONN_THREAD_READ_ACTIVE 1295
+#define WT_STAT_CONN_THREAD_READ_ACTIVE 1297
/*! thread-state: active filesystem write calls */
-#define WT_STAT_CONN_THREAD_WRITE_ACTIVE 1296
+#define WT_STAT_CONN_THREAD_WRITE_ACTIVE 1298
/*! thread-yield: application thread time evicting (usecs) */
-#define WT_STAT_CONN_APPLICATION_EVICT_TIME 1297
+#define WT_STAT_CONN_APPLICATION_EVICT_TIME 1299
/*! thread-yield: application thread time waiting for cache (usecs) */
-#define WT_STAT_CONN_APPLICATION_CACHE_TIME 1298
+#define WT_STAT_CONN_APPLICATION_CACHE_TIME 1300
/*!
* thread-yield: connection close blocked waiting for transaction state
* stabilization
*/
-#define WT_STAT_CONN_TXN_RELEASE_BLOCKED 1299
+#define WT_STAT_CONN_TXN_RELEASE_BLOCKED 1301
/*! thread-yield: connection close yielded for lsm manager shutdown */
-#define WT_STAT_CONN_CONN_CLOSE_BLOCKED_LSM 1300
+#define WT_STAT_CONN_CONN_CLOSE_BLOCKED_LSM 1302
/*! thread-yield: data handle lock yielded */
-#define WT_STAT_CONN_DHANDLE_LOCK_BLOCKED 1301
+#define WT_STAT_CONN_DHANDLE_LOCK_BLOCKED 1303
/*!
* thread-yield: get reference for page index and slot time sleeping
* (usecs)
*/
-#define WT_STAT_CONN_PAGE_INDEX_SLOT_REF_BLOCKED 1302
+#define WT_STAT_CONN_PAGE_INDEX_SLOT_REF_BLOCKED 1304
/*! thread-yield: log server sync yielded for log write */
-#define WT_STAT_CONN_LOG_SERVER_SYNC_BLOCKED 1303
+#define WT_STAT_CONN_LOG_SERVER_SYNC_BLOCKED 1305
/*! thread-yield: page access yielded due to prepare state change */
-#define WT_STAT_CONN_PREPARED_TRANSITION_BLOCKED_PAGE 1304
+#define WT_STAT_CONN_PREPARED_TRANSITION_BLOCKED_PAGE 1306
/*! thread-yield: page acquire busy blocked */
-#define WT_STAT_CONN_PAGE_BUSY_BLOCKED 1305
+#define WT_STAT_CONN_PAGE_BUSY_BLOCKED 1307
/*! thread-yield: page acquire eviction blocked */
-#define WT_STAT_CONN_PAGE_FORCIBLE_EVICT_BLOCKED 1306
+#define WT_STAT_CONN_PAGE_FORCIBLE_EVICT_BLOCKED 1308
/*! thread-yield: page acquire locked blocked */
-#define WT_STAT_CONN_PAGE_LOCKED_BLOCKED 1307
+#define WT_STAT_CONN_PAGE_LOCKED_BLOCKED 1309
/*! thread-yield: page acquire read blocked */
-#define WT_STAT_CONN_PAGE_READ_BLOCKED 1308
+#define WT_STAT_CONN_PAGE_READ_BLOCKED 1310
/*! thread-yield: page acquire time sleeping (usecs) */
-#define WT_STAT_CONN_PAGE_SLEEP 1309
+#define WT_STAT_CONN_PAGE_SLEEP 1311
/*!
* thread-yield: page delete rollback time sleeping for state change
* (usecs)
*/
-#define WT_STAT_CONN_PAGE_DEL_ROLLBACK_BLOCKED 1310
+#define WT_STAT_CONN_PAGE_DEL_ROLLBACK_BLOCKED 1312
/*! thread-yield: page reconciliation yielded due to child modification */
-#define WT_STAT_CONN_CHILD_MODIFY_BLOCKED_PAGE 1311
+#define WT_STAT_CONN_CHILD_MODIFY_BLOCKED_PAGE 1313
/*! transaction: commit timestamp queue entries walked */
-#define WT_STAT_CONN_TXN_COMMIT_QUEUE_WALKED 1312
+#define WT_STAT_CONN_TXN_COMMIT_QUEUE_WALKED 1314
/*! transaction: commit timestamp queue insert to empty */
-#define WT_STAT_CONN_TXN_COMMIT_QUEUE_EMPTY 1313
+#define WT_STAT_CONN_TXN_COMMIT_QUEUE_EMPTY 1315
/*! transaction: commit timestamp queue inserts to head */
-#define WT_STAT_CONN_TXN_COMMIT_QUEUE_HEAD 1314
+#define WT_STAT_CONN_TXN_COMMIT_QUEUE_HEAD 1316
/*! transaction: commit timestamp queue inserts total */
-#define WT_STAT_CONN_TXN_COMMIT_QUEUE_INSERTS 1315
+#define WT_STAT_CONN_TXN_COMMIT_QUEUE_INSERTS 1317
/*! transaction: commit timestamp queue length */
-#define WT_STAT_CONN_TXN_COMMIT_QUEUE_LEN 1316
+#define WT_STAT_CONN_TXN_COMMIT_QUEUE_LEN 1318
/*! transaction: number of named snapshots created */
-#define WT_STAT_CONN_TXN_SNAPSHOTS_CREATED 1317
+#define WT_STAT_CONN_TXN_SNAPSHOTS_CREATED 1319
/*! transaction: number of named snapshots dropped */
-#define WT_STAT_CONN_TXN_SNAPSHOTS_DROPPED 1318
+#define WT_STAT_CONN_TXN_SNAPSHOTS_DROPPED 1320
/*! transaction: prepared transactions */
-#define WT_STAT_CONN_TXN_PREPARE 1319
+#define WT_STAT_CONN_TXN_PREPARE 1321
/*! transaction: prepared transactions committed */
-#define WT_STAT_CONN_TXN_PREPARE_COMMIT 1320
+#define WT_STAT_CONN_TXN_PREPARE_COMMIT 1322
/*! transaction: prepared transactions currently active */
-#define WT_STAT_CONN_TXN_PREPARE_ACTIVE 1321
+#define WT_STAT_CONN_TXN_PREPARE_ACTIVE 1323
/*! transaction: prepared transactions rolled back */
-#define WT_STAT_CONN_TXN_PREPARE_ROLLBACK 1322
+#define WT_STAT_CONN_TXN_PREPARE_ROLLBACK 1324
/*! transaction: query timestamp calls */
-#define WT_STAT_CONN_TXN_QUERY_TS 1323
+#define WT_STAT_CONN_TXN_QUERY_TS 1325
/*! transaction: read timestamp queue entries walked */
-#define WT_STAT_CONN_TXN_READ_QUEUE_WALKED 1324
+#define WT_STAT_CONN_TXN_READ_QUEUE_WALKED 1326
/*! transaction: read timestamp queue insert to empty */
-#define WT_STAT_CONN_TXN_READ_QUEUE_EMPTY 1325
+#define WT_STAT_CONN_TXN_READ_QUEUE_EMPTY 1327
/*! transaction: read timestamp queue inserts to head */
-#define WT_STAT_CONN_TXN_READ_QUEUE_HEAD 1326
+#define WT_STAT_CONN_TXN_READ_QUEUE_HEAD 1328
/*! transaction: read timestamp queue inserts total */
-#define WT_STAT_CONN_TXN_READ_QUEUE_INSERTS 1327
+#define WT_STAT_CONN_TXN_READ_QUEUE_INSERTS 1329
/*! transaction: read timestamp queue length */
-#define WT_STAT_CONN_TXN_READ_QUEUE_LEN 1328
+#define WT_STAT_CONN_TXN_READ_QUEUE_LEN 1330
/*! transaction: rollback to stable calls */
-#define WT_STAT_CONN_TXN_ROLLBACK_TO_STABLE 1329
+#define WT_STAT_CONN_TXN_ROLLBACK_TO_STABLE 1331
/*! transaction: rollback to stable updates aborted */
-#define WT_STAT_CONN_TXN_ROLLBACK_UPD_ABORTED 1330
+#define WT_STAT_CONN_TXN_ROLLBACK_UPD_ABORTED 1332
/*! transaction: rollback to stable updates removed from cache overflow */
-#define WT_STAT_CONN_TXN_ROLLBACK_LAS_REMOVED 1331
+#define WT_STAT_CONN_TXN_ROLLBACK_LAS_REMOVED 1333
/*! transaction: set timestamp calls */
-#define WT_STAT_CONN_TXN_SET_TS 1332
+#define WT_STAT_CONN_TXN_SET_TS 1334
/*! transaction: set timestamp commit calls */
-#define WT_STAT_CONN_TXN_SET_TS_COMMIT 1333
+#define WT_STAT_CONN_TXN_SET_TS_COMMIT 1335
/*! transaction: set timestamp commit updates */
-#define WT_STAT_CONN_TXN_SET_TS_COMMIT_UPD 1334
+#define WT_STAT_CONN_TXN_SET_TS_COMMIT_UPD 1336
/*! transaction: set timestamp oldest calls */
-#define WT_STAT_CONN_TXN_SET_TS_OLDEST 1335
+#define WT_STAT_CONN_TXN_SET_TS_OLDEST 1337
/*! transaction: set timestamp oldest updates */
-#define WT_STAT_CONN_TXN_SET_TS_OLDEST_UPD 1336
+#define WT_STAT_CONN_TXN_SET_TS_OLDEST_UPD 1338
/*! transaction: set timestamp stable calls */
-#define WT_STAT_CONN_TXN_SET_TS_STABLE 1337
+#define WT_STAT_CONN_TXN_SET_TS_STABLE 1339
/*! transaction: set timestamp stable updates */
-#define WT_STAT_CONN_TXN_SET_TS_STABLE_UPD 1338
+#define WT_STAT_CONN_TXN_SET_TS_STABLE_UPD 1340
/*! transaction: transaction begins */
-#define WT_STAT_CONN_TXN_BEGIN 1339
+#define WT_STAT_CONN_TXN_BEGIN 1341
/*! transaction: transaction checkpoint currently running */
-#define WT_STAT_CONN_TXN_CHECKPOINT_RUNNING 1340
+#define WT_STAT_CONN_TXN_CHECKPOINT_RUNNING 1342
/*! transaction: transaction checkpoint generation */
-#define WT_STAT_CONN_TXN_CHECKPOINT_GENERATION 1341
+#define WT_STAT_CONN_TXN_CHECKPOINT_GENERATION 1343
/*! transaction: transaction checkpoint max time (msecs) */
-#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_MAX 1342
+#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_MAX 1344
/*! transaction: transaction checkpoint min time (msecs) */
-#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_MIN 1343
+#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_MIN 1345
/*! transaction: transaction checkpoint most recent time (msecs) */
-#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_RECENT 1344
+#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_RECENT 1346
/*! transaction: transaction checkpoint scrub dirty target */
-#define WT_STAT_CONN_TXN_CHECKPOINT_SCRUB_TARGET 1345
+#define WT_STAT_CONN_TXN_CHECKPOINT_SCRUB_TARGET 1347
/*! transaction: transaction checkpoint scrub time (msecs) */
-#define WT_STAT_CONN_TXN_CHECKPOINT_SCRUB_TIME 1346
+#define WT_STAT_CONN_TXN_CHECKPOINT_SCRUB_TIME 1348
/*! transaction: transaction checkpoint total time (msecs) */
-#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_TOTAL 1347
+#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_TOTAL 1349
/*! transaction: transaction checkpoints */
-#define WT_STAT_CONN_TXN_CHECKPOINT 1348
+#define WT_STAT_CONN_TXN_CHECKPOINT 1350
/*!
* transaction: transaction checkpoints skipped because database was
* clean
*/
-#define WT_STAT_CONN_TXN_CHECKPOINT_SKIPPED 1349
+#define WT_STAT_CONN_TXN_CHECKPOINT_SKIPPED 1351
/*! transaction: transaction failures due to cache overflow */
-#define WT_STAT_CONN_TXN_FAIL_CACHE 1350
+#define WT_STAT_CONN_TXN_FAIL_CACHE 1352
/*!
* transaction: transaction fsync calls for checkpoint after allocating
* the transaction ID
*/
-#define WT_STAT_CONN_TXN_CHECKPOINT_FSYNC_POST 1351
+#define WT_STAT_CONN_TXN_CHECKPOINT_FSYNC_POST 1353
/*!
* transaction: transaction fsync duration for checkpoint after
* allocating the transaction ID (usecs)
*/
-#define WT_STAT_CONN_TXN_CHECKPOINT_FSYNC_POST_DURATION 1352
+#define WT_STAT_CONN_TXN_CHECKPOINT_FSYNC_POST_DURATION 1354
/*! transaction: transaction range of IDs currently pinned */
-#define WT_STAT_CONN_TXN_PINNED_RANGE 1353
+#define WT_STAT_CONN_TXN_PINNED_RANGE 1355
/*! transaction: transaction range of IDs currently pinned by a checkpoint */
-#define WT_STAT_CONN_TXN_PINNED_CHECKPOINT_RANGE 1354
+#define WT_STAT_CONN_TXN_PINNED_CHECKPOINT_RANGE 1356
/*!
* transaction: transaction range of IDs currently pinned by named
* snapshots
*/
-#define WT_STAT_CONN_TXN_PINNED_SNAPSHOT_RANGE 1355
+#define WT_STAT_CONN_TXN_PINNED_SNAPSHOT_RANGE 1357
/*! transaction: transaction range of timestamps currently pinned */
-#define WT_STAT_CONN_TXN_PINNED_TIMESTAMP 1356
+#define WT_STAT_CONN_TXN_PINNED_TIMESTAMP 1358
/*! transaction: transaction range of timestamps pinned by a checkpoint */
-#define WT_STAT_CONN_TXN_PINNED_TIMESTAMP_CHECKPOINT 1357
+#define WT_STAT_CONN_TXN_PINNED_TIMESTAMP_CHECKPOINT 1359
/*!
* transaction: transaction range of timestamps pinned by the oldest
* timestamp
*/
-#define WT_STAT_CONN_TXN_PINNED_TIMESTAMP_OLDEST 1358
+#define WT_STAT_CONN_TXN_PINNED_TIMESTAMP_OLDEST 1360
/*! transaction: transaction sync calls */
-#define WT_STAT_CONN_TXN_SYNC 1359
+#define WT_STAT_CONN_TXN_SYNC 1361
/*! transaction: transactions committed */
-#define WT_STAT_CONN_TXN_COMMIT 1360
+#define WT_STAT_CONN_TXN_COMMIT 1362
/*! transaction: transactions rolled back */
-#define WT_STAT_CONN_TXN_ROLLBACK 1361
+#define WT_STAT_CONN_TXN_ROLLBACK 1363
/*! transaction: update conflicts */
-#define WT_STAT_CONN_TXN_UPDATE_CONFLICT 1362
+#define WT_STAT_CONN_TXN_UPDATE_CONFLICT 1364
/*!
* @}
diff --git a/src/third_party/wiredtiger/src/reconcile/rec_write.c b/src/third_party/wiredtiger/src/reconcile/rec_write.c
index f67342720f3..37b0581af6b 100644
--- a/src/third_party/wiredtiger/src/reconcile/rec_write.c
+++ b/src/third_party/wiredtiger/src/reconcile/rec_write.c
@@ -1299,7 +1299,7 @@ __rec_txn_read(WT_SESSION_IMPL *session, WT_RECONCILE *r,
wt_timestamp_t *timestampp;
size_t upd_memsize;
uint64_t max_txn, txnid;
- bool all_visible, prepared, skipped_birthmark, uncommitted;
+ bool all_visible, prepared, skipped_birthmark, uncommitted, upd_saved;
#ifdef HAVE_TIMESTAMPS
WT_UPDATE *first_ts_upd;
@@ -1314,7 +1314,7 @@ __rec_txn_read(WT_SESSION_IMPL *session, WT_RECONCILE *r,
first_txn_upd = NULL;
upd_memsize = 0;
max_txn = WT_TXN_NONE;
- prepared = skipped_birthmark = uncommitted = false;
+ prepared = skipped_birthmark = uncommitted = upd_saved = false;
/*
* If called with a WT_INSERT item, use its WT_UPDATE list (which must
@@ -1557,6 +1557,7 @@ __rec_txn_read(WT_SESSION_IMPL *session, WT_RECONCILE *r,
* unresolved updates, move the entire update list.
*/
WT_RET(__rec_update_save(session, r, ins, ripcip, *updp, upd_memsize));
+ upd_saved = true;
if (upd_savedp != NULL)
*upd_savedp = true;
@@ -1602,18 +1603,15 @@ check_original_value:
/*
* Returning an update means the original on-page value might be lost,
- * and that's a problem if there's a reader that needs it. There are
- * several cases:
- * - any update from a modify operation (because the modify has to be
- * applied to a stable update, not the new on-page update),
- * - any lookaside table eviction (because the backing disk image is
- * rewritten),
- * - or any reconciliation of a backing overflow record that will be
- * physically removed once it's no longer needed.
- */
- if (*updp != NULL && (!WT_UPDATE_DATA_VALUE(*updp) ||
- F_ISSET(r, WT_REC_LOOKASIDE) || (vpack != NULL &&
- vpack->ovfl && vpack->raw != WT_CELL_VALUE_OVFL_RM)))
+ * and that's a problem if there's a reader that needs it. This call
+ * makes a copy of the on-page value and if there is a birthmark in the
+ * update list, replaces it. We do that any time there are saved
+ * updates and during reconciliation of a backing overflow record that
+ * will be physically removed once it's no longer needed.
+ */
+ if (*updp != NULL && (upd_saved ||
+ (vpack != NULL && vpack->ovfl &&
+ vpack->raw != WT_CELL_VALUE_OVFL_RM)))
WT_RET(
__rec_append_orig_value(session, page, first_upd, vpack));
diff --git a/src/third_party/wiredtiger/src/support/stat.c b/src/third_party/wiredtiger/src/support/stat.c
index ebfa481eb3b..b04b9776f7f 100644
--- a/src/third_party/wiredtiger/src/support/stat.c
+++ b/src/third_party/wiredtiger/src/support/stat.c
@@ -788,6 +788,8 @@ static const char * const __stats_connection_desc[] = {
"cache: cache overflow score",
"cache: cache overflow table entries",
"cache: cache overflow table insert calls",
+ "cache: cache overflow table max on-disk size",
+ "cache: cache overflow table on-disk size",
"cache: cache overflow table remove calls",
"cache: checkpoint blocked page eviction",
"cache: eviction calls to get a page",
@@ -1193,6 +1195,8 @@ __wt_stat_connection_clear_single(WT_CONNECTION_STATS *stats)
/* not clearing cache_lookaside_score */
/* not clearing cache_lookaside_entries */
stats->cache_lookaside_insert = 0;
+ /* not clearing cache_lookaside_ondisk_max */
+ /* not clearing cache_lookaside_ondisk */
stats->cache_lookaside_remove = 0;
stats->cache_eviction_checkpoint = 0;
stats->cache_eviction_get_ref = 0;
@@ -1586,6 +1590,10 @@ __wt_stat_connection_aggregate(
WT_STAT_READ(from, cache_lookaside_entries);
to->cache_lookaside_insert +=
WT_STAT_READ(from, cache_lookaside_insert);
+ to->cache_lookaside_ondisk_max +=
+ WT_STAT_READ(from, cache_lookaside_ondisk_max);
+ to->cache_lookaside_ondisk +=
+ WT_STAT_READ(from, cache_lookaside_ondisk);
to->cache_lookaside_remove +=
WT_STAT_READ(from, cache_lookaside_remove);
to->cache_eviction_checkpoint +=
diff --git a/src/third_party/wiredtiger/src/txn/txn_rollback_to_stable.c b/src/third_party/wiredtiger/src/txn/txn_rollback_to_stable.c
index 6baaffa532a..8f4f4de1573 100644
--- a/src/third_party/wiredtiger/src/txn/txn_rollback_to_stable.c
+++ b/src/third_party/wiredtiger/src/txn/txn_rollback_to_stable.c
@@ -250,19 +250,47 @@ __txn_abort_newer_updates(
* dirty. Otherwise, the history we need could be swept from the
* lookaside table before the page is read because the lookaside sweep
* code has no way to tell that the page image is invalid.
+ *
+ * So, if there is lookaside history for a page, first check if the
+ * history needs to be rolled back make sure that history is loaded
+ * into cache. That is, if skew_newest is true, so the disk image
+ * potentially contained unstable updates, and the history is more
+ * recent than the rollback timestamp.
+ *
+ * Also, we have separately discarded any lookaside history more recent
+ * than the rollback timestamp. For page_las structures in cache,
+ * reset any future timestamps back to the rollback timestamp. This
+ * allows those structures to be discarded once the rollback timestamp
+ * is stable (crucially for tests, they can be discarded if the
+ * connection is closed right after a rollback_to_stable call).
*/
local_read = false;
read_flags = WT_READ_WONT_NEED;
- if (ref->page_las != NULL && ref->page_las->skew_newest &&
- __wt_timestamp_cmp(rollback_timestamp,
- &ref->page_las->unstable_timestamp) < 0) {
- /* Make sure get back a page with history, not limbo page */
- WT_ASSERT(session,
- !F_ISSET(&session->txn, WT_TXN_HAS_SNAPSHOT));
- WT_RET(__wt_page_in(session, ref, read_flags));
- WT_ASSERT(session, ref->state != WT_REF_LIMBO &&
- ref->page != NULL && __wt_page_is_modified(ref->page));
- local_read = true;
+ if (ref->page_las != NULL) {
+ if (ref->page_las->skew_newest &&
+ __wt_timestamp_cmp(rollback_timestamp,
+ &ref->page_las->unstable_timestamp) < 0) {
+ /*
+ * Make sure we get back a page with history, not a
+ * limbo page.
+ */
+ WT_ASSERT(session,
+ !F_ISSET(&session->txn, WT_TXN_HAS_SNAPSHOT));
+ WT_RET(__wt_page_in(session, ref, read_flags));
+ WT_ASSERT(session, ref->state != WT_REF_LIMBO &&
+ ref->page != NULL &&
+ __wt_page_is_modified(ref->page));
+ local_read = true;
+ }
+ if (__wt_timestamp_cmp(&ref->page_las->max_timestamp,
+ rollback_timestamp) > 0)
+ ref->page_las->max_timestamp = *rollback_timestamp;
+ if (__wt_timestamp_cmp(&ref->page_las->unstable_timestamp,
+ rollback_timestamp) > 0)
+ ref->page_las->unstable_timestamp = *rollback_timestamp;
+ if (__wt_timestamp_cmp(&ref->page_las->unstable_timestamp,
+ rollback_timestamp) > 0)
+ ref->page_las->unstable_timestamp = *rollback_timestamp;
}
/* Review deleted page saved to the ref */
diff --git a/src/third_party/wiredtiger/test/csuite/Makefile.am b/src/third_party/wiredtiger/test/csuite/Makefile.am
index 7c13eb4e696..a041b564f64 100644
--- a/src/third_party/wiredtiger/test/csuite/Makefile.am
+++ b/src/third_party/wiredtiger/test/csuite/Makefile.am
@@ -127,6 +127,10 @@ test_wt4333_handle_locks_SOURCES = wt4333_handle_locks/main.c
noinst_PROGRAMS += test_wt4333_handle_locks
all_TESTS += test_wt4333_handle_locks
+test_wt4803_cache_overflow_abort_SOURCES = wt4803_cache_overflow_abort/main.c
+noinst_PROGRAMS += test_wt4803_cache_overflow_abort
+all_TESTS += test_wt4803_cache_overflow_abort
+
# Run this during a "make check" smoke test.
TESTS = $(all_TESTS)
LOG_COMPILER = $(TEST_WRAPPER)
diff --git a/src/third_party/wiredtiger/test/csuite/wt3338_partial_update/main.c b/src/third_party/wiredtiger/test/csuite/wt3338_partial_update/main.c
index fb246f87da1..e73f63cdd8a 100644
--- a/src/third_party/wiredtiger/test/csuite/wt3338_partial_update/main.c
+++ b/src/third_party/wiredtiger/test/csuite/wt3338_partial_update/main.c
@@ -32,13 +32,13 @@
* Test case description: Smoke-test the partial update construction.
*/
-#define DEBUG 0
+#define DEBUG 0
-#define DATASIZE 1024
+#define DATASIZE 1024
+#define MAX_MODIFY_ENTRIES 37 /* Maximum modify vectors */
-#define MAX_MODIFY_ENTRIES 37
-static WT_MODIFY entries[MAX_MODIFY_ENTRIES]; /* Entries vector */
-static int nentries; /* Entries count */
+static WT_MODIFY entries[1000]; /* Entries vector */
+static int nentries; /* Entries count */
/*
* The replacement bytes array is 2x the maximum replacement string so we can
@@ -213,11 +213,11 @@ slow_apply_api(WT_ITEM *orig)
}
/*
- * diff --
- * Diff the two results.
+ * compare --
+ * Compare two results.
*/
static void
-diff(WT_ITEM *local, WT_ITEM *library)
+compare(WT_ITEM *local, WT_ITEM *library)
{
#if DEBUG
if (local->size != library->size ||
@@ -232,42 +232,92 @@ diff(WT_ITEM *local, WT_ITEM *library)
local->data, library->data, local->size) == 0);
}
+static int nruns = 10000;
+
/*
- * modify_init --
- * Initialize the buffers to a known state.
+ * modify_run
+ * Run some tests:
+ * 1. Create an initial value, a copy and a fake cursor to use with the
+ * WiredTiger routines. Generate a set of modify vectors and apply them to
+ * the item stored in the cursor using the modify apply API. Also apply the
+ * same modify vector to one of the copies using a helper routine written
+ * to test the modify API. The final value generated with the modify API
+ * and the helper routine should match.
+ *
+ * 2. Use the initial value and the modified value generated above as
+ * inputs into the calculate-modify API to generate a set of modify
+ * vectors. Apply this generated vector to the initial value using the
+ * modify apply API to obtain a final value. The final value generated
+ * should match the modified value that was used as input to the
+ * calculate-modify API.
*/
static void
-modify_init(WT_ITEM *local, WT_ITEM *library)
+modify_run(bool verbose)
{
+ WT_CURSOR *cursor, _cursor;
+ WT_DECL_RET;
+ WT_ITEM *localA, _localA, *localB, _localB;
size_t len;
+ int i, j;
- len = (size_t)(__wt_random(&rnd) % MAX_REPL_BYTES);
- testutil_check(__wt_buf_set(NULL, local, modify_repl, len));
- testutil_check(__wt_buf_set(NULL, library, modify_repl, len));
-}
+ /* Initialize the RNG. */
+ __wt_random_init_seed(NULL, &rnd);
-static int nruns = 1000;
+ /* Set up replacement information. */
+ modify_repl_init();
-/*
- * modify_run
- * Run some tests.
- */
-static void
-modify_run(WT_CURSOR *cursor, WT_ITEM *local, bool verbose)
-{
- int i, j;
+ /* We need three WT_ITEMs, one of them part of a fake cursor. */
+ localA = &_localA;
+ memset(&_localA, 0, sizeof(_localA));
+ localB = &_localB;
+ memset(&_localB, 0, sizeof(_localB));
+ cursor = &_cursor;
+ memset(&_cursor, 0, sizeof(_cursor));
+ cursor->value_format = "u";
for (i = 0; i < nruns; ++i) {
- modify_init(local, &cursor->value);
+ /* Create an initial value. */
+ len = (size_t)(__wt_random(&rnd) % MAX_REPL_BYTES);
+ testutil_check(__wt_buf_set(NULL, localA, modify_repl, len));
for (j = 0; j < 1000; ++j) {
+ /* Copy the current value into the second item. */
+ testutil_check(__wt_buf_set(
+ NULL, localB, localA->data, localA->size));
+
+ /*
+ * Create a random set of modify vectors, run the
+ * underlying library modification function, then
+ * compare the result against our implementation
+ * of modify.
+ */
modify_build();
-
- slow_apply_api(local);
+ testutil_check(__wt_buf_set(
+ NULL, &cursor->value, localA->data, localA->size));
testutil_check(__wt_modify_apply_api(
NULL, cursor, entries, nentries));
-
- diff(local, &cursor->value);
+ slow_apply_api(localA);
+ compare(localA, &cursor->value);
+
+ /*
+ * Call the WiredTiger function to build a modification
+ * vector for the change, and repeat the test using the
+ * WiredTiger modification vector, then compare results
+ * against our implementation of modify.
+ */
+ nentries = WT_ELEMENTS(entries);
+ ret = wiredtiger_calc_modify(NULL,
+ localB, localA,
+ WT_MAX(localB->size, localA->size) + 100,
+ entries, &nentries);
+ if (ret == WT_NOTFOUND)
+ continue;
+ testutil_check(ret);
+ testutil_check(__wt_buf_set(
+ NULL, &cursor->value, localB->data, localB->size));
+ testutil_check(__wt_modify_apply_api(
+ NULL, cursor, entries, nentries));
+ compare(localA, &cursor->value);
}
if (verbose) {
printf("%d (%d%%)\r", i, (i * 100) / nruns);
@@ -275,18 +325,17 @@ modify_run(WT_CURSOR *cursor, WT_ITEM *local, bool verbose)
}
}
if (verbose)
- printf("\n");
+ printf("%d (100%%)\n", i);
+
+ __wt_buf_free(NULL, localA);
+ __wt_buf_free(NULL, localB);
+ __wt_buf_free(NULL, &cursor->value);
}
int
main(int argc, char *argv[])
{
TEST_OPTS *opts, _opts;
- WT_CURSOR *cursor, _cursor;
- WT_ITEM *local, _local;
-
- if (testutil_is_flag_set("TESTUTIL_ENABLE_LONG_TESTS"))
- nruns = 10000;
opts = &_opts;
memset(opts, 0, sizeof(*opts));
@@ -295,24 +344,8 @@ main(int argc, char *argv[])
testutil_check(
wiredtiger_open(opts->home, NULL, "create", &opts->conn));
- /* Initialize the RNG. */
- __wt_random_init_seed(NULL, &rnd);
-
- /* Set up replacement information. */
- modify_repl_init();
-
- /* We need two items, one of them hooked into fake cursor. */
- local = &_local;
- memset(&_local, 0, sizeof(_local));
- cursor = &_cursor;
- memset(&_cursor, 0, sizeof(_cursor));
- cursor->value_format = "u";
-
/* Run the test. */
- modify_run(cursor, local, opts->verbose);
-
- __wt_buf_free(NULL, local);
- __wt_buf_free(NULL, &cursor->value);
+ modify_run(opts->verbose);
testutil_cleanup(opts);
return (EXIT_SUCCESS);
diff --git a/src/third_party/wiredtiger/test/csuite/wt4803_cache_overflow_abort/main.c b/src/third_party/wiredtiger/test/csuite/wt4803_cache_overflow_abort/main.c
new file mode 100644
index 00000000000..7d9b0baf132
--- /dev/null
+++ b/src/third_party/wiredtiger/test/csuite/wt4803_cache_overflow_abort/main.c
@@ -0,0 +1,239 @@
+/*-
+ * Public Domain 2014-2019 MongoDB, Inc.
+ * Public Domain 2008-2014 WiredTiger, Inc.
+ *
+ * This is free and unencumbered software released into the public domain.
+ *
+ * Anyone is free to copy, modify, publish, use, compile, sell, or
+ * distribute this software, either in source code form or as a compiled
+ * binary, for any purpose, commercial or non-commercial, and by any
+ * means.
+ *
+ * In jurisdictions that recognize copyright laws, the author or authors
+ * of this software dedicate any and all copyright interest in the
+ * software to the public domain. We make this dedication for the benefit
+ * of the public at large and to the detriment of our heirs and
+ * successors. We intend this dedication to be an overt act of
+ * relinquishment in perpetuity of all present and future rights to this
+ * software under copyright law.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "test_util.h"
+
+#include <signal.h>
+#include <sys/wait.h>
+
+/*
+ * JIRA ticket reference: WT-4803
+ * Test case description: This test is checking the functionality of the
+ * lookaside file_max configuration. When the size of the lookaside file exceeds
+ * this value, we expect to panic.
+ * Failure mode: If we receive a panic in the test cases we weren't expecting to
+ * and vice versa.
+ */
+
+#define NUM_KEYS 2000
+
+/*
+ * This is a global flag that should be set before running test_las_workload.
+ * It lets the child process know whether it should be expecting a panic or not
+ * so that it can adjust its exit code as needed.
+ */
+static bool expect_panic;
+
+static int
+handle_message(WT_EVENT_HANDLER *handler,
+ WT_SESSION *session, int error, const char *message)
+{
+ WT_UNUSED(handler);
+ WT_UNUSED(session);
+
+ (void)fprintf(
+ stderr, "%s: %s\n", message, session->strerror(session, error));
+
+ if (error == WT_PANIC &&
+ strstr(message, "exceeds maximum size") != NULL) {
+ fprintf(stderr, "Got cache overflow error (expect_panic=%s)\n",
+ expect_panic ? "true" : "false");
+
+ /*
+ * If we're expecting a panic, exit with zero to indicate to the
+ * parent that this test was successful.
+ *
+ * If not, don't intercept. We'll naturally exit with non-zero
+ * if we're terminating due to panic.
+ */
+ if (expect_panic)
+ exit(EXIT_SUCCESS);
+ }
+
+ return (0);
+}
+
+static WT_EVENT_HANDLER event_handler = {
+ handle_message,
+ NULL,
+ NULL,
+ NULL
+};
+
+static void
+las_workload(TEST_OPTS *opts, const char *las_file_max)
+{
+ WT_CURSOR *cursor;
+ WT_SESSION *other_session, *session;
+ int i;
+ char buf[WT_MEGABYTE], open_config[128];
+
+ testutil_check(__wt_snprintf(open_config, sizeof(open_config),
+ "create,cache_size=50MB,cache_overflow=(file_max=%s)",
+ las_file_max));
+
+ testutil_check(wiredtiger_open(
+ opts->home, &event_handler, open_config, &opts->conn));
+ testutil_check(
+ opts->conn->open_session(opts->conn, NULL, NULL, &session));
+ testutil_check(
+ session->create(session, opts->uri, "key_format=i,value_format=S"));
+ testutil_check(
+ session->open_cursor(session, opts->uri, NULL, NULL, &cursor));
+
+ memset(buf, 0xA, WT_MEGABYTE);
+ buf[WT_MEGABYTE - 1] = '\0';
+
+ /* Populate the table. */
+ for (i = 0; i < NUM_KEYS; ++i) {
+ cursor->set_key(cursor, i);
+ cursor->set_value(cursor, buf);
+ testutil_check(cursor->insert(cursor));
+ }
+
+ /*
+ * Open a snapshot isolation transaction in another session. This forces
+ * the cache to retain all previous values. Then update all keys with a
+ * new value in the original session while keeping that snapshot
+ * transaction open. With the large value buffer, small cache and lots
+ * of keys, this will force a lot of lookaside usage.
+ *
+ * When the file_max setting is small, the maximum size should easily be
+ * reached and we should panic. When the maximum size is large or not
+ * set, then we should succeed.
+ */
+ testutil_check(
+ opts->conn->open_session(opts->conn, NULL, NULL, &other_session));
+ testutil_check(other_session->begin_transaction(
+ other_session, "isolation=snapshot"));
+
+ memset(buf, 0xB, WT_MEGABYTE);
+ buf[WT_MEGABYTE - 1] = '\0';
+
+ for (i = 0; i < NUM_KEYS; ++i) {
+ cursor->set_key(cursor, i);
+ cursor->set_value(cursor, buf);
+ testutil_check(cursor->update(cursor));
+ }
+
+ /*
+ * Cleanup.
+ * We do not get here when the file_max size is small because we will
+ * have already hit the maximum and exited. This code only executes on
+ * the successful path.
+ */
+ testutil_check(
+ other_session->rollback_transaction(other_session, NULL));
+ testutil_check(other_session->close(other_session, NULL));
+
+ testutil_check(cursor->close(cursor));
+ testutil_check(session->close(session, NULL));
+}
+
+static int
+test_las_workload(TEST_OPTS *opts, const char *las_file_max)
+{
+ pid_t pid;
+ int status;
+
+ /*
+ * We're going to run this workload for different configurations of
+ * file_max. So clean out the work directory each time.
+ */
+ testutil_make_work_dir(opts->home);
+
+ /*
+ * Since it's possible that the workload will panic and abort, we will
+ * fork the process and execute the workload in the child process.
+ *
+ * This way, we can safely check the exit code of the child process and
+ * confirm that it is what we expected.
+ */
+ pid = fork();
+ if (pid < 0)
+ /* Failed fork. */
+ testutil_die(errno, "fork");
+ else if (pid == 0) {
+ /* Child process from here. */
+ las_workload(opts, las_file_max);
+
+ /*
+ * If we're expecting a panic during the workload, we shouldn't
+ * get to this point. Exit with non-zero to indicate to parent
+ * that we should fail this test.
+ */
+ fprintf(stderr,
+ "Successfully completed workload (expect_panic=%s)\n",
+ expect_panic ? "true" : "false");
+
+ if (expect_panic)
+ exit(EXIT_FAILURE);
+ else
+ exit(EXIT_SUCCESS);
+ }
+
+ /* Parent process from here. */
+ if (waitpid(pid, &status, 0) == -1)
+ testutil_die(errno, "waitpid");
+
+ return (status);
+}
+
+int
+main(int argc, char **argv)
+{
+ TEST_OPTS opts;
+
+ memset(&opts, 0x0, sizeof(opts));
+ testutil_check(testutil_parse_opts(argc, argv, &opts));
+
+ /*
+ * The lookaside is unbounded.
+ * We don't expect any failure since we can use as much as needed.
+ */
+ expect_panic = false;
+ testutil_check(test_las_workload(&opts, "0"));
+
+ /*
+ * The lookaside is limited to 5GB.
+ * This is more than enough for this workload so we don't expect any
+ * failure.
+ */
+ expect_panic = false;
+ testutil_check(test_las_workload(&opts, "5GB"));
+
+ /*
+ * The lookaside is limited to 100MB.
+ * This is insufficient for this workload so we're expecting a failure.
+ */
+ expect_panic = true;
+ testutil_check(test_las_workload(&opts, "100MB"));
+
+ testutil_cleanup(&opts);
+
+ return (0);
+}
diff --git a/src/third_party/wiredtiger/test/suite/test_calc_modify.py b/src/third_party/wiredtiger/test/suite/test_calc_modify.py
new file mode 100644
index 00000000000..a52096a3125
--- /dev/null
+++ b/src/third_party/wiredtiger/test/suite/test_calc_modify.py
@@ -0,0 +1,118 @@
+#!/usr/bin/env python
+#
+# Public Domain 2014-2018 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 random, string
+import wiredtiger, wttest
+
+r = random.Random(42) # Make things repeatable
+
+# test_calc_modify.py
+# Test the wiredtiger_calc_modify API
+#
+# Try many combinations of:
+# - data size
+# - data randomness ('a' * N, repeated patterns, uniform random)
+# - number and type of modifications (add, remove, replace)
+# - space between the modifications
+#
+# Check that wiredtiger_calc_modify finds a set of modifies when the edit
+# difference is under the specified limits, and that applying those
+# modifications produces the expected result. If the edit difference is
+# larger than the limits, it okay for the call to fail.
+class test_calc_modify(wttest.WiredTigerTestCase):
+ uri = 'table:test_calc_modify'
+
+ # operation types
+ ADD = 1
+ REMOVE = 2
+ REPLACE = 3
+
+ def mkstring(self, size, repeat_size=1):
+ pattern = ''.join(r.choice(string.ascii_letters + string.digits) for _ in xrange(repeat_size))
+ return (pattern * ((size + repeat_size - 1) / repeat_size))[:size]
+
+ def one_test(self, c, k, oldsz, repeatsz, nmod, maxdiff):
+ oldv = self.mkstring(oldsz, repeatsz)
+
+ offsets = sorted(r.sample(xrange(oldsz), nmod))
+ modsizes = sorted(r.sample(xrange(maxdiff), nmod + 1))
+ lengths = [modsizes[i+1] - modsizes[i] for i in xrange(nmod)]
+ modtypes = [r.choice((self.ADD, self.REMOVE, self.REPLACE)) for _ in xrange(nmod)]
+
+ self.pr("offsets: %s" % offsets)
+ self.pr("modsizes: %s" % modsizes)
+ self.pr("lengths: %s" % lengths)
+ self.pr("modtypes: %s" % modtypes)
+
+ orig = oldv
+ newv = ''
+ for i in xrange(nmod):
+ if i > 0 and offsets[i] - offsets[i - 1] < maxdiff:
+ continue
+ newv += orig[:offsets[i]]
+ orig = orig[offsets[i]:]
+ if modtypes[i] == self.ADD:
+ newv += self.mkstring(lengths[i], r.randint(1, lengths[i]))
+ elif modtypes[i] == self.REMOVE:
+ orig = orig[lengths[i]:]
+ elif modtypes[i] == self.REPLACE:
+ newv += self.mkstring(lengths[i], r.randint(1, lengths[i]))
+ orig = orig[lengths[i]:]
+ newv += orig
+
+ self.pr("oldv: %s" % oldv)
+ self.pr("newv: %s" % newv)
+ try:
+ mods = wiredtiger.wiredtiger_calc_modify(None, oldv, newv, max(maxdiff, nmod * 64), nmod)
+ self.pr("calculated mods: %s" % mods)
+ except wiredtiger.WiredTigerError:
+ # When the data repeats, the algorithm can register the "wrong" repeated sequence. Retry...
+ mods = wiredtiger.wiredtiger_calc_modify(None, oldv, newv, nmod * (64 + repeatsz), nmod)
+ self.pr("calculated mods (round 2): %s" % mods)
+ self.assertIsNotNone(mods)
+
+ c[k] = oldv
+ self.session.begin_transaction('isolation=snapshot')
+ c.set_key(k)
+ c.modify(mods)
+ self.session.commit_transaction()
+ self.assertEqual(c[k], newv)
+
+ def test_calc_modify(self):
+ self.session.create(self.uri, 'key_format=i,value_format=u')
+ c = self.session.open_cursor(self.uri)
+ for k in xrange(1000):
+ size = r.randint(1000, 10000)
+ repeats = r.randint(1, size)
+ nmods = r.randint(1, 10)
+ maxdiff = r.randint(64, size / 10)
+ self.pr("size %s, repeats %s, nmods %s, maxdiff %s" % (size, repeats, nmods, maxdiff))
+ self.one_test(c, k, size, repeats, nmods, maxdiff)
+
+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
index f9131331640..e9bb23f00dd 100644
--- a/src/third_party/wiredtiger/test/suite/test_compat01.py
+++ b/src/third_party/wiredtiger/test/suite/test_compat01.py
@@ -189,12 +189,20 @@ class test_reconfig_fail(wttest.WiredTigerTestCase):
ds = SimpleDataSet(self, uri, 100, key_format='S')
ds.populate()
+ # Reconfigure to an older version.
+ compat_str = 'compatibility=(release="2.6")'
+ self.conn.reconfigure(compat_str)
+
self.session.begin_transaction("isolation=snapshot")
c = self.session.open_cursor(uri, None)
c.set_key(ds.key(20))
c.set_value("abcde")
self.assertEquals(c.update(), 0)
+ # Make sure we can reconfigure unrelated things while downgraded
+ # and we have an active transaction.
+ self.conn.reconfigure("cache_size=100M")
+
compat_str = 'compatibility=(release="3.0.0")'
msg = '/system must be quiescent/'
self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
diff --git a/src/third_party/wiredtiger/test/suite/test_las04.py b/src/third_party/wiredtiger/test/suite/test_las04.py
new file mode 100644
index 00000000000..9d35d3c17f3
--- /dev/null
+++ b/src/third_party/wiredtiger/test/suite/test_las04.py
@@ -0,0 +1,110 @@
+#!/usr/bin/env python
+#
+# Public Domain 2014-2019 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_las04.py
+# Test file_max configuration and reconfiguration for the lookaside table.
+#
+
+import wiredtiger, wttest
+from wtscenario import make_scenarios
+
+# Taken from src/include/misc.h.
+WT_MB = 1048576
+
+class test_las04(wttest.WiredTigerTestCase):
+ uri = 'table:las_04'
+ in_memory_values = [
+ ('false', dict(in_memory=False)),
+ ('none', dict(in_memory=None)),
+ ('true', dict(in_memory=True))
+ ]
+ init_file_max_values = [
+ ('default', dict(init_file_max=None, init_stat_val=0)),
+ ('non-zero', dict(init_file_max='100MB', init_stat_val=(WT_MB * 100))),
+ ('zero', dict(init_file_max='0', init_stat_val=0))
+ ]
+ reconfig_file_max_values = [
+ ('non-zero', dict(reconfig_file_max='100MB',
+ reconfig_stat_val=(WT_MB * 100))),
+ ('too-low', dict(reconfig_file_max='99MB', reconfig_stat_val=None)),
+ ('zero', dict(reconfig_file_max='0', reconfig_stat_val=0))
+ ]
+ scenarios = make_scenarios(init_file_max_values, reconfig_file_max_values,
+ in_memory_values)
+
+ def conn_config(self):
+ config = 'statistics=(fast)'
+ if self.init_file_max is not None:
+ config += ',cache_overflow=(file_max={})'.format(self.init_file_max)
+ if self.in_memory is not None:
+ config += ',in_memory=' + ('true' if self.in_memory else 'false')
+ return config
+
+ def get_stat(self, stat):
+ stat_cursor = self.session.open_cursor('statistics:')
+ val = stat_cursor[stat][2]
+ stat_cursor.close()
+ return val
+
+ def test_las(self):
+ self.session.create(self.uri, 'key_format=S,value_format=S')
+
+ if self.in_memory:
+ # For in-memory configurations, we simply ignore any lookaside
+ # related configuration.
+ self.assertEqual(
+ self.get_stat(wiredtiger.stat.conn.cache_lookaside_ondisk_max),
+ 0)
+ else:
+ self.assertEqual(
+ self.get_stat(wiredtiger.stat.conn.cache_lookaside_ondisk_max),
+ self.init_stat_val)
+
+ reconfigure = lambda: self.conn.reconfigure(
+ 'cache_overflow=(file_max={})'.format(self.reconfig_file_max))
+
+ # We expect an error when the statistic value is None because the value
+ # is out of range.
+ if self.reconfig_stat_val is None:
+ self.assertRaisesWithMessage(
+ wiredtiger.WiredTigerError, reconfigure, '/below minimum/')
+ return
+
+ reconfigure()
+
+ if self.in_memory:
+ self.assertEqual(
+ self.get_stat(wiredtiger.stat.conn.cache_lookaside_ondisk_max),
+ 0)
+ else:
+ self.assertEqual(
+ self.get_stat(wiredtiger.stat.conn.cache_lookaside_ondisk_max),
+ self.reconfig_stat_val)
+
+if __name__ == '__main__':
+ wttest.run()