diff options
author | Luke Chen <luke.chen@mongodb.com> | 2019-05-17 14:35:49 +1000 |
---|---|---|
committer | Luke Chen <luke.chen@mongodb.com> | 2019-05-17 14:35:49 +1000 |
commit | 1d05d4b956221cfeb731892a4387d1470f999114 (patch) | |
tree | ffeff3027433530538a9214a1f87f3f9760a19c2 /src | |
parent | 23ceef7c72f117ac0cc886447181d0f88433aefc (diff) | |
download | mongo-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')
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)); |