summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLuke Chen <luke.chen@mongodb.com>2019-05-17 14:35:49 +1000
committerLuke Chen <luke.chen@mongodb.com>2019-05-17 14:35:49 +1000
commit1d05d4b956221cfeb731892a4387d1470f999114 (patch)
treeffeff3027433530538a9214a1f87f3f9760a19c2 /src
parent23ceef7c72f117ac0cc886447181d0f88433aefc (diff)
downloadmongo-1d05d4b956221cfeb731892a4387d1470f999114.tar.gz
Import wiredtiger: 5d321d0c6091636a2344ef9915ca06b0c078bda3 from branch mongodb-4.2
ref: a332548202..5d321d0c60 for: 4.1.12 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-4778 MSVC build fails when optimisation is turned off WT-4794 Mark lookaside history resolved in all paths WT-4796 Enhance diagnostics that track ref state transitions
Diffstat (limited to 'src')
-rw-r--r--src/third_party/wiredtiger/import.data2
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_compact.c2
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_delete.c19
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_handle.c22
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_read.c14
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_ret.c7
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_slvg.c4
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_split.c7
-rw-r--r--src/third_party/wiredtiger/src/cache/cache_las.c2
-rw-r--r--src/third_party/wiredtiger/src/evict/evict_file.c22
-rw-r--r--src/third_party/wiredtiger/src/evict/evict_lru.c4
-rw-r--r--src/third_party/wiredtiger/src/evict/evict_page.c2
-rw-r--r--src/third_party/wiredtiger/src/include/btmem.h14
-rw-r--r--src/third_party/wiredtiger/src/include/btree.i2
-rw-r--r--src/third_party/wiredtiger/src/include/extern.h2
-rw-r--r--src/third_party/wiredtiger/src/include/txn.i34
-rw-r--r--src/third_party/wiredtiger/src/reconcile/rec_child.c4
-rw-r--r--src/third_party/wiredtiger/src/reconcile/rec_write.c3
-rw-r--r--src/third_party/wiredtiger/src/txn/txn_rollback_to_stable.c45
-rw-r--r--src/third_party/wiredtiger/test/utility/test_util.h3
20 files changed, 146 insertions, 68 deletions
diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data
index 8eaa6b77b0b..b16bb0a5058 100644
--- a/src/third_party/wiredtiger/import.data
+++ b/src/third_party/wiredtiger/import.data
@@ -1,5 +1,5 @@
{
- "commit": "a3325482022bc77846ffc0265097edfebccaadd3",
+ "commit": "5d321d0c6091636a2344ef9915ca06b0c078bda3",
"github": "wiredtiger/wiredtiger.git",
"vendor": "wiredtiger",
"branch": "mongodb-4.2"
diff --git a/src/third_party/wiredtiger/src/btree/bt_compact.c b/src/third_party/wiredtiger/src/btree/bt_compact.c
index e358e993ec4..0342f760edf 100644
--- a/src/third_party/wiredtiger/src/btree/bt_compact.c
+++ b/src/third_party/wiredtiger/src/btree/bt_compact.c
@@ -272,7 +272,7 @@ __wt_compact_page_skip(
* reference an on-page cell, and page eviction can free that memory.
* Lock the WT_REF so we can look at its address.
*/
- if (!__wt_atomic_casv32(&ref->state, WT_REF_DISK, WT_REF_LOCKED))
+ if (!WT_REF_CAS_STATE(session, ref, WT_REF_DISK, WT_REF_LOCKED))
return (0);
/*
diff --git a/src/third_party/wiredtiger/src/btree/bt_delete.c b/src/third_party/wiredtiger/src/btree/bt_delete.c
index 0d6679826a3..cfe4c242664 100644
--- a/src/third_party/wiredtiger/src/btree/bt_delete.c
+++ b/src/third_party/wiredtiger/src/btree/bt_delete.c
@@ -74,7 +74,7 @@ __wt_delete_page(WT_SESSION_IMPL *session, WT_REF *ref, bool *skipp)
/* If we have a clean page in memory, attempt to evict it. */
previous_state = ref->state;
if ((previous_state == WT_REF_MEM || previous_state == WT_REF_LIMBO) &&
- __wt_atomic_casv32(&ref->state, previous_state, WT_REF_LOCKED)) {
+ WT_REF_CAS_STATE(session, ref, previous_state, WT_REF_LOCKED)) {
if (__wt_page_is_modified(ref->page)) {
WT_REF_SET_STATE(ref, previous_state);
return (0);
@@ -99,7 +99,7 @@ __wt_delete_page(WT_SESSION_IMPL *session, WT_REF *ref, bool *skipp)
default:
return (0);
}
- if (!__wt_atomic_casv32(&ref->state, previous_state, WT_REF_LOCKED))
+ if (!WT_REF_CAS_STATE(session, ref, previous_state, WT_REF_LOCKED))
return (0);
/*
@@ -190,7 +190,7 @@ __wt_delete_page_rollback(WT_SESSION_IMPL *session, WT_REF *ref)
* If the page is still "deleted", it's as we left it,
* reset the state.
*/
- if (__wt_atomic_casv32(&ref->state,
+ if (WT_REF_CAS_STATE(session, ref,
WT_REF_DELETED, ref->page_del->previous_state))
goto done;
break;
@@ -201,8 +201,8 @@ __wt_delete_page_rollback(WT_SESSION_IMPL *session, WT_REF *ref)
break;
case WT_REF_MEM:
case WT_REF_SPLIT:
- if (__wt_atomic_casv32(
- &ref->state, current_state, WT_REF_LOCKED))
+ if (WT_REF_CAS_STATE(
+ session, ref, current_state, WT_REF_LOCKED))
locked = true;
break;
case WT_REF_DISK:
@@ -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))
+ if (!WT_REF_CAS_STATE(session, ref, 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:
@@ -300,7 +301,7 @@ __wt_delete_page_skip(WT_SESSION_IMPL *session, WT_REF *ref, bool visible_all)
__wt_free(session, ref->page_del);
}
- WT_PUBLISH(ref->state, WT_REF_DELETED);
+ WT_REF_SET_STATE(ref, WT_REF_DELETED);
return (skip);
}
diff --git a/src/third_party/wiredtiger/src/btree/bt_handle.c b/src/third_party/wiredtiger/src/btree/bt_handle.c
index 72cb2d259bd..f179fa38d91 100644
--- a/src/third_party/wiredtiger/src/btree/bt_handle.c
+++ b/src/third_party/wiredtiger/src/btree/bt_handle.c
@@ -270,6 +270,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.
*/
@@ -582,12 +592,14 @@ __btree_conf(WT_SESSION_IMPL *session, WT_CKPT *ckpt)
* Initialize a tree root reference, and link in the root page.
*/
void
-__wt_root_ref_init(WT_REF *root_ref, WT_PAGE *root, bool is_recno)
+__wt_root_ref_init(WT_SESSION_IMPL *session,
+ WT_REF *root_ref, WT_PAGE *root, bool is_recno)
{
+ WT_UNUSED(session); /* Used in a macro for diagnostic builds */
memset(root_ref, 0, sizeof(*root_ref));
root_ref->page = root;
- root_ref->state = WT_REF_MEM;
+ WT_REF_SET_STATE(root_ref, WT_REF_MEM);
root_ref->ref_recno = is_recno ? 1 : WT_RECNO_OOB;
@@ -668,7 +680,8 @@ __wt_btree_tree_open(
dsk.mem = NULL;
/* Finish initializing the root, root reference links. */
- __wt_root_ref_init(&btree->root, page, btree->type != BTREE_ROW);
+ __wt_root_ref_init(session,
+ &btree->root, page, btree->type != BTREE_ROW);
err: __wt_buf_free(session, &dsk);
__wt_scr_free(session, &tmp);
@@ -752,7 +765,8 @@ __btree_tree_open_empty(WT_SESSION_IMPL *session, bool creation)
}
/* Finish initializing the root, root reference links. */
- __wt_root_ref_init(&btree->root, root, btree->type != BTREE_ROW);
+ __wt_root_ref_init(session,
+ &btree->root, root, btree->type != BTREE_ROW);
return (0);
diff --git a/src/third_party/wiredtiger/src/btree/bt_read.c b/src/third_party/wiredtiger/src/btree/bt_read.c
index 08adaf96852..d97ad9dbf9c 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_REF *ref,
}
WT_RET(__las_page_instantiate(session, ref));
- ref->page_las->eviction_to_lookaside = false;
return (0);
}
@@ -464,7 +470,7 @@ __page_read(WT_SESSION_IMPL *session, WT_REF *ref, uint32_t flags)
default:
return (0);
}
- if (!__wt_atomic_casv32(&ref->state, previous_state, new_state))
+ if (!WT_REF_CAS_STATE(session, ref, previous_state, new_state))
return (0);
final_state = WT_REF_MEM;
@@ -540,10 +546,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 61351c26e36..52277efb85d 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_slvg.c b/src/third_party/wiredtiger/src/btree/bt_slvg.c
index 8166e24d1ea..d2b0472a11e 100644
--- a/src/third_party/wiredtiger/src/btree/bt_slvg.c
+++ b/src/third_party/wiredtiger/src/btree/bt_slvg.c
@@ -1209,7 +1209,7 @@ __slvg_col_build_internal(
++ref;
}
- __wt_root_ref_init(&ss->root_ref, page, true);
+ __wt_root_ref_init(session, &ss->root_ref, page, true);
if (0) {
err: __wt_free(session, addr);
@@ -1882,7 +1882,7 @@ __slvg_row_build_internal(
++ref;
}
- __wt_root_ref_init(&ss->root_ref, page, false);
+ __wt_root_ref_init(session, &ss->root_ref, page, false);
if (0) {
err: __wt_free(session, addr);
diff --git a/src/third_party/wiredtiger/src/btree/bt_split.c b/src/third_party/wiredtiger/src/btree/bt_split.c
index 70b8c72a0e6..b1d8dce75a5 100644
--- a/src/third_party/wiredtiger/src/btree/bt_split.c
+++ b/src/third_party/wiredtiger/src/btree/bt_split.c
@@ -684,8 +684,8 @@ __split_parent(WT_SESSION_IMPL *session, WT_REF *ref, WT_REF **ref_new,
WT_SESSION_BTREE_SYNC(session)) &&
next_ref->state == WT_REF_DELETED &&
__wt_delete_page_skip(session, next_ref, true) &&
- __wt_atomic_casv32(
- &next_ref->state, WT_REF_DELETED, WT_REF_SPLIT))) {
+ WT_REF_CAS_STATE(
+ session, next_ref, WT_REF_DELETED, WT_REF_SPLIT))) {
WT_ERR(__wt_buf_grow(session, scr,
(deleted_entries + 1) * sizeof(uint32_t)));
deleted_refs = scr->mem;
@@ -861,6 +861,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 0d2e9520961..a7e8afe7e02 100644
--- a/src/third_party/wiredtiger/src/cache/cache_las.c
+++ b/src/third_party/wiredtiger/src/cache/cache_las.c
@@ -464,7 +464,7 @@ __wt_las_page_skip(WT_SESSION_IMPL *session, WT_REF *ref)
previous_state != WT_REF_LOOKASIDE)
return (false);
- if (!__wt_atomic_casv32(&ref->state, previous_state, WT_REF_LOCKED))
+ if (!WT_REF_CAS_STATE(session, ref, previous_state, WT_REF_LOCKED))
return (false);
skip = __wt_las_page_skip_locked(session, ref);
diff --git a/src/third_party/wiredtiger/src/evict/evict_file.c b/src/third_party/wiredtiger/src/evict/evict_file.c
index 114d89fd826..0e806f20608 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));
@@ -124,7 +104,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/evict/evict_lru.c b/src/third_party/wiredtiger/src/evict/evict_lru.c
index a85117b89f6..659f584fbe4 100644
--- a/src/third_party/wiredtiger/src/evict/evict_lru.c
+++ b/src/third_party/wiredtiger/src/evict/evict_lru.c
@@ -2225,8 +2225,8 @@ __evict_get_ref(WT_SESSION_IMPL *session,
*/
if (((previous_state = evict->ref->state) != WT_REF_MEM &&
previous_state != WT_REF_LIMBO) ||
- !__wt_atomic_casv32(
- &evict->ref->state, previous_state, WT_REF_LOCKED)) {
+ !WT_REF_CAS_STATE(
+ session, evict->ref, previous_state, WT_REF_LOCKED)) {
__evict_list_clear(session, evict);
continue;
}
diff --git a/src/third_party/wiredtiger/src/evict/evict_page.c b/src/third_party/wiredtiger/src/evict/evict_page.c
index 4f472b9c9c6..5618220774b 100644
--- a/src/third_party/wiredtiger/src/evict/evict_page.c
+++ b/src/third_party/wiredtiger/src/evict/evict_page.c
@@ -74,7 +74,7 @@ __wt_page_release_evict(WT_SESSION_IMPL *session, WT_REF *ref, uint32_t flags)
*/
previous_state = ref->state;
if ((previous_state == WT_REF_MEM || previous_state == WT_REF_LIMBO) &&
- __wt_atomic_casv32(&ref->state, previous_state, WT_REF_LOCKED))
+ WT_REF_CAS_STATE(session, ref, previous_state, WT_REF_LOCKED))
locked = true;
if ((ret = __wt_hazard_clear(session, ref)) != 0 || !locked) {
if (locked)
diff --git a/src/third_party/wiredtiger/src/include/btmem.h b/src/third_party/wiredtiger/src/include/btmem.h
index c8e0aac8027..71a26862e4a 100644
--- a/src/third_party/wiredtiger/src/include/btmem.h
+++ b/src/third_party/wiredtiger/src/include/btmem.h
@@ -255,6 +255,7 @@ struct __wt_page_lookaside {
* page */
bool eviction_to_lookaside; /* Revert to lookaside on eviction */
bool has_prepares; /* One or more updates are prepared */
+ bool resolved; /* History has been read into cache */
bool skew_newest; /* Page image has newest versions */
};
@@ -896,6 +897,10 @@ struct __wt_ref {
WT_PAGE_DELETED *page_del; /* Deleted page information */
WT_PAGE_LOOKASIDE *page_las; /* Lookaside information */
+/* A macro wrapper allowing us to remember the callers code location */
+#define WT_REF_CAS_STATE(session, ref, old_state, new_state) \
+ __wt_ref_cas_state_int((session), (ref), (old_state), (new_state),\
+ __FILE__, __LINE__)
#ifdef HAVE_DIAGNOSTIC
/* Capture history of ref state changes. */
struct __wt_ref_hist {
@@ -906,14 +911,17 @@ struct __wt_ref {
uint32_t state;
} hist[3];
uint64_t histoff;
-#define WT_REF_SET_STATE(ref, s) do { \
+#define WT_REF_SAVE_STATE(ref, s, f, l) do { \
(ref)->hist[(ref)->histoff].session = session; \
(ref)->hist[(ref)->histoff].name = session->name; \
- (ref)->hist[(ref)->histoff].file = __FILE__; \
- (ref)->hist[(ref)->histoff].line = __LINE__; \
+ (ref)->hist[(ref)->histoff].file = (f); \
+ (ref)->hist[(ref)->histoff].line = (l); \
(ref)->hist[(ref)->histoff].state = s; \
(ref)->histoff = \
((ref)->histoff + 1) % WT_ELEMENTS((ref)->hist); \
+} while (0)
+#define WT_REF_SET_STATE(ref, s) do { \
+ WT_REF_SAVE_STATE(ref, s, __FILE__, __LINE__); \
WT_PUBLISH((ref)->state, s); \
} while (0)
#else
diff --git a/src/third_party/wiredtiger/src/include/btree.i b/src/third_party/wiredtiger/src/include/btree.i
index 418dbbd8488..162ea524b09 100644
--- a/src/third_party/wiredtiger/src/include/btree.i
+++ b/src/third_party/wiredtiger/src/include/btree.i
@@ -1198,6 +1198,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 || page_las->has_prepares)
return (true);
if (__wt_txn_visible_all(session, page_las->max_txn,
diff --git a/src/third_party/wiredtiger/src/include/extern.h b/src/third_party/wiredtiger/src/include/extern.h
index 13354d4996b..4a245d03f47 100644
--- a/src/third_party/wiredtiger/src/include/extern.h
+++ b/src/third_party/wiredtiger/src/include/extern.h
@@ -141,7 +141,7 @@ extern void __wt_btree_page_version_config(WT_SESSION_IMPL *session);
extern int __wt_btree_open(WT_SESSION_IMPL *session, const char *op_cfg[]) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_btree_close(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_btree_discard(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
-extern void __wt_root_ref_init(WT_REF *root_ref, WT_PAGE *root, bool is_recno);
+extern void __wt_root_ref_init(WT_SESSION_IMPL *session, WT_REF *root_ref, WT_PAGE *root, bool is_recno);
extern int __wt_btree_tree_open(WT_SESSION_IMPL *session, const uint8_t *addr, size_t addr_size) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_btree_new_leaf_page(WT_SESSION_IMPL *session, WT_PAGE **pagep) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern bool __wt_btree_immediately_durable(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
diff --git a/src/third_party/wiredtiger/src/include/txn.i b/src/third_party/wiredtiger/src/include/txn.i
index e7575f57db7..f79507e31ad 100644
--- a/src/third_party/wiredtiger/src/include/txn.i
+++ b/src/third_party/wiredtiger/src/include/txn.i
@@ -14,6 +14,35 @@ typedef enum {
WT_VISIBLE_PREPARE=1, /* Prepared update */
WT_VISIBLE_TRUE=2 /* A visible update */
} WT_VISIBLE_TYPE;
+/*
+ * __wt_ref_cas_state_int --
+ * Try to do a compare and swap, if successful update the ref history in
+ * diagnostic mode.
+ */
+static inline bool
+__wt_ref_cas_state_int(WT_SESSION_IMPL *session, WT_REF *ref,
+ uint32_t old_state, uint32_t new_state, const char *file, int line)
+{
+ bool cas_result;
+
+ /* Parameters that are used in a macro for diagnostic builds */
+ WT_UNUSED(session);
+ WT_UNUSED(file);
+ WT_UNUSED(line);
+
+ cas_result = __wt_atomic_casv32(&ref->state, old_state, new_state);
+
+#ifdef HAVE_DIAGNOSTIC
+ /*
+ * The history update here has potential to race; if the state gets
+ * updated again after the CAS above but before the history has been
+ * updated.
+ */
+ if (cas_result)
+ WT_REF_SAVE_STATE(ref, new_state, file, line);
+#endif
+ return (cas_result);
+}
/*
* __wt_txn_timestamp_flags --
@@ -380,9 +409,8 @@ __wt_txn_op_apply_prepare_state(
for (;; __wt_yield()) {
previous_state = ref->state;
WT_ASSERT(session, previous_state != WT_REF_READING);
- if (previous_state != WT_REF_LOCKED &&
- __wt_atomic_casv32(
- &ref->state, previous_state, WT_REF_LOCKED))
+ if (previous_state != WT_REF_LOCKED && WT_REF_CAS_STATE(
+ session, ref, previous_state, WT_REF_LOCKED))
break;
}
diff --git a/src/third_party/wiredtiger/src/reconcile/rec_child.c b/src/third_party/wiredtiger/src/reconcile/rec_child.c
index 74bff4719a2..f1d261c8f42 100644
--- a/src/third_party/wiredtiger/src/reconcile/rec_child.c
+++ b/src/third_party/wiredtiger/src/reconcile/rec_child.c
@@ -165,8 +165,8 @@ __wt_rec_child_modify(WT_SESSION_IMPL *session,
* to see if the delete is visible to us. Lock down the
* structure.
*/
- if (!__wt_atomic_casv32(
- &ref->state, WT_REF_DELETED, WT_REF_LOCKED))
+ if (!WT_REF_CAS_STATE(
+ session, ref, WT_REF_DELETED, WT_REF_LOCKED))
break;
ret = __rec_child_deleted(session, r, ref, statep);
WT_REF_SET_STATE(ref, WT_REF_DELETED);
diff --git a/src/third_party/wiredtiger/src/reconcile/rec_write.c b/src/third_party/wiredtiger/src/reconcile/rec_write.c
index ec967c3cfe8..84f07e317ff 100644
--- a/src/third_party/wiredtiger/src/reconcile/rec_write.c
+++ b/src/third_party/wiredtiger/src/reconcile/rec_write.c
@@ -496,7 +496,8 @@ __rec_root_write(WT_SESSION_IMPL *session, WT_PAGE *page, uint32_t flags)
/*
* Fake up a reference structure, and write the next root page.
*/
- __wt_root_ref_init(&fake_ref, next, page->type == WT_PAGE_COL_INT);
+ __wt_root_ref_init(session,
+ &fake_ref, next, page->type == WT_PAGE_COL_INT);
return (__wt_reconcile(session, &fake_ref, NULL, flags, NULL));
err: __wt_page_out(session, &next);
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 6c264c757fd..1779a48774a 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
@@ -245,18 +245,45 @@ __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 &&
- rollback_timestamp < ref->page_las->unstable_durable_timestamp) {
- /* 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 && rollback_timestamp <
+ ref->page_las->unstable_durable_timestamp) {
+ /*
+ * 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 (ref->page_las->max_timestamp > rollback_timestamp)
+ ref->page_las->max_timestamp = rollback_timestamp;
+ if (ref->page_las->unstable_durable_timestamp >
+ rollback_timestamp)
+ ref->page_las->unstable_durable_timestamp =
+ rollback_timestamp;
+ if (ref->page_las->unstable_timestamp > rollback_timestamp)
+ ref->page_las->unstable_timestamp = rollback_timestamp;
}
/* Review deleted page saved to the ref */
diff --git a/src/third_party/wiredtiger/test/utility/test_util.h b/src/third_party/wiredtiger/test/utility/test_util.h
index b77a4fe5b77..27310de0006 100644
--- a/src/third_party/wiredtiger/test/utility/test_util.h
+++ b/src/third_party/wiredtiger/test/utility/test_util.h
@@ -224,6 +224,9 @@ u64_to_string_zf(uint64_t n, char *buf, size_t len)
/* Allow tests to add their own death handling. */
extern void (*custom_die)(void);
+#ifdef _WIN32
+__declspec(noreturn)
+#endif
void testutil_die(int, const char *, ...)
WT_GCC_FUNC_DECL_ATTRIBUTE((noreturn));